. default is false.
180 | allow_embedding = false
181 |
182 | # Set to true if you want to enable http strict transport security (HSTS) response header.
183 | # This is only sent when HTTPS is enabled in this configuration.
184 | # HSTS tells browsers that the site should only be accessed using HTTPS.
185 | # The default will change to true in the next minor release, 6.3.
186 | strict_transport_security = false
187 |
188 | # Sets how long a browser should cache HSTS. Only applied if strict_transport_security is enabled.
189 | strict_transport_security_max_age_seconds = 86400
190 |
191 | # Set to true if to enable HSTS preloading option. Only applied if strict_transport_security is enabled.
192 | strict_transport_security_preload = false
193 |
194 | # Set to true if to enable the HSTS includeSubDomains option. Only applied if strict_transport_security is enabled.
195 | strict_transport_security_subdomains = false
196 |
197 | # Set to true to enable the X-Content-Type-Options response header.
198 | # The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised
199 | # in the Content-Type headers should not be changed and be followed. The default will change to true in the next minor release, 6.3.
200 | x_content_type_options = false
201 |
202 | # Set to true to enable the X-XSS-Protection header, which tells browsers to stop pages from loading
203 | # when they detect reflected cross-site scripting (XSS) attacks. The default will change to true in the next minor release, 6.3.
204 | x_xss_protection = false
205 |
206 |
207 | #################################### Snapshots ###########################
208 | [snapshots]
209 | # snapshot sharing options
210 | external_enabled = true
211 | external_snapshot_url = https://snapshots-origin.raintank.io
212 | external_snapshot_name = Publish to snapshot.raintank.io
213 |
214 | # remove expired snapshot
215 | snapshot_remove_expired = true
216 |
217 | #################################### Dashboards ##################
218 |
219 | [dashboards]
220 | # Number dashboard versions to keep (per dashboard). Default: 20, Minimum: 1
221 | versions_to_keep = 20
222 |
223 | #################################### Users ###############################
224 | [users]
225 | # disable user signup / registration
226 | allow_sign_up = false
227 |
228 | # Allow non admin users to create organizations
229 | allow_org_create = false
230 |
231 | # Set to true to automatically assign new users to the default organization (id 1)
232 | auto_assign_org = true
233 |
234 | # Set this value to automatically add new users to the provided organization (if auto_assign_org above is set to true)
235 | auto_assign_org_id = 1
236 |
237 | # Default role new users will be automatically assigned (if auto_assign_org above is set to true)
238 | auto_assign_org_role = Viewer
239 |
240 | # Require email validation before sign up completes
241 | verify_email_enabled = false
242 |
243 | # Background text for the user field on the login page
244 | login_hint = email or username
245 | password_hint = password
246 |
247 | # Default UI theme ("dark" or "light")
248 | default_theme = dark
249 |
250 | # External user management
251 | external_manage_link_url =
252 | external_manage_link_name =
253 | external_manage_info =
254 |
255 | # Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard.
256 | viewers_can_edit = false
257 |
258 | # Editors can administrate dashboard, folders and teams they create
259 | editors_can_admin = false
260 |
261 | [auth]
262 | # Login cookie name
263 | login_cookie_name = grafana_session
264 |
265 | # The lifetime (days) an authenticated user can be inactive before being required to login at next visit. Default is 7 days.
266 | login_maximum_inactive_lifetime_days = 7
267 |
268 | # The maximum lifetime (days) an authenticated user can be logged in since login time before being required to login. Default is 30 days.
269 | login_maximum_lifetime_days = 30
270 |
271 | # How often should auth tokens be rotated for authenticated users when being active. The default is each 10 minutes.
272 | token_rotation_interval_minutes = 10
273 |
274 | # Set to true to disable (hide) the login form, useful if you use OAuth
275 | disable_login_form = false
276 |
277 | # Set to true to disable the signout link in the side menu. useful if you use auth.proxy
278 | disable_signout_menu = false
279 |
280 | # URL to redirect the user to after sign out
281 | signout_redirect_url =
282 |
283 | # Set to true to attempt login with OAuth automatically, skipping the login screen.
284 | # This setting is ignored if multiple OAuth providers are configured.
285 | oauth_auto_login = false
286 |
287 | #################################### Anonymous Auth ######################
288 | [auth.anonymous]
289 | # enable anonymous access
290 | enabled = true
291 |
292 | # specify organization name that should be used for unauthenticated users
293 | org_name = Main Org.
294 |
295 | # specify role for unauthenticated users
296 | org_role = Admin
297 |
298 | #################################### Github Auth #########################
299 | [auth.github]
300 | enabled = false
301 | allow_sign_up = true
302 | client_id = some_id
303 | client_secret = some_secret
304 | scopes = user:email,read:org
305 | auth_url = https://github.com/login/oauth/authorize
306 | token_url = https://github.com/login/oauth/access_token
307 | api_url = https://api.github.com/user
308 | team_ids =
309 | allowed_organizations =
310 |
311 | #################################### GitLab Auth #########################
312 | [auth.gitlab]
313 | enabled = false
314 | allow_sign_up = true
315 | client_id = some_id
316 | client_secret = some_secret
317 | scopes = api
318 | auth_url = https://gitlab.com/oauth/authorize
319 | token_url = https://gitlab.com/oauth/token
320 | api_url = https://gitlab.com/api/v4
321 | allowed_groups =
322 |
323 | #################################### Google Auth #########################
324 | [auth.google]
325 | enabled = false
326 | allow_sign_up = true
327 | client_id = some_client_id
328 | client_secret = some_client_secret
329 | scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email
330 | auth_url = https://accounts.google.com/o/oauth2/auth
331 | token_url = https://accounts.google.com/o/oauth2/token
332 | api_url = https://www.googleapis.com/oauth2/v1/userinfo
333 | allowed_domains =
334 | hosted_domain =
335 |
336 | #################################### Grafana.com Auth ####################
337 | # legacy key names (so they work in env variables)
338 | [auth.grafananet]
339 | enabled = false
340 | allow_sign_up = true
341 | client_id = some_id
342 | client_secret = some_secret
343 | scopes = user:email
344 | allowed_organizations =
345 |
346 | [auth.grafana_com]
347 | enabled = false
348 | allow_sign_up = true
349 | client_id = some_id
350 | client_secret = some_secret
351 | scopes = user:email
352 | allowed_organizations =
353 |
354 | #################################### Generic OAuth #######################
355 | [auth.generic_oauth]
356 | name = OAuth
357 | enabled = false
358 | allow_sign_up = true
359 | client_id = some_id
360 | client_secret = some_secret
361 | scopes = user:email
362 | email_attribute_name = email:primary
363 | auth_url =
364 | token_url =
365 | api_url =
366 | team_ids =
367 | allowed_organizations =
368 | tls_skip_verify_insecure = false
369 | tls_client_cert =
370 | tls_client_key =
371 | tls_client_ca =
372 | send_client_credentials_via_post = false
373 |
374 | #################################### Basic Auth ##########################
375 | [auth.basic]
376 | enabled = true
377 |
378 | #################################### Auth Proxy ##########################
379 | [auth.proxy]
380 | enabled = false
381 | header_name = X-WEBAUTH-USER
382 | header_property = username
383 | auto_sign_up = true
384 | ldap_sync_ttl = 60
385 | whitelist =
386 | headers =
387 |
388 | #################################### Auth LDAP ###########################
389 | [auth.ldap]
390 | enabled = false
391 | config_file = /etc/grafana/ldap.toml
392 | allow_sign_up = true
393 |
394 | # LDAP backround sync (Enterprise only)
395 | sync_cron = @hourly
396 | active_sync_enabled = false
397 |
398 | #################################### SMTP / Emailing #####################
399 | [smtp]
400 | enabled = false
401 | host = localhost:25
402 | user =
403 | # If the password contains # or ; you have to wrap it with triple quotes. Ex """#password;"""
404 | password =
405 | cert_file =
406 | key_file =
407 | skip_verify = false
408 | from_address = admin@grafana.localhost
409 | from_name = Grafana
410 | ehlo_identity =
411 |
412 | [emails]
413 | welcome_email_on_sign_up = false
414 | templates_pattern = emails/*.html
415 |
416 | #################################### Logging ##########################
417 | [log]
418 | # Either "console", "file", "syslog". Default is console and file
419 | # Use space to separate multiple modes, e.g. "console file"
420 | mode = console file
421 |
422 | # Either "debug", "info", "warn", "error", "critical", default is "info"
423 | level = info
424 |
425 | # optional settings to set different levels for specific loggers. Ex filters = sqlstore:debug
426 | filters =
427 |
428 | # For "console" mode only
429 | [log.console]
430 | level =
431 |
432 | # log line format, valid options are text, console and json
433 | format = console
434 |
435 | # For "file" mode only
436 | [log.file]
437 | level =
438 |
439 | # log line format, valid options are text, console and json
440 | format = text
441 |
442 | # This enables automated log rotate(switch of following options), default is true
443 | log_rotate = true
444 |
445 | # Max line number of single file, default is 1000000
446 | max_lines = 1000000
447 |
448 | # Max size shift of single file, default is 28 means 1 << 28, 256MB
449 | max_size_shift = 28
450 |
451 | # Segment log daily, default is true
452 | daily_rotate = true
453 |
454 | # Expired days of log file(delete after max days), default is 7
455 | max_days = 7
456 |
457 | [log.syslog]
458 | level =
459 |
460 | # log line format, valid options are text, console and json
461 | format = text
462 |
463 | # Syslog network type and address. This can be udp, tcp, or unix. If left blank, the default unix endpoints will be used.
464 | network =
465 | address =
466 |
467 | # Syslog facility. user, daemon and local0 through local7 are valid.
468 | facility =
469 |
470 | # Syslog tag. By default, the process' argv[0] is used.
471 | tag =
472 |
473 | #################################### Usage Quotas ########################
474 | [quota]
475 | enabled = false
476 |
477 | #### set quotas to -1 to make unlimited. ####
478 | # limit number of users per Org.
479 | org_user = 10
480 |
481 | # limit number of dashboards per Org.
482 | org_dashboard = 100
483 |
484 | # limit number of data_sources per Org.
485 | org_data_source = 10
486 |
487 | # limit number of api_keys per Org.
488 | org_api_key = 10
489 |
490 | # limit number of orgs a user can create.
491 | user_org = 10
492 |
493 | # Global limit of users.
494 | global_user = -1
495 |
496 | # global limit of orgs.
497 | global_org = -1
498 |
499 | # global limit of dashboards
500 | global_dashboard = -1
501 |
502 | # global limit of api_keys
503 | global_api_key = -1
504 |
505 | # global limit on number of logged in users.
506 | global_session = -1
507 |
508 | #################################### Alerting ############################
509 | [alerting]
510 | # Disable alerting engine & UI features
511 | enabled = true
512 | # Makes it possible to turn off alert rule execution but alerting UI is visible
513 | execute_alerts = true
514 |
515 | # Default setting for new alert rules. Defaults to categorize error and timeouts as alerting. (alerting, keep_state)
516 | error_or_timeout = alerting
517 |
518 | # Default setting for how Grafana handles nodata or null values in alerting. (alerting, no_data, keep_state, ok)
519 | nodata_or_nullvalues = no_data
520 |
521 | # Alert notifications can include images, but rendering many images at the same time can overload the server
522 | # This limit will protect the server from render overloading and make sure notifications are sent out quickly
523 | concurrent_render_limit = 5
524 |
525 | # Default setting for alert calculation timeout. Default value is 30
526 | evaluation_timeout_seconds = 30
527 |
528 | # Default setting for alert notification timeout. Default value is 30
529 | notification_timeout_seconds = 30
530 |
531 | # Default setting for max attempts to sending alert notifications. Default value is 3
532 | max_attempts = 3
533 |
534 |
535 | #################################### Explore #############################
536 | [explore]
537 | # Enable the Explore section
538 | enabled = true
539 |
540 | #################################### Internal Grafana Metrics ############
541 | # Metrics available at HTTP API Url /metrics
542 | [metrics]
543 | enabled = true
544 | interval_seconds = 10
545 |
546 | #If both are set, basic auth will be required for the metrics endpoint.
547 | basic_auth_username =
548 | basic_auth_password =
549 |
550 | # Send internal Grafana metrics to graphite
551 | [metrics.graphite]
552 | # Enable by setting the address setting (ex localhost:2003)
553 | address =
554 | prefix = prod.grafana.%(instance_name)s.
555 |
556 | [grafana_net]
557 | url = https://grafana.com
558 |
559 | [grafana_com]
560 | url = https://grafana.com
561 |
562 | #################################### Distributed tracing ############
563 | [tracing.jaeger]
564 | # jaeger destination (ex localhost:6831)
565 | address =
566 | # tag that will always be included in when creating new spans. ex (tag1:value1,tag2:value2)
567 | always_included_tag =
568 | # Type specifies the type of the sampler: const, probabilistic, rateLimiting, or remote
569 | sampler_type = const
570 | # jaeger samplerconfig param
571 | # for "const" sampler, 0 or 1 for always false/true respectively
572 | # for "probabilistic" sampler, a probability between 0 and 1
573 | # for "rateLimiting" sampler, the number of spans per second
574 | # for "remote" sampler, param is the same as for "probabilistic"
575 | # and indicates the initial sampling rate before the actual one
576 | # is received from the mothership
577 | sampler_param = 1
578 |
579 | #################################### External Image Storage ##############
580 | [external_image_storage]
581 | # You can choose between (s3, webdav, gcs, azure_blob, local)
582 | provider =
583 |
584 | [external_image_storage.s3]
585 | bucket_url =
586 | bucket =
587 | region =
588 | path =
589 | access_key =
590 | secret_key =
591 |
592 | [external_image_storage.webdav]
593 | url =
594 | username =
595 | password =
596 | public_url =
597 |
598 | [external_image_storage.gcs]
599 | key_file =
600 | bucket =
601 | path =
602 |
603 | [external_image_storage.azure_blob]
604 | account_name =
605 | account_key =
606 | container_name =
607 |
608 | [external_image_storage.local]
609 | # does not require any configuration
610 |
611 | [rendering]
612 | # Options to configure external image rendering server like https://github.com/grafana/grafana-image-renderer
613 | server_url =
614 | callback_url =
615 |
616 | [panels]
617 | # here for to support old env variables, can remove after a few months
618 | enable_alpha = false
619 | disable_sanitize_html = false
620 |
621 | [plugins]
622 | enable_alpha = false
623 | app_tls_skip_verify_insecure = false
624 |
625 | [enterprise]
626 | license_path =
627 |
--------------------------------------------------------------------------------
/docker/grafana/nginx-api-dashboard.json:
--------------------------------------------------------------------------------
1 | {
2 | "annotations": {
3 | "list": [
4 | {
5 | "builtIn": 1,
6 | "datasource": "-- Grafana --",
7 | "enable": true,
8 | "hide": true,
9 | "iconColor": "rgba(0, 211, 255, 1)",
10 | "name": "Annotations & Alerts",
11 | "type": "dashboard"
12 | }
13 | ]
14 | },
15 | "editable": true,
16 | "gnetId": null,
17 | "graphTooltip": 0,
18 | "id": 7,
19 | "iteration": 1562122446903,
20 | "links": [
21 | {
22 | "asDropdown": true,
23 | "icon": "external link",
24 | "keepTime": true,
25 | "tags": [
26 | "nginx"
27 | ],
28 | "targetBlank": true,
29 | "title": "# NGINX",
30 | "type": "dashboards"
31 | }
32 | ],
33 | "panels": [
34 | {
35 | "collapsed": false,
36 | "gridPos": {
37 | "h": 1,
38 | "w": 24,
39 | "x": 0,
40 | "y": 0
41 | },
42 | "id": 126,
43 | "panels": [],
44 | "title": "Overall",
45 | "type": "row"
46 | },
47 | {
48 | "aliasColors": {},
49 | "bars": true,
50 | "dashLength": 10,
51 | "dashes": false,
52 | "datasource": "Prometheus-Aggregator",
53 | "fill": 1,
54 | "gridPos": {
55 | "h": 4,
56 | "w": 8,
57 | "x": 0,
58 | "y": 1
59 | },
60 | "id": 140,
61 | "legend": {
62 | "alignAsTable": true,
63 | "avg": true,
64 | "current": false,
65 | "hideEmpty": true,
66 | "hideZero": true,
67 | "max": true,
68 | "min": false,
69 | "rightSide": true,
70 | "show": false,
71 | "sideWidth": null,
72 | "sort": "max",
73 | "sortDesc": true,
74 | "total": false,
75 | "values": true
76 | },
77 | "lines": false,
78 | "linewidth": 1,
79 | "links": [],
80 | "nullPointMode": "null",
81 | "options": {},
82 | "percentage": false,
83 | "pointradius": 5,
84 | "points": false,
85 | "renderer": "flot",
86 | "seriesOverrides": [],
87 | "spaceLength": 10,
88 | "stack": false,
89 | "steppedLine": false,
90 | "targets": [
91 | {
92 | "expr": "job:nginx_http_request_duration_seconds_count:counter_1min_by_host_3XX{host=~\"$host\"}",
93 | "format": "time_series",
94 | "hide": false,
95 | "instant": false,
96 | "intervalFactor": 2,
97 | "legendFormat": "3XX - 1min - {{host}}",
98 | "refId": "A"
99 | }
100 | ],
101 | "thresholds": [],
102 | "timeFrom": null,
103 | "timeRegions": [],
104 | "timeShift": null,
105 | "title": "ERROR 3XX - 1min",
106 | "tooltip": {
107 | "shared": true,
108 | "sort": 2,
109 | "value_type": "individual"
110 | },
111 | "type": "graph",
112 | "xaxis": {
113 | "buckets": null,
114 | "mode": "time",
115 | "name": null,
116 | "show": true,
117 | "values": []
118 | },
119 | "yaxes": [
120 | {
121 | "decimals": 0,
122 | "format": "none",
123 | "label": null,
124 | "logBase": 1,
125 | "max": null,
126 | "min": null,
127 | "show": true
128 | },
129 | {
130 | "format": "short",
131 | "label": null,
132 | "logBase": 1,
133 | "max": null,
134 | "min": null,
135 | "show": true
136 | }
137 | ],
138 | "yaxis": {
139 | "align": false,
140 | "alignLevel": null
141 | }
142 | },
143 | {
144 | "aliasColors": {},
145 | "bars": false,
146 | "dashLength": 10,
147 | "dashes": false,
148 | "datasource": "Prometheus-Aggregator",
149 | "fill": 1,
150 | "gridPos": {
151 | "h": 4,
152 | "w": 8,
153 | "x": 8,
154 | "y": 1
155 | },
156 | "id": 112,
157 | "legend": {
158 | "alignAsTable": false,
159 | "avg": false,
160 | "current": false,
161 | "max": false,
162 | "min": false,
163 | "rightSide": false,
164 | "show": false,
165 | "sort": "current",
166 | "sortDesc": true,
167 | "total": false,
168 | "values": false
169 | },
170 | "lines": true,
171 | "linewidth": 1,
172 | "links": [],
173 | "nullPointMode": "null",
174 | "options": {},
175 | "percentage": false,
176 | "pointradius": 5,
177 | "points": false,
178 | "renderer": "flot",
179 | "seriesOverrides": [
180 | {
181 | "alias": "Summary",
182 | "transform": "negative-Y"
183 | }
184 | ],
185 | "spaceLength": 10,
186 | "stack": false,
187 | "steppedLine": false,
188 | "targets": [
189 | {
190 | "expr": "job:nginx_http_request_duration_seconds:qps_by_host_2XX{host=~\"$host\"}",
191 | "format": "time_series",
192 | "hide": false,
193 | "intervalFactor": 1,
194 | "legendFormat": "{{host}}",
195 | "refId": "A"
196 | }
197 | ],
198 | "thresholds": [],
199 | "timeFrom": null,
200 | "timeRegions": [],
201 | "timeShift": null,
202 | "title": "2XX QPS By Host",
203 | "tooltip": {
204 | "shared": true,
205 | "sort": 2,
206 | "value_type": "individual"
207 | },
208 | "type": "graph",
209 | "xaxis": {
210 | "buckets": null,
211 | "mode": "time",
212 | "name": null,
213 | "show": true,
214 | "values": []
215 | },
216 | "yaxes": [
217 | {
218 | "format": "short",
219 | "label": null,
220 | "logBase": 1,
221 | "max": null,
222 | "min": null,
223 | "show": true
224 | },
225 | {
226 | "format": "short",
227 | "label": null,
228 | "logBase": 1,
229 | "max": null,
230 | "min": null,
231 | "show": true
232 | }
233 | ],
234 | "yaxis": {
235 | "align": false,
236 | "alignLevel": 1
237 | }
238 | },
239 | {
240 | "aliasColors": {},
241 | "bars": false,
242 | "dashLength": 10,
243 | "dashes": false,
244 | "datasource": "Prometheus-Aggregator",
245 | "fill": 1,
246 | "gridPos": {
247 | "h": 4,
248 | "w": 8,
249 | "x": 16,
250 | "y": 1
251 | },
252 | "id": 129,
253 | "legend": {
254 | "alignAsTable": false,
255 | "avg": false,
256 | "current": false,
257 | "max": false,
258 | "min": false,
259 | "rightSide": false,
260 | "show": false,
261 | "sort": "current",
262 | "sortDesc": true,
263 | "total": false,
264 | "values": false
265 | },
266 | "lines": true,
267 | "linewidth": 1,
268 | "links": [],
269 | "nullPointMode": "null",
270 | "options": {},
271 | "percentage": false,
272 | "pointradius": 5,
273 | "points": false,
274 | "renderer": "flot",
275 | "seriesOverrides": [
276 | {
277 | "alias": "Summary",
278 | "transform": "negative-Y"
279 | }
280 | ],
281 | "spaceLength": 10,
282 | "stack": false,
283 | "steppedLine": false,
284 | "targets": [
285 | {
286 | "expr": "sum (job:nginx_http_request_duration_seconds:qps_by_host_2XX{host=~\"$host\"})",
287 | "format": "time_series",
288 | "hide": true,
289 | "intervalFactor": 1,
290 | "legendFormat": "2XX",
291 | "refId": "A"
292 | },
293 | {
294 | "expr": "sum (job:nginx_http_request_duration_seconds:qps_by_host_4XX{host=~\"$host\"})",
295 | "format": "time_series",
296 | "hide": false,
297 | "intervalFactor": 1,
298 | "legendFormat": "4XX",
299 | "refId": "B"
300 | },
301 | {
302 | "expr": "sum (job:nginx_http_request_duration_seconds:qps_by_host_5XX{host=~\"$host\"})",
303 | "format": "time_series",
304 | "hide": false,
305 | "intervalFactor": 1,
306 | "legendFormat": "5XX",
307 | "refId": "C"
308 | },
309 | {
310 | "expr": "sum (job:nginx_http_request_duration_seconds:qps_by_host_403{host=~\"$host\"})",
311 | "format": "time_series",
312 | "hide": false,
313 | "intervalFactor": 1,
314 | "legendFormat": "403",
315 | "refId": "D"
316 | }
317 | ],
318 | "thresholds": [],
319 | "timeFrom": null,
320 | "timeRegions": [],
321 | "timeShift": null,
322 | "title": "QPS",
323 | "tooltip": {
324 | "shared": true,
325 | "sort": 2,
326 | "value_type": "individual"
327 | },
328 | "type": "graph",
329 | "xaxis": {
330 | "buckets": null,
331 | "mode": "time",
332 | "name": null,
333 | "show": true,
334 | "values": []
335 | },
336 | "yaxes": [
337 | {
338 | "format": "short",
339 | "label": null,
340 | "logBase": 1,
341 | "max": null,
342 | "min": null,
343 | "show": true
344 | },
345 | {
346 | "format": "short",
347 | "label": null,
348 | "logBase": 1,
349 | "max": null,
350 | "min": null,
351 | "show": true
352 | }
353 | ],
354 | "yaxis": {
355 | "align": false,
356 | "alignLevel": 1
357 | }
358 | },
359 | {
360 | "aliasColors": {},
361 | "bars": true,
362 | "dashLength": 10,
363 | "dashes": false,
364 | "datasource": "Prometheus-Aggregator",
365 | "fill": 1,
366 | "gridPos": {
367 | "h": 4,
368 | "w": 8,
369 | "x": 0,
370 | "y": 5
371 | },
372 | "id": 128,
373 | "legend": {
374 | "alignAsTable": true,
375 | "avg": true,
376 | "current": false,
377 | "hideEmpty": true,
378 | "hideZero": true,
379 | "max": true,
380 | "min": false,
381 | "rightSide": true,
382 | "show": false,
383 | "sideWidth": null,
384 | "sort": "max",
385 | "sortDesc": true,
386 | "total": false,
387 | "values": true
388 | },
389 | "lines": false,
390 | "linewidth": 1,
391 | "links": [],
392 | "nullPointMode": "null",
393 | "options": {},
394 | "percentage": false,
395 | "pointradius": 5,
396 | "points": false,
397 | "renderer": "flot",
398 | "seriesOverrides": [],
399 | "spaceLength": 10,
400 | "stack": false,
401 | "steppedLine": false,
402 | "targets": [
403 | {
404 | "expr": "job:nginx_http_request_duration_seconds_count:counter_1min_by_host_4XX{host=~\"$host\"}",
405 | "format": "time_series",
406 | "hide": false,
407 | "instant": false,
408 | "intervalFactor": 2,
409 | "legendFormat": "4XX - 1min - {{host}}",
410 | "refId": "B"
411 | }
412 | ],
413 | "thresholds": [],
414 | "timeFrom": null,
415 | "timeRegions": [],
416 | "timeShift": null,
417 | "title": "ERROR 4XX - 1min",
418 | "tooltip": {
419 | "shared": true,
420 | "sort": 2,
421 | "value_type": "individual"
422 | },
423 | "type": "graph",
424 | "xaxis": {
425 | "buckets": null,
426 | "mode": "time",
427 | "name": null,
428 | "show": true,
429 | "values": []
430 | },
431 | "yaxes": [
432 | {
433 | "decimals": 0,
434 | "format": "none",
435 | "label": null,
436 | "logBase": 1,
437 | "max": null,
438 | "min": null,
439 | "show": true
440 | },
441 | {
442 | "format": "short",
443 | "label": null,
444 | "logBase": 1,
445 | "max": null,
446 | "min": null,
447 | "show": true
448 | }
449 | ],
450 | "yaxis": {
451 | "align": false,
452 | "alignLevel": null
453 | }
454 | },
455 | {
456 | "aliasColors": {},
457 | "bars": false,
458 | "dashLength": 10,
459 | "dashes": false,
460 | "datasource": "Prometheus-Aggregator",
461 | "fill": 1,
462 | "gridPos": {
463 | "h": 4,
464 | "w": 8,
465 | "x": 8,
466 | "y": 5
467 | },
468 | "id": 135,
469 | "legend": {
470 | "alignAsTable": false,
471 | "avg": false,
472 | "current": false,
473 | "max": false,
474 | "min": false,
475 | "rightSide": false,
476 | "show": false,
477 | "sort": "current",
478 | "sortDesc": true,
479 | "total": false,
480 | "values": false
481 | },
482 | "lines": true,
483 | "linewidth": 1,
484 | "links": [],
485 | "nullPointMode": "null",
486 | "options": {},
487 | "percentage": false,
488 | "pointradius": 5,
489 | "points": false,
490 | "renderer": "flot",
491 | "seriesOverrides": [
492 | {
493 | "alias": "Summary",
494 | "transform": "negative-Y"
495 | }
496 | ],
497 | "spaceLength": 10,
498 | "stack": false,
499 | "steppedLine": false,
500 | "targets": [
501 | {
502 | "expr": "job:nginx_http_request_duration_seconds:qps_by_host_4XX{host=~\"$host\"}",
503 | "format": "time_series",
504 | "hide": false,
505 | "intervalFactor": 1,
506 | "legendFormat": "{{host}}",
507 | "refId": "A"
508 | }
509 | ],
510 | "thresholds": [],
511 | "timeFrom": null,
512 | "timeRegions": [],
513 | "timeShift": null,
514 | "title": "4XX QPS By Host",
515 | "tooltip": {
516 | "shared": true,
517 | "sort": 2,
518 | "value_type": "individual"
519 | },
520 | "type": "graph",
521 | "xaxis": {
522 | "buckets": null,
523 | "mode": "time",
524 | "name": null,
525 | "show": true,
526 | "values": []
527 | },
528 | "yaxes": [
529 | {
530 | "format": "short",
531 | "label": null,
532 | "logBase": 1,
533 | "max": null,
534 | "min": null,
535 | "show": true
536 | },
537 | {
538 | "format": "short",
539 | "label": null,
540 | "logBase": 1,
541 | "max": null,
542 | "min": null,
543 | "show": true
544 | }
545 | ],
546 | "yaxis": {
547 | "align": false,
548 | "alignLevel": 1
549 | }
550 | },
551 | {
552 | "aliasColors": {},
553 | "bars": false,
554 | "dashLength": 10,
555 | "dashes": false,
556 | "datasource": "Prometheus-Aggregator",
557 | "fill": 1,
558 | "gridPos": {
559 | "h": 4,
560 | "w": 8,
561 | "x": 16,
562 | "y": 5
563 | },
564 | "id": 138,
565 | "legend": {
566 | "alignAsTable": true,
567 | "avg": true,
568 | "current": false,
569 | "hideEmpty": true,
570 | "hideZero": true,
571 | "max": true,
572 | "min": false,
573 | "rightSide": true,
574 | "show": false,
575 | "sideWidth": null,
576 | "sort": "max",
577 | "sortDesc": true,
578 | "total": false,
579 | "values": true
580 | },
581 | "lines": true,
582 | "linewidth": 1,
583 | "links": [],
584 | "nullPointMode": "null",
585 | "options": {},
586 | "percentage": false,
587 | "pointradius": 5,
588 | "points": false,
589 | "renderer": "flot",
590 | "seriesOverrides": [],
591 | "spaceLength": 10,
592 | "stack": false,
593 | "steppedLine": false,
594 | "targets": [
595 | {
596 | "expr": "job:nginx_http_request_duration_seconds_sum:err_rate_by_host{host=~\"$host\"}",
597 | "format": "time_series",
598 | "hide": false,
599 | "instant": false,
600 | "intervalFactor": 2,
601 | "legendFormat": "{{host}}",
602 | "refId": "A"
603 | }
604 | ],
605 | "thresholds": [],
606 | "timeFrom": null,
607 | "timeRegions": [],
608 | "timeShift": null,
609 | "title": "ERROR Rate",
610 | "tooltip": {
611 | "shared": true,
612 | "sort": 2,
613 | "value_type": "individual"
614 | },
615 | "type": "graph",
616 | "xaxis": {
617 | "buckets": null,
618 | "mode": "time",
619 | "name": null,
620 | "show": true,
621 | "values": []
622 | },
623 | "yaxes": [
624 | {
625 | "decimals": 1,
626 | "format": "percent",
627 | "label": null,
628 | "logBase": 1,
629 | "max": null,
630 | "min": null,
631 | "show": true
632 | },
633 | {
634 | "format": "short",
635 | "label": null,
636 | "logBase": 1,
637 | "max": null,
638 | "min": null,
639 | "show": true
640 | }
641 | ],
642 | "yaxis": {
643 | "align": false,
644 | "alignLevel": null
645 | }
646 | },
647 | {
648 | "aliasColors": {},
649 | "bars": true,
650 | "dashLength": 10,
651 | "dashes": false,
652 | "datasource": "Prometheus-Aggregator",
653 | "fill": 1,
654 | "gridPos": {
655 | "h": 4,
656 | "w": 8,
657 | "x": 0,
658 | "y": 9
659 | },
660 | "id": 139,
661 | "legend": {
662 | "alignAsTable": true,
663 | "avg": true,
664 | "current": false,
665 | "hideEmpty": true,
666 | "hideZero": true,
667 | "max": true,
668 | "min": false,
669 | "rightSide": true,
670 | "show": false,
671 | "sideWidth": null,
672 | "sort": "max",
673 | "sortDesc": true,
674 | "total": false,
675 | "values": true
676 | },
677 | "lines": false,
678 | "linewidth": 1,
679 | "links": [],
680 | "nullPointMode": "null",
681 | "options": {},
682 | "percentage": false,
683 | "pointradius": 5,
684 | "points": false,
685 | "renderer": "flot",
686 | "seriesOverrides": [],
687 | "spaceLength": 10,
688 | "stack": false,
689 | "steppedLine": false,
690 | "targets": [
691 | {
692 | "expr": "job:nginx_http_request_duration_seconds_count:counter_1min_by_host_5XX{host=~\"$host\"}",
693 | "format": "time_series",
694 | "hide": false,
695 | "instant": false,
696 | "intervalFactor": 2,
697 | "legendFormat": "5XX - 1min - {{host}}",
698 | "refId": "A"
699 | }
700 | ],
701 | "thresholds": [],
702 | "timeFrom": null,
703 | "timeRegions": [],
704 | "timeShift": null,
705 | "title": "ERROR 5XX - 1min",
706 | "tooltip": {
707 | "shared": true,
708 | "sort": 2,
709 | "value_type": "individual"
710 | },
711 | "type": "graph",
712 | "xaxis": {
713 | "buckets": null,
714 | "mode": "time",
715 | "name": null,
716 | "show": true,
717 | "values": []
718 | },
719 | "yaxes": [
720 | {
721 | "decimals": 0,
722 | "format": "none",
723 | "label": null,
724 | "logBase": 1,
725 | "max": null,
726 | "min": null,
727 | "show": true
728 | },
729 | {
730 | "format": "short",
731 | "label": null,
732 | "logBase": 1,
733 | "max": null,
734 | "min": null,
735 | "show": true
736 | }
737 | ],
738 | "yaxis": {
739 | "align": false,
740 | "alignLevel": null
741 | }
742 | },
743 | {
744 | "aliasColors": {},
745 | "bars": false,
746 | "dashLength": 10,
747 | "dashes": false,
748 | "datasource": "Prometheus-Aggregator",
749 | "fill": 1,
750 | "gridPos": {
751 | "h": 4,
752 | "w": 8,
753 | "x": 8,
754 | "y": 9
755 | },
756 | "id": 136,
757 | "legend": {
758 | "alignAsTable": false,
759 | "avg": false,
760 | "current": false,
761 | "max": false,
762 | "min": false,
763 | "rightSide": false,
764 | "show": false,
765 | "sort": "current",
766 | "sortDesc": true,
767 | "total": false,
768 | "values": false
769 | },
770 | "lines": true,
771 | "linewidth": 1,
772 | "links": [],
773 | "nullPointMode": "null",
774 | "options": {},
775 | "percentage": false,
776 | "pointradius": 5,
777 | "points": false,
778 | "renderer": "flot",
779 | "seriesOverrides": [
780 | {
781 | "alias": "Summary",
782 | "transform": "negative-Y"
783 | }
784 | ],
785 | "spaceLength": 10,
786 | "stack": false,
787 | "steppedLine": false,
788 | "targets": [
789 | {
790 | "expr": "job:nginx_http_request_duration_seconds:qps_by_host_5XX{host=~\"$host\"}",
791 | "format": "time_series",
792 | "hide": false,
793 | "intervalFactor": 1,
794 | "legendFormat": "{{host}}",
795 | "refId": "A"
796 | }
797 | ],
798 | "thresholds": [],
799 | "timeFrom": null,
800 | "timeRegions": [],
801 | "timeShift": null,
802 | "title": "5XX QPS By Host",
803 | "tooltip": {
804 | "shared": true,
805 | "sort": 2,
806 | "value_type": "individual"
807 | },
808 | "type": "graph",
809 | "xaxis": {
810 | "buckets": null,
811 | "mode": "time",
812 | "name": null,
813 | "show": true,
814 | "values": []
815 | },
816 | "yaxes": [
817 | {
818 | "format": "short",
819 | "label": null,
820 | "logBase": 1,
821 | "max": null,
822 | "min": null,
823 | "show": true
824 | },
825 | {
826 | "format": "short",
827 | "label": null,
828 | "logBase": 1,
829 | "max": null,
830 | "min": null,
831 | "show": true
832 | }
833 | ],
834 | "yaxis": {
835 | "align": false,
836 | "alignLevel": 1
837 | }
838 | },
839 | {
840 | "collapsed": false,
841 | "gridPos": {
842 | "h": 1,
843 | "w": 24,
844 | "x": 0,
845 | "y": 13
846 | },
847 | "id": 122,
848 | "panels": [],
849 | "title": "Host",
850 | "type": "row"
851 | },
852 | {
853 | "columns": [],
854 | "datasource": "Prometheus-Aggregator",
855 | "fontSize": "100%",
856 | "gridPos": {
857 | "h": 18,
858 | "w": 24,
859 | "x": 0,
860 | "y": 14
861 | },
862 | "id": 116,
863 | "links": [],
864 | "options": {},
865 | "pageSize": 30,
866 | "scroll": true,
867 | "showHeader": true,
868 | "sort": {
869 | "col": 2,
870 | "desc": true
871 | },
872 | "styles": [
873 | {
874 | "alias": "Time",
875 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
876 | "pattern": "Time",
877 | "type": "hidden"
878 | },
879 | {
880 | "alias": "",
881 | "colorMode": null,
882 | "colors": [
883 | "rgba(245, 54, 54, 0.9)",
884 | "rgba(237, 129, 40, 0.89)",
885 | "rgba(50, 172, 45, 0.97)"
886 | ],
887 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
888 | "decimals": 2,
889 | "link": false,
890 | "linkTargetBlank": true,
891 | "linkTooltip": "",
892 | "linkUrl": "",
893 | "mappingType": 1,
894 | "pattern": "__name__",
895 | "sanitize": false,
896 | "thresholds": [],
897 | "type": "hidden",
898 | "unit": "short"
899 | },
900 | {
901 | "alias": "QPS",
902 | "colorMode": null,
903 | "colors": [
904 | "rgba(245, 54, 54, 0.9)",
905 | "rgba(237, 129, 40, 0.89)",
906 | "rgba(50, 172, 45, 0.97)"
907 | ],
908 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
909 | "decimals": 2,
910 | "link": true,
911 | "linkTargetBlank": true,
912 | "linkTooltip": "点击进入详情",
913 | "linkUrl": "/d/_CvuD14Wk/nginx-api-host?var-host=${__cell_1}",
914 | "mappingType": 1,
915 | "pattern": "Value #A",
916 | "thresholds": [],
917 | "type": "number",
918 | "unit": "short"
919 | },
920 | {
921 | "alias": "3XX - 1min",
922 | "colorMode": null,
923 | "colors": [
924 | "rgba(245, 54, 54, 0.9)",
925 | "rgba(237, 129, 40, 0.89)",
926 | "rgba(50, 172, 45, 0.97)"
927 | ],
928 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
929 | "decimals": 2,
930 | "link": true,
931 | "linkTargetBlank": true,
932 | "linkTooltip": "点击进入详情",
933 | "linkUrl": "/d/_CvuD14Wk/nginx-api-host?var-host=${__cell_1}",
934 | "mappingType": 1,
935 | "pattern": "Value #B",
936 | "thresholds": [],
937 | "type": "number",
938 | "unit": "short"
939 | },
940 | {
941 | "alias": "4XX - 1min",
942 | "colorMode": "cell",
943 | "colors": [
944 | "rgba(50, 172, 45, 0.97)",
945 | "rgba(237, 129, 40, 0.89)",
946 | "rgba(245, 54, 54, 0.9)"
947 | ],
948 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
949 | "decimals": 2,
950 | "link": true,
951 | "linkTargetBlank": true,
952 | "linkTooltip": "点击进入详情",
953 | "linkUrl": "/d/_CvuD14Wk/nginx-api-host?var-host=${__cell_1}",
954 | "mappingType": 1,
955 | "pattern": "Value #C",
956 | "thresholds": [
957 | "100",
958 | "10"
959 | ],
960 | "type": "number",
961 | "unit": "short"
962 | },
963 | {
964 | "alias": "5XX - 1min",
965 | "colorMode": "cell",
966 | "colors": [
967 | "rgba(50, 172, 45, 0.97)",
968 | "rgba(237, 129, 40, 0.89)",
969 | "rgba(245, 54, 54, 0.9)"
970 | ],
971 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
972 | "decimals": 2,
973 | "link": true,
974 | "linkTargetBlank": true,
975 | "linkTooltip": "点击进入详情",
976 | "linkUrl": "/d/_CvuD14Wk/nginx-api-host?var-host=${__cell_1}",
977 | "mappingType": 1,
978 | "pattern": "Value #D",
979 | "thresholds": [
980 | "100",
981 | "10"
982 | ],
983 | "type": "number",
984 | "unit": "short"
985 | },
986 | {
987 | "alias": "SLA",
988 | "colorMode": "cell",
989 | "colors": [
990 | "rgba(245, 54, 54, 0.9)",
991 | "rgba(237, 129, 40, 0.89)",
992 | "rgba(50, 172, 45, 0.97)"
993 | ],
994 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
995 | "decimals": 2,
996 | "link": true,
997 | "linkTargetBlank": true,
998 | "linkTooltip": "点击进入详情",
999 | "linkUrl": "/d/_CvuD14Wk/nginx-api-host?var-host=${__cell_1}",
1000 | "mappingType": 1,
1001 | "pattern": "Value #E",
1002 | "thresholds": [
1003 | "0.999",
1004 | "0.99"
1005 | ],
1006 | "type": "number",
1007 | "unit": "percent"
1008 | },
1009 | {
1010 | "alias": "",
1011 | "colorMode": null,
1012 | "colors": [
1013 | "rgba(245, 54, 54, 0.9)",
1014 | "rgba(237, 129, 40, 0.89)",
1015 | "rgba(50, 172, 45, 0.97)"
1016 | ],
1017 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
1018 | "decimals": 2,
1019 | "link": true,
1020 | "linkTargetBlank": true,
1021 | "linkTooltip": "点击进入详情",
1022 | "linkUrl": "/d/_CvuD14Wk/nginx-api-host?var-host=${__cell_1}",
1023 | "mappingType": 1,
1024 | "pattern": "host",
1025 | "thresholds": [],
1026 | "type": "number",
1027 | "unit": "short"
1028 | },
1029 | {
1030 | "alias": "",
1031 | "colorMode": null,
1032 | "colors": [
1033 | "rgba(245, 54, 54, 0.9)",
1034 | "rgba(237, 129, 40, 0.89)",
1035 | "rgba(50, 172, 45, 0.97)"
1036 | ],
1037 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
1038 | "decimals": 2,
1039 | "mappingType": 1,
1040 | "pattern": "job",
1041 | "thresholds": [],
1042 | "type": "hidden",
1043 | "unit": "short"
1044 | },
1045 | {
1046 | "alias": "",
1047 | "colorMode": null,
1048 | "colors": [
1049 | "rgba(245, 54, 54, 0.9)",
1050 | "rgba(237, 129, 40, 0.89)",
1051 | "rgba(50, 172, 45, 0.97)"
1052 | ],
1053 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
1054 | "decimals": 2,
1055 | "mappingType": 1,
1056 | "pattern": "monitor",
1057 | "thresholds": [],
1058 | "type": "hidden",
1059 | "unit": "short"
1060 | },
1061 | {
1062 | "alias": "",
1063 | "colorMode": null,
1064 | "colors": [
1065 | "rgba(245, 54, 54, 0.9)",
1066 | "rgba(237, 129, 40, 0.89)",
1067 | "rgba(50, 172, 45, 0.97)"
1068 | ],
1069 | "decimals": 2,
1070 | "pattern": "/.*/",
1071 | "thresholds": [],
1072 | "type": "number",
1073 | "unit": "short"
1074 | }
1075 | ],
1076 | "targets": [
1077 | {
1078 | "expr": "sum(job:nginx_http_request_duration_seconds:qps_by_host_2XX{host=~\"$host\"}) by (host)",
1079 | "format": "table",
1080 | "hide": false,
1081 | "instant": true,
1082 | "intervalFactor": 1,
1083 | "refId": "A"
1084 | },
1085 | {
1086 | "expr": "sum(job:nginx_http_request_duration_seconds_count:counter_1min_by_host_3XX{host=~\"$host\"}) by (host)",
1087 | "format": "table",
1088 | "hide": false,
1089 | "instant": true,
1090 | "intervalFactor": 1,
1091 | "refId": "B"
1092 | },
1093 | {
1094 | "expr": "sum(job:nginx_http_request_duration_seconds_count:counter_1min_by_host_4XX{host=~\"$host\"}) by (host)",
1095 | "format": "table",
1096 | "hide": false,
1097 | "instant": true,
1098 | "intervalFactor": 1,
1099 | "refId": "C"
1100 | },
1101 | {
1102 | "expr": "sum(job:nginx_http_request_duration_seconds_count:counter_1min_by_host_5XX{host=~\"$host\"}) by (host)",
1103 | "format": "table",
1104 | "hide": false,
1105 | "instant": true,
1106 | "intervalFactor": 1,
1107 | "legendFormat": "5XX",
1108 | "refId": "D"
1109 | },
1110 | {
1111 | "expr": "100-job:nginx_http_request_duration_seconds_sum:err_rate_by_host{host=~\"$host\"}",
1112 | "format": "table",
1113 | "hide": false,
1114 | "instant": true,
1115 | "intervalFactor": 1,
1116 | "refId": "E"
1117 | }
1118 | ],
1119 | "title": "",
1120 | "transform": "table",
1121 | "type": "table"
1122 | }
1123 | ],
1124 | "refresh": false,
1125 | "schemaVersion": 18,
1126 | "style": "dark",
1127 | "tags": [
1128 | "nginx"
1129 | ],
1130 | "templating": {
1131 | "list": [
1132 | {
1133 | "allValue": null,
1134 | "current": {
1135 | "text": "All",
1136 | "value": [
1137 | "$__all"
1138 | ]
1139 | },
1140 | "datasource": "Prometheus-Aggregator",
1141 | "definition": "label_values(job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_2XX, host)",
1142 | "hide": 0,
1143 | "includeAll": true,
1144 | "label": "host",
1145 | "multi": true,
1146 | "name": "host",
1147 | "options": [],
1148 | "query": "label_values(job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_2XX, host)",
1149 | "refresh": 2,
1150 | "regex": "",
1151 | "skipUrlSync": false,
1152 | "sort": 0,
1153 | "tagValuesQuery": "",
1154 | "tags": [],
1155 | "tagsQuery": "",
1156 | "type": "query",
1157 | "useTags": false
1158 | }
1159 | ]
1160 | },
1161 | "time": {
1162 | "from": "now-1h",
1163 | "to": "now"
1164 | },
1165 | "timepicker": {
1166 | "refresh_intervals": [
1167 | "5s",
1168 | "10s",
1169 | "30s",
1170 | "1m",
1171 | "5m",
1172 | "15m",
1173 | "30m",
1174 | "1h",
1175 | "2h",
1176 | "1d"
1177 | ],
1178 | "time_options": [
1179 | "5m",
1180 | "15m",
1181 | "1h",
1182 | "6h",
1183 | "12h",
1184 | "24h",
1185 | "2d",
1186 | "7d",
1187 | "30d"
1188 | ]
1189 | },
1190 | "timezone": "",
1191 | "title": "NGINX / API / Dashboard",
1192 | "uid": "eaYUshVZz",
1193 | "version": 13
1194 | }
1195 |
--------------------------------------------------------------------------------
/docker/grafana/nginx-api-host-endpoint-url.json:
--------------------------------------------------------------------------------
1 | {
2 | "annotations": {
3 | "list": [
4 | {
5 | "builtIn": 1,
6 | "datasource": "-- Grafana --",
7 | "enable": true,
8 | "hide": true,
9 | "iconColor": "rgba(0, 211, 255, 1)",
10 | "name": "Annotations & Alerts",
11 | "type": "dashboard"
12 | }
13 | ]
14 | },
15 | "editable": true,
16 | "gnetId": null,
17 | "graphTooltip": 0,
18 | "id": 10,
19 | "iteration": 1562396443863,
20 | "links": [
21 | {
22 | "asDropdown": true,
23 | "icon": "external link",
24 | "keepTime": true,
25 | "tags": [
26 | "nginx"
27 | ],
28 | "targetBlank": true,
29 | "title": "# NGINX",
30 | "type": "dashboards"
31 | }
32 | ],
33 | "panels": [
34 | {
35 | "collapsed": false,
36 | "gridPos": {
37 | "h": 1,
38 | "w": 24,
39 | "x": 0,
40 | "y": 0
41 | },
42 | "id": 126,
43 | "panels": [],
44 | "title": "Overall",
45 | "type": "row"
46 | },
47 | {
48 | "aliasColors": {},
49 | "bars": false,
50 | "dashLength": 10,
51 | "dashes": false,
52 | "datasource": "Prometheus-Aggregator",
53 | "fill": 1,
54 | "gridPos": {
55 | "h": 4,
56 | "w": 8,
57 | "x": 0,
58 | "y": 1
59 | },
60 | "id": 128,
61 | "legend": {
62 | "alignAsTable": true,
63 | "avg": true,
64 | "current": false,
65 | "hideEmpty": true,
66 | "hideZero": true,
67 | "max": true,
68 | "min": false,
69 | "rightSide": true,
70 | "show": false,
71 | "sideWidth": null,
72 | "sort": "max",
73 | "sortDesc": true,
74 | "total": false,
75 | "values": true
76 | },
77 | "lines": true,
78 | "linewidth": 1,
79 | "links": [],
80 | "nullPointMode": "null",
81 | "options": {},
82 | "percentage": false,
83 | "pointradius": 5,
84 | "points": false,
85 | "renderer": "flot",
86 | "seriesOverrides": [],
87 | "spaceLength": 10,
88 | "stack": false,
89 | "steppedLine": false,
90 | "targets": [
91 | {
92 | "expr": "job:nginx_http_request_duration_seconds_sum:err_rate_by_host_endpoint_fullurl{host=~\"$host\", endpoint=~\"$endpoint\"}",
93 | "format": "time_series",
94 | "hide": false,
95 | "instant": false,
96 | "intervalFactor": 2,
97 | "legendFormat": "{{fullurl}}",
98 | "refId": "B"
99 | }
100 | ],
101 | "thresholds": [],
102 | "timeFrom": null,
103 | "timeRegions": [],
104 | "timeShift": null,
105 | "title": "ERROR Rate",
106 | "tooltip": {
107 | "shared": true,
108 | "sort": 2,
109 | "value_type": "individual"
110 | },
111 | "type": "graph",
112 | "xaxis": {
113 | "buckets": null,
114 | "mode": "time",
115 | "name": null,
116 | "show": true,
117 | "values": []
118 | },
119 | "yaxes": [
120 | {
121 | "decimals": 3,
122 | "format": "percent",
123 | "label": null,
124 | "logBase": 1,
125 | "max": null,
126 | "min": null,
127 | "show": true
128 | },
129 | {
130 | "format": "short",
131 | "label": null,
132 | "logBase": 1,
133 | "max": null,
134 | "min": null,
135 | "show": true
136 | }
137 | ],
138 | "yaxis": {
139 | "align": false,
140 | "alignLevel": null
141 | }
142 | },
143 | {
144 | "aliasColors": {},
145 | "bars": false,
146 | "dashLength": 10,
147 | "dashes": false,
148 | "datasource": "Prometheus-Aggregator",
149 | "fill": 1,
150 | "gridPos": {
151 | "h": 4,
152 | "w": 8,
153 | "x": 8,
154 | "y": 1
155 | },
156 | "id": 155,
157 | "legend": {
158 | "alignAsTable": false,
159 | "avg": false,
160 | "current": false,
161 | "max": false,
162 | "min": false,
163 | "rightSide": false,
164 | "show": true,
165 | "sort": "current",
166 | "sortDesc": true,
167 | "total": false,
168 | "values": false
169 | },
170 | "lines": true,
171 | "linewidth": 1,
172 | "links": [],
173 | "nullPointMode": "null",
174 | "options": {},
175 | "percentage": false,
176 | "pointradius": 5,
177 | "points": false,
178 | "renderer": "flot",
179 | "seriesOverrides": [
180 | {
181 | "alias": "Summary",
182 | "transform": "negative-Y"
183 | }
184 | ],
185 | "spaceLength": 10,
186 | "stack": false,
187 | "steppedLine": false,
188 | "targets": [
189 | {
190 | "expr": "job:nginx_http_request_duration_seconds:qps_by_host_endpoint_2XX{host=~\"$host\", endpoint=~\"$endpoint\"}",
191 | "format": "time_series",
192 | "hide": false,
193 | "intervalFactor": 1,
194 | "legendFormat": "2XX",
195 | "refId": "A"
196 | },
197 | {
198 | "expr": "job:nginx_http_request_duration_seconds:qps_by_host_endpoint_3XX{host=~\"$host\", endpoint=~\"$endpoint\"}",
199 | "format": "time_series",
200 | "hide": false,
201 | "intervalFactor": 1,
202 | "legendFormat": "3XX",
203 | "refId": "B"
204 | },
205 | {
206 | "expr": "job:nginx_http_request_duration_seconds:qps_by_host_endpoint_4XX{host=~\"$host\", endpoint=~\"$endpoint\"}",
207 | "format": "time_series",
208 | "hide": false,
209 | "intervalFactor": 1,
210 | "legendFormat": "4XX",
211 | "refId": "D"
212 | },
213 | {
214 | "expr": "job:nginx_http_request_duration_seconds:qps_by_host_endpoint_5XX{host=~\"$host\", endpoint=~\"$endpoint\"}",
215 | "format": "time_series",
216 | "hide": false,
217 | "intervalFactor": 1,
218 | "legendFormat": "5XX",
219 | "refId": "C"
220 | }
221 | ],
222 | "thresholds": [],
223 | "timeFrom": null,
224 | "timeRegions": [],
225 | "timeShift": null,
226 | "title": "QPS",
227 | "tooltip": {
228 | "shared": true,
229 | "sort": 2,
230 | "value_type": "individual"
231 | },
232 | "type": "graph",
233 | "xaxis": {
234 | "buckets": null,
235 | "mode": "time",
236 | "name": null,
237 | "show": true,
238 | "values": []
239 | },
240 | "yaxes": [
241 | {
242 | "format": "short",
243 | "label": null,
244 | "logBase": 1,
245 | "max": null,
246 | "min": null,
247 | "show": true
248 | },
249 | {
250 | "format": "short",
251 | "label": null,
252 | "logBase": 1,
253 | "max": null,
254 | "min": null,
255 | "show": true
256 | }
257 | ],
258 | "yaxis": {
259 | "align": false,
260 | "alignLevel": 1
261 | }
262 | },
263 | {
264 | "aliasColors": {},
265 | "bars": false,
266 | "dashLength": 10,
267 | "dashes": false,
268 | "datasource": "Prometheus-Aggregator",
269 | "fill": 1,
270 | "gridPos": {
271 | "h": 4,
272 | "w": 8,
273 | "x": 16,
274 | "y": 1
275 | },
276 | "id": 129,
277 | "legend": {
278 | "alignAsTable": false,
279 | "avg": false,
280 | "current": false,
281 | "max": false,
282 | "min": false,
283 | "rightSide": false,
284 | "show": false,
285 | "sort": "current",
286 | "sortDesc": true,
287 | "total": false,
288 | "values": false
289 | },
290 | "lines": true,
291 | "linewidth": 1,
292 | "links": [],
293 | "nullPointMode": "null",
294 | "options": {},
295 | "percentage": false,
296 | "pointradius": 5,
297 | "points": false,
298 | "renderer": "flot",
299 | "seriesOverrides": [
300 | {
301 | "alias": "Summary",
302 | "transform": "negative-Y"
303 | }
304 | ],
305 | "spaceLength": 10,
306 | "stack": false,
307 | "steppedLine": false,
308 | "targets": [
309 | {
310 | "expr": "job:nginx_http_request_duration_seconds:qps_by_host_endpoint_fullurl_2XX{host=~\"$host\", endpoint=~\"$endpoint\"}",
311 | "format": "time_series",
312 | "hide": false,
313 | "intervalFactor": 1,
314 | "legendFormat": "{{fullurl}}",
315 | "refId": "A"
316 | }
317 | ],
318 | "thresholds": [],
319 | "timeFrom": null,
320 | "timeRegions": [],
321 | "timeShift": null,
322 | "title": "QPS",
323 | "tooltip": {
324 | "shared": true,
325 | "sort": 2,
326 | "value_type": "individual"
327 | },
328 | "type": "graph",
329 | "xaxis": {
330 | "buckets": null,
331 | "mode": "time",
332 | "name": null,
333 | "show": true,
334 | "values": []
335 | },
336 | "yaxes": [
337 | {
338 | "format": "short",
339 | "label": null,
340 | "logBase": 1,
341 | "max": null,
342 | "min": null,
343 | "show": true
344 | },
345 | {
346 | "format": "short",
347 | "label": null,
348 | "logBase": 1,
349 | "max": null,
350 | "min": null,
351 | "show": true
352 | }
353 | ],
354 | "yaxis": {
355 | "align": false,
356 | "alignLevel": 1
357 | }
358 | },
359 | {
360 | "collapsed": false,
361 | "gridPos": {
362 | "h": 1,
363 | "w": 24,
364 | "x": 0,
365 | "y": 5
366 | },
367 | "id": 122,
368 | "panels": [],
369 | "repeat": "fullurl",
370 | "scopedVars": {
371 | "fullurl": {
372 | "selected": true,
373 | "text": "/ad-data-web/ad/data/process",
374 | "value": "/ad-data-web/ad/data/process"
375 | }
376 | },
377 | "title": "$fullurl",
378 | "type": "row"
379 | },
380 | {
381 | "aliasColors": {},
382 | "bars": true,
383 | "dashLength": 10,
384 | "dashes": false,
385 | "datasource": "Prometheus-Aggregator",
386 | "fill": 1,
387 | "gridPos": {
388 | "h": 6,
389 | "w": 6,
390 | "x": 0,
391 | "y": 6
392 | },
393 | "id": 142,
394 | "legend": {
395 | "alignAsTable": false,
396 | "avg": false,
397 | "current": false,
398 | "hideEmpty": true,
399 | "hideZero": true,
400 | "max": false,
401 | "min": false,
402 | "rightSide": false,
403 | "show": false,
404 | "sideWidth": null,
405 | "total": false,
406 | "values": false
407 | },
408 | "lines": false,
409 | "linewidth": 1,
410 | "links": [],
411 | "maxPerRow": 3,
412 | "nullPointMode": "null as zero",
413 | "options": {},
414 | "percentage": false,
415 | "pointradius": 5,
416 | "points": false,
417 | "renderer": "flot",
418 | "repeatDirection": "h",
419 | "scopedVars": {
420 | "fullurl": {
421 | "selected": true,
422 | "text": "/ad-data-web/ad/data/process",
423 | "value": "/ad-data-web/ad/data/process"
424 | }
425 | },
426 | "seriesOverrides": [],
427 | "spaceLength": 10,
428 | "stack": false,
429 | "steppedLine": false,
430 | "targets": [
431 | {
432 | "expr": "job:nginx_http_request_duration_seconds_count:counter_1min_by_host_3XX_endpoint_fullurl_instance{host=~\"$host\", endpoint=~\"$endpoint\", fullurl=~\"$fullurl\"}",
433 | "format": "time_series",
434 | "hide": false,
435 | "instant": false,
436 | "interval": "5m",
437 | "intervalFactor": 2,
438 | "legendFormat": "3XX - {{instance}}",
439 | "refId": "C"
440 | },
441 | {
442 | "expr": "job:nginx_http_request_duration_seconds_count:counter_1min_by_host_5XX_endpoint_fullurl_instance{host=~\"$host\", endpoint=~\"$endpoint\", fullurl=~\"$fullurl\"}",
443 | "format": "time_series",
444 | "hide": false,
445 | "instant": false,
446 | "interval": "5m",
447 | "intervalFactor": 2,
448 | "legendFormat": "5XX - {{instance}}",
449 | "refId": "B"
450 | },
451 | {
452 | "expr": "job:nginx_http_request_duration_seconds_count:counter_1min_by_host_4XX_endpoint_fullurl_instance{host=~\"$host\", endpoint=~\"$endpoint\", fullurl=~\"$fullurl\"}",
453 | "format": "time_series",
454 | "hide": false,
455 | "instant": false,
456 | "interval": "5m",
457 | "intervalFactor": 2,
458 | "legendFormat": "4XX(with out 401 & 403) - {{instance}}",
459 | "refId": "D"
460 | }
461 | ],
462 | "thresholds": [],
463 | "timeFrom": null,
464 | "timeRegions": [],
465 | "timeShift": null,
466 | "title": "ERR Count - 1min",
467 | "tooltip": {
468 | "shared": true,
469 | "sort": 0,
470 | "value_type": "individual"
471 | },
472 | "type": "graph",
473 | "xaxis": {
474 | "buckets": null,
475 | "mode": "time",
476 | "name": null,
477 | "show": true,
478 | "values": []
479 | },
480 | "yaxes": [
481 | {
482 | "decimals": 0,
483 | "format": "short",
484 | "label": null,
485 | "logBase": 1,
486 | "max": null,
487 | "min": null,
488 | "show": true
489 | },
490 | {
491 | "format": "short",
492 | "label": null,
493 | "logBase": 1,
494 | "max": null,
495 | "min": null,
496 | "show": true
497 | }
498 | ],
499 | "yaxis": {
500 | "align": false,
501 | "alignLevel": null
502 | }
503 | },
504 | {
505 | "aliasColors": {},
506 | "bars": false,
507 | "dashLength": 10,
508 | "dashes": false,
509 | "datasource": "Prometheus-Aggregator",
510 | "fill": 1,
511 | "gridPos": {
512 | "h": 6,
513 | "w": 18,
514 | "x": 6,
515 | "y": 6
516 | },
517 | "id": 130,
518 | "legend": {
519 | "alignAsTable": true,
520 | "avg": true,
521 | "current": false,
522 | "hideEmpty": true,
523 | "hideZero": true,
524 | "max": true,
525 | "min": false,
526 | "rightSide": true,
527 | "show": true,
528 | "sideWidth": null,
529 | "total": false,
530 | "values": true
531 | },
532 | "lines": true,
533 | "linewidth": 1,
534 | "links": [],
535 | "maxPerRow": 3,
536 | "nullPointMode": "null as zero",
537 | "options": {},
538 | "percentage": false,
539 | "pointradius": 5,
540 | "points": false,
541 | "renderer": "flot",
542 | "repeat": null,
543 | "repeatDirection": "h",
544 | "scopedVars": {
545 | "fullurl": {
546 | "selected": true,
547 | "text": "/ad-data-web/ad/data/process",
548 | "value": "/ad-data-web/ad/data/process"
549 | }
550 | },
551 | "seriesOverrides": [],
552 | "spaceLength": 10,
553 | "stack": false,
554 | "steppedLine": false,
555 | "targets": [
556 | {
557 | "expr": "job:nginx_http_request_duration_seconds:p999_by_host_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"}",
558 | "format": "time_series",
559 | "hide": false,
560 | "instant": false,
561 | "interval": "30s",
562 | "intervalFactor": 2,
563 | "legendFormat": "p999",
564 | "refId": "C"
565 | },
566 | {
567 | "expr": "job:nginx_http_request_duration_seconds:p99_by_host_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"}",
568 | "format": "time_series",
569 | "hide": false,
570 | "instant": false,
571 | "interval": "30s",
572 | "intervalFactor": 2,
573 | "legendFormat": "p99",
574 | "refId": "G"
575 | },
576 | {
577 | "expr": "job:nginx_http_request_duration_seconds:p90_by_host_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"}",
578 | "format": "time_series",
579 | "hide": false,
580 | "instant": false,
581 | "interval": "30s",
582 | "intervalFactor": 2,
583 | "legendFormat": "p90",
584 | "refId": "H"
585 | },
586 | {
587 | "expr": "job:nginx_http_request_duration_seconds:avg_by_host_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"}",
588 | "format": "time_series",
589 | "hide": false,
590 | "instant": false,
591 | "interval": "30s",
592 | "intervalFactor": 2,
593 | "legendFormat": "avg",
594 | "refId": "I"
595 | }
596 | ],
597 | "thresholds": [],
598 | "timeFrom": null,
599 | "timeRegions": [],
600 | "timeShift": null,
601 | "title": "Latency",
602 | "tooltip": {
603 | "shared": true,
604 | "sort": 0,
605 | "value_type": "individual"
606 | },
607 | "type": "graph",
608 | "xaxis": {
609 | "buckets": null,
610 | "mode": "time",
611 | "name": null,
612 | "show": true,
613 | "values": []
614 | },
615 | "yaxes": [
616 | {
617 | "decimals": null,
618 | "format": "s",
619 | "label": null,
620 | "logBase": 1,
621 | "max": null,
622 | "min": null,
623 | "show": true
624 | },
625 | {
626 | "format": "short",
627 | "label": null,
628 | "logBase": 1,
629 | "max": null,
630 | "min": null,
631 | "show": true
632 | }
633 | ],
634 | "yaxis": {
635 | "align": false,
636 | "alignLevel": null
637 | }
638 | },
639 | {
640 | "aliasColors": {},
641 | "bars": false,
642 | "dashLength": 10,
643 | "dashes": false,
644 | "datasource": "Prometheus-Aggregator",
645 | "fill": 1,
646 | "gridPos": {
647 | "h": 6,
648 | "w": 6,
649 | "x": 0,
650 | "y": 12
651 | },
652 | "id": 134,
653 | "legend": {
654 | "alignAsTable": false,
655 | "avg": false,
656 | "current": false,
657 | "max": false,
658 | "min": false,
659 | "rightSide": false,
660 | "show": false,
661 | "sort": "current",
662 | "sortDesc": true,
663 | "total": false,
664 | "values": false
665 | },
666 | "lines": true,
667 | "linewidth": 1,
668 | "links": [],
669 | "nullPointMode": "null",
670 | "options": {},
671 | "percentage": false,
672 | "pointradius": 5,
673 | "points": false,
674 | "renderer": "flot",
675 | "scopedVars": {
676 | "fullurl": {
677 | "selected": true,
678 | "text": "/ad-data-web/ad/data/process",
679 | "value": "/ad-data-web/ad/data/process"
680 | }
681 | },
682 | "seriesOverrides": [
683 | {
684 | "alias": "Summary",
685 | "transform": "negative-Y"
686 | }
687 | ],
688 | "spaceLength": 10,
689 | "stack": false,
690 | "steppedLine": false,
691 | "targets": [
692 | {
693 | "expr": "job:nginx_http_request_duration_seconds:qps_by_host_endpoint_fullurl_2XX{host=~\"$host\", endpoint=~\"$endpoint\", fullurl=~\"$fullurl\"}",
694 | "format": "time_series",
695 | "hide": false,
696 | "intervalFactor": 1,
697 | "legendFormat": "QPS",
698 | "refId": "A"
699 | }
700 | ],
701 | "thresholds": [],
702 | "timeFrom": null,
703 | "timeRegions": [],
704 | "timeShift": null,
705 | "title": "2XX QPS",
706 | "tooltip": {
707 | "shared": true,
708 | "sort": 2,
709 | "value_type": "individual"
710 | },
711 | "type": "graph",
712 | "xaxis": {
713 | "buckets": null,
714 | "mode": "time",
715 | "name": null,
716 | "show": true,
717 | "values": []
718 | },
719 | "yaxes": [
720 | {
721 | "format": "short",
722 | "label": null,
723 | "logBase": 1,
724 | "max": null,
725 | "min": null,
726 | "show": true
727 | },
728 | {
729 | "format": "short",
730 | "label": null,
731 | "logBase": 1,
732 | "max": null,
733 | "min": null,
734 | "show": true
735 | }
736 | ],
737 | "yaxis": {
738 | "align": false,
739 | "alignLevel": 1
740 | }
741 | },
742 | {
743 | "aliasColors": {},
744 | "bars": false,
745 | "dashLength": 10,
746 | "dashes": false,
747 | "datasource": "Prometheus-Aggregator",
748 | "fill": 1,
749 | "gridPos": {
750 | "h": 6,
751 | "w": 6,
752 | "x": 6,
753 | "y": 12
754 | },
755 | "id": 131,
756 | "legend": {
757 | "alignAsTable": true,
758 | "avg": true,
759 | "current": false,
760 | "hideEmpty": true,
761 | "hideZero": true,
762 | "max": true,
763 | "min": false,
764 | "rightSide": true,
765 | "show": false,
766 | "sideWidth": null,
767 | "total": false,
768 | "values": true
769 | },
770 | "lines": true,
771 | "linewidth": 1,
772 | "links": [],
773 | "maxPerRow": 3,
774 | "nullPointMode": "null as zero",
775 | "options": {},
776 | "percentage": false,
777 | "pointradius": 5,
778 | "points": false,
779 | "renderer": "flot",
780 | "repeatDirection": "h",
781 | "scopedVars": {
782 | "fullurl": {
783 | "selected": true,
784 | "text": "/ad-data-web/ad/data/process",
785 | "value": "/ad-data-web/ad/data/process"
786 | }
787 | },
788 | "seriesOverrides": [],
789 | "spaceLength": 10,
790 | "stack": false,
791 | "steppedLine": false,
792 | "targets": [
793 | {
794 | "expr": "job:nginx_http_request_duration_seconds:p90_by_host_instance_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"}",
795 | "format": "time_series",
796 | "hide": false,
797 | "instant": false,
798 | "interval": "",
799 | "intervalFactor": 2,
800 | "legendFormat": "{{instance}}",
801 | "refId": "A"
802 | }
803 | ],
804 | "thresholds": [],
805 | "timeFrom": null,
806 | "timeRegions": [],
807 | "timeShift": null,
808 | "title": "2XX P90",
809 | "tooltip": {
810 | "shared": true,
811 | "sort": 0,
812 | "value_type": "individual"
813 | },
814 | "type": "graph",
815 | "xaxis": {
816 | "buckets": null,
817 | "mode": "time",
818 | "name": null,
819 | "show": true,
820 | "values": []
821 | },
822 | "yaxes": [
823 | {
824 | "decimals": null,
825 | "format": "s",
826 | "label": null,
827 | "logBase": 1,
828 | "max": null,
829 | "min": null,
830 | "show": true
831 | },
832 | {
833 | "format": "short",
834 | "label": null,
835 | "logBase": 1,
836 | "max": null,
837 | "min": null,
838 | "show": true
839 | }
840 | ],
841 | "yaxis": {
842 | "align": false,
843 | "alignLevel": null
844 | }
845 | },
846 | {
847 | "aliasColors": {},
848 | "bars": false,
849 | "dashLength": 10,
850 | "dashes": false,
851 | "datasource": "Prometheus-Aggregator",
852 | "fill": 1,
853 | "gridPos": {
854 | "h": 6,
855 | "w": 6,
856 | "x": 12,
857 | "y": 12
858 | },
859 | "id": 132,
860 | "legend": {
861 | "alignAsTable": true,
862 | "avg": true,
863 | "current": false,
864 | "hideEmpty": true,
865 | "hideZero": true,
866 | "max": true,
867 | "min": false,
868 | "rightSide": true,
869 | "show": false,
870 | "sideWidth": null,
871 | "total": false,
872 | "values": true
873 | },
874 | "lines": true,
875 | "linewidth": 1,
876 | "links": [],
877 | "maxPerRow": 3,
878 | "nullPointMode": "null as zero",
879 | "options": {},
880 | "percentage": false,
881 | "pointradius": 5,
882 | "points": false,
883 | "renderer": "flot",
884 | "repeatDirection": "h",
885 | "scopedVars": {
886 | "fullurl": {
887 | "selected": true,
888 | "text": "/ad-data-web/ad/data/process",
889 | "value": "/ad-data-web/ad/data/process"
890 | }
891 | },
892 | "seriesOverrides": [],
893 | "spaceLength": 10,
894 | "stack": false,
895 | "steppedLine": false,
896 | "targets": [
897 | {
898 | "expr": "job:nginx_http_request_duration_seconds:p99_by_host_instance_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"}",
899 | "format": "time_series",
900 | "hide": false,
901 | "instant": false,
902 | "interval": "",
903 | "intervalFactor": 2,
904 | "legendFormat": "{{instance}}",
905 | "refId": "A"
906 | }
907 | ],
908 | "thresholds": [],
909 | "timeFrom": null,
910 | "timeRegions": [],
911 | "timeShift": null,
912 | "title": "2XX P99",
913 | "tooltip": {
914 | "shared": true,
915 | "sort": 0,
916 | "value_type": "individual"
917 | },
918 | "type": "graph",
919 | "xaxis": {
920 | "buckets": null,
921 | "mode": "time",
922 | "name": null,
923 | "show": true,
924 | "values": []
925 | },
926 | "yaxes": [
927 | {
928 | "decimals": null,
929 | "format": "s",
930 | "label": null,
931 | "logBase": 1,
932 | "max": null,
933 | "min": null,
934 | "show": true
935 | },
936 | {
937 | "format": "short",
938 | "label": null,
939 | "logBase": 1,
940 | "max": null,
941 | "min": null,
942 | "show": true
943 | }
944 | ],
945 | "yaxis": {
946 | "align": false,
947 | "alignLevel": null
948 | }
949 | },
950 | {
951 | "aliasColors": {},
952 | "bars": false,
953 | "dashLength": 10,
954 | "dashes": false,
955 | "datasource": "Prometheus-Aggregator",
956 | "fill": 1,
957 | "gridPos": {
958 | "h": 6,
959 | "w": 6,
960 | "x": 18,
961 | "y": 12
962 | },
963 | "id": 133,
964 | "legend": {
965 | "alignAsTable": true,
966 | "avg": true,
967 | "current": false,
968 | "hideEmpty": true,
969 | "hideZero": true,
970 | "max": true,
971 | "min": false,
972 | "rightSide": true,
973 | "show": false,
974 | "sideWidth": null,
975 | "total": false,
976 | "values": true
977 | },
978 | "lines": true,
979 | "linewidth": 1,
980 | "links": [],
981 | "maxPerRow": 3,
982 | "nullPointMode": "null as zero",
983 | "options": {},
984 | "percentage": false,
985 | "pointradius": 5,
986 | "points": false,
987 | "renderer": "flot",
988 | "repeatDirection": "h",
989 | "scopedVars": {
990 | "fullurl": {
991 | "selected": true,
992 | "text": "/ad-data-web/ad/data/process",
993 | "value": "/ad-data-web/ad/data/process"
994 | }
995 | },
996 | "seriesOverrides": [],
997 | "spaceLength": 10,
998 | "stack": false,
999 | "steppedLine": false,
1000 | "targets": [
1001 | {
1002 | "expr": "job:nginx_http_request_duration_seconds:p999_by_host_instance_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"}",
1003 | "format": "time_series",
1004 | "hide": false,
1005 | "instant": false,
1006 | "interval": "",
1007 | "intervalFactor": 2,
1008 | "legendFormat": "{{instance}}",
1009 | "refId": "A"
1010 | }
1011 | ],
1012 | "thresholds": [],
1013 | "timeFrom": null,
1014 | "timeRegions": [],
1015 | "timeShift": null,
1016 | "title": "2XX P999",
1017 | "tooltip": {
1018 | "shared": true,
1019 | "sort": 0,
1020 | "value_type": "individual"
1021 | },
1022 | "type": "graph",
1023 | "xaxis": {
1024 | "buckets": null,
1025 | "mode": "time",
1026 | "name": null,
1027 | "show": true,
1028 | "values": []
1029 | },
1030 | "yaxes": [
1031 | {
1032 | "decimals": null,
1033 | "format": "s",
1034 | "label": null,
1035 | "logBase": 1,
1036 | "max": null,
1037 | "min": null,
1038 | "show": true
1039 | },
1040 | {
1041 | "format": "short",
1042 | "label": null,
1043 | "logBase": 1,
1044 | "max": null,
1045 | "min": null,
1046 | "show": true
1047 | }
1048 | ],
1049 | "yaxis": {
1050 | "align": false,
1051 | "alignLevel": null
1052 | }
1053 | },
1054 | {
1055 | "aliasColors": {},
1056 | "bars": false,
1057 | "dashLength": 10,
1058 | "dashes": false,
1059 | "datasource": "Prometheus-Aggregator",
1060 | "fill": 1,
1061 | "gridPos": {
1062 | "h": 6,
1063 | "w": 6,
1064 | "x": 0,
1065 | "y": 18
1066 | },
1067 | "id": 112,
1068 | "legend": {
1069 | "alignAsTable": false,
1070 | "avg": false,
1071 | "current": false,
1072 | "max": false,
1073 | "min": false,
1074 | "rightSide": false,
1075 | "show": false,
1076 | "sort": "current",
1077 | "sortDesc": true,
1078 | "total": false,
1079 | "values": false
1080 | },
1081 | "lines": true,
1082 | "linewidth": 1,
1083 | "links": [],
1084 | "nullPointMode": "null",
1085 | "options": {},
1086 | "percentage": false,
1087 | "pointradius": 5,
1088 | "points": false,
1089 | "renderer": "flot",
1090 | "scopedVars": {
1091 | "fullurl": {
1092 | "selected": true,
1093 | "text": "/ad-data-web/ad/data/process",
1094 | "value": "/ad-data-web/ad/data/process"
1095 | }
1096 | },
1097 | "seriesOverrides": [
1098 | {
1099 | "alias": "Summary",
1100 | "transform": "negative-Y"
1101 | }
1102 | ],
1103 | "spaceLength": 10,
1104 | "stack": false,
1105 | "steppedLine": false,
1106 | "targets": [
1107 | {
1108 | "expr": "job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_fullurl_2XX{host=~\"$host\", endpoint=~\"$endpoint\", fullurl=~\"$fullurl\"}",
1109 | "format": "time_series",
1110 | "hide": false,
1111 | "intervalFactor": 1,
1112 | "legendFormat": "{{instance}}",
1113 | "refId": "A"
1114 | }
1115 | ],
1116 | "thresholds": [],
1117 | "timeFrom": null,
1118 | "timeRegions": [],
1119 | "timeShift": null,
1120 | "title": "2XX QPS By Instance",
1121 | "tooltip": {
1122 | "shared": true,
1123 | "sort": 2,
1124 | "value_type": "individual"
1125 | },
1126 | "type": "graph",
1127 | "xaxis": {
1128 | "buckets": null,
1129 | "mode": "time",
1130 | "name": null,
1131 | "show": true,
1132 | "values": []
1133 | },
1134 | "yaxes": [
1135 | {
1136 | "format": "short",
1137 | "label": null,
1138 | "logBase": 1,
1139 | "max": null,
1140 | "min": null,
1141 | "show": true
1142 | },
1143 | {
1144 | "format": "short",
1145 | "label": null,
1146 | "logBase": 1,
1147 | "max": null,
1148 | "min": null,
1149 | "show": true
1150 | }
1151 | ],
1152 | "yaxis": {
1153 | "align": false,
1154 | "alignLevel": 1
1155 | }
1156 | },
1157 | {
1158 | "aliasColors": {},
1159 | "bars": false,
1160 | "dashLength": 10,
1161 | "dashes": false,
1162 | "datasource": "Prometheus-Aggregator",
1163 | "fill": 1,
1164 | "gridPos": {
1165 | "h": 6,
1166 | "w": 6,
1167 | "x": 6,
1168 | "y": 18
1169 | },
1170 | "id": 151,
1171 | "legend": {
1172 | "alignAsTable": false,
1173 | "avg": true,
1174 | "current": false,
1175 | "hideEmpty": true,
1176 | "hideZero": true,
1177 | "max": true,
1178 | "min": false,
1179 | "rightSide": false,
1180 | "show": false,
1181 | "sideWidth": null,
1182 | "total": false,
1183 | "values": true
1184 | },
1185 | "lines": true,
1186 | "linewidth": 1,
1187 | "links": [],
1188 | "maxPerRow": 3,
1189 | "nullPointMode": "null as zero",
1190 | "options": {},
1191 | "percentage": false,
1192 | "pointradius": 5,
1193 | "points": false,
1194 | "renderer": "flot",
1195 | "repeat": null,
1196 | "repeatDirection": "h",
1197 | "scopedVars": {
1198 | "fullurl": {
1199 | "selected": true,
1200 | "text": "/ad-data-web/ad/data/process",
1201 | "value": "/ad-data-web/ad/data/process"
1202 | }
1203 | },
1204 | "seriesOverrides": [],
1205 | "spaceLength": 10,
1206 | "stack": false,
1207 | "steppedLine": false,
1208 | "targets": [
1209 | {
1210 | "expr": "job:nginx_http_request_duration_seconds:p90_by_host_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"}",
1211 | "format": "time_series",
1212 | "hide": false,
1213 | "instant": false,
1214 | "interval": "30s",
1215 | "intervalFactor": 2,
1216 | "legendFormat": "ToDay - p90",
1217 | "refId": "B"
1218 | },
1219 | {
1220 | "expr": "job:nginx_http_request_duration_seconds:p90_by_host_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"} offset 24h",
1221 | "format": "time_series",
1222 | "hide": false,
1223 | "instant": false,
1224 | "interval": "30s",
1225 | "intervalFactor": 2,
1226 | "legendFormat": "LastDay - p90",
1227 | "refId": "F"
1228 | },
1229 | {
1230 | "expr": "job:nginx_http_request_duration_seconds:p90_by_host_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"} offset 7d",
1231 | "format": "time_series",
1232 | "hide": false,
1233 | "instant": false,
1234 | "interval": "30s",
1235 | "intervalFactor": 2,
1236 | "legendFormat": "LastWeek - p90",
1237 | "refId": "A"
1238 | }
1239 | ],
1240 | "thresholds": [],
1241 | "timeFrom": null,
1242 | "timeRegions": [],
1243 | "timeShift": null,
1244 | "title": "P90 - History Diff",
1245 | "tooltip": {
1246 | "shared": true,
1247 | "sort": 0,
1248 | "value_type": "individual"
1249 | },
1250 | "type": "graph",
1251 | "xaxis": {
1252 | "buckets": null,
1253 | "mode": "time",
1254 | "name": null,
1255 | "show": true,
1256 | "values": []
1257 | },
1258 | "yaxes": [
1259 | {
1260 | "decimals": null,
1261 | "format": "s",
1262 | "label": null,
1263 | "logBase": 1,
1264 | "max": null,
1265 | "min": null,
1266 | "show": true
1267 | },
1268 | {
1269 | "format": "short",
1270 | "label": null,
1271 | "logBase": 1,
1272 | "max": null,
1273 | "min": null,
1274 | "show": true
1275 | }
1276 | ],
1277 | "yaxis": {
1278 | "align": false,
1279 | "alignLevel": null
1280 | }
1281 | },
1282 | {
1283 | "aliasColors": {},
1284 | "bars": false,
1285 | "dashLength": 10,
1286 | "dashes": false,
1287 | "datasource": "Prometheus-Aggregator",
1288 | "fill": 1,
1289 | "gridPos": {
1290 | "h": 6,
1291 | "w": 6,
1292 | "x": 12,
1293 | "y": 18
1294 | },
1295 | "id": 152,
1296 | "legend": {
1297 | "alignAsTable": false,
1298 | "avg": true,
1299 | "current": false,
1300 | "hideEmpty": true,
1301 | "hideZero": true,
1302 | "max": true,
1303 | "min": false,
1304 | "rightSide": false,
1305 | "show": false,
1306 | "sideWidth": null,
1307 | "total": false,
1308 | "values": true
1309 | },
1310 | "lines": true,
1311 | "linewidth": 1,
1312 | "links": [],
1313 | "maxPerRow": 3,
1314 | "nullPointMode": "null as zero",
1315 | "options": {},
1316 | "percentage": false,
1317 | "pointradius": 5,
1318 | "points": false,
1319 | "renderer": "flot",
1320 | "repeatDirection": "h",
1321 | "scopedVars": {
1322 | "fullurl": {
1323 | "selected": true,
1324 | "text": "/ad-data-web/ad/data/process",
1325 | "value": "/ad-data-web/ad/data/process"
1326 | }
1327 | },
1328 | "seriesOverrides": [],
1329 | "spaceLength": 10,
1330 | "stack": false,
1331 | "steppedLine": false,
1332 | "targets": [
1333 | {
1334 | "expr": "job:nginx_http_request_duration_seconds:p99_by_host_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"}",
1335 | "format": "time_series",
1336 | "hide": false,
1337 | "instant": false,
1338 | "interval": "30s",
1339 | "intervalFactor": 2,
1340 | "legendFormat": "Today - p99",
1341 | "refId": "B"
1342 | },
1343 | {
1344 | "expr": "job:nginx_http_request_duration_seconds:p99_by_host_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"} offset 24h",
1345 | "format": "time_series",
1346 | "hide": false,
1347 | "instant": false,
1348 | "interval": "30s",
1349 | "intervalFactor": 2,
1350 | "legendFormat": "LastDay - p99",
1351 | "refId": "F"
1352 | },
1353 | {
1354 | "expr": "job:nginx_http_request_duration_seconds:p99_by_host_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"} offset 7d",
1355 | "format": "time_series",
1356 | "hide": false,
1357 | "instant": false,
1358 | "interval": "30s",
1359 | "intervalFactor": 2,
1360 | "legendFormat": "LastWeek - p99",
1361 | "refId": "A"
1362 | }
1363 | ],
1364 | "thresholds": [],
1365 | "timeFrom": null,
1366 | "timeRegions": [],
1367 | "timeShift": null,
1368 | "title": "P99 - History Diff",
1369 | "tooltip": {
1370 | "shared": true,
1371 | "sort": 0,
1372 | "value_type": "individual"
1373 | },
1374 | "type": "graph",
1375 | "xaxis": {
1376 | "buckets": null,
1377 | "mode": "time",
1378 | "name": null,
1379 | "show": true,
1380 | "values": []
1381 | },
1382 | "yaxes": [
1383 | {
1384 | "decimals": null,
1385 | "format": "s",
1386 | "label": null,
1387 | "logBase": 1,
1388 | "max": null,
1389 | "min": null,
1390 | "show": true
1391 | },
1392 | {
1393 | "format": "short",
1394 | "label": null,
1395 | "logBase": 1,
1396 | "max": null,
1397 | "min": null,
1398 | "show": true
1399 | }
1400 | ],
1401 | "yaxis": {
1402 | "align": false,
1403 | "alignLevel": null
1404 | }
1405 | },
1406 | {
1407 | "aliasColors": {},
1408 | "bars": false,
1409 | "dashLength": 10,
1410 | "dashes": false,
1411 | "datasource": "Prometheus-Aggregator",
1412 | "fill": 1,
1413 | "gridPos": {
1414 | "h": 6,
1415 | "w": 6,
1416 | "x": 18,
1417 | "y": 18
1418 | },
1419 | "id": 153,
1420 | "legend": {
1421 | "alignAsTable": false,
1422 | "avg": true,
1423 | "current": false,
1424 | "hideEmpty": true,
1425 | "hideZero": true,
1426 | "max": true,
1427 | "min": false,
1428 | "rightSide": false,
1429 | "show": false,
1430 | "sideWidth": null,
1431 | "total": false,
1432 | "values": true
1433 | },
1434 | "lines": true,
1435 | "linewidth": 1,
1436 | "links": [],
1437 | "maxPerRow": 3,
1438 | "nullPointMode": "null as zero",
1439 | "options": {},
1440 | "percentage": false,
1441 | "pointradius": 5,
1442 | "points": false,
1443 | "renderer": "flot",
1444 | "repeatDirection": "h",
1445 | "scopedVars": {
1446 | "fullurl": {
1447 | "selected": true,
1448 | "text": "/ad-data-web/ad/data/process",
1449 | "value": "/ad-data-web/ad/data/process"
1450 | }
1451 | },
1452 | "seriesOverrides": [],
1453 | "spaceLength": 10,
1454 | "stack": false,
1455 | "steppedLine": false,
1456 | "targets": [
1457 | {
1458 | "expr": "job:nginx_http_request_duration_seconds:p999_by_host_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"}",
1459 | "format": "time_series",
1460 | "hide": false,
1461 | "instant": false,
1462 | "interval": "30s",
1463 | "intervalFactor": 2,
1464 | "legendFormat": "Today - p999",
1465 | "refId": "B"
1466 | },
1467 | {
1468 | "expr": "job:nginx_http_request_duration_seconds:p999_by_host_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"} offset 24h",
1469 | "format": "time_series",
1470 | "hide": false,
1471 | "instant": false,
1472 | "interval": "30s",
1473 | "intervalFactor": 2,
1474 | "legendFormat": "LastDay - p999",
1475 | "refId": "F"
1476 | },
1477 | {
1478 | "expr": "job:nginx_http_request_duration_seconds:p999_by_host_fullurl_2XX{host=~\"$host\", fullurl=~\"$fullurl\"} offset 7d",
1479 | "format": "time_series",
1480 | "hide": false,
1481 | "instant": false,
1482 | "interval": "30s",
1483 | "intervalFactor": 2,
1484 | "legendFormat": "LastWeek - p999",
1485 | "refId": "A"
1486 | }
1487 | ],
1488 | "thresholds": [],
1489 | "timeFrom": null,
1490 | "timeRegions": [],
1491 | "timeShift": null,
1492 | "title": "P999 - History Diff",
1493 | "tooltip": {
1494 | "shared": true,
1495 | "sort": 0,
1496 | "value_type": "individual"
1497 | },
1498 | "type": "graph",
1499 | "xaxis": {
1500 | "buckets": null,
1501 | "mode": "time",
1502 | "name": null,
1503 | "show": true,
1504 | "values": []
1505 | },
1506 | "yaxes": [
1507 | {
1508 | "decimals": null,
1509 | "format": "s",
1510 | "label": null,
1511 | "logBase": 1,
1512 | "max": null,
1513 | "min": null,
1514 | "show": true
1515 | },
1516 | {
1517 | "format": "short",
1518 | "label": null,
1519 | "logBase": 1,
1520 | "max": null,
1521 | "min": null,
1522 | "show": true
1523 | }
1524 | ],
1525 | "yaxis": {
1526 | "align": false,
1527 | "alignLevel": null
1528 | }
1529 | }
1530 | ],
1531 | "refresh": false,
1532 | "schemaVersion": 18,
1533 | "style": "dark",
1534 | "tags": [
1535 | "nginx"
1536 | ],
1537 | "templating": {
1538 | "list": [
1539 | {
1540 | "allValue": null,
1541 | "current": {
1542 | "selected": true,
1543 | "text": "xwz.coohua.com",
1544 | "value": "xwz.coohua.com"
1545 | },
1546 | "datasource": "Prometheus-Aggregator",
1547 | "definition": "label_values(job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_2XX, host)",
1548 | "hide": 0,
1549 | "includeAll": false,
1550 | "label": "host",
1551 | "multi": false,
1552 | "name": "host",
1553 | "options": [],
1554 | "query": "label_values(job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_2XX, host)",
1555 | "refresh": 2,
1556 | "regex": "",
1557 | "skipUrlSync": false,
1558 | "sort": 0,
1559 | "tagValuesQuery": "",
1560 | "tags": [],
1561 | "tagsQuery": "",
1562 | "type": "query",
1563 | "useTags": false
1564 | },
1565 | {
1566 | "allValue": null,
1567 | "current": {
1568 | "selected": false,
1569 | "text": "/ad-data-web",
1570 | "value": "/ad-data-web"
1571 | },
1572 | "datasource": "Prometheus-Aggregator",
1573 | "definition": "label_values(job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_2XX{host=~\"$host\"}, endpoint)",
1574 | "hide": 0,
1575 | "includeAll": false,
1576 | "label": "endpoint",
1577 | "multi": false,
1578 | "name": "endpoint",
1579 | "options": [],
1580 | "query": "label_values(job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_2XX{host=~\"$host\"}, endpoint)",
1581 | "refresh": 2,
1582 | "regex": "",
1583 | "skipUrlSync": false,
1584 | "sort": 0,
1585 | "tagValuesQuery": "",
1586 | "tags": [],
1587 | "tagsQuery": "",
1588 | "type": "query",
1589 | "useTags": false
1590 | },
1591 | {
1592 | "allValue": null,
1593 | "current": {
1594 | "selected": true,
1595 | "text": "/ad-data-web/ad/data/process",
1596 | "value": "/ad-data-web/ad/data/process"
1597 | },
1598 | "datasource": "Prometheus-Aggregator",
1599 | "definition": "label_values(job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_fullurl_2XX{host=~\"$host\",endpoint=~\"$endpoint\"}, fullurl)",
1600 | "hide": 0,
1601 | "includeAll": false,
1602 | "label": "fullurl",
1603 | "multi": true,
1604 | "name": "fullurl",
1605 | "options": [],
1606 | "query": "label_values(job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_fullurl_2XX{host=~\"$host\",endpoint=~\"$endpoint\"}, fullurl)",
1607 | "refresh": 2,
1608 | "regex": "",
1609 | "skipUrlSync": false,
1610 | "sort": 0,
1611 | "tagValuesQuery": "",
1612 | "tags": [],
1613 | "tagsQuery": "",
1614 | "type": "query",
1615 | "useTags": false
1616 | }
1617 | ]
1618 | },
1619 | "time": {
1620 | "from": "now-30m",
1621 | "to": "now"
1622 | },
1623 | "timepicker": {
1624 | "refresh_intervals": [
1625 | "5s",
1626 | "10s",
1627 | "30s",
1628 | "1m",
1629 | "5m",
1630 | "15m",
1631 | "30m",
1632 | "1h",
1633 | "2h",
1634 | "1d"
1635 | ],
1636 | "time_options": [
1637 | "5m",
1638 | "15m",
1639 | "1h",
1640 | "6h",
1641 | "12h",
1642 | "24h",
1643 | "2d",
1644 | "7d",
1645 | "30d"
1646 | ]
1647 | },
1648 | "timezone": "",
1649 | "title": "NGINX / API / Host / Endpoint / URL",
1650 | "uid": "utbSxXVZz",
1651 | "version": 8
1652 | }
1653 |
--------------------------------------------------------------------------------
/docker/grafana/nginx-api-host-endpoint.json:
--------------------------------------------------------------------------------
1 | {
2 | "annotations": {
3 | "list": [
4 | {
5 | "builtIn": 1,
6 | "datasource": "-- Grafana --",
7 | "enable": true,
8 | "hide": true,
9 | "iconColor": "rgba(0, 211, 255, 1)",
10 | "name": "Annotations & Alerts",
11 | "type": "dashboard"
12 | }
13 | ]
14 | },
15 | "editable": true,
16 | "gnetId": null,
17 | "graphTooltip": 0,
18 | "id": 9,
19 | "iteration": 1562396612058,
20 | "links": [
21 | {
22 | "asDropdown": true,
23 | "icon": "external link",
24 | "keepTime": true,
25 | "tags": [
26 | "nginx"
27 | ],
28 | "targetBlank": true,
29 | "title": "# NGINX",
30 | "type": "dashboards"
31 | }
32 | ],
33 | "panels": [
34 | {
35 | "collapsed": false,
36 | "gridPos": {
37 | "h": 1,
38 | "w": 24,
39 | "x": 0,
40 | "y": 0
41 | },
42 | "id": 126,
43 | "panels": [],
44 | "title": "Overall",
45 | "type": "row"
46 | },
47 | {
48 | "aliasColors": {},
49 | "bars": true,
50 | "dashLength": 10,
51 | "dashes": false,
52 | "datasource": "Prometheus-Aggregator",
53 | "fill": 1,
54 | "gridPos": {
55 | "h": 4,
56 | "w": 8,
57 | "x": 0,
58 | "y": 1
59 | },
60 | "id": 133,
61 | "legend": {
62 | "alignAsTable": true,
63 | "avg": true,
64 | "current": false,
65 | "hideEmpty": true,
66 | "hideZero": true,
67 | "max": true,
68 | "min": false,
69 | "rightSide": true,
70 | "show": false,
71 | "sideWidth": null,
72 | "sort": "max",
73 | "sortDesc": true,
74 | "total": false,
75 | "values": true
76 | },
77 | "lines": false,
78 | "linewidth": 1,
79 | "links": [],
80 | "nullPointMode": "null",
81 | "options": {},
82 | "percentage": false,
83 | "pointradius": 5,
84 | "points": false,
85 | "renderer": "flot",
86 | "seriesOverrides": [],
87 | "spaceLength": 10,
88 | "stack": false,
89 | "steppedLine": false,
90 | "targets": [
91 | {
92 | "expr": "job:nginx_http_request_duration_seconds_count:counter_1min_by_host_endpoint_fullurl_3XX{host=~\"$host\", endpoint=~\"$endpoint\"}",
93 | "format": "time_series",
94 | "hide": false,
95 | "instant": false,
96 | "intervalFactor": 2,
97 | "legendFormat": "3XX - 1min - {{fullurl}} ",
98 | "refId": "D"
99 | }
100 | ],
101 | "thresholds": [],
102 | "timeFrom": null,
103 | "timeRegions": [],
104 | "timeShift": null,
105 | "title": "ERROR 3XX - 1min",
106 | "tooltip": {
107 | "shared": true,
108 | "sort": 2,
109 | "value_type": "individual"
110 | },
111 | "type": "graph",
112 | "xaxis": {
113 | "buckets": null,
114 | "mode": "time",
115 | "name": null,
116 | "show": true,
117 | "values": []
118 | },
119 | "yaxes": [
120 | {
121 | "decimals": 0,
122 | "format": "none",
123 | "label": null,
124 | "logBase": 1,
125 | "max": null,
126 | "min": "0",
127 | "show": true
128 | },
129 | {
130 | "format": "short",
131 | "label": null,
132 | "logBase": 1,
133 | "max": null,
134 | "min": null,
135 | "show": true
136 | }
137 | ],
138 | "yaxis": {
139 | "align": false,
140 | "alignLevel": null
141 | }
142 | },
143 | {
144 | "aliasColors": {},
145 | "bars": false,
146 | "dashLength": 10,
147 | "dashes": false,
148 | "datasource": "Prometheus-Aggregator",
149 | "fill": 1,
150 | "gridPos": {
151 | "h": 4,
152 | "w": 8,
153 | "x": 8,
154 | "y": 1
155 | },
156 | "id": 112,
157 | "legend": {
158 | "alignAsTable": false,
159 | "avg": false,
160 | "current": false,
161 | "max": false,
162 | "min": false,
163 | "rightSide": false,
164 | "show": false,
165 | "sort": "current",
166 | "sortDesc": true,
167 | "total": false,
168 | "values": false
169 | },
170 | "lines": true,
171 | "linewidth": 1,
172 | "links": [],
173 | "nullPointMode": "null",
174 | "options": {},
175 | "percentage": false,
176 | "pointradius": 5,
177 | "points": false,
178 | "renderer": "flot",
179 | "seriesOverrides": [
180 | {
181 | "alias": "Summary",
182 | "transform": "negative-Y"
183 | }
184 | ],
185 | "spaceLength": 10,
186 | "stack": false,
187 | "steppedLine": false,
188 | "targets": [
189 | {
190 | "expr": "job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_2XX{host=~\"$host\", endpoint=~\"$endpoint\"}",
191 | "format": "time_series",
192 | "hide": false,
193 | "intervalFactor": 1,
194 | "legendFormat": "{{instance}}",
195 | "refId": "A"
196 | }
197 | ],
198 | "thresholds": [],
199 | "timeFrom": null,
200 | "timeRegions": [],
201 | "timeShift": null,
202 | "title": "2XX QPS By Instance",
203 | "tooltip": {
204 | "shared": true,
205 | "sort": 2,
206 | "value_type": "individual"
207 | },
208 | "type": "graph",
209 | "xaxis": {
210 | "buckets": null,
211 | "mode": "time",
212 | "name": null,
213 | "show": true,
214 | "values": []
215 | },
216 | "yaxes": [
217 | {
218 | "format": "short",
219 | "label": null,
220 | "logBase": 1,
221 | "max": null,
222 | "min": null,
223 | "show": true
224 | },
225 | {
226 | "format": "short",
227 | "label": null,
228 | "logBase": 1,
229 | "max": null,
230 | "min": null,
231 | "show": true
232 | }
233 | ],
234 | "yaxis": {
235 | "align": false,
236 | "alignLevel": 1
237 | }
238 | },
239 | {
240 | "aliasColors": {},
241 | "bars": false,
242 | "dashLength": 10,
243 | "dashes": false,
244 | "datasource": "Prometheus-Aggregator",
245 | "fill": 1,
246 | "gridPos": {
247 | "h": 4,
248 | "w": 8,
249 | "x": 16,
250 | "y": 1
251 | },
252 | "id": 129,
253 | "legend": {
254 | "alignAsTable": false,
255 | "avg": false,
256 | "current": false,
257 | "max": false,
258 | "min": false,
259 | "rightSide": false,
260 | "show": true,
261 | "sort": "current",
262 | "sortDesc": true,
263 | "total": false,
264 | "values": false
265 | },
266 | "lines": true,
267 | "linewidth": 1,
268 | "links": [],
269 | "nullPointMode": "null",
270 | "options": {},
271 | "percentage": false,
272 | "pointradius": 5,
273 | "points": false,
274 | "renderer": "flot",
275 | "seriesOverrides": [
276 | {
277 | "alias": "Summary",
278 | "transform": "negative-Y"
279 | }
280 | ],
281 | "spaceLength": 10,
282 | "stack": false,
283 | "steppedLine": false,
284 | "targets": [
285 | {
286 | "expr": "job:nginx_http_request_duration_seconds:qps_by_host_endpoint_2XX{host=~\"$host\", endpoint=~\"$endpoint\"}",
287 | "format": "time_series",
288 | "hide": false,
289 | "intervalFactor": 1,
290 | "legendFormat": "2XX",
291 | "refId": "A"
292 | },
293 | {
294 | "expr": "job:nginx_http_request_duration_seconds:qps_by_host_endpoint_4XX{host=~\"$host\", endpoint=~\"$endpoint\"}",
295 | "format": "time_series",
296 | "hide": false,
297 | "intervalFactor": 1,
298 | "legendFormat": "4XX",
299 | "refId": "B"
300 | },
301 | {
302 | "expr": "job:nginx_http_request_duration_seconds:qps_by_host_endpoint_5XX{host=~\"$host\", endpoint=~\"$endpoint\"}",
303 | "format": "time_series",
304 | "hide": false,
305 | "intervalFactor": 1,
306 | "legendFormat": "5XX",
307 | "refId": "C"
308 | }
309 | ],
310 | "thresholds": [],
311 | "timeFrom": null,
312 | "timeRegions": [],
313 | "timeShift": null,
314 | "title": "QPS",
315 | "tooltip": {
316 | "shared": true,
317 | "sort": 2,
318 | "value_type": "individual"
319 | },
320 | "type": "graph",
321 | "xaxis": {
322 | "buckets": null,
323 | "mode": "time",
324 | "name": null,
325 | "show": true,
326 | "values": []
327 | },
328 | "yaxes": [
329 | {
330 | "format": "short",
331 | "label": null,
332 | "logBase": 1,
333 | "max": null,
334 | "min": null,
335 | "show": true
336 | },
337 | {
338 | "format": "short",
339 | "label": null,
340 | "logBase": 1,
341 | "max": null,
342 | "min": null,
343 | "show": true
344 | }
345 | ],
346 | "yaxis": {
347 | "align": false,
348 | "alignLevel": 1
349 | }
350 | },
351 | {
352 | "aliasColors": {},
353 | "bars": true,
354 | "dashLength": 10,
355 | "dashes": false,
356 | "datasource": "Prometheus-Aggregator",
357 | "fill": 1,
358 | "gridPos": {
359 | "h": 4,
360 | "w": 8,
361 | "x": 0,
362 | "y": 5
363 | },
364 | "id": 136,
365 | "legend": {
366 | "alignAsTable": true,
367 | "avg": true,
368 | "current": false,
369 | "hideEmpty": true,
370 | "hideZero": true,
371 | "max": true,
372 | "min": false,
373 | "rightSide": true,
374 | "show": false,
375 | "sideWidth": null,
376 | "sort": "max",
377 | "sortDesc": true,
378 | "total": false,
379 | "values": true
380 | },
381 | "lines": false,
382 | "linewidth": 1,
383 | "links": [],
384 | "nullPointMode": "null",
385 | "options": {},
386 | "percentage": false,
387 | "pointradius": 5,
388 | "points": false,
389 | "renderer": "flot",
390 | "seriesOverrides": [],
391 | "spaceLength": 10,
392 | "stack": false,
393 | "steppedLine": false,
394 | "targets": [
395 | {
396 | "expr": "job:nginx_http_request_duration_seconds_count:counter_1min_by_host_endpoint_fullurl_4XX{host=~\"$host\", endpoint=~\"$endpoint\"}",
397 | "format": "time_series",
398 | "hide": false,
399 | "instant": false,
400 | "intervalFactor": 2,
401 | "legendFormat": "4XX - 1min - {{fullurl}} ",
402 | "refId": "D"
403 | }
404 | ],
405 | "thresholds": [],
406 | "timeFrom": null,
407 | "timeRegions": [],
408 | "timeShift": null,
409 | "title": "ERROR 4XX - 1min",
410 | "tooltip": {
411 | "shared": true,
412 | "sort": 2,
413 | "value_type": "individual"
414 | },
415 | "type": "graph",
416 | "xaxis": {
417 | "buckets": null,
418 | "mode": "time",
419 | "name": null,
420 | "show": true,
421 | "values": []
422 | },
423 | "yaxes": [
424 | {
425 | "decimals": 0,
426 | "format": "none",
427 | "label": null,
428 | "logBase": 1,
429 | "max": null,
430 | "min": null,
431 | "show": true
432 | },
433 | {
434 | "format": "short",
435 | "label": null,
436 | "logBase": 1,
437 | "max": null,
438 | "min": null,
439 | "show": true
440 | }
441 | ],
442 | "yaxis": {
443 | "align": false,
444 | "alignLevel": null
445 | }
446 | },
447 | {
448 | "aliasColors": {},
449 | "bars": false,
450 | "dashLength": 10,
451 | "dashes": false,
452 | "datasource": "Prometheus-Aggregator",
453 | "fill": 1,
454 | "gridPos": {
455 | "h": 4,
456 | "w": 8,
457 | "x": 8,
458 | "y": 5
459 | },
460 | "id": 130,
461 | "legend": {
462 | "alignAsTable": false,
463 | "avg": false,
464 | "current": false,
465 | "max": false,
466 | "min": false,
467 | "rightSide": false,
468 | "show": false,
469 | "sort": "current",
470 | "sortDesc": true,
471 | "total": false,
472 | "values": false
473 | },
474 | "lines": true,
475 | "linewidth": 1,
476 | "links": [],
477 | "nullPointMode": "null",
478 | "options": {},
479 | "percentage": false,
480 | "pointradius": 5,
481 | "points": false,
482 | "renderer": "flot",
483 | "seriesOverrides": [
484 | {
485 | "alias": "Summary",
486 | "transform": "negative-Y"
487 | }
488 | ],
489 | "spaceLength": 10,
490 | "stack": false,
491 | "steppedLine": false,
492 | "targets": [
493 | {
494 | "expr": "job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_4XX{host=~\"$host\", endpoint=~\"$endpoint\"}",
495 | "format": "time_series",
496 | "hide": false,
497 | "intervalFactor": 1,
498 | "legendFormat": "{{instance}}",
499 | "refId": "A"
500 | }
501 | ],
502 | "thresholds": [],
503 | "timeFrom": null,
504 | "timeRegions": [],
505 | "timeShift": null,
506 | "title": "4XX QPS By Instance",
507 | "tooltip": {
508 | "shared": true,
509 | "sort": 2,
510 | "value_type": "individual"
511 | },
512 | "type": "graph",
513 | "xaxis": {
514 | "buckets": null,
515 | "mode": "time",
516 | "name": null,
517 | "show": true,
518 | "values": []
519 | },
520 | "yaxes": [
521 | {
522 | "format": "short",
523 | "label": null,
524 | "logBase": 1,
525 | "max": null,
526 | "min": null,
527 | "show": true
528 | },
529 | {
530 | "format": "short",
531 | "label": null,
532 | "logBase": 1,
533 | "max": null,
534 | "min": null,
535 | "show": true
536 | }
537 | ],
538 | "yaxis": {
539 | "align": false,
540 | "alignLevel": 1
541 | }
542 | },
543 | {
544 | "aliasColors": {},
545 | "bars": false,
546 | "dashLength": 10,
547 | "dashes": false,
548 | "datasource": "Prometheus-Aggregator",
549 | "fill": 1,
550 | "gridPos": {
551 | "h": 4,
552 | "w": 8,
553 | "x": 16,
554 | "y": 5
555 | },
556 | "id": 135,
557 | "legend": {
558 | "alignAsTable": true,
559 | "avg": true,
560 | "current": true,
561 | "max": true,
562 | "min": false,
563 | "rightSide": true,
564 | "show": false,
565 | "sort": "max",
566 | "sortDesc": true,
567 | "total": false,
568 | "values": true
569 | },
570 | "lines": true,
571 | "linewidth": 1,
572 | "links": [],
573 | "nullPointMode": "null",
574 | "options": {},
575 | "percentage": false,
576 | "pointradius": 5,
577 | "points": false,
578 | "renderer": "flot",
579 | "seriesOverrides": [
580 | {
581 | "alias": "QPS",
582 | "dashes": true,
583 | "yaxis": 2
584 | }
585 | ],
586 | "spaceLength": 10,
587 | "stack": false,
588 | "steppedLine": false,
589 | "targets": [
590 | {
591 | "expr": "job:nginx_http_request_duration_seconds:p999_by_host_endpoint_2XX{host=~\"[[host]]\", endpoint=~\"$endpoint\"}",
592 | "format": "time_series",
593 | "intervalFactor": 1,
594 | "legendFormat": "2XX-P999",
595 | "refId": "A"
596 | },
597 | {
598 | "expr": "job:nginx_http_request_duration_seconds:p99_by_host_endpoint_2XX{host=~\"[[host]]\", endpoint=~\"$endpoint\"}",
599 | "format": "time_series",
600 | "intervalFactor": 1,
601 | "legendFormat": "2XX-P99",
602 | "refId": "B"
603 | },
604 | {
605 | "expr": "job:nginx_http_request_duration_seconds:p90_by_host_endpoint_2XX{host=~\"[[host]]\", endpoint=~\"$endpoint\"}",
606 | "format": "time_series",
607 | "intervalFactor": 1,
608 | "legendFormat": "2XX-P90",
609 | "refId": "C"
610 | },
611 | {
612 | "expr": "job:nginx_http_request_duration_seconds:avg_by_host_endpoint_2XX{host=~\"[[host]]\", endpoint=~\"$endpoint\"}",
613 | "format": "time_series",
614 | "intervalFactor": 1,
615 | "legendFormat": "2XX-AVG",
616 | "refId": "D"
617 | }
618 | ],
619 | "thresholds": [],
620 | "timeFrom": null,
621 | "timeRegions": [],
622 | "timeShift": null,
623 | "title": "2XX Latency",
624 | "tooltip": {
625 | "shared": true,
626 | "sort": 0,
627 | "value_type": "individual"
628 | },
629 | "type": "graph",
630 | "xaxis": {
631 | "buckets": null,
632 | "mode": "time",
633 | "name": null,
634 | "show": true,
635 | "values": []
636 | },
637 | "yaxes": [
638 | {
639 | "format": "s",
640 | "label": null,
641 | "logBase": 1,
642 | "max": null,
643 | "min": null,
644 | "show": true
645 | },
646 | {
647 | "format": "short",
648 | "label": null,
649 | "logBase": 1,
650 | "max": null,
651 | "min": null,
652 | "show": true
653 | }
654 | ],
655 | "yaxis": {
656 | "align": false,
657 | "alignLevel": null
658 | }
659 | },
660 | {
661 | "aliasColors": {},
662 | "bars": true,
663 | "dashLength": 10,
664 | "dashes": false,
665 | "datasource": "Prometheus-Aggregator",
666 | "fill": 1,
667 | "gridPos": {
668 | "h": 4,
669 | "w": 8,
670 | "x": 0,
671 | "y": 9
672 | },
673 | "id": 137,
674 | "legend": {
675 | "alignAsTable": true,
676 | "avg": true,
677 | "current": false,
678 | "hideEmpty": true,
679 | "hideZero": true,
680 | "max": true,
681 | "min": false,
682 | "rightSide": true,
683 | "show": false,
684 | "sideWidth": null,
685 | "sort": "max",
686 | "sortDesc": true,
687 | "total": false,
688 | "values": true
689 | },
690 | "lines": false,
691 | "linewidth": 1,
692 | "links": [],
693 | "nullPointMode": "null",
694 | "options": {},
695 | "percentage": false,
696 | "pointradius": 5,
697 | "points": false,
698 | "renderer": "flot",
699 | "seriesOverrides": [],
700 | "spaceLength": 10,
701 | "stack": false,
702 | "steppedLine": false,
703 | "targets": [
704 | {
705 | "expr": "job:nginx_http_request_duration_seconds_count:counter_1min_by_host_endpoint_fullurl_5XX{host=~\"$host\", endpoint=~\"$endpoint\"}",
706 | "format": "time_series",
707 | "hide": false,
708 | "instant": false,
709 | "intervalFactor": 2,
710 | "legendFormat": "5XX - 1min - {{fullurl}} ",
711 | "refId": "D"
712 | }
713 | ],
714 | "thresholds": [],
715 | "timeFrom": null,
716 | "timeRegions": [],
717 | "timeShift": null,
718 | "title": "ERROR 5XX - 1min",
719 | "tooltip": {
720 | "shared": true,
721 | "sort": 2,
722 | "value_type": "individual"
723 | },
724 | "type": "graph",
725 | "xaxis": {
726 | "buckets": null,
727 | "mode": "time",
728 | "name": null,
729 | "show": true,
730 | "values": []
731 | },
732 | "yaxes": [
733 | {
734 | "decimals": 0,
735 | "format": "none",
736 | "label": null,
737 | "logBase": 1,
738 | "max": null,
739 | "min": "0",
740 | "show": true
741 | },
742 | {
743 | "format": "short",
744 | "label": null,
745 | "logBase": 1,
746 | "max": null,
747 | "min": null,
748 | "show": true
749 | }
750 | ],
751 | "yaxis": {
752 | "align": false,
753 | "alignLevel": null
754 | }
755 | },
756 | {
757 | "aliasColors": {},
758 | "bars": false,
759 | "dashLength": 10,
760 | "dashes": false,
761 | "datasource": "Prometheus-Aggregator",
762 | "fill": 1,
763 | "gridPos": {
764 | "h": 4,
765 | "w": 8,
766 | "x": 8,
767 | "y": 9
768 | },
769 | "id": 131,
770 | "legend": {
771 | "alignAsTable": false,
772 | "avg": false,
773 | "current": false,
774 | "max": false,
775 | "min": false,
776 | "rightSide": false,
777 | "show": false,
778 | "sort": "current",
779 | "sortDesc": true,
780 | "total": false,
781 | "values": false
782 | },
783 | "lines": true,
784 | "linewidth": 1,
785 | "links": [],
786 | "nullPointMode": "null",
787 | "options": {},
788 | "percentage": false,
789 | "pointradius": 5,
790 | "points": false,
791 | "renderer": "flot",
792 | "seriesOverrides": [
793 | {
794 | "alias": "Summary",
795 | "transform": "negative-Y"
796 | }
797 | ],
798 | "spaceLength": 10,
799 | "stack": false,
800 | "steppedLine": false,
801 | "targets": [
802 | {
803 | "expr": "job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_5XX{host=~\"$host\", endpoint=~\"$endpoint\"}",
804 | "format": "time_series",
805 | "hide": false,
806 | "intervalFactor": 1,
807 | "legendFormat": "{{instance}}",
808 | "refId": "A"
809 | }
810 | ],
811 | "thresholds": [],
812 | "timeFrom": null,
813 | "timeRegions": [],
814 | "timeShift": null,
815 | "title": "5XX QPS By Instance",
816 | "tooltip": {
817 | "shared": true,
818 | "sort": 2,
819 | "value_type": "individual"
820 | },
821 | "type": "graph",
822 | "xaxis": {
823 | "buckets": null,
824 | "mode": "time",
825 | "name": null,
826 | "show": true,
827 | "values": []
828 | },
829 | "yaxes": [
830 | {
831 | "format": "short",
832 | "label": null,
833 | "logBase": 1,
834 | "max": null,
835 | "min": "0",
836 | "show": true
837 | },
838 | {
839 | "format": "short",
840 | "label": null,
841 | "logBase": 1,
842 | "max": null,
843 | "min": null,
844 | "show": true
845 | }
846 | ],
847 | "yaxis": {
848 | "align": false,
849 | "alignLevel": 1
850 | }
851 | },
852 | {
853 | "aliasColors": {},
854 | "bars": false,
855 | "dashLength": 10,
856 | "dashes": false,
857 | "datasource": "Prometheus-Aggregator",
858 | "fill": 1,
859 | "gridPos": {
860 | "h": 4,
861 | "w": 8,
862 | "x": 16,
863 | "y": 9
864 | },
865 | "id": 128,
866 | "legend": {
867 | "alignAsTable": true,
868 | "avg": true,
869 | "current": false,
870 | "hideEmpty": true,
871 | "hideZero": true,
872 | "max": true,
873 | "min": false,
874 | "rightSide": true,
875 | "show": false,
876 | "sideWidth": null,
877 | "sort": "max",
878 | "sortDesc": true,
879 | "total": false,
880 | "values": true
881 | },
882 | "lines": true,
883 | "linewidth": 1,
884 | "links": [],
885 | "nullPointMode": "null",
886 | "options": {},
887 | "percentage": false,
888 | "pointradius": 5,
889 | "points": false,
890 | "renderer": "flot",
891 | "seriesOverrides": [],
892 | "spaceLength": 10,
893 | "stack": false,
894 | "steppedLine": false,
895 | "targets": [
896 | {
897 | "expr": "job:nginx_http_request_duration_seconds_sum:err_rate_by_host_endpoint_fullurl{host=~\"$host\", endpoint=~\"$endpoint\"}",
898 | "format": "time_series",
899 | "hide": false,
900 | "instant": false,
901 | "intervalFactor": 2,
902 | "legendFormat": "{{fullurl}}",
903 | "refId": "B"
904 | }
905 | ],
906 | "thresholds": [],
907 | "timeFrom": null,
908 | "timeRegions": [],
909 | "timeShift": null,
910 | "title": "ERROR Rate",
911 | "tooltip": {
912 | "shared": true,
913 | "sort": 2,
914 | "value_type": "individual"
915 | },
916 | "type": "graph",
917 | "xaxis": {
918 | "buckets": null,
919 | "mode": "time",
920 | "name": null,
921 | "show": true,
922 | "values": []
923 | },
924 | "yaxes": [
925 | {
926 | "decimals": 3,
927 | "format": "percent",
928 | "label": null,
929 | "logBase": 1,
930 | "max": null,
931 | "min": null,
932 | "show": true
933 | },
934 | {
935 | "format": "short",
936 | "label": null,
937 | "logBase": 1,
938 | "max": null,
939 | "min": null,
940 | "show": true
941 | }
942 | ],
943 | "yaxis": {
944 | "align": false,
945 | "alignLevel": null
946 | }
947 | },
948 | {
949 | "collapsed": false,
950 | "gridPos": {
951 | "h": 1,
952 | "w": 24,
953 | "x": 0,
954 | "y": 13
955 | },
956 | "id": 122,
957 | "panels": [],
958 | "title": "URL",
959 | "type": "row"
960 | },
961 | {
962 | "columns": [],
963 | "datasource": "Prometheus-Aggregator",
964 | "fontSize": "100%",
965 | "gridPos": {
966 | "h": 10,
967 | "w": 8,
968 | "x": 0,
969 | "y": 14
970 | },
971 | "id": 116,
972 | "links": [],
973 | "options": {},
974 | "pageSize": 10,
975 | "scroll": false,
976 | "showHeader": true,
977 | "sort": {
978 | "col": 2,
979 | "desc": true
980 | },
981 | "styles": [
982 | {
983 | "alias": "Time",
984 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
985 | "pattern": "Time",
986 | "type": "hidden"
987 | },
988 | {
989 | "alias": "",
990 | "colorMode": null,
991 | "colors": [
992 | "rgba(245, 54, 54, 0.9)",
993 | "rgba(237, 129, 40, 0.89)",
994 | "rgba(50, 172, 45, 0.97)"
995 | ],
996 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
997 | "decimals": 2,
998 | "link": false,
999 | "mappingType": 1,
1000 | "pattern": "__name__",
1001 | "thresholds": [],
1002 | "type": "hidden",
1003 | "unit": "short"
1004 | },
1005 | {
1006 | "alias": "QPS",
1007 | "colorMode": null,
1008 | "colors": [
1009 | "rgba(245, 54, 54, 0.9)",
1010 | "rgba(237, 129, 40, 0.89)",
1011 | "rgba(50, 172, 45, 0.97)"
1012 | ],
1013 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
1014 | "decimals": 2,
1015 | "link": true,
1016 | "linkTargetBlank": true,
1017 | "linkTooltip": "点击查看详情",
1018 | "linkUrl": "/d/utbSxXVZz/nginx-api-host-endpoint-url?var-host=$host&&var-endpoint=${endpoint}&&var-fullurl=${__cell_1}",
1019 | "mappingType": 1,
1020 | "pattern": "Value",
1021 | "thresholds": [],
1022 | "type": "number",
1023 | "unit": "short"
1024 | },
1025 | {
1026 | "alias": "",
1027 | "colorMode": null,
1028 | "colors": [
1029 | "rgba(245, 54, 54, 0.9)",
1030 | "rgba(237, 129, 40, 0.89)",
1031 | "rgba(50, 172, 45, 0.97)"
1032 | ],
1033 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
1034 | "decimals": 2,
1035 | "link": true,
1036 | "linkTargetBlank": true,
1037 | "linkTooltip": "点击查看详情",
1038 | "linkUrl": "/d/utbSxXVZz/nginx-api-host-endpoint-url?var-host=$host&&var-endpoint=${endpoint}&&var-fullurl=${__cell_1}",
1039 | "mappingType": 1,
1040 | "pattern": "fullurl",
1041 | "thresholds": [],
1042 | "type": "number",
1043 | "unit": "short"
1044 | },
1045 | {
1046 | "alias": "",
1047 | "colorMode": null,
1048 | "colors": [
1049 | "rgba(245, 54, 54, 0.9)",
1050 | "rgba(237, 129, 40, 0.89)",
1051 | "rgba(50, 172, 45, 0.97)"
1052 | ],
1053 | "decimals": 2,
1054 | "pattern": "/.*/",
1055 | "thresholds": [],
1056 | "type": "number",
1057 | "unit": "short"
1058 | }
1059 | ],
1060 | "targets": [
1061 | {
1062 | "expr": "topk(10, sum by(fullurl) (job:nginx_http_request_duration_seconds:qps_by_host_endpoint_fullurl_2XX{host=~\"$host\", endpoint=~\"$endpoint\"}))",
1063 | "format": "table",
1064 | "hide": false,
1065 | "instant": true,
1066 | "intervalFactor": 1,
1067 | "refId": "A"
1068 | }
1069 | ],
1070 | "title": "TOP 10 QPS",
1071 | "transform": "table",
1072 | "type": "table"
1073 | },
1074 | {
1075 | "columns": [],
1076 | "datasource": "Prometheus-Aggregator",
1077 | "fontSize": "100%",
1078 | "gridPos": {
1079 | "h": 10,
1080 | "w": 8,
1081 | "x": 8,
1082 | "y": 14
1083 | },
1084 | "id": 123,
1085 | "links": [],
1086 | "options": {},
1087 | "pageSize": 10,
1088 | "scroll": false,
1089 | "showHeader": true,
1090 | "sort": {
1091 | "col": 2,
1092 | "desc": true
1093 | },
1094 | "styles": [
1095 | {
1096 | "alias": "Time",
1097 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
1098 | "pattern": "Time",
1099 | "type": "hidden"
1100 | },
1101 | {
1102 | "alias": "",
1103 | "colorMode": null,
1104 | "colors": [
1105 | "rgba(245, 54, 54, 0.9)",
1106 | "rgba(237, 129, 40, 0.89)",
1107 | "rgba(50, 172, 45, 0.97)"
1108 | ],
1109 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
1110 | "decimals": 2,
1111 | "link": false,
1112 | "mappingType": 1,
1113 | "pattern": "__name__",
1114 | "thresholds": [],
1115 | "type": "hidden",
1116 | "unit": "short"
1117 | },
1118 | {
1119 | "alias": "4XX",
1120 | "colorMode": null,
1121 | "colors": [
1122 | "rgba(245, 54, 54, 0.9)",
1123 | "rgba(237, 129, 40, 0.89)",
1124 | "rgba(50, 172, 45, 0.97)"
1125 | ],
1126 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
1127 | "decimals": 2,
1128 | "link": true,
1129 | "linkTargetBlank": true,
1130 | "linkTooltip": "点击查看详情",
1131 | "linkUrl": "/d/utbSxXVZz/nginx-api-host-endpoint-url?var-host=$host&&var-endpoint=${endpoint}&&var-fullurl=${__cell_1}",
1132 | "mappingType": 1,
1133 | "pattern": "Value",
1134 | "thresholds": [],
1135 | "type": "number",
1136 | "unit": "short"
1137 | },
1138 | {
1139 | "alias": "",
1140 | "colorMode": null,
1141 | "colors": [
1142 | "rgba(245, 54, 54, 0.9)",
1143 | "rgba(237, 129, 40, 0.89)",
1144 | "rgba(50, 172, 45, 0.97)"
1145 | ],
1146 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
1147 | "decimals": 2,
1148 | "link": true,
1149 | "linkTargetBlank": true,
1150 | "linkTooltip": "点击查看详情",
1151 | "linkUrl": "/d/utbSxXVZz/nginx-api-host-endpoint-url?var-host=$host&&var-endpoint=${endpoint}&&var-fullurl=${__cell_1}",
1152 | "mappingType": 1,
1153 | "pattern": "fullurl",
1154 | "thresholds": [],
1155 | "type": "number",
1156 | "unit": "short"
1157 | },
1158 | {
1159 | "alias": "",
1160 | "colorMode": null,
1161 | "colors": [
1162 | "rgba(245, 54, 54, 0.9)",
1163 | "rgba(237, 129, 40, 0.89)",
1164 | "rgba(50, 172, 45, 0.97)"
1165 | ],
1166 | "decimals": 2,
1167 | "pattern": "/.*/",
1168 | "thresholds": [],
1169 | "type": "number",
1170 | "unit": "short"
1171 | }
1172 | ],
1173 | "targets": [
1174 | {
1175 | "expr": "topk(10, sum(job:nginx_http_request_duration_seconds_count:counter_1min_by_host_endpoint_fullurl_4XX{host=~\"$host\", endpoint=~\"$endpoint\"}) by (fullurl)>0)",
1176 | "format": "table",
1177 | "hide": false,
1178 | "instant": true,
1179 | "intervalFactor": 1,
1180 | "refId": "B"
1181 | }
1182 | ],
1183 | "title": "TOP 10 4XX - 1min",
1184 | "transform": "table",
1185 | "type": "table"
1186 | },
1187 | {
1188 | "columns": [],
1189 | "datasource": "Prometheus-Aggregator",
1190 | "fontSize": "100%",
1191 | "gridPos": {
1192 | "h": 10,
1193 | "w": 8,
1194 | "x": 16,
1195 | "y": 14
1196 | },
1197 | "id": 124,
1198 | "links": [],
1199 | "options": {},
1200 | "pageSize": 10,
1201 | "scroll": false,
1202 | "showHeader": true,
1203 | "sort": {
1204 | "col": 2,
1205 | "desc": true
1206 | },
1207 | "styles": [
1208 | {
1209 | "alias": "Time",
1210 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
1211 | "pattern": "Time",
1212 | "type": "hidden"
1213 | },
1214 | {
1215 | "alias": "",
1216 | "colorMode": null,
1217 | "colors": [
1218 | "rgba(245, 54, 54, 0.9)",
1219 | "rgba(237, 129, 40, 0.89)",
1220 | "rgba(50, 172, 45, 0.97)"
1221 | ],
1222 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
1223 | "decimals": 2,
1224 | "link": false,
1225 | "mappingType": 1,
1226 | "pattern": "__name__",
1227 | "thresholds": [],
1228 | "type": "hidden",
1229 | "unit": "short"
1230 | },
1231 | {
1232 | "alias": "5XX",
1233 | "colorMode": null,
1234 | "colors": [
1235 | "rgba(245, 54, 54, 0.9)",
1236 | "rgba(237, 129, 40, 0.89)",
1237 | "rgba(50, 172, 45, 0.97)"
1238 | ],
1239 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
1240 | "decimals": 2,
1241 | "link": true,
1242 | "linkTargetBlank": true,
1243 | "linkTooltip": "点击查看详情",
1244 | "linkUrl": "/d/utbSxXVZz/nginx-api-host-endpoint-url?var-host=$host&&var-endpoint=${endpoint}&&var-fullurl=${__cell_1}",
1245 | "mappingType": 1,
1246 | "pattern": "Value",
1247 | "thresholds": [],
1248 | "type": "number",
1249 | "unit": "short"
1250 | },
1251 | {
1252 | "alias": "",
1253 | "colorMode": null,
1254 | "colors": [
1255 | "rgba(245, 54, 54, 0.9)",
1256 | "rgba(237, 129, 40, 0.89)",
1257 | "rgba(50, 172, 45, 0.97)"
1258 | ],
1259 | "dateFormat": "YYYY-MM-DD HH:mm:ss",
1260 | "decimals": 2,
1261 | "link": true,
1262 | "linkTargetBlank": true,
1263 | "linkTooltip": "点击查看详情",
1264 | "linkUrl": "/d/utbSxXVZz/nginx-api-host-endpoint-url?var-host=$host&&var-endpoint=${endpoint}&&var-fullurl=${__cell_1}",
1265 | "mappingType": 1,
1266 | "pattern": "fullurl",
1267 | "thresholds": [],
1268 | "type": "number",
1269 | "unit": "short"
1270 | },
1271 | {
1272 | "alias": "",
1273 | "colorMode": null,
1274 | "colors": [
1275 | "rgba(245, 54, 54, 0.9)",
1276 | "rgba(237, 129, 40, 0.89)",
1277 | "rgba(50, 172, 45, 0.97)"
1278 | ],
1279 | "decimals": 2,
1280 | "pattern": "/.*/",
1281 | "thresholds": [],
1282 | "type": "number",
1283 | "unit": "short"
1284 | }
1285 | ],
1286 | "targets": [
1287 | {
1288 | "expr": "topk(10, sum(job:nginx_http_request_duration_seconds_count:counter_1min_by_host_endpoint_fullurl_5XX{host=~\"$host\", endpoint=~\"$endpoint\"}) by (fullurl)>0)",
1289 | "format": "table",
1290 | "hide": false,
1291 | "instant": true,
1292 | "intervalFactor": 1,
1293 | "refId": "B"
1294 | }
1295 | ],
1296 | "title": "TOP 10 5XX - 1min",
1297 | "transform": "table",
1298 | "type": "table"
1299 | }
1300 | ],
1301 | "refresh": false,
1302 | "schemaVersion": 18,
1303 | "style": "dark",
1304 | "tags": [
1305 | "nginx"
1306 | ],
1307 | "templating": {
1308 | "list": [
1309 | {
1310 | "allValue": null,
1311 | "current": {
1312 | "text": "xwz.coohua.com",
1313 | "value": "xwz.coohua.com"
1314 | },
1315 | "datasource": "Prometheus-Aggregator",
1316 | "definition": "label_values(job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_2XX, host)",
1317 | "hide": 0,
1318 | "includeAll": false,
1319 | "label": "host",
1320 | "multi": false,
1321 | "name": "host",
1322 | "options": [],
1323 | "query": "label_values(job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_2XX, host)",
1324 | "refresh": 2,
1325 | "regex": "",
1326 | "skipUrlSync": false,
1327 | "sort": 0,
1328 | "tagValuesQuery": "",
1329 | "tags": [],
1330 | "tagsQuery": "",
1331 | "type": "query",
1332 | "useTags": false
1333 | },
1334 | {
1335 | "allValue": null,
1336 | "current": {
1337 | "text": "/ad",
1338 | "value": "/ad"
1339 | },
1340 | "datasource": "Prometheus-Aggregator",
1341 | "definition": "label_values(job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_2XX{host=~\"$host\"}, endpoint)",
1342 | "hide": 0,
1343 | "includeAll": false,
1344 | "label": "endpoint",
1345 | "multi": false,
1346 | "name": "endpoint",
1347 | "options": [],
1348 | "query": "label_values(job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_2XX{host=~\"$host\"}, endpoint)",
1349 | "refresh": 2,
1350 | "regex": "",
1351 | "skipUrlSync": false,
1352 | "sort": 0,
1353 | "tagValuesQuery": "",
1354 | "tags": [],
1355 | "tagsQuery": "",
1356 | "type": "query",
1357 | "useTags": false
1358 | }
1359 | ]
1360 | },
1361 | "time": {
1362 | "from": "now-15m",
1363 | "to": "now"
1364 | },
1365 | "timepicker": {
1366 | "refresh_intervals": [
1367 | "5s",
1368 | "10s",
1369 | "30s",
1370 | "1m",
1371 | "5m",
1372 | "15m",
1373 | "30m",
1374 | "1h",
1375 | "2h",
1376 | "1d"
1377 | ],
1378 | "time_options": [
1379 | "5m",
1380 | "15m",
1381 | "1h",
1382 | "6h",
1383 | "12h",
1384 | "24h",
1385 | "2d",
1386 | "7d",
1387 | "30d"
1388 | ]
1389 | },
1390 | "timezone": "",
1391 | "title": "NGINX / API / Host / Endpoint",
1392 | "uid": "u8pccJ4Zk",
1393 | "version": 11
1394 | }
1395 |
--------------------------------------------------------------------------------
/docker/grafana/provisioning.yml:
--------------------------------------------------------------------------------
1 | # config file version
2 | apiVersion: 1
3 |
4 | providers:
5 | - name: 'default'
6 | orgId: 1
7 | folder: ''
8 | folderUid: ''
9 | type: file
10 | options:
11 | path: /var/lib/grafana/dashboards
12 |
13 |
--------------------------------------------------------------------------------
/docker/grafana/push.sh:
--------------------------------------------------------------------------------
1 | docker push zrbcool/prometheus-lua-grafana:latest
2 | VERSION=$1
3 | docker tag zrbcool/prometheus-lua-grafana:latest zrbcool/prometheus-lua-grafana:$VERSION
4 | docker push zrbcool/prometheus-lua-grafana:$VERSION
5 |
--------------------------------------------------------------------------------
/docker/nginx/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openresty/openresty:stretch-fat
2 |
3 | COPY workdir/conf.d/counter.conf /etc/nginx/conf.d/counter.conf
4 | COPY workdir/conf.d/backend.conf /etc/nginx/conf.d/backend.conf
5 | COPY workdir/lua/prometheus.lua /etc/nginx/conf.d/prometheus.lua
6 | COPY workdir/lua/counter.lua /etc/nginx/conf.d/counter.lua
7 |
--------------------------------------------------------------------------------
/docker/nginx/buid.sh:
--------------------------------------------------------------------------------
1 | cd ../../
2 | docker build -t zrbcool/prometheus-lua-nginx:latest -f docker/nginx/Dockerfile .
3 |
4 |
--------------------------------------------------------------------------------
/docker/nginx/push.sh:
--------------------------------------------------------------------------------
1 | docker push zrbcool/prometheus-lua-nginx:latest
2 | VERSION=$1
3 | docker tag zrbcool/prometheus-lua-nginx:latest zrbcool/prometheus-lua-nginx:$VERSION
4 | docker push zrbcool/prometheus-lua-nginx:$VERSION
5 |
--------------------------------------------------------------------------------
/docker/prometheus/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM prom/prometheus
2 |
3 | COPY prometheus.yml /etc/prometheus/prometheus.yml
4 | COPY nginx.alert.rule /etc/prometheus/nginx.alert.rule
5 | COPY nginx.counter.rule /etc/prometheus/nginx.counter.rule
6 | COPY nginx.errrate.rule /etc/prometheus/nginx.errrate.rule
7 | COPY nginx.latency.rule /etc/prometheus/nginx.latency.rule
8 | COPY nginx.qps.rule /etc/prometheus/nginx.qps.rule
9 |
10 |
--------------------------------------------------------------------------------
/docker/prometheus/build.sh:
--------------------------------------------------------------------------------
1 | docker build -t zrbcool/prometheus-lua-prom:latest -f Dockerfile .
2 |
--------------------------------------------------------------------------------
/docker/prometheus/nginx.alert.rule:
--------------------------------------------------------------------------------
1 | groups:
2 | - name: alert
3 | rules:
4 |
5 | - alert: InstanceStatus
6 | expr: up{instance!="172.16.10.227:8300",job!~"prometheus|node|tap-web"} == 0
7 | for: 10s
8 | labels:
9 | instance: "{{ $labels.instance }}"
10 | annotations:
11 | summary: "服务器 {{ $labels.instance }} 运行状态"
12 | description: "服务器{{ $labels.instance }}已当机超过20s"
13 |
14 | - alert: APIHighRequestLatency
15 | expr: sum(rate(nginx_http_request_duration_seconds_sum[1m])) by(host,endpoint) / sum(rate(nginx_http_request_duration_seconds_count[1m])) by(host,endpoint) > 1
16 | for: 2m
17 | annotations:
18 | summary: "{{ $labels.host }} 接口{{ $labels.endpoint }} 运行状态"
19 | description: "{{ $labels.host }} 接口{{ $labels.endpoint }}响应超过1s(current value: {{ $value }}s)"
20 |
21 | - alert: API502Status
22 | expr: sum(irate(nginx_http_request_duration_seconds_count{status="502"}[1m])) by (host,endpoint) > 100
23 | for: 3m
24 | annotations:
25 | summary: " {{ $labels.host }} 接口{{ $labels.endpoint }} 运行状态"
26 | description: "{{ $labels.host }} 接口{{ $labels.endpoint }}502大于100(current value: {{ $value }}s)"
27 |
28 | - alert: APIErrorRate
29 | expr: topk(5, 100*sum(rate(nginx_http_request_duration_seconds_count{endpoint!~"/task|/ac|/invite|/grow|/coohua|/taskDaily",status!~"200|304|403",host!~"forum.coohua.com|coomall.coohua.com"}[1m])) by (host, endpoint)/sum(rate(nginx_http_request_duration_seconds_count{endpoint!~"/task|/ac|/invite|/grow|/coohua|/taskDaily",host!~"forum.coohua.com|coomall.coohua.com"}[5m])) by (host, endpoint)) > 10
30 | for: 3m
31 | annotations:
32 | summary: "{{ $labels.host }} 接口{{ $labels.endpoint }} 运行状态"
33 | description: "{{ $labels.host }} 接口{{ $labels.endpoint }}错误率大于10%(current value: {{ $value }}%)"
34 |
35 | - alert: API404Status
36 | expr: topk(5, sum by(host, fullurl) (irate(nginx_http_request_duration_seconds_count{host!="coomall.coohua.com",status="404",fullurl!="/activityV1/ladderActivity/conf"}[1m]))) > 20
37 | for: 3m
38 | annotations:
39 | summary: " {{ $labels.host }} 接口{{ $labels.endpoint }} 运行状态"
40 | description: "{{ $labels.host }} 接口{{ $labels.endpoint }}404错误率大于20(current value: {{ $value }})"
41 |
42 | - name: dingtalk2
43 | rules:
44 | - alert: "性能下降告警"
45 | expr: round((avg(avg_over_time(job:nginx_http_request_duration_seconds:p99_by_host_instance_fullurl_2XX{host="xwz.coohua.com"}[1h])) by (fullurl,host)/avg(avg_over_time(job:nginx_http_request_duration_seconds:p99_by_host_instance_fullurl_2XX{host="xwz.coohua.com"}[1h] offset 24h)) by (fullurl,host) > 1.5) * 100)/100
46 | for: 10s
47 | labels:
48 | fullurl: "{{ $labels.fullurl }}"
49 | host: "{{ $labels.host }}"
50 | debug: "true"
51 | annotations:
52 | desc: "P99耗时(过去1小时平均值)是昨日同期{{ $value }}倍"
53 |
54 |
--------------------------------------------------------------------------------
/docker/prometheus/nginx.counter.rule:
--------------------------------------------------------------------------------
1 | groups:
2 | - name: counter
3 | rules:
4 | #host
5 | - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_3XX
6 | expr: sum(increase(nginx_http_request_duration_seconds_count{status=~"3.."}[1m])) by (host)
7 | - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_4XX
8 | expr: sum(increase(nginx_http_request_duration_seconds_count{status=~"40[^3]{1}|4[^0]{1}."}[1m])) by (host)
9 | - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_5XX
10 | expr: sum(increase(nginx_http_request_duration_seconds_count{status=~"5.."}[1m])) by (host)
11 | #host,endpoint
12 | - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_endpoint_3XX
13 | expr: sum(increase(nginx_http_request_duration_seconds_count{status=~"3.."}[1m])) by (host, endpoint)
14 | - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_endpoint_4XX
15 | expr: sum(increase(nginx_http_request_duration_seconds_count{status=~"40[^3]{1}|4[^0]{1}."}[1m])) by (host, endpoint)
16 | - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_endpoint_5XX
17 | expr: sum(increase(nginx_http_request_duration_seconds_count{status=~"5.."}[1m])) by (host, endpoint)
18 | #host,endpoint,fullurl
19 | - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_endpoint_fullurl_3XX
20 | expr: sum(increase(nginx_http_request_duration_seconds_count{status=~"3.."}[1m])) by (host, endpoint, fullurl)
21 | - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_endpoint_fullurl_4XX
22 | expr: sum(increase(nginx_http_request_duration_seconds_count{status=~"40[^3]{1}|4[^0]{1}."}[1m])) by (host, endpoint, fullurl)
23 | - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_endpoint_fullurl_5XX
24 | expr: sum(increase(nginx_http_request_duration_seconds_count{status=~"5.."}[1m])) by (host, endpoint, fullurl)
25 | #host,endpoint,fullurl,instance
26 | - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_3XX_endpoint_fullurl_instance
27 | expr: sum(increase(nginx_http_request_duration_seconds_count{status=~"3.."}[1m])) by (host,endpoint,fullurl,instance)
28 | - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_5XX_endpoint_fullurl_instance
29 | expr: sum(increase(nginx_http_request_duration_seconds_count{status=~"5.."}[1m])) by (host,endpoint,fullurl,instance)
30 | - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_4XX_endpoint_fullurl_instance
31 | expr: sum(increase(nginx_http_request_duration_seconds_count{status=~"40[^3]{1}|4[^0]{1}."}[1m])) by (host,endpoint,fullurl,instance)
32 | #host,endpoint,fullurl,instance,status
33 | - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_status_endpoint_fullurl_instance
34 | expr: sum(increase(nginx_http_request_duration_seconds_count{}[1m])) by (host,status,endpoint,fullurl,instance)
35 | # - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_2XX_endpoint_fullurl
36 | # expr: sum(increase(nginx_http_request_duration_seconds_count{status=~"2.."}[1m])) by (host,endpoint,fullurl)
37 | # - record: job:nginx_http_request_duration_seconds_count:counter_1min_by_host_2XX_endpoint_fullurl_instance
38 | # expr: sum(increase(nginx_http_request_duration_seconds_count{status=~"2.."}[1m])) by (host,endpoint,fullurl,instance)
39 | # - record: job:nginx_http_request_duration_seconds_count:err_counter_403_by_endpoint_instance
40 | # expr: sum(nginx_http_request_duration_seconds_count{status="403"}) by (endpoint, instance)
41 | # - record: job:nginx_http_request_duration_seconds_count:err_counter_403_by_endpoint_host_instance
42 | # expr: sum by(endpoint, host, instance) (nginx_http_request_duration_seconds_count{status="403"})
43 | # - record: job:nginx_http_request_duration_seconds_count:counter_by_host
44 | # expr: count(count(nginx_http_request_duration_seconds_count) by (host, instance)) by (host)
45 |
--------------------------------------------------------------------------------
/docker/prometheus/nginx.errrate.rule:
--------------------------------------------------------------------------------
1 | groups:
2 | - name: err_rate
3 | rules:
4 | - record: job:nginx_http_request_duration_seconds_sum:err_rate_by_host
5 | expr: (sum(increase(nginx_http_request_duration_seconds_count{status!~"2..|403|304"}[10m])) by (host) / sum(increase(nginx_http_request_duration_seconds_count{}[10m])) by (host)) * 100
6 | - record: job:nginx_http_request_duration_seconds_sum:err_rate_by_host_endpoint
7 | expr: (sum(increase(nginx_http_request_duration_seconds_count{status!~"2..|403|304"}[10m])) by (host,endpoint) / sum(increase(nginx_http_request_duration_seconds_count{}[10m])) by (host,endpoint)) * 100
8 | - record: job:nginx_http_request_duration_seconds_sum:err_rate_by_host_endpoint_fullurl
9 | expr: (sum(increase(nginx_http_request_duration_seconds_count{status!~"2..|403|304"}[10m])) by (host, endpoint, fullurl) / sum(increase(nginx_http_request_duration_seconds_count{}[10m])) by (host, endpoint, fullurl)) * 100
10 | # - record: job:nginx_http_request_duration_seconds_sum:err_rate_by_instance
11 | # expr: (sum(increase(nginx_http_request_duration_seconds_count{status!~"2..|403|304"}[10m])) by (instance) / sum(increase(nginx_http_request_duration_seconds_count{}[10m])) by (instance)) * 100
12 | # - record: job:nginx_http_request_duration_seconds_sum:err_rate_by_host_instance
13 | # expr: (sum by(host,instance) (increase(nginx_http_request_duration_seconds_count{status!~"2..|403|304"}[10m])) / sum by(host,instance) (increase(nginx_http_request_duration_seconds_count[10m]))) * 100
14 | # - record: job:nginx_http_request_duration_seconds_sum:err_rate
15 | # expr: (sum(increase(nginx_http_request_duration_seconds_count{status!~"2..|403|304"}[10m])) / sum(increase(nginx_http_request_duration_seconds_count{}[10m]))) * 100
16 |
--------------------------------------------------------------------------------
/docker/prometheus/nginx.latency.rule:
--------------------------------------------------------------------------------
1 | groups:
2 | - name: p90
3 | rules:
4 | - record: job:nginx_http_request_duration_seconds:p90_by_host_2XX
5 | expr: histogram_quantile(0.9, sum (rate(nginx_http_request_duration_seconds_bucket{status=~"2.."}[3m])) by(host, le))
6 | - record: job:nginx_http_request_duration_seconds:p90_by_host_endpoint_2XX
7 | expr: histogram_quantile(0.9, sum (rate(nginx_http_request_duration_seconds_bucket{status=~"2.."}[3m])) by(host, endpoint, le))
8 | - record: job:nginx_http_request_duration_seconds:p90_by_host_fullurl_2XX
9 | expr: histogram_quantile(0.9, sum(rate(nginx_http_request_duration_seconds_bucket{status=~"2.."}[3m])) by (host, fullurl, le))
10 | - record: job:nginx_http_request_duration_seconds:p90_by_host_instance_fullurl_2XX
11 | expr: histogram_quantile(0.9, sum(rate(nginx_http_request_duration_seconds_bucket{status=~"2.."}[3m])) by (host, instance, fullurl, le))
12 | - name: p99
13 | rules:
14 | - record: job:nginx_http_request_duration_seconds:p99_by_host_2XX
15 | expr: histogram_quantile(0.99, sum by(host, le) (rate(nginx_http_request_duration_seconds_bucket{status=~"2.."}[3m])))
16 | - record: job:nginx_http_request_duration_seconds:p99_by_host_endpoint_2XX
17 | expr: histogram_quantile(0.99, sum by(host, endpoint, le) (rate(nginx_http_request_duration_seconds_bucket{status=~"2.."}[3m])))
18 | - record: job:nginx_http_request_duration_seconds:p99_by_host_fullurl_2XX
19 | expr: histogram_quantile(0.99, sum(rate(nginx_http_request_duration_seconds_bucket{status=~"2.."}[3m])) by (host, fullurl, le))
20 | - record: job:nginx_http_request_duration_seconds:p99_by_host_instance_fullurl_2XX
21 | expr: histogram_quantile(0.99, sum(rate(nginx_http_request_duration_seconds_bucket{status=~"2.."}[3m])) by (host, instance, fullurl, le))
22 | # - record: job:nginx_http_request_duration_seconds:p99_2XX
23 | # expr: histogram_quantile(0.99, sum by(le) (rate(nginx_http_request_duration_seconds_bucket{status=~"2.."}[3m])))
24 | - name: p999
25 | rules:
26 | - record: job:nginx_http_request_duration_seconds:p999_by_host_2XX
27 | expr: histogram_quantile(0.999, sum by(host, le) (rate(nginx_http_request_duration_seconds_bucket{status=~"2.."}[3m])))
28 | - record: job:nginx_http_request_duration_seconds:p999_by_host_endpoint_2XX
29 | expr: histogram_quantile(0.999, sum by(host, endpoint, le) (rate(nginx_http_request_duration_seconds_bucket{status=~"2.."}[3m])))
30 | - record: job:nginx_http_request_duration_seconds:p999_by_host_fullurl_2XX
31 | expr: histogram_quantile(0.999, sum(rate(nginx_http_request_duration_seconds_bucket{status=~"2.."}[3m])) by (host, fullurl, le))
32 | - record: job:nginx_http_request_duration_seconds:p999_by_host_instance_fullurl_2XX
33 | expr: histogram_quantile(0.999, sum(rate(nginx_http_request_duration_seconds_bucket{status=~"2.."}[3m])) by (host, instance, fullurl, le))
34 | # - record: job:nginx_http_request_duration_seconds:p999_2XX
35 | # expr: histogram_quantile(0.999, sum by(le) (rate(nginx_http_request_duration_seconds_bucket{status=~"2.."}[3m])))
36 | - name: avg
37 | rules:
38 | - record: job:nginx_http_request_duration_seconds:avg_by_host_2XX
39 | expr: sum(rate(nginx_http_request_duration_seconds_sum{status=~"2.."}[1m])) by (host) / sum(rate(nginx_http_request_duration_seconds_count{status=~"2.."}[1m])) by (host)
40 | - record: job:nginx_http_request_duration_seconds:avg_by_host_endpoint_2XX
41 | expr: sum(rate(nginx_http_request_duration_seconds_sum{status=~"2.."}[1m])) by (host, endpoint) / sum(rate(nginx_http_request_duration_seconds_count{status=~"2.."}[1m])) by (host, endpoint)
42 | - record: job:nginx_http_request_duration_seconds:avg_by_host_fullurl_2XX
43 | expr: sum(rate(nginx_http_request_duration_seconds_sum{status=~"2.."}[3m])) by (host, fullurl, le) / sum(rate(nginx_http_request_duration_seconds_count{status=~"2.."}[3m])) by (host, fullurl, le)
44 | # - record: job:nginx_http_request_duration_seconds:avg_by_host_instance_fullurl_2XX
45 | # expr: sum(rate(nginx_http_request_duration_seconds_sum{status=~"2.."}[3m])) by (host, instance, fullurl, le) / sum(rate(nginx_http_request_duration_seconds_count{status=~"2.."}[3m])) by (host, instance, fullurl, le)
46 | # - record: job:nginx_http_request_duration_seconds:avg_2XX
47 | # expr: sum(rate(nginx_http_request_duration_seconds_sum{status=~"2.."}[1m])) / sum(rate(nginx_http_request_duration_seconds_count{status=~"2.."}[1m]))
48 |
--------------------------------------------------------------------------------
/docker/prometheus/nginx.qps.rule:
--------------------------------------------------------------------------------
1 | groups:
2 | - name: qps
3 | rules:
4 | # host
5 | - record: job:nginx_http_request_duration_seconds:qps_by_host_2XX
6 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"2.."}[3m])) by (host)
7 | - record: job:nginx_http_request_duration_seconds:qps_by_host_4XX
8 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"40[^3]{1}|4[^0]{1}."}[3m])) by (host)
9 | - record: job:nginx_http_request_duration_seconds:qps_by_host_403
10 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"403"}[3m])) by (host)
11 | - record: job:nginx_http_request_duration_seconds:qps_by_host_5XX
12 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"5.."}[3m])) by (host)
13 | # host, instance
14 | - record: job:nginx_http_request_duration_seconds:qps_by_instance_host_2XX
15 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"2.."}[3m])) by (instance, host)
16 | - record: job:nginx_http_request_duration_seconds:qps_by_instance_host_4XX
17 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"40[^3]{1}|4[^0]{1}."}[3m])) by (instance, host)
18 | - record: job:nginx_http_request_duration_seconds:qps_by_instance_host_5XX
19 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"5.."}[3m])) by (instance, host)
20 | # host, endpoint
21 | - record: job:nginx_http_request_duration_seconds:qps_by_host_endpoint_2XX
22 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"2.."}[3m])) by (host, endpoint)
23 | - record: job:nginx_http_request_duration_seconds:qps_by_host_endpoint_3XX
24 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"3.."}[3m])) by (host, endpoint)
25 | - record: job:nginx_http_request_duration_seconds:qps_by_host_endpoint_4XX
26 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"40[^3]{1}|4[^0]{1}."}[3m])) by (host, endpoint)
27 | - record: job:nginx_http_request_duration_seconds:qps_by_host_endpoint_5XX
28 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"5.."}[3m])) by (host, endpoint)
29 | # host, endpoint, fullurl
30 | - record: job:nginx_http_request_duration_seconds:qps_by_host_endpoint_fullurl_2XX
31 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"2.."}[3m])) by (host, endpoint, fullurl)
32 | # host, endpoint, instance
33 | - record: job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_2XX
34 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"2.."}[3m])) by (instance, host, endpoint)
35 | - record: job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_4XX
36 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"40[^3]{1}|4[^0]{1}."}[3m])) by (instance, host, endpoint)
37 | - record: job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_5XX
38 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"5.."}[3m])) by (instance, host, endpoint)
39 | - record: job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_403
40 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"403"}[3m])) by (instance, host, endpoint)
41 | # host, endpoint, fullurl, instance
42 | - record: job:nginx_http_request_duration_seconds:qps_by_instance_host_endpoint_fullurl_2XX
43 | expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"2.."}[3m])) by (instance, host, endpoint, fullurl)
44 | # - record: job:nginx_http_request_duration_seconds:qps_by_instance_host_status_method_3XX
45 | # expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"3.."}[3m])) by (instance, host)
46 | # - record: job:nginx_http_request_duration_seconds:qps_by_instance_host_status_method_403
47 | # expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"403"}[3m])) by (instance, host)
48 | # - record: job:nginx_http_request_duration_seconds:qps_by_endpoint_fullurl_2XX
49 | # expr: sum(rate(nginx_http_request_duration_seconds_count{status=~"2.."}[3m])) by (endpoint, fullurl)
50 |
--------------------------------------------------------------------------------
/docker/prometheus/prometheus.yml:
--------------------------------------------------------------------------------
1 | global:
2 | scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
3 | evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
4 | external_labels:
5 | monitor: 'coohua-prometheus'
6 |
7 | alerting:
8 | alertmanagers:
9 | - static_configs:
10 | # - targets: ['172.16.11.42:9093']
11 |
12 | rule_files:
13 | - "nginx.*.rule"
14 |
15 | scrape_configs:
16 | - job_name: 'prometheus'
17 | static_configs:
18 | - targets: ['localhost:9090']
19 | - targets: ['resty:9145']
20 |
--------------------------------------------------------------------------------
/docker/prometheus/push.sh:
--------------------------------------------------------------------------------
1 | COMPONENT="prom"
2 | docker push zrbcool/prometheus-lua-$COMPONENT:latest
3 | VERSION=$1
4 | docker tag zrbcool/prometheus-lua-$COMPONENT:latest zrbcool/prometheus-lua-$COMPONENT:$VERSION
5 | docker push zrbcool/prometheus-lua-$COMPONENT:$VERSION
6 |
--------------------------------------------------------------------------------
/gitpush.sh:
--------------------------------------------------------------------------------
1 | git add .
2 | git commit -m 'we will rock you!!!'
3 | git pull
4 | git push
5 |
--------------------------------------------------------------------------------
/pictures/resty-lua-prometheus-snapshot01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrbcool/prometheus-lua-nginx/ee4be42a8e998a646c122a8a81541ed22505d359/pictures/resty-lua-prometheus-snapshot01.png
--------------------------------------------------------------------------------
/pictures/resty-lua-prometheus-snapshot02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrbcool/prometheus-lua-nginx/ee4be42a8e998a646c122a8a81541ed22505d359/pictures/resty-lua-prometheus-snapshot02.png
--------------------------------------------------------------------------------
/pictures/resty-lua-prometheus-snapshot03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrbcool/prometheus-lua-nginx/ee4be42a8e998a646c122a8a81541ed22505d359/pictures/resty-lua-prometheus-snapshot03.png
--------------------------------------------------------------------------------
/pictures/resty-lua-prometheus-snapshot04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zrbcool/prometheus-lua-nginx/ee4be42a8e998a646c122a8a81541ed22505d359/pictures/resty-lua-prometheus-snapshot04.png
--------------------------------------------------------------------------------
/workdir/conf.d/backend.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | server_name "";
4 |
5 | location / {
6 | proxy_pass http://backend:8081/;
7 | proxy_set_header Host $host;
8 | proxy_set_header X-Real-IP $remote_addr;
9 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
10 | proxy_http_version 1.1;
11 | proxy_set_header Connection "";
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/workdir/conf.d/counter.conf:
--------------------------------------------------------------------------------
1 | # Please copy to nginx's conf.d directory
2 | # Set search paths for pure Lua external libraries (';;' is the default path):
3 | lua_package_path "/etc/nginx/conf.d/?.lua;;/opt/openresty/workdir/lua/?.lua;;";
4 |
5 | # Set Prometheus global dict
6 | lua_shared_dict prometheus_metrics 10M; #init 10M memory
7 | lua_shared_dict uri_by_host 10M;
8 | lua_shared_dict global_set 1M;
9 | # Development option, if deploy production, pls cache on!
10 | lua_code_cache off;
11 |
12 | init_by_lua_block {
13 | counter = require 'counter'
14 | counter.init()
15 | }
16 |
17 | log_by_lua_block {
18 | counter.log()
19 | }
20 |
21 | # Expose prometheus's metrics scrape port
22 | server {
23 | listen 9145;
24 | allow all;
25 | deny all;
26 | access_log off;
27 | location /metrics {
28 | content_by_lua 'prometheus:collect()';
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/workdir/html/50x.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Error
5 |
12 |
13 |
14 | An error occurred.
15 | Sorry, the page you are looking for is currently unavailable.
16 | Please try again later.
17 | If you are the system administrator of this resource then you should check
18 | the error log for details.
19 | Faithfully yours, OpenResty.
20 |
21 |
22 |
--------------------------------------------------------------------------------
/workdir/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Welcome to OpenResty!
5 |
12 |
13 |
14 | Welcome to OpenResty!
15 | If you see this page, the OpenResty web platform is successfully installed and
16 | working. Further configuration is required.
17 |
18 | For online documentation and support please refer to
19 | openresty.org .
20 | Commercial support is available at
21 | openresty.com .
22 |
23 | Thank you for flying OpenResty.
24 |
25 |
26 |
--------------------------------------------------------------------------------
/workdir/lua/counter.lua:
--------------------------------------------------------------------------------
1 | local pcall = pcall
2 | local ngx = ngx
3 | local ngx_log = ngx.log
4 | local ngx_err = ngx.ERR
5 | local _M = {}
6 | function _M.init()
7 | uris = ngx.shared.uri_by_host
8 | global_set = ngx.shared.global_set
9 | global_set:set("initted", false)
10 | global_set:set("looped", false)
11 | prometheus = require("prometheus").init("prometheus_metrics")
12 | metric_latency = prometheus:histogram("nginx_http_request_duration_seconds", "HTTP request latency status", {"host", "status", "scheme", "method", "endpoint", "fullurl"})
13 | end
14 | local function split(inputstr, sep)
15 | if sep == nil then
16 | sep = "%s"
17 | end
18 | local t={} ; i=1
19 | for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
20 | t[i] = str
21 | i = i + 1
22 | end
23 | return t
24 | end
25 | local function parse_fullurl(request_uri)
26 | result_table = {}
27 | if string.find(request_uri, "%.") ~= nil then
28 | return nil
29 | end
30 | parts = split(request_uri, "/")
31 | if table.getn(parts) == 1 then
32 | return nil
33 | end
34 | for j=1, #parts do
35 | if(j == 1) then
36 | endpoint = "/"..parts[j]
37 | fullurl = "/"..parts[j]
38 | elseif(j <= 5) then
39 | if tonumber(parts[j]) ~= nil then
40 | break
41 | end
42 | fullurl = fullurl.."/"..parts[j]
43 | else
44 | break
45 | end
46 | end
47 | result_table["endpoint"] = endpoint
48 | result_table["fullurl"] = fullurl
49 | return result_table
50 | end
51 | function _M.log()
52 | local request_host = ngx.var.host
53 | local request_uri = ngx.unescape_uri(ngx.var.uri)
54 | local request_status = ngx.var.status
55 | local request_scheme = ngx.var.scheme
56 | local request_method = ngx.var.request_method
57 | local remote_ip = ngx.var.remote_addr
58 | local ngx_sent = ngx.var.body_bytes_sent
59 | local latency = ngx.var.upstream_response_time or 0
60 |
61 |
62 | result_table = parse_fullurl(request_uri)
63 | if result_table == nil then
64 | return
65 | end
66 | ngx_log(ngx_err,"latency=", tonumber(latency), ",status=", request_status, ",endpoint=", result_table["endpoint"], ",fullurl=", result_table["fullurl"])
67 | metric_latency:observe(tonumber(latency), {request_host, request_status, request_scheme, request_method, result_table["endpoint"], result_table["fullurl"]})
68 | end
69 | return _M
70 |
--------------------------------------------------------------------------------
/workdir/lua/prometheus.lua:
--------------------------------------------------------------------------------
1 | -- vim: ts=2:sw=2:sts=2:expandtab
2 | --
3 | -- This module uses a single dictionary shared between Nginx workers to keep
4 | -- all metrics. Each counter is stored as a separate entry in that dictionary,
5 | -- which allows us to increment them using built-in `incr` method.
6 | --
7 | -- Prometheus requires that (a) all samples for a given metric are presented
8 | -- as one uninterrupted group, and (b) buckets of a histogram appear in
9 | -- increasing numerical order. We satisfy that by carefully constructing full
10 | -- metric names (i.e. metric name along with all labels) so that they meet
11 | -- those requirements while being sorted alphabetically. In particular:
12 | --
13 | -- * all labels for a given metric are presented in reproducible order (the one
14 | -- used when labels were declared). "le" label for histogram metrics always
15 | -- goes last;
16 | -- * bucket boundaries (which are exposed as values of the "le" label) are
17 | -- presented as floating point numbers with leading and trailing zeroes.
18 | -- Number of of zeroes is determined for each bucketer automatically based on
19 | -- bucket boundaries;
20 | -- * internally "+Inf" bucket is stored as "Inf" (to make it appear after
21 | -- all numeric buckets), and gets replaced by "+Inf" just before we
22 | -- expose the metrics.
23 | --
24 | -- For example, if you define your bucket boundaries as {0.00005, 10, 1000}
25 | -- then we will keep the following samples for a metric `m1` with label
26 | -- `site` set to `site1`:
27 | --
28 | -- m1_bucket{site="site1",le="0000.00005"}
29 | -- m1_bucket{site="site1",le="0010.00000"}
30 | -- m1_bucket{site="site1",le="1000.00000"}
31 | -- m1_bucket{site="site1",le="Inf"}
32 | -- m1_count{site="site1"}
33 | -- m1_sum{site="site1"}
34 | --
35 | -- "Inf" will be replaced by "+Inf" while publishing metrics.
36 | --
37 | -- You can find the latest version and documentation at
38 | -- https://github.com/knyar/nginx-lua-prometheus
39 | -- Released under MIT license.
40 |
41 |
42 | -- Default set of latency buckets, 5ms to 10s:
43 | local DEFAULT_BUCKETS = {0.005, 0.01, 0.02, 0.03, 0.05, 0.075, 0.1, 0.2, 0.3,
44 | 0.4, 0.5, 0.75, 1, 1.5, 2, 3, 4, 5, 10}
45 |
46 | -- Metric is a "parent class" for all metrics.
47 | local Metric = {}
48 | function Metric:new(o)
49 | o = o or {}
50 | setmetatable(o, self)
51 | self.__index = self
52 | return o
53 | end
54 |
55 | -- Checks that the right number of labels values have been passed.
56 | --
57 | -- Args:
58 | -- label_values: an array of label values.
59 | --
60 | -- Returns:
61 | -- an error message or nil
62 | function Metric:check_label_values(label_values)
63 | if self.label_names == nil and label_values == nil then
64 | return
65 | elseif self.label_names == nil and label_values ~= nil then
66 | return "Expected no labels for " .. self.name .. ", got " .. #label_values
67 | elseif label_values == nil and self.label_names ~= nil then
68 | return "Expected " .. #self.label_names .. " labels for " ..
69 | self.name .. ", got none"
70 | elseif #self.label_names ~= #label_values then
71 | return "Wrong number of labels for " .. self.name .. ". Expected " ..
72 | #self.label_names .. ", got " .. #label_values
73 | else
74 | for i, k in ipairs(self.label_names) do
75 | if label_values[i] == nil then
76 | return "Unexpected nil value for label " .. k .. " of " .. self.name
77 | end
78 | end
79 | end
80 | end
81 |
82 | local Counter = Metric:new()
83 | -- Increase a given counter by `value`
84 | --
85 | -- Args:
86 | -- value: (number) a value to add to the counter. Defaults to 1 if skipped.
87 | -- label_values: an array of label values. Can be nil (i.e. not defined) for
88 | -- metrics that have no labels.
89 | function Counter:inc(value, label_values)
90 | local err = self:check_label_values(label_values)
91 | if err ~= nil then
92 | self.prometheus:log_error(err)
93 | return
94 | end
95 | if value ~= nil and value < 0 then
96 | self.prometheus:log_error_kv(self.name, value, "Value should not be negative")
97 | return
98 | end
99 |
100 | self.prometheus:inc(self.name, self.label_names, label_values, value or 1)
101 | end
102 |
103 | local Gauge = Metric:new()
104 | -- Set a given gauge to `value`
105 | --
106 | -- Args:
107 | -- value: (number) a value to set the gauge to. Should be defined.
108 | -- label_values: an array of label values. Can be nil (i.e. not defined) for
109 | -- metrics that have no labels.
110 | function Gauge:set(value, label_values)
111 | if value == nil then
112 | self.prometheus:log_error("No value passed for " .. self.name)
113 | return
114 | end
115 | local err = self:check_label_values(label_values)
116 | if err ~= nil then
117 | self.prometheus:log_error(err)
118 | return
119 | end
120 | self.prometheus:set(self.name, self.label_names, label_values, value)
121 | end
122 |
123 |
124 | -- Increase a given gauge by `value`
125 | --
126 | -- Args:
127 | -- value: (number) a value to add to the gauge (a negative value when you
128 | -- need to decrease the value of the gauge). Defaults to 1 if skipped.
129 | -- label_values: an array of label values. Can be nil (i.e. not defined) for
130 | -- metrics that have no labels.
131 | function Gauge:inc(value, label_values)
132 | local err = self:check_label_values(label_values)
133 | if err ~= nil then
134 | self.prometheus:log_error(err)
135 | return
136 | end
137 | self.prometheus:inc(self.name, self.label_names, label_values, value or 1)
138 | end
139 |
140 | local Histogram = Metric:new()
141 | -- Record a given value in a histogram.
142 | --
143 | -- Args:
144 | -- value: (number) a value to record. Should be defined.
145 | -- label_values: an array of label values. Can be nil (i.e. not defined) for
146 | -- metrics that have no labels.
147 | function Histogram:observe(value, label_values)
148 | if value == nil then
149 | self.prometheus:log_error("No value passed for " .. self.name)
150 | return
151 | end
152 | local err = self:check_label_values(label_values)
153 | if err ~= nil then
154 | self.prometheus:log_error(err)
155 | return
156 | end
157 | self.prometheus:histogram_observe(self.name, self.label_names, label_values, value)
158 | end
159 |
160 | local Prometheus = {}
161 | Prometheus.__index = Prometheus
162 | Prometheus.initialized = false
163 |
164 | -- Generate full metric name that includes all labels.
165 | --
166 | -- Args:
167 | -- name: string
168 | -- label_names: (array) a list of label keys.
169 | -- label_values: (array) a list of label values.
170 | -- Returns:
171 | -- (string) full metric name.
172 | local function full_metric_name(name, label_names, label_values)
173 | if not label_names then
174 | return name
175 | end
176 | local label_parts = {}
177 | for idx, key in ipairs(label_names) do
178 | local label_value = (string.format("%s", label_values[idx])
179 | :gsub("[^\032-\126]", "") -- strip non-printable characters
180 | :gsub("\\", "\\\\")
181 | :gsub('"', '\\"'))
182 | table.insert(label_parts, key .. '="' .. label_value .. '"')
183 | end
184 | return name .. "{" .. table.concat(label_parts, ",") .. "}"
185 | end
186 |
187 | -- Construct bucket format for a list of buckets.
188 | --
189 | -- This receives a list of buckets and returns a sprintf template that should
190 | -- be used for bucket boundaries to make them come in increasing order when
191 | -- sorted alphabetically.
192 | --
193 | -- To re-phrase, this is where we detect how many leading and trailing zeros we
194 | -- need.
195 | --
196 | -- Args:
197 | -- buckets: a list of buckets
198 | --
199 | -- Returns:
200 | -- (string) a sprintf template.
201 | local function construct_bucket_format(buckets)
202 | local max_order = 1
203 | local max_precision = 1
204 | for _, bucket in ipairs(buckets) do
205 | assert(type(bucket) == "number", "bucket boundaries should be numeric")
206 | -- floating point number with all trailing zeros removed
207 | local as_string = string.format("%f", bucket):gsub("0*$", "")
208 | local dot_idx = as_string:find(".", 1, true)
209 | max_order = math.max(max_order, dot_idx - 1)
210 | max_precision = math.max(max_precision, as_string:len() - dot_idx)
211 | end
212 | return "%0" .. (max_order + max_precision + 1) .. "." .. max_precision .. "f"
213 | end
214 |
215 | -- Extract short metric name from the full one.
216 | --
217 | -- Args:
218 | -- full_name: (string) full metric name that can include labels.
219 | --
220 | -- Returns:
221 | -- (string) short metric name with no labels. For a `*_bucket` metric of
222 | -- histogram the _bucket suffix will be removed.
223 | local function short_metric_name(full_name)
224 | local labels_start, _ = full_name:find("{")
225 | if not labels_start then
226 | -- no labels
227 | return full_name
228 | end
229 | local suffix_idx, _ = full_name:find("_bucket{")
230 | if suffix_idx and full_name:find("le=") then
231 | -- this is a histogram metric
232 | return full_name:sub(1, suffix_idx - 1)
233 | end
234 | -- this is not a histogram metric
235 | return full_name:sub(1, labels_start - 1)
236 | end
237 |
238 | -- Makes a shallow copy of a table
239 | local function copy_table(table)
240 | local new = {}
241 | if table ~= nil then
242 | for k, v in ipairs(table) do
243 | new[k] = v
244 | end
245 | end
246 | return new
247 | end
248 |
249 | -- Check metric name and label names for correctness.
250 | --
251 | -- Regular expressions to validate metric and label names are
252 | -- documented in https://prometheus.io/docs/concepts/data_model/
253 | --
254 | -- Args:
255 | -- metric_name: (string) metric name.
256 | -- label_names: label names (array of strings).
257 | --
258 | -- Returns:
259 | -- Either an error string, or nil of no errors were found.
260 | local function check_metric_and_label_names(metric_name, label_names)
261 | if not metric_name:match("^[a-zA-Z_:][a-zA-Z0-9_:]*$") then
262 | return "Metric name '" .. metric_name .. "' is invalid"
263 | end
264 | for _, label_name in ipairs(label_names or {}) do
265 | if label_name == "le" then
266 | return "Invalid label name 'le' in " .. metric_name
267 | end
268 | if not label_name:match("^[a-zA-Z_][a-zA-Z0-9_]*$") then
269 | return "Metric '" .. metric_name .. "' label name '" .. label_name ..
270 | "' is invalid"
271 | end
272 | end
273 | end
274 |
275 | -- Initialize the module.
276 | --
277 | -- This should be called once from the `init_by_lua` section in nginx
278 | -- configuration.
279 | --
280 | -- Args:
281 | -- dict_name: (string) name of the nginx shared dictionary which will be
282 | -- used to store all metrics
283 | -- prefix: (optional string) if supplied, prefix is added to all
284 | -- metric names on output
285 | --
286 | -- Returns:
287 | -- an object that should be used to register metrics.
288 | function Prometheus.init(dict_name, prefix)
289 | local self = setmetatable({}, Prometheus)
290 | dict_name = dict_name or "prometheus_metrics"
291 | self.dict = ngx.shared[dict_name]
292 | if self.dict == nil then
293 | ngx.log(ngx.ERR,
294 | "Dictionary '", dict_name, "' does not seem to exist. ",
295 | "Please define the dictionary using `lua_shared_dict`.")
296 | return self
297 | end
298 | self.help = {}
299 | if prefix then
300 | self.prefix = prefix
301 | else
302 | self.prefix = ''
303 | end
304 | self.type = {}
305 | self.registered = {}
306 | self.buckets = {}
307 | self.bucket_format = {}
308 | self.initialized = true
309 |
310 | self:counter("nginx_metric_errors_total",
311 | "Number of nginx-lua-prometheus errors")
312 | self.dict:set("nginx_metric_errors_total", 0)
313 | return self
314 | end
315 |
316 | function Prometheus:log_error(...)
317 | ngx.log(ngx.ERR, ...)
318 | self.dict:incr("nginx_metric_errors_total", 1)
319 | end
320 |
321 | function Prometheus:log_error_kv(key, value, err)
322 | self:log_error(
323 | "Error while setting '", key, "' to '", value, "': '", err, "'")
324 | end
325 |
326 | -- Register a counter.
327 | --
328 | -- Args:
329 | -- name: (string) name of the metric. Required.
330 | -- description: (string) description of the metric. Will be used for the HELP
331 | -- comment on the metrics page. Optional.
332 | -- label_names: array of strings, defining a list of metrics. Optional.
333 | --
334 | -- Returns:
335 | -- a Counter object.
336 | function Prometheus:counter(name, description, label_names)
337 | if not self.initialized then
338 | ngx.log(ngx.ERR, "Prometheus module has not been initialized")
339 | return
340 | end
341 |
342 | local err = check_metric_and_label_names(name, label_names)
343 | if err ~= nil then
344 | self:log_error(err)
345 | return
346 | end
347 |
348 | if self.registered[name] then
349 | self:log_error("Duplicate metric " .. name)
350 | return
351 | end
352 | self.registered[name] = true
353 | self.help[name] = description
354 | self.type[name] = "counter"
355 |
356 | return Counter:new{name=name, label_names=label_names, prometheus=self}
357 | end
358 |
359 | -- Register a gauge.
360 | --
361 | -- Args:
362 | -- name: (string) name of the metric. Required.
363 | -- description: (string) description of the metric. Will be used for the HELP
364 | -- comment on the metrics page. Optional.
365 | -- label_names: array of strings, defining a list of metrics. Optional.
366 | --
367 | -- Returns:
368 | -- a Gauge object.
369 | function Prometheus:gauge(name, description, label_names)
370 | if not self.initialized then
371 | ngx.log(ngx.ERR, "Prometheus module has not been initialized")
372 | return
373 | end
374 |
375 | local err = check_metric_and_label_names(name, label_names)
376 | if err ~= nil then
377 | self:log_error(err)
378 | return
379 | end
380 |
381 | if self.registered[name] then
382 | self:log_error("Duplicate metric " .. name)
383 | return
384 | end
385 | self.registered[name] = true
386 | self.help[name] = description
387 | self.type[name] = "gauge"
388 |
389 | return Gauge:new{name=name, label_names=label_names, prometheus=self}
390 | end
391 |
392 |
393 | -- Register a histogram.
394 | --
395 | -- Args:
396 | -- name: (string) name of the metric. Required.
397 | -- description: (string) description of the metric. Will be used for the HELP
398 | -- comment on the metrics page. Optional.
399 | -- label_names: array of strings, defining a list of metrics. Optional.
400 | -- buckets: array if numbers, defining bucket boundaries. Optional.
401 | --
402 | -- Returns:
403 | -- a Histogram object.
404 | function Prometheus:histogram(name, description, label_names, buckets)
405 | if not self.initialized then
406 | ngx.log(ngx.ERR, "Prometheus module has not been initialized")
407 | return
408 | end
409 |
410 | local err = check_metric_and_label_names(name, label_names)
411 | if err ~= nil then
412 | self:log_error(err)
413 | return
414 | end
415 |
416 | for _, suffix in ipairs({"", "_bucket", "_count", "_sum"}) do
417 | if self.registered[name .. suffix] then
418 | self:log_error("Duplicate metric " .. name .. suffix)
419 | return
420 | end
421 | self.registered[name .. suffix] = true
422 | end
423 | self.help[name] = description
424 | self.type[name] = "histogram"
425 |
426 | self.buckets[name] = buckets or DEFAULT_BUCKETS
427 | self.bucket_format[name] = construct_bucket_format(self.buckets[name])
428 |
429 | return Histogram:new{name=name, label_names=label_names, prometheus=self}
430 | end
431 |
432 | -- Set a given dictionary key.
433 | -- This overwrites existing values, so it should only be used when initializing
434 | -- metrics or when explicitely overwriting the previous value of a metric.
435 | function Prometheus:set_key(key, value)
436 | local ok, err = self.dict:safe_set(key, value)
437 | if not ok then
438 | self:log_error_kv(key, value, err)
439 | end
440 | end
441 |
442 | -- Increment a given metric by `value`.
443 | --
444 | -- Args:
445 | -- name: (string) short metric name without any labels.
446 | -- label_names: (array) a list of label keys.
447 | -- label_values: (array) a list of label values.
448 | -- value: (number) value to add (a negative value when you need to decrease
449 | -- the value of the gauge). Optional, defaults to 1.
450 | function Prometheus:inc(name, label_names, label_values, value)
451 | local key = full_metric_name(name, label_names, label_values)
452 | if value == nil then value = 1 end
453 |
454 | local newval, err = self.dict:incr(key, value)
455 | if newval then
456 | return
457 | end
458 | -- Yes, this looks like a race, so I guess we might under-report some values
459 | -- when multiple workers simultaneously try to create the same metric.
460 | -- Hopefully this does not happen too often (shared dictionary does not get
461 | -- reset during configuation reload).
462 | if err == "not found" then
463 | self:set_key(key, value)
464 | return
465 | end
466 | -- Unexpected error
467 | self:log_error_kv(key, value, err)
468 | end
469 |
470 | -- Set the current value of a gauge to `value`
471 | --
472 | -- Args:
473 | -- name: (string) short metric name without any labels.
474 | -- label_names: (array) a list of label keys.
475 | -- label_values: (array) a list of label values.
476 | -- value: (number) the new value for the gauge.
477 | function Prometheus:set(name, label_names, label_values, value)
478 | local key = full_metric_name(name, label_names, label_values)
479 | self:set_key(key, value)
480 | end
481 |
482 | -- Record a given value into a histogram metric.
483 | --
484 | -- Args:
485 | -- name: (string) short metric name without any labels.
486 | -- label_names: (array) a list of label keys.
487 | -- label_values: (array) a list of label values.
488 | -- value: (number) value to observe.
489 | function Prometheus:histogram_observe(name, label_names, label_values, value)
490 | self:inc(name .. "_count", label_names, label_values, 1)
491 | self:inc(name .. "_sum", label_names, label_values, value)
492 |
493 | -- we are going to mutate arrays of label names and values, so create a copy.
494 | local l_names = copy_table(label_names)
495 | local l_values = copy_table(label_values)
496 |
497 | -- Last bucket. Note, that the label value is "Inf" rather than "+Inf"
498 | -- required by Prometheus. This is necessary for this bucket to be the last
499 | -- one when all metrics are lexicographically sorted. "Inf" will get replaced
500 | -- by "+Inf" in Prometheus:collect().
501 | table.insert(l_names, "le")
502 | table.insert(l_values, "Inf")
503 | self:inc(name .. "_bucket", l_names, l_values, 1)
504 |
505 | local label_count = #l_names
506 | for _, bucket in ipairs(self.buckets[name]) do
507 | if value <= bucket then
508 | -- last label is now "le"
509 | l_values[label_count] = self.bucket_format[name]:format(bucket)
510 | self:inc(name .. "_bucket", l_names, l_values, 1)
511 | end
512 | end
513 | end
514 |
515 | -- Prometheus compatible metric data as an array of strings.
516 | --
517 | -- Returns:
518 | -- Array of strings with all metrics in a text format compatible with
519 | -- Prometheus.
520 | function Prometheus:metric_data()
521 | if not self.initialized then
522 | ngx.log(ngx.ERR, "Prometheus module has not been initialized")
523 | return
524 | end
525 |
526 | local keys = self.dict:get_keys(0)
527 | -- Prometheus server expects buckets of a histogram to appear in increasing
528 | -- numerical order of their label values.
529 | table.sort(keys)
530 |
531 | local seen_metrics = {}
532 | local output = {}
533 | for _, key in ipairs(keys) do
534 | local value, err = self.dict:get(key)
535 | if value then
536 | local short_name = short_metric_name(key)
537 | if not seen_metrics[short_name] then
538 | if self.help[short_name] then
539 | table.insert(output, string.format("# HELP %s%s %s\n",
540 | self.prefix, short_name, self.help[short_name]))
541 | end
542 | if self.type[short_name] then
543 | table.insert(output, string.format("# TYPE %s%s %s\n",
544 | self.prefix, short_name, self.type[short_name]))
545 | end
546 | seen_metrics[short_name] = true
547 | end
548 | -- Replace "Inf" with "+Inf" in each metric's last bucket 'le' label.
549 | if key:find('le="Inf"', 1, true) then
550 | key = key:gsub('le="Inf"', 'le="+Inf"')
551 | end
552 | table.insert(output, string.format("%s%s %s\n", self.prefix, key, value))
553 | else
554 | self:log_error("Error getting '", key, "': ", err)
555 | end
556 | end
557 | return output
558 | end
559 |
560 | -- Present all metrics in a text format compatible with Prometheus.
561 | --
562 | -- This function should be used to expose the metrics on a separate HTTP page.
563 | -- It will get the metrics from the dictionary, sort them, and expose them
564 | -- aling with TYPE and HELP comments.
565 | function Prometheus:collect()
566 | ngx.header.content_type = "text/plain"
567 | ngx.print(self:metric_data())
568 | end
569 |
570 | return Prometheus
571 |
--------------------------------------------------------------------------------
/workdir/nginx.conf:
--------------------------------------------------------------------------------
1 | worker_processes 1;
2 | error_log logs/error.log;
3 | events {
4 | worker_connections 1024;
5 | }
6 | http {
7 | server {
8 | listen 8080;
9 | location / {
10 | default_type text/html;
11 | content_by_lua_block {
12 | ngx.say("hello, world
")
13 | }
14 | }
15 | }
16 | server {
17 | listen 81;
18 | server_name localhost;
19 |
20 | #access_log logs/host.access.log main;
21 |
22 | location / {
23 | root html;
24 | index index.html index.htm;
25 | }
26 |
27 | error_page 500 502 503 504 /50x.html;
28 | location = /50x.html {
29 | root html;
30 | }
31 |
32 | }
33 | include conf.d/*.conf;
34 | }
35 |
--------------------------------------------------------------------------------