diff --git a/deployments/configs/dashboards.md b/deployments/configs/dashboards.md new file mode 100644 index 00000000..999b1d8f --- /dev/null +++ b/deployments/configs/dashboards.md @@ -0,0 +1,8 @@ +# Dashboards + +- [Introducing ASP.NET Core metrics and Grafana dashboards in .NET 8](https://devblogs.microsoft.com/dotnet/introducing-aspnetcore-metrics-and-grafana-dashboards-in-dotnet-8/) +- [ASP.NET Core](https://grafana.com/grafana/dashboards/19924-asp-net-core/) +- [ASP.NET Core Endpoint](https://grafana.com/grafana/dashboards/19925-asp-net-core-endpoint/) +- [Node Exporter Quickstart and Dashboard](https://grafana.com/grafana/dashboards/13978-node-exporter-quickstart-and-dashboard/) +- [PostgreSQL Exporter Quickstart and Dashboard](https://grafana.com/grafana/dashboards/14114-postgres-overview/) +- [RabbitMQ-Overview](https://grafana.com/grafana/dashboards/10991-rabbitmq-overview/) \ No newline at end of file diff --git a/deployments/docker-compose/monitoring/dashboards/ASP.NET Core Endpoint.json b/deployments/configs/grafana/dashboards/dotnet-core-endpoint.json similarity index 100% rename from deployments/docker-compose/monitoring/dashboards/ASP.NET Core Endpoint.json rename to deployments/configs/grafana/dashboards/dotnet-core-endpoint.json diff --git a/deployments/docker-compose/monitoring/dashboards/ASP.NET Core.json b/deployments/configs/grafana/dashboards/dotnet-core.json similarity index 100% rename from deployments/docker-compose/monitoring/dashboards/ASP.NET Core.json rename to deployments/configs/grafana/dashboards/dotnet-core.json diff --git a/deployments/configs/grafana/dashboards/node-exporter.json b/deployments/configs/grafana/dashboards/node-exporter.json new file mode 100644 index 00000000..4839d46a --- /dev/null +++ b/deployments/configs/grafana/dashboards/node-exporter.json @@ -0,0 +1,892 @@ +{ + "__inputs": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.4.3" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + } + ], + "annotations": { + "list": [] + }, + "editable": false, + "gnetId": 13978, + "graphTooltip": 0, + "hideControls": false, + "id": null, + "links": [], + "refresh": "", + "rows": [ + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": {}, + "id": 2, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(\n (1 - rate(node_cpu_seconds_total{job=\"node\", mode=\"idle\", instance=\"$instance\"}[$__interval]))\n/ ignoring(cpu) group_left\n count without (cpu)( node_cpu_seconds_total{job=\"node\", mode=\"idle\", instance=\"$instance\"})\n)\n", + "format": "time_series", + "interval": "1m", + "intervalFactor": 5, + "legendFormat": "{{cpu}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "CPU Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": 1, + "min": 0, + "show": true + }, + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": 1, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 0, + "fillGradient": 0, + "gridPos": {}, + "id": 3, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "node_load1{job=\"node\", instance=\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "1m load average", + "refId": "A" + }, + { + "expr": "node_load5{job=\"node\", instance=\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "5m load average", + "refId": "B" + }, + { + "expr": "node_load15{job=\"node\", instance=\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "15m load average", + "refId": "C" + }, + { + "expr": "count(node_cpu_seconds_total{job=\"node\", instance=\"$instance\", mode=\"idle\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "logical cores", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Load Average", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Dashboard Row", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": {}, + "id": 4, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [], + "spaceLength": 10, + "span": 9, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "(\n node_memory_MemTotal_bytes{job=\"node\", instance=\"$instance\"}\n-\n node_memory_MemFree_bytes{job=\"node\", instance=\"$instance\"}\n-\n node_memory_Buffers_bytes{job=\"node\", instance=\"$instance\"}\n-\n node_memory_Cached_bytes{job=\"node\", instance=\"$instance\"}\n)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "memory used", + "refId": "A" + }, + { + "expr": "node_memory_Buffers_bytes{job=\"node\", instance=\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "memory buffers", + "refId": "B" + }, + { + "expr": "node_memory_Cached_bytes{job=\"node\", instance=\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "memory cached", + "refId": "C" + }, + { + "expr": "node_memory_MemFree_bytes{job=\"node\", instance=\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "memory free", + "refId": "D" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Memory Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(50, 172, 45, 0.97)", + "rgba(237, 129, 40, 0.89)", + "rgba(245, 54, 54, 0.9)" + ], + "datasource": "$datasource", + "format": "percent", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": true, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": {}, + "id": 5, + "interval": null, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "span": 3, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "tableColumn": "", + "targets": [ + { + "expr": "100 -\n(\n avg(node_memory_MemAvailable_bytes{job=\"node\", instance=\"$instance\"})\n/\n avg(node_memory_MemTotal_bytes{job=\"node\", instance=\"$instance\"})\n* 100\n)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "", + "refId": "A" + } + ], + "thresholds": "80, 90", + "title": "Memory Usage", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current" + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Dashboard Row", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 0, + "fillGradient": 0, + "gridPos": {}, + "id": 6, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + { + "alias": "/ read| written/", + "yaxis": 1 + }, + { + "alias": "/ io time/", + "yaxis": 2 + } + ], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(node_disk_read_bytes_total{job=\"node\", instance=\"$instance\", device!=\"\"}[$__interval])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 2, + "legendFormat": "{{device}} read", + "refId": "A" + }, + { + "expr": "rate(node_disk_written_bytes_total{job=\"node\", instance=\"$instance\", device!=\"\"}[$__interval])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 2, + "legendFormat": "{{device}} written", + "refId": "B" + }, + { + "expr": "rate(node_disk_io_time_seconds_total{job=\"node\", instance=\"$instance\", device!=\"\"}[$__interval])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 2, + "legendFormat": "{{device}} io time", + "refId": "C" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Disk I/O", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "s", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 1, + "fillGradient": 0, + "gridPos": {}, + "id": 7, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [ + { + "alias": "used", + "color": "#E0B400" + }, + { + "alias": "available", + "color": "#73BF69" + } + ], + "spaceLength": 10, + "span": 6, + "stack": true, + "steppedLine": false, + "targets": [ + { + "expr": "sum(\n max by (device) (\n node_filesystem_size_bytes{job=\"node\", instance=\"$instance\", fstype!=\"\"}\n -\n node_filesystem_avail_bytes{job=\"node\", instance=\"$instance\", fstype!=\"\"}\n )\n)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "used", + "refId": "A" + }, + { + "expr": "sum(\n max by (device) (\n node_filesystem_avail_bytes{job=\"node\", instance=\"$instance\", fstype!=\"\"}\n )\n)\n", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "available", + "refId": "B" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Disk Space Usage", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Dashboard Row", + "titleSize": "h6", + "type": "row" + }, + { + "collapse": false, + "collapsed": false, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 0, + "fillGradient": 0, + "gridPos": {}, + "id": 8, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(node_network_receive_bytes_total{job=\"node\", instance=\"$instance\", device!=\"lo\"}[$__interval])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 2, + "legendFormat": "{{device}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Network Received", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "fill": 0, + "fillGradient": 0, + "gridPos": {}, + "id": 9, + "legend": { + "alignAsTable": false, + "avg": false, + "current": false, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": null, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "repeat": null, + "seriesOverrides": [], + "spaceLength": 10, + "span": 6, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "rate(node_network_transmit_bytes_total{job=\"node\", instance=\"$instance\", device!=\"lo\"}[$__interval])", + "format": "time_series", + "interval": "1m", + "intervalFactor": 2, + "legendFormat": "{{device}}", + "refId": "A" + } + ], + "thresholds": [], + "timeFrom": null, + "timeShift": null, + "title": "Network Transmitted", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "bytes", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + } + ] + } + ], + "repeat": null, + "repeatIteration": null, + "repeatRowId": null, + "showTitle": false, + "title": "Dashboard Row", + "titleSize": "h6", + "type": "row" + } + ], + "schemaVersion": 14, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "text": "Prometheus", + "value": "Prometheus" + }, + "hide": 0, + "label": null, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + }, + { + "allValue": null, + "current": {}, + "datasource": "$datasource", + "hide": 0, + "includeAll": false, + "label": null, + "multi": false, + "name": "instance", + "options": [], + "query": "label_values(node_exporter_build_info{job=\"node\"}, instance)", + "refresh": 2, + "regex": "", + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Node Exporter Quickstart and Dashboard", + "version": 0, + "description": "A quickstart to setup Prometheus Node Exporter with preconfigured dashboards, alerting rules, and recording rules." +} \ No newline at end of file diff --git a/deployments/configs/grafana/dashboards/postgresql.json b/deployments/configs/grafana/dashboards/postgresql.json new file mode 100644 index 00000000..d1d696f4 --- /dev/null +++ b/deployments/configs/grafana/dashboards/postgresql.json @@ -0,0 +1,1459 @@ +{ + "__inputs": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "7.2.0" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "A quickstart to setup the Prometheus PostgreSQL Exporter with preconfigured dashboards, alerting rules, and recording rules.", + "editable": true, + "gnetId": 14114, + "graphTooltip": 0, + "id": 1, + "iteration": 1603191461722, + "links": [], + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 20, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 1, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.2.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "fetched", + "dsType": "prometheus", + "expr": "sum(irate(pg_stat_database_tup_fetched{datname=~\"$db\",instance=~\"$instance\"}[5m]))", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "legendFormat": "fetched", + "measurement": "postgresql", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "tup_fetched" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "step": 120, + "tags": [ + { + "key": "instance", + "operator": "=~", + "value": "/^$instance$/" + } + ] + }, + { + "alias": "fetched", + "dsType": "prometheus", + "expr": "sum(irate(pg_stat_database_tup_returned{datname=~\"$db\",instance=~\"$instance\"}[5m]))", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "legendFormat": "returned", + "measurement": "postgresql", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "tup_fetched" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "step": 120, + "tags": [ + { + "key": "instance", + "operator": "=~", + "value": "/^$instance$/" + } + ] + }, + { + "alias": "fetched", + "dsType": "prometheus", + "expr": "sum(irate(pg_stat_database_tup_inserted{datname=~\"$db\",instance=~\"$instance\"}[5m]))", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "legendFormat": "inserted", + "measurement": "postgresql", + "policy": "default", + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "tup_fetched" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "step": 120, + "tags": [ + { + "key": "instance", + "operator": "=~", + "value": "/^$instance$/" + } + ] + }, + { + "alias": "fetched", + "dsType": "prometheus", + "expr": "sum(irate(pg_stat_database_tup_updated{datname=~\"$db\",instance=~\"$instance\"}[5m]))", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "legendFormat": "updated", + "measurement": "postgresql", + "policy": "default", + "refId": "D", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "tup_fetched" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "step": 120, + "tags": [ + { + "key": "instance", + "operator": "=~", + "value": "/^$instance$/" + } + ] + }, + { + "alias": "fetched", + "dsType": "prometheus", + "expr": "sum(irate(pg_stat_database_tup_deleted{datname=~\"$db\",instance=~\"$instance\"}[5m]))", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "legendFormat": "deleted", + "measurement": "postgresql", + "policy": "default", + "refId": "E", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "tup_fetched" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "step": 120, + "tags": [ + { + "key": "instance", + "operator": "=~", + "value": "/^$instance$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Rows", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": "$datasource", + "decimals": 0, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "format": "none", + "gauge": { + "maxValue": 100, + "minValue": 0, + "show": false, + "thresholdLabels": false, + "thresholdMarkers": true + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 20, + "y": 0 + }, + "height": "55px", + "id": 11, + "interval": null, + "isNew": true, + "links": [], + "mappingType": 1, + "mappingTypes": [ + { + "name": "value to text", + "value": 1 + }, + { + "name": "range to text", + "value": 2 + } + ], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "rangeMaps": [ + { + "from": "null", + "text": "N/A", + "to": "null" + } + ], + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": true, + "lineColor": "rgb(31, 120, 193)", + "show": true + }, + "tableColumn": "", + "targets": [ + { + "dsType": "prometheus", + "expr": "sum(irate(pg_stat_database_xact_commit{datname=~\"$db\",instance=~\"$instance\"}[5m])) + sum(irate(pg_stat_database_xact_rollback{datname=~\"$db\",instance=~\"$instance\"}[5m]))", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "measurement": "postgresql", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "xact_commit" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [ + "10s" + ], + "type": "non_negative_derivative" + } + ] + ], + "step": 1800, + "tags": [ + { + "key": "instance", + "operator": "=~", + "value": "/^$instance$/" + } + ] + } + ], + "thresholds": "", + "title": "QPS", + "transparent": true, + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "decimals": 1, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 7 + }, + "hiddenSeries": false, + "id": 2, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideZero": true, + "max": true, + "min": true, + "rightSide": false, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.2.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Buffers Allocated", + "dsType": "prometheus", + "expr": "irate(pg_stat_bgwriter_buffers_alloc{instance=~'$instance'}[5m])", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "legendFormat": "buffers_alloc", + "measurement": "postgresql", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "buffers_alloc" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "difference" + } + ] + ], + "step": 240, + "tags": [ + { + "key": "instance", + "operator": "=~", + "value": "/^$instance$/" + } + ] + }, + { + "alias": "Buffers Allocated", + "dsType": "prometheus", + "expr": "irate(pg_stat_bgwriter_buffers_backend_fsync{instance=~'$instance'}[5m])", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "legendFormat": "buffers_backend_fsync", + "measurement": "postgresql", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "buffers_alloc" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "difference" + } + ] + ], + "step": 240, + "tags": [ + { + "key": "instance", + "operator": "=~", + "value": "/^$instance$/" + } + ] + }, + { + "alias": "Buffers Allocated", + "dsType": "prometheus", + "expr": "irate(pg_stat_bgwriter_buffers_backend{instance=~'$instance'}[5m])", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "legendFormat": "buffers_backend", + "measurement": "postgresql", + "policy": "default", + "refId": "C", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "buffers_alloc" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "difference" + } + ] + ], + "step": 240, + "tags": [ + { + "key": "instance", + "operator": "=~", + "value": "/^$instance$/" + } + ] + }, + { + "alias": "Buffers Allocated", + "dsType": "prometheus", + "expr": "irate(pg_stat_bgwriter_buffers_clean{instance=~'$instance'}[5m])", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "legendFormat": "buffers_clean", + "measurement": "postgresql", + "policy": "default", + "refId": "D", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "buffers_alloc" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "difference" + } + ] + ], + "step": 240, + "tags": [ + { + "key": "instance", + "operator": "=~", + "value": "/^$instance$/" + } + ] + }, + { + "alias": "Buffers Allocated", + "dsType": "prometheus", + "expr": "irate(pg_stat_bgwriter_buffers_checkpoint{instance=~'$instance'}[5m])", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "legendFormat": "buffers_checkpoint", + "measurement": "postgresql", + "policy": "default", + "refId": "E", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "buffers_alloc" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "difference" + } + ] + ], + "step": 240, + "tags": [ + { + "key": "instance", + "operator": "=~", + "value": "/^$instance$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Buffers", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 7 + }, + "hiddenSeries": false, + "id": 3, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.2.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "conflicts", + "dsType": "prometheus", + "expr": "sum(rate(pg_stat_database_deadlocks{datname=~\"$db\",instance=~\"$instance\"}[5m]))", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "legendFormat": "deadlocks", + "measurement": "postgresql", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "conflicts" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "difference" + } + ] + ], + "step": 240, + "tags": [ + { + "key": "instance", + "operator": "=~", + "value": "/^$instance$/" + } + ] + }, + { + "alias": "deadlocks", + "dsType": "prometheus", + "expr": "sum(rate(pg_stat_database_conflicts{datname=~\"$db\",instance=~\"$instance\"}[5m]))", + "format": "time_series", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "intervalFactor": 2, + "legendFormat": "conflicts", + "measurement": "postgresql", + "policy": "default", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "deadlocks" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + }, + { + "params": [], + "type": "difference" + } + ] + ], + "step": 240, + "tags": [ + { + "key": "instance", + "operator": "=~", + "value": "/^$instance$/" + } + ] + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Conflicts/Deadlocks", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": 0, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 14 + }, + "hiddenSeries": false, + "id": 12, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": true, + "pluginVersion": "7.2.1", + "pointradius": 1, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "sum(pg_stat_database_blks_hit{datname=~\"$db\",instance=~\"$instance\"}) / (sum(pg_stat_database_blks_hit{datname=~\"$db\",instance=~\"$instance\"}) + sum(pg_stat_database_blks_read{datname=~\"$db\",instance=~\"$instance\"}))", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "cache hit rate", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Cache hit ratio", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "percentunit", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": "$datasource", + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "custom": {} + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 14 + }, + "hiddenSeries": false, + "id": 13, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "7.2.1", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "expr": "pg_stat_database_numbackends{datname=~\"$db\",instance=~\"$instance\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "{{__name__}}", + "refId": "A", + "step": 240 + } + ], + "thresholds": [], + "timeFrom": null, + "timeRegions": [], + "timeShift": null, + "title": "Number of active connections", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "buckets": null, + "mode": "time", + "name": null, + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ], + "yaxis": { + "align": false, + "alignLevel": null + } + } + ], + "refresh": false, + "schemaVersion": 26, + "style": "dark", + "tags": [ + "postgres" + ], + "templating": { + "list": [ + { + "allValue": ".*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": "$datasource", + "definition": "", + "hide": 0, + "includeAll": true, + "label": null, + "multi": false, + "name": "instance", + "options": [], + "query": "label_values(up{job=~\"postgres.*\"},instance)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": "$datasource", + "definition": "label_values(pg_stat_database_tup_fetched{instance=~\"$instance\",datname!~\"template.*|postgres\"},datname)", + "hide": 0, + "includeAll": true, + "label": "db", + "multi": false, + "name": "db", + "options": [], + "query": "label_values(pg_stat_database_tup_fetched{instance=~\"$instance\",datname!~\"template.*|postgres\"},datname)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "Postgres Overview", + "value": "Postgres Overview" + }, + "hide": 0, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": null, + "current": { + "selected": true, + "text": "postgres", + "value": "postgres" + }, + "datasource": "$datasource", + "definition": "label_values(pg_up, job)", + "hide": 0, + "includeAll": false, + "label": "job", + "multi": false, + "name": "job", + "options": [ + { + "selected": true, + "text": "postgres", + "value": "postgres" + } + ], + "query": "label_values(pg_up, job)", + "refresh": 0, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tags": [], + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "PostgreSQL Exporter Quickstart and Dashboard", + "uid": "wGgaPlciz", + "version": 5 +} \ No newline at end of file diff --git a/deployments/configs/grafana/dashboards/rabbitmq.json b/deployments/configs/grafana/dashboards/rabbitmq.json new file mode 100644 index 00000000..b199b4b7 --- /dev/null +++ b/deployments/configs/grafana/dashboards/rabbitmq.json @@ -0,0 +1,8209 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": [], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "8.3.4" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": "-- Grafana --", + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "A new RabbitMQ Management Overview", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": null, + "iteration": 1659711638455, + "links": [ + { + "icon": "doc", + "tags": [], + "targetBlank": true, + "title": "Monitoring with Prometheus & Grafana", + "tooltip": "", + "type": "link", + "url": "https://www.rabbitmq.com/prometheus.html" + } + ], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#37872D", + "value": null + }, + { + "color": "#1F60C4", + "value": 10000 + }, + { + "color": "#C4162A", + "value": 100000 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "id": 64, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rabbitmq_queue_messages_ready * on(instance, job) group_left(rabbitmq_cluster) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"})", + "format": "time_series", + "hide": false, + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Ready messages", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#C4162A", + "value": null + }, + { + "color": "#1F60C4", + "value": -1 + }, + { + "color": "#37872D", + "value": 50 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 6, + "y": 0 + }, + "id": 62, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_received_total[60s]) * on(instance, job) group_left(rabbitmq_cluster) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"})", + "format": "time_series", + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Incoming messages / s", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#C4162A", + "value": null + }, + { + "color": "#1F60C4", + "value": 0 + }, + { + "color": "#37872D", + "value": 10 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 12, + "y": 0 + }, + "id": 66, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rabbitmq_global_publishers * on(instance, job) group_left(rabbitmq_cluster) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"})", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Publishers", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#C4162A", + "value": null + }, + { + "color": "#1F60C4", + "value": 0 + }, + { + "color": "#37872D", + "value": 10 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 16, + "y": 0 + }, + "id": 37, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rabbitmq_connections * on(instance, job) group_left(rabbitmq_cluster) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"})", + "format": "time_series", + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Connections", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#C4162A", + "value": null + }, + { + "color": "#1F60C4", + "value": 0 + }, + { + "color": "#37872D", + "value": 10 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 20, + "y": 0 + }, + "id": 40, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rabbitmq_queues * on(instance, job) group_left(rabbitmq_cluster) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"})", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Queues", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#37872D", + "value": null + }, + { + "color": "#1F60C4", + "value": 100 + }, + { + "color": "#C4162A", + "value": 500 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 65, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rabbitmq_queue_messages_unacked * on(instance, job) group_left(rabbitmq_cluster) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"})", + "format": "time_series", + "hide": false, + "instant": false, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Unacknowledged messages", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#C4162A", + "value": null + }, + { + "color": "#1F60C4", + "value": -1 + }, + { + "color": "#37872D", + "value": 50 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 6, + "y": 3 + }, + "id": 63, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_redelivered_total[60s]) * on(instance, job) group_left(rabbitmq_cluster) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) +\nsum(rate(rabbitmq_global_messages_delivered_consume_auto_ack_total[60s]) * on(instance, job) group_left(rabbitmq_cluster) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) +\nsum(rate(rabbitmq_global_messages_delivered_consume_manual_ack_total[60s]) * on(instance, job) group_left(rabbitmq_cluster) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) +\nsum(rate(rabbitmq_global_messages_delivered_get_auto_ack_total[60s]) * on(instance, job) group_left(rabbitmq_cluster) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) +\nsum(rate(rabbitmq_global_messages_delivered_get_manual_ack_total[60s]) * on(instance, job) group_left(rabbitmq_cluster) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"})", + "format": "time_series", + "hide": false, + "instant": false, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Outgoing messages / s", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#C4162A", + "value": null + }, + { + "color": "#1F60C4", + "value": 0 + }, + { + "color": "#37872D", + "value": 10 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 12, + "y": 3 + }, + "id": 41, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rabbitmq_consumers * on(instance, job) group_left(rabbitmq_cluster) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"})", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Consumers", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#C4162A", + "value": null + }, + { + "color": "#1F60C4", + "value": 0 + }, + { + "color": "#37872D", + "value": 10 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 16, + "y": 3 + }, + "id": 38, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rabbitmq_channels * on(instance, job) group_left(rabbitmq_cluster) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"})", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Channels", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#1F60C4", + "value": null + }, + { + "color": "#37872D", + "value": 3 + }, + { + "color": "#C4162A", + "value": 8 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 20, + "y": 3 + }, + "id": 67, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rabbitmq_build_info * on(instance, job) group_left(rabbitmq_cluster) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"})", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "title": "Nodes", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 4, + "panels": [], + "title": "NODES", + "type": "row" + }, + { + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "erlang_version" + }, + "properties": [ + { + "id": "displayName", + "value": "Erlang/OTP" + }, + { + "id": "unit", + "value": "none" + }, + { + "id": "custom.align" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)" + } + ] + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "rabbitmq_version" + }, + "properties": [ + { + "id": "displayName", + "value": "RabbitMQ" + }, + { + "id": "unit", + "value": "none" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(245, 54, 54, 0.9)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)" + } + ] + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "instance" + }, + "properties": [ + { + "id": "displayName", + "value": "Host" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "rabbitmq_node" + }, + "properties": [ + { + "id": "displayName", + "value": "Node name" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + }, + { + "id": "thresholds", + "value": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(245, 54, 54, 0.9)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)" + } + ] + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Value" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "job" + }, + "properties": [ + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "rabbitmq_cluster" + }, + "properties": [ + { + "id": "displayName", + "value": "Cluster" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "prometheus_client_version" + }, + "properties": [ + { + "id": "displayName", + "value": "prometheus.erl" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "prometheus_plugin_version" + }, + "properties": [ + { + "id": "displayName", + "value": "rabbitmq_prometheus" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "custom.align" + } + ] + } + ] + }, + "gridPos": { + "h": 4, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 69, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": false, + "expr": "rabbitmq_build_info * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}", + "format": "table", + "instant": true, + "interval": "", + "intervalFactor": 1, + "legendFormat": "", + "refId": "A" + } + ], + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "If the value is zero or less, the memory alarm will be triggered and all publishing connections across all cluster nodes will be blocked.\n\nThis value can temporarily go negative because the memory alarm is triggered with a slight delay.\n\nThe kernel's view of the amount of memory used by the node can differ from what the node itself can observe. This means that this value can be negative for a sustained period of time.\n\nBy default nodes use resident set size (RSS) to compute how much memory they use. This strategy can be changed (see the guides below).\n\n* [Alarms](https://www.rabbitmq.com/alarms.html)\n* [Memory Alarms](https://www.rabbitmq.com/memory.html)\n* [Reasoning About Memory Use](https://www.rabbitmq.com/memory-use.html)\n* [Blocked Connection Notifications](https://www.rabbitmq.com/connection-blocked.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "decimals": 1, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 0 + }, + { + "color": "transparent", + "value": 536870912 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 11 + }, + "id": 7, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "(rabbitmq_resident_memory_limit_bytes * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) -\n(rabbitmq_process_resident_memory_bytes * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"})", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Memory available before publishers blocked", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "This metric is reported for the partition where the RabbitMQ data directory is stored.\n\nIf the value is zero or less, the disk alarm will be triggered and all publishing connections across all cluster nodes will be blocked.\n\nThis value can temporarily go negative because the free disk space alarm is triggered with a slight delay.\n\n* [Alarms](https://www.rabbitmq.com/alarms.html)\n* [Disk Space Alarms](https://www.rabbitmq.com/disk-alarms.html)\n* [Disk Space](https://www.rabbitmq.com/production-checklist.html#resource-limits-disk-space)\n* [Persistence Configuration](https://www.rabbitmq.com/persistence-conf.html)\n* [Blocked Connection Notifications](https://www.rabbitmq.com/connection-blocked.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "decimals": 1, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 1073741824 + }, + { + "color": "transparent", + "value": 5368709120 + } + ] + }, + "unit": "bytes" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 12, + "y": 11 + }, + "id": 8, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "rabbitmq_disk_space_available_bytes * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Disk space available before publishers blocked", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "When this value reaches zero, new connections will not be accepted and disk write operations may fail.\n\nClient libraries, peer nodes and CLI tools will not be able to connect when the node runs out of available file descriptors.\n\n* [Open File Handles Limit](https://www.rabbitmq.com/production-checklist.html#resource-limits-file-handle-limit)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 500 + }, + { + "color": "transparent", + "value": 1000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 20, + "y": 11 + }, + "id": 2, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "(rabbitmq_process_max_fds * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) -\n(rabbitmq_process_open_fds * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"})", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "File descriptors available", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "When this value reaches zero, new connections will not be accepted.\n\nClient libraries, peer nodes and CLI tools will not be able to connect when the node runs out of available file descriptors.\n\n* [Networking and RabbitMQ](https://www.rabbitmq.com/networking.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "red", + "value": null + }, + { + "color": "orange", + "value": 500 + }, + { + "color": "transparent", + "value": 1000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 20, + "y": 15 + }, + "id": 5, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "(rabbitmq_process_max_tcp_sockets * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) -\n(rabbitmq_process_open_tcp_sockets * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"})", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "TCP sockets available", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 19 + }, + "id": 27, + "panels": [], + "title": "QUEUED MESSAGES", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Total number of ready messages ready to be delivered to consumers.\n\nAim to keep this value as low as possible. RabbitMQ behaves best when messages are flowing through it. It's OK for publishers to occasionally outpace consumers, but the expectation is that consumers will eventually process all ready messages.\n\nIf this metric keeps increasing, your system will eventually run out of memory and/or disk space. Consider using TTL or Queue Length Limit to prevent unbounded message growth.\n\n* [Queues](https://www.rabbitmq.com/queues.html)\n* [Consumers](https://www.rabbitmq.com/consumers.html)\n* [Queue Length Limit](https://www.rabbitmq.com/maxlength.html)\n* [Time-To-Live and Expiration](https://www.rabbitmq.com/ttl.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 9, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rabbitmq_queue_messages_ready * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Messages ready to be delivered to consumers", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The total number of messages that are either in-flight to consumers, currently being processed by consumers or simply waiting for the consumer acknowledgements to be processed by the queue. Until the queue processes the message acknowledgement, the message will remain unacknowledged.\n\n* [Queues](https://www.rabbitmq.com/queues.html)\n* [Confirms and Acknowledgements](https://www.rabbitmq.com/confirms.html)\n* [Consumer Prefetch](https://www.rabbitmq.com/consumer-prefetch.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 19, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rabbitmq_queue_messages_unacked * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Messages pending consumer acknowledgement", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 25 + }, + "id": 11, + "panels": [], + "title": "INCOMING MESSAGES", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The incoming message rate before any routing rules are applied.\n\nIf this value is lower than the number of messages published to queues, it may indicate that some messages are delivered to more than one queue.\n\nIf this value is higher than the number of messages published to queues, messages cannot be routed and will either be dropped or returned to publishers.\n\n* [Publishers](https://www.rabbitmq.com/publishers.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 26 + }, + "id": 13, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_received_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Messages published / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of messages confirmed by the broker to publishers. Publishers must opt-in to receive message confirmations.\n\nIf this metric is consistently at zero it may suggest that publisher confirms are not used by clients. The safety of published messages is likely to be at risk.\n\n* [Publisher Confirms](https://www.rabbitmq.com/confirms.html#publisher-confirms)\n* [Publisher Confirms and Data Safety](https://www.rabbitmq.com/publishers.html#data-safety)\n* [When Will Published Messages Be Confirmed by the Broker?](https://www.rabbitmq.com/confirms.html#when-publishes-are-confirmed)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 26 + }, + "id": 18, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_confirmed_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Messages confirmed to publishers / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of messages received from publishers and successfully routed to the master queue replicas.\n\n* [Queues](https://www.rabbitmq.com/queues.html)\n* [Publishers](https://www.rabbitmq.com/publishers.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 31 + }, + "id": 61, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_routed_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Messages routed to queues / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of messages received from publishers that have publisher confirms enabled and the broker has not confirmed yet.\n\n* [Publishers](https://www.rabbitmq.com/publishers.html)\n* [Confirms and Acknowledgements](https://www.rabbitmq.com/confirms.html)\n* [When Will Published Messages Be Confirmed by the Broker?](https://www.rabbitmq.com/confirms.html#when-publishes-are-confirmed)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 31 + }, + "id": 12, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_received_confirm_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"} - \nrate(rabbitmq_global_messages_confirmed_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}\n) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Messages unconfirmed to publishers / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of messages that cannot be routed and are dropped. \n\nAny value above zero means message loss and likely suggests a routing problem on the publisher end.\n\n* [Unroutable Message Handling](https://www.rabbitmq.com/publishers.html#unroutable)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "red", + "value": 0 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/rabbit/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C4162A", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 36 + }, + "id": 34, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_unroutable_dropped_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Unroutable messages dropped / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of messages that cannot be routed and are returned back to publishers.\n\nSustained values above zero may indicate a routing problem on the publisher end.\n\n* [Unroutable Message Handling](https://www.rabbitmq.com/publishers.html#unroutable)\n* [When Will Published Messages Be Confirmed by the Broker?](https://www.rabbitmq.com/confirms.html#when-publishes-are-confirmed)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "red", + "value": 0 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/rabbit/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C4162A", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 36 + }, + "id": 16, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_unroutable_returned_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Unroutable messages returned to publishers / s", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 41 + }, + "id": 29, + "panels": [], + "title": "OUTGOING MESSAGES", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of messages delivered to consumers. It includes messages that have been redelivered.\n\nThis metric does not include messages that have been fetched by consumers using `basic.get` (consumed by polling).\n\n* [Consumers](https://www.rabbitmq.com/consumers.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 42 + }, + "id": 14, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(\n (rate(rabbitmq_global_messages_delivered_consume_auto_ack_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) +\n (rate(rabbitmq_global_messages_delivered_consume_manual_ack_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"})\n) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Messages delivered / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of messages that have been redelivered to consumers. It includes messages that have been requeued automatically and redelivered due to channel exceptions or connection closures.\n\nHaving some redeliveries is expected, but if this metric is consistently non-zero, it is worth investigating why.\n\n* [Negative Acknowledgement and Requeuing of Deliveries](https://www.rabbitmq.com/confirms.html#consumer-nacks-requeue)\n* [Consumers](https://www.rabbitmq.com/consumers.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "orange", + "value": 20 + }, + { + "color": "red", + "value": 100 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 42 + }, + "id": 15, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_redelivered_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Messages redelivered / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of message deliveries to consumers that use manual acknowledgement mode.\n\nWhen this mode is used, RabbitMQ waits for consumers to acknowledge messages before more messages can be delivered.\n\nThis is the safest way of consuming messages.\n\n* [Consumer Acknowledgements](https://www.rabbitmq.com/confirms.html)\n* [Consumer Prefetch](https://www.rabbitmq.com/consumer-prefetch.html)\n* [Consumer Acknowledgement Modes, Prefetch and Throughput](https://www.rabbitmq.com/confirms.html#channel-qos-prefetch-throughput)\n* [Consumers](https://www.rabbitmq.com/consumers.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 47 + }, + "id": 20, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_delivered_consume_manual_ack_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Messages delivered with manual ack / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of message deliveries to consumers that use automatic acknowledgement mode.\n\nWhen this mode is used, RabbitMQ does not wait for consumers to acknowledge message deliveries.\n\nThis mode is fire-and-forget and does not offer any delivery safety guarantees. It tends to provide higher throughput and it may lead to consumer overload and higher consumer memory usage.\n\n* [Consumer Acknowledgement Modes, Prefetch and Throughput](https://www.rabbitmq.com/confirms.html#channel-qos-prefetch-throughput)\n* [Consumers](https://www.rabbitmq.com/consumers.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 47 + }, + "id": 21, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_delivered_consume_auto_ack_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Messages delivered auto ack / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of message acknowledgements coming from consumers that use manual acknowledgement mode.\n\n* [Consumer Acknowledgements](https://www.rabbitmq.com/confirms.html)\n* [Consumer Prefetch](https://www.rabbitmq.com/consumer-prefetch.html)\n* [Consumer Acknowledgement Modes, Prefetch and Throughput](https://www.rabbitmq.com/confirms.html#channel-qos-prefetch-throughput)\n* [Consumers](https://www.rabbitmq.com/consumers.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 52 + }, + "id": 22, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_acknowledged_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Messages acknowledged / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of messages delivered to polling consumers that use automatic acknowledgement mode.\n\nThe use of polling consumers is highly inefficient and therefore strongly discouraged.\n\n* [Fetching individual messages](https://www.rabbitmq.com/consumers.html#fetching)\n* [Consumers](https://www.rabbitmq.com/consumers.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "red", + "value": 0 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/rabbit/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C4162A", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 52 + }, + "id": 24, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_delivered_get_auto_ack_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Polling operations with auto ack / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of polling consumer operations that yield no result.\n\nAny value above zero means that RabbitMQ resources are wasted by polling consumers.\n\nCompare this metric to the other polling consumer metrics to see the inefficiency rate.\n\nThe use of polling consumers is highly inefficient and therefore strongly discouraged.\n\n* [Fetching individual messages](https://www.rabbitmq.com/consumers.html#fetching)\n* [Consumers](https://www.rabbitmq.com/consumers.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "red", + "value": 0 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/rabbit/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C4162A", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 57 + }, + "id": 25, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_get_empty_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Polling operations that yield no result / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of messages delivered to polling consumers that use manual acknowledgement mode.\n\nThe use of polling consumers is highly inefficient and therefore strongly discouraged.\n\n* [Fetching individual messages](https://www.rabbitmq.com/consumers.html#fetching)\n* [Consumers](https://www.rabbitmq.com/consumers.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "red", + "value": 0 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/rabbit/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#C4162A", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 57 + }, + "id": 23, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_global_messages_delivered_get_manual_ack_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Polling operations with manual ack / s", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 62 + }, + "id": 53, + "panels": [], + "title": "QUEUES", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Total number of queue masters per node. \n\nThis metric makes it easy to see sub-optimal queue distribution in a cluster.\n\n* [Queue Masters, Data Locality](https://www.rabbitmq.com/ha.html#master-migration-data-locality)\n* [Queues](https://www.rabbitmq.com/queues.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 63 + }, + "id": 57, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "rabbitmq_queues * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}", + "format": "time_series", + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Total queues", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of queue declarations performed by clients.\n\nLow sustained values above zero are to be expected. High rates may be indicative of queue churn or high rates of connection recovery. Confirm connection recovery rates by using the _Connections opened_ metric.\n\n* [Queues](https://www.rabbitmq.com/queues.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "orange", + "value": 2 + }, + { + "color": "red", + "value": 10 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 12, + "y": 63 + }, + "id": 58, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_queues_declared_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Queues declared / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of new queues created (as opposed to redeclarations).\n\nLow sustained values above zero are to be expected. High rates may be indicative of queue churn or high rates of connection recovery. Confirm connection recovery rates by using the _Connections opened_ metric.\n\n* [Queues](https://www.rabbitmq.com/queues.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "orange", + "value": 2 + }, + { + "color": "red", + "value": 10 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 16, + "y": 63 + }, + "id": 60, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_queues_created_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Queues created / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of queues deleted.\n\nLow sustained values above zero are to be expected. High rates may be indicative of queue churn or high rates of connection recovery. Confirm connection recovery rates by using the _Connections opened_ metric.\n\n* [Queues](https://www.rabbitmq.com/queues.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "orange", + "value": 2 + }, + { + "color": "red", + "value": 10 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 4, + "x": 20, + "y": 63 + }, + "id": 59, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_queues_deleted_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Queues deleted / s", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 68 + }, + "id": 51, + "panels": [], + "title": "CHANNELS", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Total number of channels on all currently opened connections.\n\nIf this metric grows monotonically it is highly likely a channel leak in one of the applications. Confirm channel leaks by using the _Channels opened_ and _Channels closed_ metrics.\n\n* [Channel Leak](https://www.rabbitmq.com/channels.html#channel-leaks)\n* [Channels](https://www.rabbitmq.com/channels.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 69 + }, + "id": 54, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "rabbitmq_channels * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Total channels", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of new channels opened by applications across all connections. Channels are expected to be long-lived.\n\nLow sustained values above zero are to be expected. High rates may be indicative of channel churn or mass connection recovery. Confirm connection recovery rates by using the _Connections opened_ metric.\n\n* [High Channel Churn](https://www.rabbitmq.com/channels.html#high-channel-churn)\n* [Channels](https://www.rabbitmq.com/channels.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "orange", + "value": 2 + }, + { + "color": "red", + "value": 10 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 12, + "y": 69 + }, + "id": 55, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_channels_opened_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Channels opened / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of channels closed by applications across all connections. Channels are expected to be long-lived.\n\nLow sustained values above zero are to be expected. High rates may be indicative of channel churn or mass connection recovery. Confirm connection recovery rates by using the _Connections opened_ metric.\n\n* [High Channel Churn](https://www.rabbitmq.com/channels.html#high-channel-churn)\n* [Channels](https://www.rabbitmq.com/channels.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "orange", + "value": 2 + }, + { + "color": "red", + "value": 10 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 18, + "y": 69 + }, + "id": 56, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_channels_closed_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Channels closed / s", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 74 + }, + "id": 46, + "panels": [], + "title": "CONNECTIONS", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Total number of client connections.\n\nIf this metric grows monotonically it is highly likely a connection leak in one of the applications. Confirm connection leaks by using the _Connections opened_ and _Connections closed_ metrics.\n\n* [Connection Leak](https://www.rabbitmq.com/connections.html#monitoring)\n* [Connections](https://www.rabbitmq.com/connections.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 75 + }, + "id": 47, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "rabbitmq_connections * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Total connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of new connections opened by clients. Connections are expected to be long-lived.\n\nLow sustained values above zero are to be expected. High rates may be indicative of connection churn or mass connection recovery.\n\n* [Connection Leak](https://www.rabbitmq.com/connections.html#monitoring)\n* [Connections](https://www.rabbitmq.com/connections.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "orange", + "value": 2 + }, + { + "color": "red", + "value": 10 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 12, + "y": 75 + }, + "id": 48, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_connections_opened_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "interval": "", + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Connections opened / s", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "The rate of connections closed. Connections are expected to be long-lived.\n\nLow sustained values above zero are to be expected. High rates may be indicative of connection churn or mass connection recovery.\n\n* [Connections](https://www.rabbitmq.com/connections.html)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 100, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "line+area" + } + }, + "links": [], + "mappings": [], + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "transparent", + "value": null + }, + { + "color": "orange", + "value": 2 + }, + { + "color": "red", + "value": 10 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?0(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#56A64B", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?1(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#F2CC0C", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?2(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#3274D9", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?3(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#A352CC", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?4(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FF780A", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?5(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#96D98D", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?6(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFEE52", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?7(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#8AB8FF", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?8(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#CA95E5", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "/^rabbit@[a-zA-Z\\.\\-]*?9(\\b|\\.)/" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#FFB357", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 18, + "y": 75 + }, + "id": 49, + "links": [], + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "max", + "min" + ], + "displayMode": "hidden", + "placement": "bottom" + }, + "tooltip": { + "mode": "multi" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "expr": "sum(rate(rabbitmq_connections_closed_total[60s]) * on(instance, job) group_left(rabbitmq_cluster, rabbitmq_node) rabbitmq_identity_info{rabbitmq_cluster=\"$rabbitmq_cluster\", namespace=\"$namespace\"}) by(rabbitmq_node)", + "format": "time_series", + "instant": false, + "intervalFactor": 1, + "legendFormat": "{{rabbitmq_node}}", + "refId": "A" + } + ], + "title": "Connections closed / s", + "type": "timeseries" + } + ], + "refresh": "15s", + "schemaVersion": 34, + "style": "dark", + "tags": [ + "rabbitmq-prometheus" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "datasource": "PBFA97CFB590B2093", + "hide": 2, + "includeAll": false, + "label": "datasource", + "multi": false, + "name": "DS_PROMETHEUS", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(rabbitmq_identity_info, namespace)", + "hide": 0, + "includeAll": false, + "label": "Namespace", + "multi": false, + "name": "namespace", + "options": [], + "query": { + "query": "label_values(rabbitmq_identity_info, namespace)", + "refId": "Prometheus-namespace-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "definition": "label_values(rabbitmq_identity_info{namespace=\"$namespace\"}, rabbitmq_cluster)", + "hide": 0, + "includeAll": false, + "label": "RabbitMQ Cluster", + "multi": false, + "name": "rabbitmq_cluster", + "options": [], + "query": { + "query": "label_values(rabbitmq_identity_info{namespace=\"$namespace\"}, rabbitmq_cluster)", + "refId": "Prometheus-rabbitmq_cluster-Variable-Query" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "15s", + "30s", + "1m", + "5m", + "10m" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "", + "title": "RabbitMQ-Overview", + "uid": "Kn5xm-gZk", + "version": 20220805, + "weekStart": "", + "gnetId": 10991 +} \ No newline at end of file diff --git a/deployments/configs/grafana/provisioning/dashboards/dashboard.yml b/deployments/configs/grafana/provisioning/dashboards/dashboard.yml new file mode 100644 index 00000000..f1fb0bb2 --- /dev/null +++ b/deployments/configs/grafana/provisioning/dashboards/dashboard.yml @@ -0,0 +1,14 @@ +# https://grafana.com/docs/grafana/latest/administration/provisioning/#dashboards +apiVersion: 1 + +providers: + - name: "default" + orgId: 1 + folder: "" + type: file + disableDeletion: false + editable: true + allowUiUpdates: true + updateIntervalSeconds: 5 # how often Grafana will scan for changed dashboards + options: + path: /var/lib/grafana/dashboards # path to dashboards on disk \ No newline at end of file diff --git a/deployments/configs/grafana/provisioning/datasources/datasource.yml b/deployments/configs/grafana/provisioning/datasources/datasource.yml new file mode 100644 index 00000000..5b04359b --- /dev/null +++ b/deployments/configs/grafana/provisioning/datasources/datasource.yml @@ -0,0 +1,88 @@ +# https://grafana.com/docs/grafana/latest/administration/provisioning/ +# https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/grafana-datasources.yaml +# https://github.com/grafana/intro-to-mltp/blob/main/grafana/provisioning/datasources/datasources.yaml + +apiVersion: 1 + +datasources: + # https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/grafana-datasources.yaml + - name: Prometheus + type: prometheus + typeName: Prometheus + uid: prometheus-uid + access: proxy + orgId: 1 + url: http://prometheus:9090 + basicAuth: false + isDefault: true + readOnly: false + user: '' + database: '' + version: 1 + editable: false + jsonData: + httpMethod: GET + + - name: Jaeger + type: jaeger + access: proxy + url: http://jaeger-all-in-one:16686 + editable: false + uid: jaeger-uid + + - name: Zipkin + type: zipkin + access: proxy + url: http://zipkin-all-in-one:9411 + editable: false + uid: zipkin-uid + + # https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/grafana-datasources.yaml + - name: Tempo + type: tempo + access: proxy + orgId: 1 + url: http://tempo:3200 + basicAuth: false + isDefault: false + version: 1 + editable: false + apiVersion: 1 + uid: tempo-uid + jsonData: + httpMethod: GET + serviceMap: + datasourceUid: prometheus-uid + streamingEnabled: + search: true + + #https://github.com/grafana/intro-to-mltp/blob/main/grafana/provisioning/datasources/datasources.yaml + - name: Loki + type: loki + access: proxy + uid: loki-uid + url: http://loki:3100 + user: '' + database: '' + readOnly: false + jsonData: + derivedFields: + - datasourceUid: tempo-uid + matcherRegex: "^.*?traceI[d|D]=(\\w+).*$" + name: traceId + url: '$${__value.raw}' + + - name: Kibana + type: elasticsearch + url: http://elasticsearch:9200 + access: proxy + isDefault: false + uid: kibana-uid + jsonData: + esVersion: 7 + timeField: "@timestamp" + maxConcurrentShardRequests: 256 + interval: Daily + logMessageField: "message" # Optional: Field for log messages + logLevelField: "level" # Optional: Field for log levels + editable: true \ No newline at end of file diff --git a/deployments/configs/loki-config.yaml b/deployments/configs/loki-config.yaml new file mode 100644 index 00000000..414d7626 --- /dev/null +++ b/deployments/configs/loki-config.yaml @@ -0,0 +1,44 @@ +# https://grafana.com/docs/loki/latest/configure/examples/configuration-examples/ +# https://github.com/grafana/loki/issues/2018#issuecomment-970789233 +# https://grafana.com/docs/opentelemetry/collector/send-logs-to-loki/ +# https://github.com/grafana/loki/blob/main/examples/getting-started/loki-config.yaml +# https://github.com/grafana/loki/blob/main/cmd/loki/loki-local-config.yaml +# https://grafana.com/docs/loki/latest/configure/examples/configuration-examples/#1-local-configuration-exampleyaml + +--- +# https://grafana.com/docs/loki/latest/configure/examples/configuration-examples/#1-local-configuration-exampleyaml +auth_enabled: false + +# This is a complete configuration to deploy Loki backed by the filesystem. +# The index will be shipped to the storage via tsdb-shipper. +server: + http_listen_port: 3100 + +common: + ring: + instance_addr: 127.0.0.1 + kvstore: + store: inmemory + replication_factor: 1 + path_prefix: /tmp/loki + +schema_config: + configs: + - from: 2020-05-15 + store: tsdb + object_store: filesystem + schema: v13 + index: + prefix: index_ + period: 24h + +storage_config: + filesystem: + directory: /tmp/loki/chunks + +# https://grafana.com/docs/loki/latest/send-data/otel/ +# https://grafana.com/docs/loki/latest/send-data/otel/#changing-the-default-mapping-of-otlp-to-loki-format +limits_config: + # this attribute should be `true` when we use `otlphttp/loki`, but if we want to use `loki component` from `opentelemetry-collector-contrib` it should be false. + allow_structured_metadata: true + diff --git a/deployments/configs/otel-collector-config.yaml b/deployments/configs/otel-collector-config.yaml new file mode 100644 index 00000000..ea6ef405 --- /dev/null +++ b/deployments/configs/otel-collector-config.yaml @@ -0,0 +1,131 @@ +# ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/examples/demo/otel-collector-config.yaml +# https://opentelemetry.io/docs/collector/configuration/ +# https://opentelemetry.io/docs/collector/architecture/ +# https://betterstack.com/community/guides/observability/opentelemetry-collector/ +# https://signoz.io/blog/opentelemetry-collector-complete-guide/ + +# This configuration sets up an OpenTelemetry Collector that receives trace data via the OTLP protocol over HTTP on port 4318, applies batch processing, and then exports the processed traces +# to exporter components like `Jaeger` endpoint located at `jaeger-all-in-one:4317`. It also includes a health_check extension for monitoring the collector's status. + +# Receivers in the OpenTelemetry Collector are components that collect telemetry data (traces, metrics, and logs) from various sources, such as instrumented applications or agents. +# They act as entry points, converting incoming data into OpenTelemetry's internal format for processing and export. +# https://betterstack.com/community/guides/observability/opentelemetry-collector/#exploring-the-opentelemetry-collector-components +# https://opentelemetry.io/docs/collector/architecture/#receivers +# https://github.com/open-telemetry/opentelemetry-collector/blob/main/receiver/README.md +# https://opentelemetry.io/docs/collector/configuration/#receivers +receivers: + # supported receivers + # https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver + # instead of specifying details explicitly we can just use `otlp` and it uses both grpc and http + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 +# prometheus: +# config: +# scrape_configs: +# - job_name: 'node-exporter' +# scrape_interval: 10s +# static_configs: +# - targets: [ 'node-exporter:9100' ] + + +# Processors in the OpenTelemetry Collector modify and enhance telemetry data by filtering, transforming, enriching, or batching it to prepare it for export. +# https://github.com/open-telemetry/opentelemetry-collector/tree/main/processor +processors: + batch: # Batches logs for better performance + +# - Exporters in the OpenTelemetry Collector send processed telemetry data to backend systems like observability platforms, databases, or cloud services for storage, visualization, and analysis. +# - The `key` follows the `type/name` format, where `type` specifies the exporter `type` (e.g., otlp, kafka, prometheus), and `name` (optional) can be appended to provide a unique name for multiple instance of the same type +# https://betterstack.com/community/guides/observability/opentelemetry-collector/#exploring-the-opentelemetry-collector-components +# https://opentelemetry.io/docs/collector/architecture/#exporters +# https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter +# https://github.com/open-telemetry/opentelemetry-collector/tree/main/exporter +# https://opentelemetry.io/docs/collector/configuration/#exporters +exporters: + + # valid values: [prometheusremotewrite zipkin otlphttp file kafka prometheus debug nop otlp opencensus] + + # Prometheus exporter metrics + prometheus: + endpoint: "0.0.0.0:8889" + + prometheusremotewrite: + endpoint: "http://prometheus:9090/api/v1/write" + + # https://grafana.com/docs/loki/latest/send-data/otel/ + # https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/exporter/lokiexporter/README.md + otlphttp/loki: + endpoint: "http://loki:3100/otlp" + tls: + insecure: true + + # # we can also use `loki component` from `opentelemetry-collector-contrib` if we don't want to use builtin `otlphttp` exporter type and `http://loki:3100/otlp` loki endpoint + # loki: + # endpoint: "http://loki:3100/loki/api/v1/push" + # tls: + # insecure: true + + debug: + + # https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/elasticsearchexporter + # using `elasticsearch` from `opentelemetry-collector-contrib` components because it doesn't exist in `opentelemetry-collector` + elasticsearch: + endpoint: "http://elasticsearch:9200" + + zipkin: + endpoint: "http://zipkin-all-in-one:9411/api/v2/spans" + format: proto + + # export collected telemetry traces to jaeger OTLP grpc port, we can send data to other available endpoints and ports on jaeger as well + otlp/jaeger: + endpoint: "http://jaeger-all-in-one:4317" + tls: + insecure: true + + otlp/tempo: + endpoint: "http://tempo:4317" + tls: + insecure: true + + # seq-otlp: + # endpoint: "http://seq:5341/ingest/otlp" + +# https://opentelemetry.io/docs/collector/configuration/#extensions +# https://github.com/open-telemetry/opentelemetry-collector/blob/main/extension/README.md +extensions: + pprof: + endpoint: 0.0.0.0:1888 + zpages: + endpoint: 0.0.0.0:55679 + health_check: + endpoint: 0.0.0.0:13133 + +# - The service section is used to configure what components are enabled in the Collector based on the configuration found in the receivers, processors, exporters, and extensions sections. +# - If a component is configured, but not defined within the service section, then it’s not enabled. +# https://betterstack.com/community/guides/observability/opentelemetry-collector/#exploring-the-opentelemetry-collector-components +# https://github.com/open-telemetry/opentelemetry-collector/blob/main/exporter/README.md +# https://opentelemetry.io/docs/collector/architecture/ +# https://opentelemetry.io/docs/collector/configuration/#service +service: + # The `service.extensions` subsection determines which of the configured extensions will be enabled + extensions: [pprof, zpages, health_check] + # The `service.pipeline` Each pipeline starts with one or more receivers collecting data, which is then processed sequentially by processors (applying transformations, filtering, or sampling). + # The processed data is finally sent to all configured exporters, ensuring each receives a copy. Components must be pre-configured in their respective sections before being used in a pipeline. + # pipeline activate predefined components, defined components are disabled by default + pipelines: + traces: + receivers: [otlp] + processors: [batch] + # https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#exporter-selection + exporters: [debug, zipkin, otlp/jaeger, otlp/tempo] + metrics: + receivers: [otlp] + processors: [batch] + exporters: [debug, prometheusremotewrite, prometheus] + logs: + receivers: [otlp] + processors: [batch] + exporters: [otlphttp/loki, elasticsearch] \ No newline at end of file diff --git a/deployments/configs/prometheus.yaml b/deployments/configs/prometheus.yaml new file mode 100644 index 00000000..1928aafd --- /dev/null +++ b/deployments/configs/prometheus.yaml @@ -0,0 +1,48 @@ +# ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/examples/demo/prometheus.yaml +# https://prometheus.io/docs/introduction/first_steps/ +# https://grafana.com/docs/grafana-cloud/send-data/metrics/metrics-prometheus/prometheus-config-examples/docker-compose-linux/ + +global: + scrape_interval: 5s + +scrape_configs: + # when we use otel-collector we should comment other jobs in prometheus config, and we read configs from `otel-collector-config` + - job_name: "otel-collector" + scrape_interval: 10s + static_configs: + # otel-collector Prometheus exporter metrics + - targets: [ 'otel-collector:8889' ] + - targets: [ 'otel-collector:8888' ] + + - job_name: "prometheus" + static_configs: + - targets: ["prometheus:9090"] + +# # https://prometheus.io/docs/guides/node-exporter/ +# # https://grafana.com/docs/grafana-cloud/send-data/metrics/metrics-prometheus/prometheus-config-examples/docker-compose-linux/ +# - job_name: "node-exporter" +# static_configs: +# - targets: [ 'node-exporter:9100' ] + +# # if we don't use otel collector we should uncomment this +# # scrap application metrics +# # http://localhost:4000/metrics by AddPrometheusExporter() +# - job_name: vertical-slice-template-api +# scrape_interval: 10s +# metrics_path: /metrics +# static_configs: +# - targets: ['host.docker.internal:4000'] +# +# # if we don't use otel collector we should uncomment this +# # scrap application health metrics +# # http://localhost:4000/health/metrics by AddPrometheusExporter() +# - job_name: vertical-slice-template-api-healthchecks +# scrape_interval: 10s +# metrics_path: /health/metrics +# static_configs: +# - targets: ['host.docker.internal:4000'] + +## https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/prometheus.yaml +# - job_name: 'tempo' +# static_configs: +# - targets: [ 'tempo:3200' ] \ No newline at end of file diff --git a/deployments/configs/tempo.yaml b/deployments/configs/tempo.yaml new file mode 100644 index 00000000..fcb2ed38 --- /dev/null +++ b/deployments/configs/tempo.yaml @@ -0,0 +1,49 @@ +# https://grafana.com/docs/tempo/latest/configuration/ +# https://github.com/grafana/tempo/blob/main/example/docker-compose/local/tempo.yaml + +# https://github.com/grafana/tempo/blob/main/example/docker-compose/shared/tempo.yaml +stream_over_http_enabled: true +server: + http_listen_port: 3200 + log_level: info + +distributor: + receivers: + otlp: + protocols: + grpc: + endpoint: "tempo:4317" + +ingester: + max_block_duration: 5m # cut the headblock when this much time passes. this is being set for demo purposes and should probably be left alone normally + +compactor: + compaction: + block_retention: 1h # overall Tempo trace retention. set for demo purposes + +metrics_generator: + registry: + external_labels: + source: tempo + cluster: docker-compose + storage: + path: /var/tempo/generator/wal + remote_write: + - url: http://prometheus:9090/api/v1/write + send_exemplars: true + traces_storage: + path: /var/tempo/generator/traces + +storage: + trace: + backend: local # backend configuration to use + wal: + path: /var/tempo/wal # where to store the wal locally + local: + path: /var/tempo/blocks + +overrides: + defaults: + metrics_generator: + processors: [service-graphs, span-metrics, local-blocks] # enables metrics generator + generate_native_histograms: both \ No newline at end of file diff --git a/deployments/docker-compose/docker-compose.infrastructure.yaml b/deployments/docker-compose/docker-compose.infrastructure.yaml new file mode 100644 index 00000000..630517ea --- /dev/null +++ b/deployments/docker-compose/docker-compose.infrastructure.yaml @@ -0,0 +1,362 @@ +# ref: https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/examples/demo/docker-compose.yaml +# ref: https://github.com/joaofbantunes/DotNetMicroservicesObservabilitySample/blob/main/docker-compose.yml +# ref: https://github.com/oskardudycz/EventSourcing.NetCore/blob/main/docker-compose.yml +# https://github.com/grafana/intro-to-mltp +# https://stackoverflow.com/questions/65272764/ports-are-not-available-listen-tcp-0-0-0-0-50070-bind-an-attempt-was-made-to + + +name: booking-microservices + +services: + ####################################################### + # rabbitmq + ####################################################### + rabbitmq: + image: rabbitmq:management + container_name: rabbitmq + restart: unless-stopped + ports: + - "5672:5672" + - "15672:15672" + # volumes: + # - rabbitmq:/var/lib/rabbitmq + networks: + - infrastructure + + ####################################################### + # postgres + ####################################################### + postgres: + image: postgres:latest + container_name: postgres + restart: unless-stopped + ports: + - '5432:5432' + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + command: + - "postgres" + - "-c" + - "wal_level=logical" + - "-c" + - "max_prepared_transactions=10" + volumes: + - postgres-data:/var/lib/postgresql/data + networks: + - infrastructure + + + ####################################################### + # EventStoreDB + ####################################################### + eventstore: + container_name: eventstore + image: eventstore/eventstore:latest + restart: unless-stopped + environment: + - EVENTSTORE_CLUSTER_SIZE=1 + - EVENTSTORE_RUN_PROJECTIONS=All + - EVENTSTORE_START_STANDARD_PROJECTIONS=True + - EVENTSTORE_HTTP_PORT=2113 + - EVENTSTORE_INSECURE=True + - EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=True + ports: + - "2113:2113" + networks: + - infrastructure + + + ####################################################### + # Mongo + ####################################################### + mongo: + image: mongo:latest + container_name: mongo + restart: unless-stopped + # environment: + # - MONGO_INITDB_ROOT_USERNAME=root + # - MONGO_INITDB_ROOT_PASSWORD=secret + ports: + - 27017:27017 + networks: + - infrastructure + + + ####################################################### + # Redis + ####################################################### + redis: + image: redis + container_name: redis + restart: unless-stopped + ports: + - 6379:6379 + networks: + - infrastructure + + + ####################################################### + # jaeger + # https://www.jaegertracing.io/docs/1.64/deployment/ + # https://www.jaegertracing.io/docs/1.6/deployment/ + ####################################################### + jaeger-all-in-one: + image: jaegertracing/all-in-one:latest + container_name: jaeger-all-in-one + restart: unless-stopped + ports: + - "6831:6831/udp" # UDP port for Jaeger agent + - "16686:16686" # endpoints and Jaeger UI + - "14268:14268" # HTTP port for accept trace spans directly from clients + - "14317:4317" # OTLP gRPC receiver for jaeger + - "14318:4318" # OTLP http receiver for jaeger + # - "9411" # Accepts Zipkin spans - /api/v2/spans + networks: + - infrastructure + + + ####################################################### + # zipkin + # https://zipkin.io/pages/quickstart + ####################################################### + zipkin-all-in-one: + image: openzipkin/zipkin:latest + container_name: zipkin-all-in-one + restart: unless-stopped + ports: + - "9411:9411" + networks: + - infrastructure + + + ####################################################### + # otel-collector + # https://opentelemetry.io/docs/collector/installation/ + # https://github.com/open-telemetry/opentelemetry-collector + # https://github.com/open-telemetry/opentelemetry-collector-contrib + # we can use none contrib docker `otel/opentelemetry-collector` version from `https://github.com/open-telemetry/opentelemetry-collector` repository but, + # if we need more components like `elasticsearch` we should use `otel/opentelemetry-collector-contrib` image of `https://github.com/open-telemetry/opentelemetry-collector-contrib` repository. + ####################################################### + otel-collector: + image: otel/opentelemetry-collector-contrib:latest + container_name: otel-collector + restart: unless-stopped + command: ["--config=/etc/otelcol-contrib/config.yaml"] + volumes: + - ./../configs/otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml + ports: + - "11888:1888" # pprof extension + - "8888:8888" # Prometheus metrics exposed by the Collector + - "8889:8889" # Prometheus exporter metrics + - "13133:13133" # health_check extension + - "4317:4317" # OTLP gRPC receiver + - "4318:4318" # OTLP http receiver + - "55679:55679" # zpages extension + networks: + - infrastructure + + + ####################################################### + # prometheus + # https://prometheus.io/docs/introduction/first_steps/ + # https://prometheus.io/docs/prometheus/3.1/installation/ + # https://grafana.com/docs/grafana-cloud/send-data/metrics/metrics-prometheus/prometheus-config-examples/docker-compose-linux/ + ####################################################### + prometheus: + image: prom/prometheus:latest + restart: unless-stopped + ports: + - "9090:9090" + volumes: + - ./../configs/prometheus.yaml:/etc/prometheus/prometheus.yml + # to passe one flag, such as "--log.level=debug" or "--web.enable-remote-write-receiver", we need to override the whole command, as we can't just pass one extra argument + command: + - "--config.file=/etc/prometheus/prometheus.yml" + - "--storage.tsdb.path=/prometheus" + - "--web.console.libraries=/usr/share/prometheus/console_libraries" + - "--web.console.templates=/usr/share/prometheus/consoles" + # need this for the OpenTelemetry collector to be able to put metrics into Prometheus + - "--web.enable-remote-write-receiver" + # - "--log.level=debug" + networks: + - infrastructure + + + ####################################################### + # node-exporter + # https://prometheus.io/docs/guides/node-exporter/ + # https://grafana.com/docs/grafana-cloud/send-data/metrics/metrics-prometheus/prometheus-config-examples/docker-compose-linux/ + ####################################################### + node-exporter: + image: prom/node-exporter:latest + container_name: node-exporter + restart: unless-stopped + volumes: + - /proc:/host/proc:ro + - /sys:/host/sys:ro + - /:/rootfs:ro + command: + - '--path.procfs=/host/proc' + - '--path.rootfs=/rootfs' + - '--path.sysfs=/host/sys' + ports: + - "9101:9100" + networks: + - infrastructure + + + ####################################################### + # grafana + # https://grafana.com/docs/grafana/latest/administration/provisioning/ + # https://grafana.com/docs/grafana/latest/setup-grafana/installation/docker/ + # https://grafana.com/docs/grafana/latest/setup-grafana/configure-docker/ + # https://github.com/grafana/intro-to-mltp/blob/main/grafana/provisioning/datasources/datasources.yaml + ####################################################### + grafana: + image: grafana/grafana:latest + container_name: grafana + restart: unless-stopped + environment: + - GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource + - GF_SECURITY_ADMIN_USER=admin + - GF_SECURITY_ADMIN_PASSWORD=admin + - GF_FEATURE_TOGGLES_ENABLE=traceqlEditor + # - GF_AUTH_ANONYMOUS_ENABLED=true + # - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin + # - GF_AUTH_DISABLE_LOGIN_FORM=true + depends_on: + - prometheus + ports: + - "3000:3000" + volumes: + - ./../configs/grafana/provisioning:/etc/grafana/provisioning + - ./../configs/grafana/dashboards:/var/lib/grafana/dashboards + ## https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/ + # - ./../configs/grafana/grafana.ini:/etc/grafana/grafana.ini + networks: + - infrastructure + + + ####################################################### + # tempo + # https://github.com/grafana/tempo/blob/main/example/docker-compose/otel-collector/docker-compose.yaml + # https://github.com/grafana/tempo/blob/main/example/docker-compose/shared + # https://github.com/grafana/tempo/blob/main/example/docker-compose/local + # https://github.com/grafana/tempo/tree/main/example/docker-compose + ####################################################### + tempo: + image: grafana/tempo:latest + container_name: tempo + restart: unless-stopped + command: [ "-config.file=/etc/tempo.yaml" ] + volumes: + - ./../configs/tempo.yaml:/etc/tempo.yaml + ports: + - "3200" # tempo + - "24317:4317" # otlp grpc + - "24318:4318" # otlp http + networks: + - infrastructure + + + ####################################################### + # loki + # https://grafana.com/docs/opentelemetry/collector/send-logs-to-loki/ + # https://github.com/grafana/loki/blob/main/production/docker-compose.yaml + # https://github.com/grafana/loki/blob/main/examples/getting-started/docker-compose.yaml + ####################################################### + loki: + image: grafana/loki:latest + hostname: loki + container_name: loki + ports: + - "3100:3100" + command: -config.file=/etc/loki/local-config.yaml + volumes: + - ./../configs/loki-config.yaml:/etc/loki/local-config.yaml + networks: + - infrastructure + + + ####################################################### + # elasticsearch + # https://www.elastic.co/guide/en/elasticsearch/reference/7.17/docker.html#docker-compose-file + ####################################################### + elasticsearch: + container_name: elasticsearch + restart: unless-stopped + image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0 + environment: + - discovery.type=single-node + - cluster.name=docker-cluster + - node.name=docker-node + - "ES_JAVA_OPTS=-Xms512m -Xmx512m" + - xpack.security.enabled=false + - xpack.security.http.ssl.enabled=false + - xpack.security.transport.ssl.enabled=false + - network.host=0.0.0.0 + - http.port=9200 + - transport.host=localhost + - bootstrap.memory_lock=true + - cluster.routing.allocation.disk.threshold_enabled=false + ulimits: + memlock: + soft: -1 + hard: -1 + volumes: + - elastic-data:/usr/share/elasticsearch/data + ports: + - ${ELASTIC_HOST_PORT:-9200}:${ELASTIC_PORT:-9200} + - 9300:9300 + networks: + - infrastructure + + + ####################################################### + # kibana + # https://www.elastic.co/guide/en/kibana/current/docker.html + ####################################################### + kibana: + image: docker.elastic.co/kibana/kibana:8.17.0 + container_name: kibana + restart: unless-stopped + environment: + - ELASTICSEARCH_HOSTS=http://elasticsearch:9200 + ports: + - ${KIBANA_HOST_PORT:-5601}:${KIBANA_PORT:-5601} + depends_on: + - elasticsearch + networks: + - infrastructure + + + ####################################################### + # cadvisor + ####################################################### + cadvisor: + image: gcr.io/cadvisor/cadvisor:latest + container_name: cadvisor + restart: unless-stopped + ports: + - "8080:8080" + volumes: + - /:/rootfs:ro + - /var/run:/var/run:ro + - /sys:/sys:ro + - /var/lib/docker/:/var/lib/docker:ro + - /dev/disk/:/dev/disk:ro + devices: + - /dev/kmsg + networks: + - infrastructure + + +networks: + infrastructure: + name: infrastructure + driver: bridge + +volumes: + elastic-data: + postgres-data: \ No newline at end of file diff --git a/deployments/docker-compose/docker-compose.yaml b/deployments/docker-compose/docker-compose.yaml index e6ee7f73..4c288dde 100644 --- a/deployments/docker-compose/docker-compose.yaml +++ b/deployments/docker-compose/docker-compose.yaml @@ -1,79 +1,49 @@ -version: "3.3" -services: - - ####################################################### - # Postgres - ###################################################### - postgres: - image: postgres:latest - container_name: postgres - restart: unless-stopped - ports: - - '5432:5432' - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - command: - - "postgres" - - "-c" - - "wal_level=logical" - - "-c" - - "max_prepared_transactions=10" - networks: - - booking - - - - ####################################################### - # SqlServer - ####################################################### - # sql: - # container_name: sql - # image: mcr.microsoft.com/mssql/server - # restart: unless-stopped - # ports: - # - "1433:1433" - # environment: - # SA_PASSWORD: "Password@1234" - # ACCEPT_EULA: "Y" +name: booking-microservices +services: - ####################################################### - # Rabbitmq - ####################################################### + ####################################################### + # rabbitmq + ####################################################### rabbitmq: - container_name: rabbitmq image: rabbitmq:management + container_name: rabbitmq restart: unless-stopped ports: - - 5672:5672 - - 15672:15672 + - "5672:5672" + - "15672:15672" + # volumes: + # - rabbitmq:/var/lib/rabbitmq networks: - booking - - ####################################################### - # Jaeger - ####################################################### - jaeger: - image: jaegertracing/all-in-one - container_name: jaeger + ####################################################### + # postgres + ####################################################### + postgres: + image: postgres:latest + container_name: postgres restart: unless-stopped + ports: + - '5432:5432' + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + command: + - "postgres" + - "-c" + - "wal_level=logical" + - "-c" + - "max_prepared_transactions=10" + volumes: + - postgres-data:/var/lib/postgresql/data networks: - booking - ports: - - 5775:5775/udp - - 5778:5778 - - 6831:6831/udp - - 6832:6832/udp - - 9411:9411 - - 14268:14268 - - 16686:16686 - ####################################################### - # EventStoreDB - ####################################################### + ####################################################### + # EventStoreDB + ####################################################### eventstore: container_name: eventstore image: eventstore/eventstore:latest @@ -88,12 +58,12 @@ services: ports: - "2113:2113" networks: - - booking + - booking - ####################################################### - # Mongo - ####################################################### + ####################################################### + # Mongo + ####################################################### mongo: image: mongo:latest container_name: mongo @@ -101,93 +71,260 @@ services: # environment: # - MONGO_INITDB_ROOT_USERNAME=root # - MONGO_INITDB_ROOT_PASSWORD=secret + ports: + - 27017:27017 networks: - booking + + + ####################################################### + # Redis + ####################################################### + redis: + image: redis + container_name: redis + restart: unless-stopped ports: - - 27017:27017 + - 6379:6379 + networks: + - booking - ####################################################### - # Elastic Search - ####################################################### - elasticsearch: - container_name: elasticsearch - image: elasticsearch:7.17.9 + + ####################################################### + # jaeger + # https://www.jaegertracing.io/docs/1.64/deployment/ + # https://www.jaegertracing.io/docs/1.6/deployment/ + ####################################################### + jaeger-all-in-one: + image: jaegertracing/all-in-one:latest + container_name: jaeger-all-in-one restart: unless-stopped ports: - - 9200:9200 - volumes: - - elasticsearch-data:/usr/share/elasticsearch/data - environment: - - xpack.monitoring.enabled=true - - xpack.watcher.enabled=false - - "ES_JAVA_OPTS=-Xms512m -Xmx512m" - - discovery.type=single-node + - "6831:6831/udp" # UDP port for Jaeger agent + - "16686:16686" # endpoints and Jaeger UI + - "14268:14268" # HTTP port for accept trace spans directly from clients + - "14317:4317" # OTLP gRPC receiver for jaeger + - "14318:4318" # OTLP http receiver for jaeger + # - "9411" # Accepts Zipkin spans - /api/v2/spans networks: - booking - ####################################################### - # Kibana - ####################################################### - kibana: - container_name: kibana - image: kibana:7.17.9 + + ####################################################### + # zipkin + # https://zipkin.io/pages/quickstart + ####################################################### + zipkin-all-in-one: + image: openzipkin/zipkin:latest + container_name: zipkin-all-in-one restart: unless-stopped ports: - - 5601:5601 - depends_on: - - elasticsearch - environment: - - ELASTICSEARCH_URL=elasticsearch:9200 + - "9411:9411" networks: - booking - ####################################################### - # prometheus - ####################################################### + + ####################################################### + # otel-collector + # https://opentelemetry.io/docs/collector/installation/ + # https://github.com/open-telemetry/opentelemetry-collector + # https://github.com/open-telemetry/opentelemetry-collector-contrib + # we can use none contrib docker `otel/opentelemetry-collector` version from `https://github.com/open-telemetry/opentelemetry-collector` repository but, + # if we need more components like `elasticsearch` we should use `otel/opentelemetry-collector-contrib` image of `https://github.com/open-telemetry/opentelemetry-collector-contrib` repository. + ####################################################### + otel-collector: + image: otel/opentelemetry-collector-contrib:latest + container_name: otel-collector + restart: unless-stopped + command: ["--config=/etc/otelcol-contrib/config.yaml"] + volumes: + - ./../configs/otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml + ports: + - "11888:1888" # pprof extension + - "8888:8888" # Prometheus metrics exposed by the Collector + - "8889:8889" # Prometheus exporter metrics + - "13133:13133" # health_check extension + - "4317:4317" # OTLP gRPC receiver + - "4318:4318" # OTLP http receiver + - "55679:55679" # zpages extension + networks: + - booking + + + ####################################################### + # prometheus + # https://prometheus.io/docs/introduction/first_steps/ + # https://prometheus.io/docs/prometheus/3.1/installation/ + # https://grafana.com/docs/grafana-cloud/send-data/metrics/metrics-prometheus/prometheus-config-examples/docker-compose-linux/ + ####################################################### prometheus: image: prom/prometheus:latest - container_name: prometheus restart: unless-stopped ports: - "9090:9090" - environment: - - TZ=UTC volumes: - - ./monitoring/prom/prometheus.yml:/etc/prometheus/prometheus.yml + - ./../configs/prometheus.yaml:/etc/prometheus/prometheus.yml + # to passe one flag, such as "--log.level=debug" or "--web.enable-remote-write-receiver", we need to override the whole command, as we can't just pass one extra argument + command: + - "--config.file=/etc/prometheus/prometheus.yml" + - "--storage.tsdb.path=/prometheus" + - "--web.console.libraries=/usr/share/prometheus/console_libraries" + - "--web.console.templates=/usr/share/prometheus/consoles" + # need this for the OpenTelemetry collector to be able to put metrics into Prometheus + - "--web.enable-remote-write-receiver" + # - "--log.level=debug" networks: - booking - ####################################################### - # grafana - ####################################################### + + ####################################################### + # node-exporter + # https://prometheus.io/docs/guides/node-exporter/ + # https://grafana.com/docs/grafana-cloud/send-data/metrics/metrics-prometheus/prometheus-config-examples/docker-compose-linux/ + ####################################################### + node-exporter: + image: prom/node-exporter:latest + container_name: node-exporter + restart: unless-stopped + volumes: + - /proc:/host/proc:ro + - /sys:/host/sys:ro + - /:/rootfs:ro + command: + - '--path.procfs=/host/proc' + - '--path.rootfs=/rootfs' + - '--path.sysfs=/host/sys' + ports: + - "9101:9100" + networks: + - booking + + + ####################################################### + # grafana + # https://grafana.com/docs/grafana/latest/administration/provisioning/ + # https://grafana.com/docs/grafana/latest/setup-grafana/installation/docker/ + # https://grafana.com/docs/grafana/latest/setup-grafana/configure-docker/ + # https://github.com/grafana/intro-to-mltp/blob/main/grafana/provisioning/datasources/datasources.yaml + ####################################################### grafana: - image: grafana/grafana + image: grafana/grafana:latest container_name: grafana restart: unless-stopped + environment: + - GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource + - GF_SECURITY_ADMIN_USER=admin + - GF_SECURITY_ADMIN_PASSWORD=admin + - GF_FEATURE_TOGGLES_ENABLE=traceqlEditor + # - GF_AUTH_ANONYMOUS_ENABLED=true + # - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin + # - GF_AUTH_DISABLE_LOGIN_FORM=true + depends_on: + - prometheus ports: - "3000:3000" volumes: - - ./monitoring/grafana-data/data:/var/lib/grafana + - ./../configs/grafana/provisioning:/etc/grafana/provisioning + - ./../configs/grafana/dashboards:/var/lib/grafana/dashboards + ## https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/ + # - ./../configs/grafana/grafana.ini:/etc/grafana/grafana.ini networks: - booking - ####################################################### - # node_exporter - ####################################################### - node_exporter: - image: quay.io/prometheus/node-exporter:latest - container_name: node_exporter + + ####################################################### + # tempo + # https://github.com/grafana/tempo/blob/main/example/docker-compose/otel-collector/docker-compose.yaml + # https://github.com/grafana/tempo/blob/main/example/docker-compose/shared + # https://github.com/grafana/tempo/blob/main/example/docker-compose/local + # https://github.com/grafana/tempo/tree/main/example/docker-compose + ####################################################### + tempo: + image: grafana/tempo:latest + container_name: tempo restart: unless-stopped - command: - - '--path.rootfs=/host' - pid: host + command: [ "-config.file=/etc/tempo.yaml" ] volumes: - - /proc:/host/proc:ro - - /sys:/host/sys:ro - - /:/rootfs:ro + - ./../configs/tempo.yaml:/etc/tempo.yaml + ports: + - "3200" # tempo + - "24317:4317" # otlp grpc + - "24318:4318" # otlp http + networks: + - booking + + + ####################################################### + # loki + # https://grafana.com/docs/opentelemetry/collector/send-logs-to-loki/ + # https://github.com/grafana/loki/blob/main/production/docker-compose.yaml + # https://github.com/grafana/loki/blob/main/examples/getting-started/docker-compose.yaml + ####################################################### + loki: + image: grafana/loki:latest + hostname: loki + container_name: loki + ports: + - "3100:3100" + command: -config.file=/etc/loki/local-config.yaml + volumes: + - ./../configs/loki-config.yaml:/etc/loki/local-config.yaml networks: - booking + + + ####################################################### + # elasticsearch + # https://www.elastic.co/guide/en/elasticsearch/reference/7.17/docker.html#docker-compose-file + ####################################################### + elasticsearch: + container_name: elasticsearch + restart: unless-stopped + image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0 + environment: + - discovery.type=single-node + - cluster.name=docker-cluster + - node.name=docker-node + - "ES_JAVA_OPTS=-Xms512m -Xmx512m" + - xpack.security.enabled=false + - xpack.security.http.ssl.enabled=false + - xpack.security.transport.ssl.enabled=false + - network.host=0.0.0.0 + - http.port=9200 + - transport.host=localhost + - bootstrap.memory_lock=true + - cluster.routing.allocation.disk.threshold_enabled=false + ulimits: + memlock: + soft: -1 + hard: -1 + volumes: + - elastic-data:/usr/share/elasticsearch/data + ports: + - ${ELASTIC_HOST_PORT:-9200}:${ELASTIC_PORT:-9200} + - 9300:9300 + networks: + - booking + + ####################################################### + # kibana + # https://www.elastic.co/guide/en/kibana/current/docker.html + ####################################################### + kibana: + image: docker.elastic.co/kibana/kibana:8.17.0 + container_name: kibana + restart: unless-stopped + environment: + - ELASTICSEARCH_HOSTS=http://elasticsearch:9200 + ports: + - ${KIBANA_HOST_PORT:-5601}:${KIBANA_PORT:-5601} + depends_on: + - elasticsearch + networks: + - booking + + ####################################################### # cadvisor ####################################################### @@ -208,6 +345,7 @@ services: networks: - booking + ###################################################### # Gateway ###################################################### @@ -344,9 +482,11 @@ services: networks: booking: - + name: booking + driver: bridge + volumes: - elasticsearch-data: - + elastic-data: + postgres-data: diff --git a/deployments/docker-compose/infrastructure.yaml b/deployments/docker-compose/infrastructure.yaml deleted file mode 100644 index 9a17a5b3..00000000 --- a/deployments/docker-compose/infrastructure.yaml +++ /dev/null @@ -1,234 +0,0 @@ -version: "3.3" -services: - - ####################################################### - # Rabbitmq - ####################################################### - rabbitmq: - container_name: rabbitmq - image: rabbitmq:management - restart: unless-stopped - ports: - - 5672:5672 - - 15672:15672 - networks: - - booking - - - ####################################################### - # Postgres - ###################################################### - postgres: - image: postgres:latest - container_name: postgres - restart: unless-stopped - ports: - - '5432:5432' - environment: - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - command: - - "postgres" - - "-c" - - "wal_level=logical" - - "-c" - - "max_prepared_transactions=10" - networks: - - booking - - - ####################################################### - # SqlServer - ####################################################### - # sql: - # container_name: sql - # image: mcr.microsoft.com/mssql/server - # restart: unless-stopped - # ports: - # - "1433:1433" - # environment: - # SA_PASSWORD: "Password@1234" - # ACCEPT_EULA: "Y" - - - ####################################################### - # Jaeger - ####################################################### - jaeger: - container_name: jaeger - image: jaegertracing/all-in-one - restart: unless-stopped - networks: - - booking - ports: - - 5775:5775/udp - - 5778:5778 - - 6831:6831/udp - - 6832:6832/udp - - 9411:9411 - - 14268:14268 - - 16686:16686 - - - # ####################################################### - # # EventStoreDB - # ####################################################### - # #https://stackoverflow.com/questions/65272764/ports-are-not-available-listen-tcp-0-0-0-0-50070-bind-an-attempt-was-made-to - - eventstore: - container_name: eventstore - image: eventstore/eventstore:latest - restart: unless-stopped - environment: - - EVENTSTORE_CLUSTER_SIZE=1 - - EVENTSTORE_RUN_PROJECTIONS=All - - EVENTSTORE_START_STANDARD_PROJECTIONS=True - - EVENTSTORE_HTTP_PORT=2113 - - EVENTSTORE_INSECURE=True - - EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP=True - ports: - - "2113:2113" - networks: - - booking - - - ####################################################### - # Mongo - ####################################################### - mongo: - image: mongo:latest - container_name: mongo - restart: unless-stopped - # environment: - # - MONGO_INITDB_ROOT_USERNAME=root - # - MONGO_INITDB_ROOT_PASSWORD=secret - networks: - - booking - ports: - - 27017:27017 - - - ####################################################### - # Elastic Search - ####################################################### - elasticsearch: - container_name: elasticsearch - image: elasticsearch:7.17.9 - restart: unless-stopped - ports: - - 9200:9200 - volumes: - - elasticsearch-data:/usr/share/elasticsearch/data - environment: - - xpack.monitoring.enabled=true - - xpack.watcher.enabled=false - - "ES_JAVA_OPTS=-Xms512m -Xmx512m" - - discovery.type=single-node - networks: - - booking - - ####################################################### - # Kibana - ####################################################### - kibana: - container_name: kibana - image: kibana:7.17.9 - restart: unless-stopped - ports: - - 5601:5601 - depends_on: - - elasticsearch - environment: - - ELASTICSEARCH_URL=http://localhost:9200 - networks: - - booking - - ####################################################### - # Redis - ####################################################### - redis: - image: redis - container_name: redis - restart: unless-stopped - networks: - - booking - ports: - - 6379:6379 - - ####################################################### - # prometheus - ####################################################### - prometheus: - image: prom/prometheus:latest - container_name: prometheus - restart: unless-stopped - ports: - - "9090:9090" - environment: - - TZ=UTC - volumes: - - ./monitoring/prom/prometheus.yml:/etc/prometheus/prometheus.yml - networks: - - booking - - ####################################################### - # grafana - ####################################################### - grafana: - image: grafana/grafana - container_name: grafana - restart: unless-stopped - ports: - - "3000:3000" - volumes: - - ./monitoring/grafana-data/data:/var/lib/grafana - networks: - - booking - - ####################################################### - # node_exporter - ####################################################### - node_exporter: - image: quay.io/prometheus/node-exporter:latest - container_name: node_exporter - restart: unless-stopped - command: - - '--path.rootfs=/host' - pid: host - volumes: - - /proc:/host/proc:ro - - /sys:/host/sys:ro - - /:/rootfs:ro - networks: - - booking - - ####################################################### - # cadvisor - ####################################################### - cadvisor: - image: gcr.io/cadvisor/cadvisor:latest - container_name: cadvisor - restart: unless-stopped - ports: - - "8080:8080" - volumes: - - /:/rootfs:ro - - /var/run:/var/run:ro - - /sys:/sys:ro - - /var/lib/docker/:/var/lib/docker:ro - - /dev/disk/:/dev/disk:ro - devices: - - /dev/kmsg - networks: - - booking - - -networks: - booking: - -volumes: - elasticsearch-data: - - - - diff --git a/deployments/docker-compose/monitoring/prom/prometheus.yml b/deployments/docker-compose/monitoring/prom/prometheus.yml deleted file mode 100644 index 6aaff5bf..00000000 --- a/deployments/docker-compose/monitoring/prom/prometheus.yml +++ /dev/null @@ -1,69 +0,0 @@ -global: - scrape_interval: 15s - scrape_timeout: 10s - evaluation_interval: 15s -alerting: - alertmanagers: - - scheme: http - timeout: 10s - api_version: v1 - static_configs: - - targets: [] -scrape_configs: -- job_name: prometheus - honor_timestamps: true - scrape_interval: 15s - scrape_timeout: 10s - metrics_path: /metrics - scheme: http - static_configs: - - targets: - - localhost:9090 -- job_name: cadvisor - static_configs: - - targets: - - cadvisor:8080 -- job_name: node_exporter - static_configs: - - targets: - - node_exporter:9100 -- job_name: flight - scrape_interval: 15s - scrape_timeout: 10s - metrics_path: /metrics - scheme: http - static_configs: - - targets: - - host.docker.internal:5004 -- job_name: identity - scrape_interval: 15s - scrape_timeout: 10s - metrics_path: /metrics - scheme: http - static_configs: - - targets: - - host.docker.internal:6005 -- job_name: passenger - scrape_interval: 15s - scrape_timeout: 10s - metrics_path: /metrics - scheme: http - static_configs: - - targets: - - host.docker.internal:6012 -- job_name: booking - scrape_interval: 15s - scrape_timeout: 10s - metrics_path: /metrics - scheme: http - static_configs: - - targets: - - host.docker.internal:6010 -- job_name: gateway - scrape_interval: 15s - scrape_timeout: 10s - metrics_path: /metrics - scheme: https - static_configs: - - targets: - - host.docker.internal:5000 \ No newline at end of file diff --git a/deployments/kubernetes/booking-microservices.yml b/deployments/kubernetes/booking-microservices.yml index 5a1ac92a..68aa5b29 100644 --- a/deployments/kubernetes/booking-microservices.yml +++ b/deployments/kubernetes/booking-microservices.yml @@ -24,89 +24,95 @@ spec: apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: kompose convert -f infrastracture.yaml - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: elasticsearch name: elasticsearch spec: replicas: 1 selector: matchLabels: - io.kompose.service: elasticsearch - strategy: - type: Recreate + app: elasticsearch template: metadata: - annotations: - kompose.cmd: kompose convert -f infrastracture.yaml - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null labels: - io.kompose.network/booking: "true" - io.kompose.service: elasticsearch + app: elasticsearch spec: containers: - - env: - - name: ES_JAVA_OPTS - value: -Xms512m -Xmx512m - - name: discovery.type - value: single-node - - name: xpack.monitoring.enabled - value: "true" - - name: xpack.watcher.enabled - value: "false" - image: elasticsearch:7.17.9 - name: elasticsearch - ports: - - containerPort: 9200 - resources: {} - volumeMounts: - - mountPath: /usr/share/elasticsearch/data - name: elasticsearch-data - restartPolicy: Always + - name: elasticsearch + image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0 + env: + - name: discovery.type + value: "single-node" + - name: cluster.name + value: "docker-cluster" + - name: node.name + value: "docker-node" + - name: ES_JAVA_OPTS + value: "-Xms512m -Xmx512m" + - name: xpack.security.enabled + value: "false" + - name: xpack.security.http.ssl.enabled + value: "false" + - name: xpack.security.transport.ssl.enabled + value: "false" + - name: network.host + value: "0.0.0.0" + - name: http.port + value: "9200" + - name: transport.host + value: "localhost" + - name: bootstrap.memory_lock + value: "true" + - name: cluster.routing.allocation.disk.threshold_enabled + value: "false" + ports: + - containerPort: 9200 + - containerPort: 9300 + volumeMounts: + - mountPath: /usr/share/elasticsearch/data + name: elastic-data volumes: - - name: elasticsearch-data - persistentVolumeClaim: - claimName: elasticsearch-data -status: {} + - name: elastic-data + persistentVolumeClaim: + claimName: elasticsearch-pvc +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: elasticsearch-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi --- apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: kompose convert -f infrastracture.yaml - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: elasticsearch name: elasticsearch spec: - ports: - - name: "9200" - port: 9200 - targetPort: 9200 selector: - io.kompose.service: elasticsearch -status: - loadBalancer: {} + app: elasticsearch + ports: + - port: 9200 + targetPort: 9200 + - port: 9300 + targetPort: 9300 + type: ClusterIP --- apiVersion: v1 -kind: PersistentVolumeClaim +kind: PersistentVolume metadata: - creationTimestamp: null + name: elasticsearch-pv labels: - io.kompose.service: elasticsearch-data - name: elasticsearch-data + type: local spec: + storageClassName: manual + capacity: + storage: 10Gi accessModes: - ReadWriteOnce - resources: - requests: - storage: 100Mi -status: {} + hostPath: + path: "/mnt/data" --- ####################################################### # Kibana @@ -114,847 +120,824 @@ status: {} apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: kompose convert -f infrastracture.yaml - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: kibana name: kibana spec: replicas: 1 selector: matchLabels: - io.kompose.service: kibana - strategy: {} + app: kibana template: metadata: - annotations: - kompose.cmd: kompose convert -f infrastracture.yaml - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null labels: - io.kompose.network/booking: "true" - io.kompose.service: kibana + app: kibana spec: containers: - - env: - - name: ELASTICSEARCH_URL - value: elasticsearch:9200 - image: kibana:7.17.9 - name: kibana - ports: - - containerPort: 5601 - resources: {} - restartPolicy: Always -status: {} + - name: kibana + image: docker.elastic.co/kibana/kibana:8.17.0 + env: + - name: ELASTICSEARCH_HOSTS + value: "http://elasticsearch:9200" + ports: + - containerPort: 5601 + resources: + requests: + memory: "512Mi" + cpu: "500m" + limits: + memory: "1Gi" + cpu: "1" --- apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: kompose convert -f infrastracture.yaml - kompose.version: 1.26.0 (40646f47) - creationTimestamp: null - labels: - io.kompose.service: kibana name: kibana spec: - ports: - - name: "5601" - port: 5601 - targetPort: 5601 selector: - io.kompose.service: kibana -status: - loadBalancer: {} + app: kibana + ports: + - port: 5601 + targetPort: 5601 + type: ClusterIP --- ####################################################### -# Event Store +# Tempo ####################################################### apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe convert -f infrastructure.yaml - kompose.version: 1.34.0 (cbf2835db) - labels: - io.kompose.service: eventstore - name: eventstore + name: tempo spec: replicas: 1 selector: matchLabels: - io.kompose.service: eventstore + app: tempo template: metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe convert -f infrastructure.yaml - kompose.version: 1.34.0 (cbf2835db) labels: - io.kompose.service: eventstore + app: tempo spec: containers: - - env: - - name: EVENTSTORE_CLUSTER_SIZE - value: "1" - - name: EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP - value: "True" - - name: EVENTSTORE_HTTP_PORT - value: "2113" - - name: EVENTSTORE_INSECURE - value: "True" - - name: EVENTSTORE_RUN_PROJECTIONS - value: All - - name: EVENTSTORE_START_STANDARD_PROJECTIONS - value: "True" - image: eventstore/eventstore:latest - name: eventstore - ports: - - containerPort: 2113 - protocol: TCP - restartPolicy: Always + - name: tempo + image: grafana/tempo:latest + args: + - "-config.file=/etc/tempo.yaml" + ports: + - containerPort: 3200 + - containerPort: 4317 + - containerPort: 4318 + volumeMounts: + - mountPath: /etc/tempo.yaml + name: tempo-config + subPath: tempo.yaml + volumes: + - name: tempo-config + configMap: + name: tempo-config +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: tempo-config +data: + tempo.yaml: | + # Your Tempo configuration here --- apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe convert -f infrastructure.yaml - kompose.version: 1.34.0 (cbf2835db) - labels: - io.kompose.service: eventstore - name: eventstore + name: tempo spec: - ports: - - name: "2113" - port: 2113 - targetPort: 2113 selector: - io.kompose.service: eventstore + app: tempo + ports: + - port: 3200 + targetPort: 3200 + - port: 4317 + targetPort: 4317 + - port: 4318 + targetPort: 4318 + type: ClusterIP --- -# ####################################################### -# # Jaeger -# ####################################################### +####################################################### +# Looki +####################################################### apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe -f infrastracture.yaml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: jaeger - name: jaeger + name: loki spec: replicas: 1 selector: matchLabels: - io.kompose.service: jaeger - strategy: {} + app: loki template: metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe -f infrastracture.yaml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null labels: - io.kompose.network/booking: "true" - io.kompose.service: jaeger + app: loki spec: containers: - - image: jaegertracing/all-in-one - name: jaeger - ports: - - containerPort: 5775 - protocol: UDP - - containerPort: 5778 - - containerPort: 6831 - protocol: UDP - - containerPort: 6832 - protocol: UDP - - containerPort: 9411 - - containerPort: 14268 - - containerPort: 16686 - resources: {} - restartPolicy: Always -status: {} + - name: loki + image: grafana/loki:latest + args: + - "-config.file=/etc/loki/local-config.yaml" + ports: + - containerPort: 3100 + volumeMounts: + - mountPath: /etc/loki/local-config.yaml + name: loki-config + subPath: local-config.yaml + volumes: + - name: loki-config + configMap: + name: loki-config +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: loki-config +data: + local-config.yaml: | + # Your Loki configuration here --- apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe -f infrastracture.yaml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: jaeger - name: jaeger + name: loki spec: - ports: - - name: "5775" - port: 5775 - protocol: UDP - targetPort: 5775 - - name: "5778" - port: 5778 - targetPort: 5778 - - name: "6831" - port: 6831 - protocol: UDP - targetPort: 6831 - - name: "6832" - port: 6832 - protocol: UDP - targetPort: 6832 - - name: "9411" - port: 9411 - targetPort: 9411 - - name: "14268" - port: 14268 - targetPort: 14268 - - name: "16686" - port: 16686 - targetPort: 16686 selector: - io.kompose.service: jaeger -status: - loadBalancer: {} + app: loki + ports: + - port: 3100 + targetPort: 3100 + type: ClusterIP --- ####################################################### -# Prometheus +# Event Store ####################################################### apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe convert -f infrastracture.yaml - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: prometheus - name: prometheus + name: eventstore spec: replicas: 1 selector: matchLabels: - io.kompose.service: prometheus - strategy: - type: Recreate + app: eventstore template: metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe convert -f infrastracture.yaml - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null labels: - io.kompose.network/newfolder-booking: "true" - io.kompose.service: prometheus + app: eventstore spec: containers: - - env: - - name: TZ - value: UTC - image: prom/prometheus:latest - name: prometheus - ports: - - containerPort: 9090 - resources: {} - volumeMounts: - - mountPath: /etc/prometheus/prometheus.yml - name: prometheus-claim0 - restartPolicy: Always - volumes: - - name: prometheus-claim0 - persistentVolumeClaim: - claimName: prometheus-claim0 -status: {} + - name: eventstore + image: eventstore/eventstore:latest + env: + - name: EVENTSTORE_CLUSTER_SIZE + value: "1" + - name: EVENTSTORE_RUN_PROJECTIONS + value: "All" + - name: EVENTSTORE_START_STANDARD_PROJECTIONS + value: "True" + - name: EVENTSTORE_HTTP_PORT + value: "2113" + - name: EVENTSTORE_INSECURE + value: "True" + - name: EVENTSTORE_ENABLE_ATOM_PUB_OVER_HTTP + value: "True" + ports: + - containerPort: 2113 + resources: + requests: + memory: "512Mi" + cpu: "500m" + limits: + memory: "1Gi" + cpu: "1" --- apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe convert -f infrastracture.yaml - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: prometheus - name: prometheus + name: eventstore spec: + selector: + app: eventstore ports: - - name: "9090" - port: 9090 - targetPort: 9090 + - port: 2113 + targetPort: 2113 + type: ClusterIP +--- +####################################################### +# Jaeger +####################################################### +apiVersion: apps/v1 +kind: Deployment +metadata: + name: jaeger +spec: + replicas: 1 selector: - io.kompose.service: prometheus -status: - loadBalancer: {} + matchLabels: + app: jaeger + template: + metadata: + labels: + app: jaeger + spec: + containers: + - name: jaeger + image: jaegertracing/all-in-one:latest + ports: + - containerPort: 6831 + protocol: UDP + - containerPort: 16686 + - containerPort: 14268 + - containerPort: 4317 + - containerPort: 4318 + resources: + requests: + memory: "512Mi" + cpu: "500m" + limits: + memory: "1Gi" + cpu: "1" --- apiVersion: v1 -kind: PersistentVolumeClaim +kind: Service metadata: - creationTimestamp: null - labels: - io.kompose.service: prometheus-claim0 - name: prometheus-claim0 + name: jaeger spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 100Mi -status: {} + selector: + app: jaeger + ports: + - port: 6831 + targetPort: 6831 + protocol: UDP + - port: 16686 + targetPort: 16686 + - port: 14268 + targetPort: 14268 + - port: 4317 + targetPort: 4317 + - port: 4318 + targetPort: 4318 + type: ClusterIP --- ####################################################### -# Grafana +# Zipkin ####################################################### apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe convert -f infrastracture.yaml - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: grafana - name: grafana + name: zipkin spec: replicas: 1 selector: matchLabels: - io.kompose.service: grafana - strategy: - type: Recreate + app: zipkin template: metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe convert -f infrastracture.yaml - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null labels: - io.kompose.network/newfolder-booking: "true" - io.kompose.service: grafana + app: zipkin spec: containers: - - image: grafana/grafana - name: grafana - ports: - - containerPort: 3000 - resources: {} - volumeMounts: - - mountPath: /var/lib/grafana - name: grafana-claim0 - restartPolicy: Always - volumes: - - name: grafana-claim0 - persistentVolumeClaim: - claimName: grafana-claim0 -status: {} + - name: zipkin + image: openzipkin/zipkin:latest + ports: + - containerPort: 9411 + resources: + requests: + memory: "512Mi" + cpu: "500m" + limits: + memory: "1Gi" + cpu: "1" --- apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe convert -f infrastracture.yaml - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: grafana - name: grafana + name: zipkin spec: + selector: + app: zipkin ports: - - name: "3000" - port: 3000 - targetPort: 3000 + - port: 9411 + targetPort: 9411 + type: ClusterIP + +--- +####################################################### +# OpenTelemetry Collector +####################################################### +apiVersion: apps/v1 +kind: Deployment +metadata: + name: otel-collector +spec: + replicas: 1 selector: - io.kompose.service: grafana -status: - loadBalancer: {} + matchLabels: + app: otel-collector + template: + metadata: + labels: + app: otel-collector + spec: + containers: + - name: otel-collector + image: otel/opentelemetry-collector-contrib:latest + args: ["--config=/etc/otelcol-contrib/config.yaml"] + ports: + - containerPort: 11888 + - containerPort: 8888 + - containerPort: 8889 + - containerPort: 13133 + - containerPort: 4317 + - containerPort: 4318 + - containerPort: 55679 + volumeMounts: + - mountPath: /etc/otelcol-contrib/config.yaml + name: otel-config + subPath: config.yaml + volumes: + - name: otel-config + configMap: + name: otel-collector-config --- apiVersion: v1 -kind: PersistentVolumeClaim +kind: ConfigMap metadata: - creationTimestamp: null - labels: - io.kompose.service: grafana-claim0 - name: grafana-claim0 + name: otel-collector-config +data: + config.yaml: | + # Your OpenTelemetry Collector configuration here +--- +apiVersion: v1 +kind: Service +metadata: + name: otel-collector spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 100Mi -status: {} + selector: + app: otel-collector + ports: + - port: 11888 + targetPort: 11888 + - port: 8888 + targetPort: 8888 + - port: 8889 + targetPort: 8889 + - port: 13133 + targetPort: 13133 + - port: 4317 + targetPort: 4317 + - port: 4318 + targetPort: 4318 + - port: 55679 + targetPort: 55679 + type: ClusterIP --- -# ####################################################### -# # Node Exporter -# ####################################################### +####################################################### +# Prometheus +####################################################### apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe convert -f infrastructure.yaml - kompose.version: 1.34.0 (cbf2835db) - labels: - io.kompose.service: node-exporter - name: node-exporter + name: prometheus spec: replicas: 1 selector: matchLabels: - io.kompose.service: node-exporter - strategy: - type: Recreate + app: prometheus template: metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe convert -f infrastructure.yaml - kompose.version: 1.34.0 (cbf2835db) labels: - io.kompose.service: node-exporter + app: prometheus spec: containers: - - args: - - --path.rootfs=/host - image: quay.io/prometheus/node-exporter:latest - name: node-exporter - volumeMounts: - - mountPath: /host/proc - name: node-exporter-claim0 - readOnly: true - - mountPath: /host/sys - name: node-exporter-claim1 - readOnly: true - restartPolicy: Always + - name: prometheus + image: prom/prometheus:latest + args: + - "--config.file=/etc/prometheus/prometheus.yml" + - "--storage.tsdb.path=/prometheus" + - "--web.console.libraries=/usr/share/prometheus/console_libraries" + - "--web.console.templates=/usr/share/prometheus/consoles" + - "--web.enable-remote-write-receiver" + ports: + - containerPort: 9090 + volumeMounts: + - mountPath: /etc/prometheus/prometheus.yml + name: prometheus-config + subPath: prometheus.yml volumes: - - name: node-exporter-claim0 - persistentVolumeClaim: - claimName: node-exporter-claim0 - readOnly: true - - name: node-exporter-claim1 - persistentVolumeClaim: - claimName: node-exporter-claim1 - readOnly: true + - name: prometheus-config + configMap: + name: prometheus-config --- apiVersion: v1 -kind: PersistentVolumeClaim +kind: ConfigMap metadata: - labels: - io.kompose.service: node-exporter-claim0 - name: node-exporter-claim0 -spec: - accessModes: - - ReadOnlyMany - resources: - requests: - storage: 100Mi + name: prometheus-config +data: + prometheus.yml: | + # Your Prometheus configuration here --- apiVersion: v1 -kind: PersistentVolumeClaim +kind: Service metadata: - labels: - io.kompose.service: node-exporter-claim1 - name: node-exporter-claim1 + name: prometheus spec: - accessModes: - - ReadOnlyMany - resources: - requests: - storage: 100Mi + selector: + app: prometheus + ports: + - port: 9090 + targetPort: 9090 + type: ClusterIP --- -# ####################################################### -# # Cadvisor -# ####################################################### +####################################################### +# Grafana +####################################################### apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe convert -f infrastracture.yaml - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: cadvisor - name: cadvisor + name: grafana spec: replicas: 1 selector: matchLabels: - io.kompose.service: cadvisor - strategy: - type: Recreate + app: grafana template: metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe convert -f infrastracture.yaml - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null labels: - io.kompose.network/newfolder-booking: "true" - io.kompose.service: cadvisor + app: grafana spec: containers: - - image: gcr.io/cadvisor/cadvisor:latest - name: cadvisor - ports: - - containerPort: 8080 - resources: {} - volumeMounts: - - mountPath: /rootfs - name: cadvisor-claim0 - readOnly: true - - mountPath: /var/run - name: cadvisor-claim1 - readOnly: true - - mountPath: /sys - name: cadvisor-claim2 - readOnly: true - - mountPath: /var/lib/docker - name: cadvisor-claim3 - readOnly: true - - mountPath: /dev/disk - name: cadvisor-claim4 - readOnly: true - restartPolicy: Always + - name: grafana + image: grafana/grafana:latest + env: + - name: GF_INSTALL_PLUGINS + value: "grafana-clock-panel,grafana-simple-json-datasource" + - name: GF_SECURITY_ADMIN_USER + value: "admin" + - name: GF_SECURITY_ADMIN_PASSWORD + value: "admin" + - name: GF_FEATURE_TOGGLES_ENABLE + value: "traceqlEditor" + ports: + - containerPort: 3000 + volumeMounts: + - mountPath: /etc/grafana/provisioning + name: grafana-provisioning + - mountPath: /var/lib/grafana/dashboards + name: grafana-dashboards volumes: - - name: cadvisor-claim0 - persistentVolumeClaim: - claimName: cadvisor-claim0 - readOnly: true - - name: cadvisor-claim1 - persistentVolumeClaim: - claimName: cadvisor-claim1 - readOnly: true - - name: cadvisor-claim2 - persistentVolumeClaim: - claimName: cadvisor-claim2 - readOnly: true - - name: cadvisor-claim3 - persistentVolumeClaim: - claimName: cadvisor-claim3 - readOnly: true - - name: cadvisor-claim4 - persistentVolumeClaim: - claimName: cadvisor-claim4 - readOnly: true -status: {} + - name: grafana-provisioning + configMap: + name: grafana-provisioning + - name: grafana-dashboards + configMap: + name: grafana-dashboards --- apiVersion: v1 -kind: Service +kind: ConfigMap metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe convert -f infrastracture.yaml - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: cadvisor - name: cadvisor -spec: - ports: - - name: "8080" - port: 8080 - targetPort: 8080 - selector: - io.kompose.service: cadvisor -status: - loadBalancer: {} + name: grafana-provisioning +data: + # Your Grafana provisioning configuration here --- apiVersion: v1 -kind: PersistentVolumeClaim +kind: ConfigMap metadata: - creationTimestamp: null - labels: - io.kompose.service: cadvisor-claim0 - name: cadvisor-claim0 -spec: - accessModes: - - ReadOnlyMany - resources: - requests: - storage: 100Mi -status: {} + name: grafana-dashboards +data: + # Your Grafana dashboards configuration here --- apiVersion: v1 -kind: PersistentVolumeClaim +kind: Service metadata: - creationTimestamp: null - labels: - io.kompose.service: cadvisor-claim1 - name: cadvisor-claim1 + name: grafana spec: - accessModes: - - ReadOnlyMany - resources: - requests: - storage: 100Mi -status: {} + selector: + app: grafana + ports: + - port: 3000 + targetPort: 3000 + type: ClusterIP --- -apiVersion: v1 -kind: PersistentVolumeClaim +####################################################### +# Node Exporter +####################################################### +apiVersion: apps/v1 +kind: Deployment metadata: - creationTimestamp: null - labels: - io.kompose.service: cadvisor-claim2 - name: cadvisor-claim2 + name: node-exporter spec: - accessModes: - - ReadOnlyMany - resources: - requests: - storage: 100Mi -status: {} + replicas: 1 + selector: + matchLabels: + app: node-exporter + template: + metadata: + labels: + app: node-exporter + spec: + containers: + - name: node-exporter + image: prom/node-exporter:latest + args: + - "--path.procfs=/host/proc" + - "--path.rootfs=/rootfs" + - "--path.sysfs=/host/sys" + ports: + - containerPort: 9100 + volumeMounts: + - mountPath: /host/proc + name: proc + readOnly: true + - mountPath: /host/sys + name: sys + readOnly: true + - mountPath: /rootfs + name: rootfs + readOnly: true + volumes: + - name: proc + hostPath: + path: /proc + - name: sys + hostPath: + path: /sys + - name: rootfs + hostPath: + path: / --- apiVersion: v1 -kind: PersistentVolumeClaim +kind: Service metadata: - creationTimestamp: null - labels: - io.kompose.service: cadvisor-claim3 - name: cadvisor-claim3 + name: node-exporter spec: - accessModes: - - ReadOnlyMany - resources: - requests: - storage: 100Mi -status: {} + selector: + app: node-exporter + ports: + - port: 9100 + targetPort: 9100 + type: ClusterIP +--- +####################################################### +# Cadvisor +####################################################### +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cadvisor +spec: + replicas: 1 + selector: + matchLabels: + app: cadvisor + template: + metadata: + labels: + app: cadvisor + spec: + containers: + - name: cadvisor + image: gcr.io/cadvisor/cadvisor:latest + ports: + - containerPort: 8080 + volumeMounts: + - mountPath: /rootfs + name: rootfs + readOnly: true + - mountPath: /var/run + name: var-run + readOnly: true + - mountPath: /sys + name: sys + readOnly: true + - mountPath: /var/lib/docker + name: var-lib-docker + readOnly: true + - mountPath: /dev/disk + name: dev-disk + readOnly: true + volumes: + - name: rootfs + hostPath: + path: / + - name: var-run + hostPath: + path: /var/run + - name: sys + hostPath: + path: /sys + - name: var-lib-docker + hostPath: + path: /var/lib/docker + - name: dev-disk + hostPath: + path: /dev/disk --- apiVersion: v1 -kind: PersistentVolumeClaim +kind: Service metadata: - creationTimestamp: null - labels: - io.kompose.service: cadvisor-claim4 - name: cadvisor-claim4 + name: cadvisor spec: - accessModes: - - ReadOnlyMany - resources: - requests: - storage: 100Mi -status: {} + selector: + app: cadvisor + ports: + - port: 8080 + targetPort: 8080 + type: ClusterIP --- -# ####################################################### -# # Mongo -# ####################################################### +####################################################### +# Mongo +####################################################### apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe -f infrastracture.yaml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: mongo name: mongo spec: replicas: 1 selector: matchLabels: - io.kompose.service: mongo - strategy: {} + app: mongo template: metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe -f infrastracture.yaml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null labels: - io.kompose.network/booking: "true" - io.kompose.service: mongo + app: mongo spec: containers: - - image: mongo:latest - name: mongo - ports: - - containerPort: 27017 - resources: {} - restartPolicy: Always -status: {} + - name: mongo + image: mongo:latest + ports: + - containerPort: 27017 + resources: + requests: + memory: "512Mi" + cpu: "500m" + limits: + memory: "1Gi" + cpu: "1" --- apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe -f infrastracture.yaml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: mongo name: mongo spec: - ports: - - name: "27017" - port: 27017 - targetPort: 27017 selector: - io.kompose.service: mongo -status: - loadBalancer: {} + app: mongo + ports: + - port: 27017 + targetPort: 27017 + type: ClusterIP --- -# ####################################################### -# # Postgres -# ####################################################### -apiVersion: v1 -kind: Pod +####################################################### +# Postgres +####################################################### +apiVersion: apps/v1 +kind: Deployment metadata: - labels: - app: postgres name: postgres spec: - containers: - - args: - - postgres - - -c - - wal_level=logical - - -c - - max_prepared_transactions=10 - env: - - name: POSTGRES_PASSWORD - value: postgres + replicas: 1 + selector: + matchLabels: + app: postgres + template: + metadata: + labels: + app: postgres + spec: + containers: + - name: postgres + image: postgres:latest + env: - name: POSTGRES_USER value: postgres - image: postgres:latest - name: postgres - ports: + - name: POSTGRES_PASSWORD + value: postgres + ports: - containerPort: 5432 - restartPolicy: Always + volumeMounts: + - mountPath: /var/lib/postgresql/data + name: postgres-data + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: postgres-pvc +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: postgres-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi --- apiVersion: v1 kind: Service metadata: - labels: - app: postgres name: postgres spec: - ports: - - name: "5432" - port: 5432 - targetPort: 5432 selector: app: postgres + ports: + - port: 5432 + targetPort: 5432 + type: ClusterIP --- -# ####################################################### -# # Rabbitmq -# ####################################################### +####################################################### +# Rabbitmq +####################################################### apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe -f infrastracture.yaml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: rabbitmq name: rabbitmq spec: replicas: 1 selector: matchLabels: - io.kompose.service: rabbitmq - strategy: {} + app: rabbitmq template: metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe -f infrastracture.yaml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null labels: - io.kompose.network/booking: "true" - io.kompose.service: rabbitmq + app: rabbitmq spec: containers: - - image: rabbitmq:management - name: rabbitmq - ports: - - containerPort: 5672 - - containerPort: 15672 - resources: {} - restartPolicy: Always -status: {} + - name: rabbitmq + image: rabbitmq:management + ports: + - containerPort: 5672 + - containerPort: 15672 + resources: + requests: + memory: "512Mi" + cpu: "500m" + limits: + memory: "1Gi" + cpu: "1" --- apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe -f infrastracture.yaml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: rabbitmq name: rabbitmq spec: - ports: - - name: "5672" - port: 5672 - targetPort: 5672 - - name: "15672" - port: 15672 - targetPort: 15672 selector: - io.kompose.service: rabbitmq -status: - loadBalancer: {} + app: rabbitmq + ports: + - port: 5672 + targetPort: 5672 + - port: 15672 + targetPort: 15672 + type: ClusterIP --- -# ####################################################### -# # Redis -# ####################################################### +####################################################### +# Redis +####################################################### apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe -f infrastracture.yaml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: redis name: redis spec: replicas: 1 selector: matchLabels: - io.kompose.service: redis - strategy: {} + app: redis template: metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe -f infrastracture.yaml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null labels: - io.kompose.network/booking: "true" - io.kompose.service: redis + app: redis spec: containers: - - image: redis - name: redis - ports: - - containerPort: 6379 - resources: {} - restartPolicy: Always -status: {} + - name: redis + image: redis + ports: + - containerPort: 6379 + resources: + requests: + memory: "512Mi" + cpu: "500m" + limits: + memory: "1Gi" + cpu: "1" --- apiVersion: v1 kind: Service metadata: - annotations: - kompose.cmd: C:\ProgramData\chocolatey\lib\kubernetes-kompose\tools\kompose.exe -f infrastracture.yaml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: redis name: redis spec: - ports: - - name: "6379" - port: 6379 - targetPort: 6379 selector: - io.kompose.service: redis -status: - loadBalancer: {} + app: redis + ports: + - port: 6379 + targetPort: 6379 + type: ClusterIP --- -# ####################################################### +####################################################### # ConfigMap AppSettings -# ####################################################### +####################################################### apiVersion: v1 kind: ConfigMap metadata: @@ -966,9 +949,9 @@ data: } #ref: https://www.mrjamiebowman.com/software-development/dotnet/kubernetes-configmaps-with-net-core/ --- -# ####################################################### +####################################################### # Flight -# ####################################################### +####################################################### apiVersion: apps/v1 kind: Deployment metadata: @@ -1017,9 +1000,9 @@ spec: targetPort: 80 type: ClusterIP --- -# ####################################################### +####################################################### # Identity -# ####################################################### +####################################################### apiVersion: apps/v1 kind: Deployment metadata: @@ -1068,9 +1051,9 @@ spec: targetPort: 80 type: ClusterIP --- -# ####################################################### +####################################################### # Booking -# ####################################################### +####################################################### apiVersion: apps/v1 kind: Deployment metadata: @@ -1119,9 +1102,9 @@ spec: targetPort: 80 type: ClusterIP --- -# ####################################################### +####################################################### # Passenger -# ####################################################### +####################################################### apiVersion: apps/v1 kind: Deployment metadata: @@ -1156,9 +1139,9 @@ spec: configMap: name: appsettings --- -# ####################################################### +####################################################### # Ingress Controller -# ####################################################### +####################################################### apiVersion: v1 kind: Service metadata: diff --git a/src/BuildingBlocks/BuildingBlocks.csproj b/src/BuildingBlocks/BuildingBlocks.csproj index 2a34911d..7f8b487c 100644 --- a/src/BuildingBlocks/BuildingBlocks.csproj +++ b/src/BuildingBlocks/BuildingBlocks.csproj @@ -29,8 +29,6 @@ - - @@ -50,10 +48,8 @@ - - @@ -68,8 +64,8 @@ - - + + @@ -85,14 +81,18 @@ - - - - - - - - + + + + + + + + + + + + diff --git a/src/BuildingBlocks/HealthCheck/Extensions.cs b/src/BuildingBlocks/HealthCheck/Extensions.cs index bd8623ed..137ed4e9 100644 --- a/src/BuildingBlocks/HealthCheck/Extensions.cs +++ b/src/BuildingBlocks/HealthCheck/Extensions.cs @@ -2,6 +2,7 @@ using BuildingBlocks.Logging; using BuildingBlocks.MassTransit; using BuildingBlocks.Mongo; +using BuildingBlocks.OpenTelemetryCollector; using BuildingBlocks.Web; using HealthChecks.UI.Client; using Microsoft.AspNetCore.Builder; @@ -25,13 +26,11 @@ public static IServiceCollection AddCustomHealthCheck(this IServiceCollection se var postgresOptions = services.GetOptions(nameof(PostgresOptions)); var rabbitMqOptions = services.GetOptions(nameof(RabbitMqOptions)); var mongoOptions = services.GetOptions(nameof(MongoOptions)); - var logOptions = services.GetOptions(nameof(LogOptions)); var healthChecksBuilder = services.AddHealthChecks() .AddRabbitMQ( rabbitConnectionString: - $"amqp://{rabbitMqOptions.UserName}:{rabbitMqOptions.Password}@{rabbitMqOptions.HostName}") - .AddElasticsearch(logOptions.Elastic.ElasticServiceUrl); + $"amqp://{rabbitMqOptions.UserName}:{rabbitMqOptions.Password}@{rabbitMqOptions.HostName}"); if (mongoOptions.ConnectionString is not null) healthChecksBuilder.AddMongoDb(mongoOptions.ConnectionString); diff --git a/src/BuildingBlocks/Logging/ElasticOptions.cs b/src/BuildingBlocks/Logging/ElasticOptions.cs deleted file mode 100644 index 65e210ba..00000000 --- a/src/BuildingBlocks/Logging/ElasticOptions.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace BuildingBlocks.Logging; - -public class ElasticOptions -{ - public bool Enabled { get; set; } - public string ElasticServiceUrl { get; set; } - public string ElasticSearchIndex { get; set; } -} diff --git a/src/BuildingBlocks/Logging/Extensions.cs b/src/BuildingBlocks/Logging/Extensions.cs index ed1813eb..1c765c05 100644 --- a/src/BuildingBlocks/Logging/Extensions.cs +++ b/src/BuildingBlocks/Logging/Extensions.cs @@ -7,7 +7,6 @@ using Serilog; using Serilog.Events; using Serilog.Exceptions; -using Serilog.Sinks.Elasticsearch; using Serilog.Sinks.SpectreConsole; namespace BuildingBlocks.Logging @@ -18,10 +17,7 @@ public static WebApplicationBuilder AddCustomSerilog(this WebApplicationBuilder { builder.Host.UseSerilog((context, services, loggerConfiguration) => { - var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); var logOptions = context.Configuration.GetSection(nameof(LogOptions)).Get(); - var appOptions = context.Configuration.GetSection(nameof(AppOptions)).Get(); - var logLevel = Enum.TryParse(logOptions.Level, true, out var level) ? level @@ -39,35 +35,6 @@ public static WebApplicationBuilder AddCustomSerilog(this WebApplicationBuilder .Enrich.FromLogContext() .ReadFrom.Configuration(context.Configuration); - if (logOptions.Elastic is { Enabled: true }) - { - loggerConfiguration.WriteTo.Elasticsearch( - new ElasticsearchSinkOptions(new Uri(logOptions.Elastic.ElasticServiceUrl)) - { - AutoRegisterTemplate = true, - IndexFormat = $"{appOptions.Name}-{environment?.ToLower(CultureInfo.CurrentCulture)}" - }); - } - - - if (logOptions?.Sentry is { Enabled: true }) - { - var minimumBreadcrumbLevel = Enum.TryParse(logOptions.Level, true, out var minBreadcrumbLevel) - ? minBreadcrumbLevel - : LogEventLevel.Information; - - var minimumEventLevel = Enum.TryParse(logOptions.Sentry.MinimumEventLevel, true, out var minEventLevel) - ? minEventLevel - : LogEventLevel.Error; - - loggerConfiguration.WriteTo.Sentry(o => - { - o.Dsn = logOptions.Sentry.Dsn; - o.MinimumBreadcrumbLevel = minimumBreadcrumbLevel; - o.MinimumEventLevel = minimumEventLevel; - }); - } - if (logOptions.File is { Enabled: true }) { var root = env.ContentRootPath; diff --git a/src/BuildingBlocks/Logging/LogOptions.cs b/src/BuildingBlocks/Logging/LogOptions.cs index 8fac194e..ee4f7775 100644 --- a/src/BuildingBlocks/Logging/LogOptions.cs +++ b/src/BuildingBlocks/Logging/LogOptions.cs @@ -3,9 +3,6 @@ namespace BuildingBlocks.Logging public class LogOptions { public string Level { get; set; } - public ElasticOptions Elastic { get; set; } - - public SentryOptions Sentry { get; set; } public FileOptions File { get; set; } public string LogTemplate { get; set; } } diff --git a/src/BuildingBlocks/Logging/SentryOptions.cs b/src/BuildingBlocks/Logging/SentryOptions.cs deleted file mode 100644 index 8556bbe2..00000000 --- a/src/BuildingBlocks/Logging/SentryOptions.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace BuildingBlocks.Logging; - -public class SentryOptions -{ - public bool Enabled { get; set; } - public string Dsn { get; set; } - public string MinimumBreadcrumbLevel { get; set; } - public string MinimumEventLevel { get; set; } -} diff --git a/src/BuildingBlocks/OpenTelemetry/Extensions.cs b/src/BuildingBlocks/OpenTelemetry/Extensions.cs deleted file mode 100644 index a31a3d96..00000000 --- a/src/BuildingBlocks/OpenTelemetry/Extensions.cs +++ /dev/null @@ -1,44 +0,0 @@ -using BuildingBlocks.Utils; -using BuildingBlocks.Web; -using Microsoft.Extensions.DependencyInjection; -using OpenTelemetry.Resources; -using OpenTelemetry.Trace; - -namespace BuildingBlocks.OpenTelemetry; - -using global::OpenTelemetry.Metrics; - -public static class Extensions -{ - public static IServiceCollection AddCustomOpenTelemetry(this IServiceCollection services) - { - services.AddOpenTelemetry() - .WithTracing(builder => builder - .AddGrpcClientInstrumentation() - .AddMassTransitInstrumentation() - .AddAspNetCoreInstrumentation() - .AddHttpClientInstrumentation() - .SetResourceBuilder(ResourceBuilder.CreateDefault() - .AddService(services.GetOptions("AppOptions").Name)) - .AddJaegerExporter()) - .WithMetrics(builder => - { - builder.AddPrometheusExporter(); - builder.AddMeter( - "Microsoft.AspNetCore.Hosting", - "Microsoft.AspNetCore.Server.Kestrel" - ); - builder.AddView("request-duration", - new ExplicitBucketHistogramConfiguration - { - Boundaries = new[] - { - 0, 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10 - } - }); - } - ); - - return services; - } -} diff --git a/src/BuildingBlocks/OpenTelemetryCollector/ActivityExtensions.cs b/src/BuildingBlocks/OpenTelemetryCollector/ActivityExtensions.cs new file mode 100644 index 00000000..fb06a1c5 --- /dev/null +++ b/src/BuildingBlocks/OpenTelemetryCollector/ActivityExtensions.cs @@ -0,0 +1,175 @@ +using System.Diagnostics; +using System.Globalization; + +namespace BuildingBlocks.OpenTelemetryCollector; + +internal static class ActivityExtensions +{ + /// + /// Retrieves the tags from the parent of the current Activity, if available. + /// + /// The current Activity. + /// A dictionary containing the parent tags, or an empty dictionary if no parent tags are available. + public static Dictionary GetParentTags(this Activity activity) + { + ArgumentNullException.ThrowIfNull(activity); + + var parentTags = new Dictionary(); + + // Check if the current activity has a parent + var parentActivity = activity.Parent; + + if (parentActivity != null) + { + foreach (var tag in parentActivity.Tags) + { + parentTags[tag.Key] = tag.Value; + } + } + else + { + // If no parent Activity is available, check for links + foreach (var link in activity.Links) + { + // Extract tags from the first link's context (assuming it's the parent-like context) + if (link.Tags != null) + { + foreach (var tag in link.Tags) + { + parentTags[tag.Key] = tag.Value; + } + } + + // Break after processing the first link, as there should only be one parent context. + break; + } + } + + return parentTags; + } + + /// + /// Extracts important information from an Activity into an ActivityInfo object. + /// + /// The Activity from which to extract information. + /// An ActivityInfo object containing the extracted information. + public static ActivityInfo ExtractImportantInformation(this Activity activity) + { + ArgumentNullException.ThrowIfNull(activity); + + var activityInfo = new ActivityInfo + { + Name = activity.DisplayName, + StartTime = activity.StartTimeUtc, + Duration = activity.Duration, + Status = + activity.Tags.FirstOrDefault(tag => tag.Key == TelemetryTags.Tracing.Otel.StatusCode).Value + ?? "Unknown", + StatusDescription = activity + .Tags.FirstOrDefault(tag => tag.Key == TelemetryTags.Tracing.Otel.StatusDescription) + .Value, + Tags = activity.Tags.ToDictionary(tag => tag.Key, tag => tag.Value), + Events = activity + .Events.Select(e => new ActivityEventInfo + { + Name = e.Name, + Timestamp = e.Timestamp, + Attributes = e.Tags.ToDictionary(tag => tag.Key, tag => tag.Value), + }) + .ToList(), + TraceId = activity.TraceId.ToString(), + SpanId = activity.SpanId.ToString(), + }; + + return activityInfo; + } + + /// + /// Sets an "OK" status on the provided Activity, indicating a successful operation. + /// + /// The Activity to update. + /// An optional description of the successful operation. + /// The updated Activity with the status and tags set. + public static Activity SetOkStatus(this Activity activity, string? description = null) + { + ArgumentNullException.ThrowIfNull(activity); + + // Set the status of the activity to "OK" + activity.SetStatus(ActivityStatusCode.Ok, description); + + // Add telemetry tags for status + activity.SetTag( + TelemetryTags.Tracing.Otel.StatusCode, + nameof(ActivityStatusCode.Ok).ToUpper(CultureInfo.InvariantCulture) + ); + if (!string.IsNullOrEmpty(description)) + activity.SetTag(TelemetryTags.Tracing.Otel.StatusDescription, description); + + return activity; + } + + /// + /// Sets an "Unset" status on the provided Activity, indicating no explicit status was applied. + /// + /// The Activity to update. + /// An optional description of the unset status. + /// The updated Activity with the status and tags set. + public static Activity SetUnsetStatus(this Activity activity, string? description = null) + { + ArgumentNullException.ThrowIfNull(activity); + + // Set the status of the activity to "Unset" + activity.SetStatus(ActivityStatusCode.Unset, description); + + // Add telemetry tags for status + activity.SetTag( + TelemetryTags.Tracing.Otel.StatusCode, + nameof(ActivityStatusCode.Unset).ToUpper(CultureInfo.InvariantCulture) + ); + if (!string.IsNullOrEmpty(description)) + activity.SetTag(TelemetryTags.Tracing.Otel.StatusDescription, description); + + return activity; + } + + /// + /// Sets an "Error" status on the provided Activity, indicating a failed operation. + /// + /// The Activity to update. + /// The exception associated with the error, if available. + /// An optional description of the error. + /// The updated Activity with the status, error details, and tags set. + public static Activity SetErrorStatus(this Activity activity, System.Exception? exception, string? description = null) + { + ArgumentNullException.ThrowIfNull(activity); + + // Add telemetry tags for status + activity.SetTag( + TelemetryTags.Tracing.Otel.StatusCode, + nameof(ActivityStatusCode.Error).ToUpper(CultureInfo.InvariantCulture) + ); + if (!string.IsNullOrEmpty(description)) + activity.SetTag(TelemetryTags.Tracing.Otel.StatusDescription, description); + + // Add detailed exception tags, if an exception is provided + return activity.SetExceptionTags(exception); + } + + // See https://opentelemetry.io/docs/specs/otel/trace/semantic_conventions/exceptions/ + public static Activity SetExceptionTags(this Activity activity, System.Exception? ex) + { + if (ex is null) + { + return activity; + } + + activity.SetStatus(ActivityStatusCode.Error); + activity.AddException(ex); + + activity.AddTag(TelemetryTags.Tracing.Exception.Message, ex.Message); + activity.AddTag(TelemetryTags.Tracing.Exception.Stacktrace, ex.ToString()); + activity.AddTag(TelemetryTags.Tracing.Exception.Type, ex.GetType().FullName); + + return activity; + } +} diff --git a/src/BuildingBlocks/OpenTelemetryCollector/ActivityInfo.cs b/src/BuildingBlocks/OpenTelemetryCollector/ActivityInfo.cs new file mode 100644 index 00000000..0392f0f4 --- /dev/null +++ b/src/BuildingBlocks/OpenTelemetryCollector/ActivityInfo.cs @@ -0,0 +1,29 @@ +using System.Diagnostics; + +namespace BuildingBlocks.OpenTelemetryCollector; + +public class ActivityInfo +{ + public string Name { get; set; } = default!; + public DateTime StartTime { get; set; } + public TimeSpan Duration { get; set; } + public string Status { get; set; } = default!; + public string? StatusDescription { get; set; } + public IDictionary Tags { get; set; } = new Dictionary(); + public IList Events { get; set; } = new List(); + public string TraceId { get; set; } = default!; + public string SpanId { get; set; } = default!; + + public string? ParentId { get; set; } + + public ActivityContext? Parent { get; set; } + + public ActivityKind Kind { get; set; } +} + +public class ActivityEventInfo +{ + public string Name { get; set; } = default!; + public DateTimeOffset Timestamp { get; set; } + public IDictionary Attributes { get; set; } = new Dictionary(); +} diff --git a/src/BuildingBlocks/OpenTelemetryCollector/Behaviors/ObservabilityPipelineBehavior.cs b/src/BuildingBlocks/OpenTelemetryCollector/Behaviors/ObservabilityPipelineBehavior.cs new file mode 100644 index 00000000..aadb938f --- /dev/null +++ b/src/BuildingBlocks/OpenTelemetryCollector/Behaviors/ObservabilityPipelineBehavior.cs @@ -0,0 +1,85 @@ +using BuildingBlocks.Core.CQRS; +using BuildingBlocks.OpenTelemetryCollector.CoreDiagnostics.Commands; +using BuildingBlocks.OpenTelemetryCollector.CoreDiagnostics.Query; +using MediatR; + +namespace BuildingBlocks.OpenTelemetryCollector.Behaviors; + +public class ObservabilityPipelineBehavior( + CommandHandlerActivity commandActivity, + CommandHandlerMetrics commandMetrics, + QueryHandlerActivity queryActivity, + QueryHandlerMetrics queryMetrics +) : IPipelineBehavior + where TRequest : IRequest + where TResponse : notnull +{ + public async Task Handle(TRequest message, RequestHandlerDelegate next, CancellationToken cancellationToken) + { + var isCommand = message is IQuery; + var isQuery = message is ICommand; + + if (isCommand) + { + commandMetrics.StartExecuting(); + } + + if (isQuery) + { + queryMetrics.StartExecuting(); + } + + try + { + if (isCommand) + { + var commandResult = await commandActivity.Execute( + async (activity, ct) => + { + var response = await next(); + + return response; + }, + cancellationToken + ); + + commandMetrics.FinishExecuting(); + + return commandResult; + } + + if (isQuery) + { + var queryResult = await queryActivity.Execute( + async (activity, ct) => + { + var response = await next(); + + return response; + }, + cancellationToken + ); + + queryMetrics.FinishExecuting(); + + return queryResult; + } + } + catch (System.Exception) + { + if (isQuery) + { + queryMetrics.FailedCommand(); + } + + if (isCommand) + { + commandMetrics.FailedCommand(); + } + + throw; + } + + return await next(); + } +} diff --git a/src/BuildingBlocks/OpenTelemetryCollector/CoreDiagnostics/Commands/CommandHandlerActivity.cs b/src/BuildingBlocks/OpenTelemetryCollector/CoreDiagnostics/Commands/CommandHandlerActivity.cs new file mode 100644 index 00000000..c136ff34 --- /dev/null +++ b/src/BuildingBlocks/OpenTelemetryCollector/CoreDiagnostics/Commands/CommandHandlerActivity.cs @@ -0,0 +1,86 @@ +using System.Diagnostics; +using BuildingBlocks.Core.CQRS; +using BuildingBlocks.OpenTelemetryCollector.DiagnosticsProvider; + +namespace BuildingBlocks.OpenTelemetryCollector.CoreDiagnostics.Commands; + +public class CommandHandlerActivity(IDiagnosticsProvider diagnosticsProvider) +{ + public async Task Execute( + Func action, + CancellationToken cancellationToken + ) + { + var commandName = typeof(TCommand).Name; + var handlerType = typeof(TCommand) + .Assembly.GetTypes() + .FirstOrDefault(t => + t.GetInterfaces() + .Any(i => + i.IsGenericType + && i.GetGenericTypeDefinition() == typeof(ICommandHandler<,>) + && i.GetGenericArguments()[0] == typeof(TCommand) + ) + ); + var commandHandlerName = handlerType?.Name; + + // usually we use class/methodName + var activityName = $"{ObservabilityConstant.Components.CommandHandler}.{commandHandlerName}/{commandName}"; + + await diagnosticsProvider.ExecuteActivityAsync( + new CreateActivityInfo + { + Name = activityName, + ActivityKind = ActivityKind.Consumer, + Tags = new Dictionary + { + { TelemetryTags.Tracing.Application.Commands.Command, commandName }, + { TelemetryTags.Tracing.Application.Commands.CommandType, typeof(TCommand).FullName }, + { TelemetryTags.Tracing.Application.Commands.CommandHandler, commandHandlerName }, + { TelemetryTags.Tracing.Application.Commands.CommandHandlerType, handlerType?.FullName }, + }, + }, + action, + cancellationToken + ); + } + + public async Task Execute( + Func> action, + CancellationToken cancellationToken + ) + { + var commandName = typeof(TCommand).Name; + var handlerType = typeof(TCommand) + .Assembly.GetTypes() + .FirstOrDefault(t => + t.GetInterfaces() + .Any(i => + i.IsGenericType + && i.GetGenericTypeDefinition() == typeof(ICommandHandler<,>) + && i.GetGenericArguments()[0] == typeof(TCommand) + ) + ); + var commandHandlerName = handlerType?.Name; + + // usually we use class/methodName + var activityName = $"{ObservabilityConstant.Components.CommandHandler}.{commandHandlerName}/{commandName}"; + + return await diagnosticsProvider.ExecuteActivityAsync( + new CreateActivityInfo + { + Name = activityName, + ActivityKind = ActivityKind.Consumer, + Tags = new Dictionary + { + { TelemetryTags.Tracing.Application.Commands.Command, commandName }, + { TelemetryTags.Tracing.Application.Commands.CommandType, typeof(TCommand).FullName }, + { TelemetryTags.Tracing.Application.Commands.CommandHandler, commandHandlerName }, + { TelemetryTags.Tracing.Application.Commands.CommandHandlerType, handlerType?.FullName }, + }, + }, + action, + cancellationToken + ); + } +} diff --git a/src/BuildingBlocks/OpenTelemetryCollector/CoreDiagnostics/Commands/CommandHandlerMetrics.cs b/src/BuildingBlocks/OpenTelemetryCollector/CoreDiagnostics/Commands/CommandHandlerMetrics.cs new file mode 100644 index 00000000..1fc87acd --- /dev/null +++ b/src/BuildingBlocks/OpenTelemetryCollector/CoreDiagnostics/Commands/CommandHandlerMetrics.cs @@ -0,0 +1,157 @@ +using System.Diagnostics; +using System.Diagnostics.Metrics; +using BuildingBlocks.Core.CQRS; +using BuildingBlocks.OpenTelemetryCollector; +using BuildingBlocks.OpenTelemetryCollector.DiagnosticsProvider; + +namespace BuildingBlocks.OpenTelemetryCollector.CoreDiagnostics.Commands; + +public class CommandHandlerMetrics +{ + private readonly UpDownCounter _activeCommandsCounter; + private readonly Counter _totalCommandsNumber; + private readonly Counter _successCommandsNumber; + private readonly Counter _failedCommandsNumber; + private readonly Histogram _handlerDuration; + + private Stopwatch _timer; + + public CommandHandlerMetrics(IDiagnosticsProvider diagnosticsProvider) + { + _activeCommandsCounter = diagnosticsProvider.Meter.CreateUpDownCounter( + TelemetryTags.Metrics.Application.Commands.ActiveCount, + unit: "{active_commands}", + description: "Number of commands currently being handled" + ); + + _totalCommandsNumber = diagnosticsProvider.Meter.CreateCounter( + TelemetryTags.Metrics.Application.Commands.TotalExecutedCount, + unit: "{total_commands}", + description: "Total number of executed command that sent to command handlers" + ); + + _successCommandsNumber = diagnosticsProvider.Meter.CreateCounter( + TelemetryTags.Metrics.Application.Commands.SuccessCount, + unit: "{success_commands}", + description: "Number commands that handled successfully" + ); + + _failedCommandsNumber = diagnosticsProvider.Meter.CreateCounter( + TelemetryTags.Metrics.Application.Commands.FaildCount, + unit: "{failed_commands}", + description: "Number commands that handled with errors" + ); + + _handlerDuration = diagnosticsProvider.Meter.CreateHistogram( + TelemetryTags.Metrics.Application.Commands.HandlerDuration, + unit: "s", + description: "Measures the duration of command handler" + ); + } + + public void StartExecuting() + { + var commandName = typeof(TCommand).Name; + var handlerType = typeof(TCommand) + .Assembly.GetTypes() + .FirstOrDefault(t => + t.GetInterfaces() + .Any(i => + i.IsGenericType + && i.GetGenericTypeDefinition() == typeof(ICommandHandler<,>) + && i.GetGenericArguments()[0] == typeof(TCommand) + ) + ); + var commandHandlerName = handlerType?.Name; + + var tags = new TagList + { + { TelemetryTags.Tracing.Application.Commands.Command, commandName }, + { TelemetryTags.Tracing.Application.Commands.CommandType, typeof(TCommand).FullName }, + { TelemetryTags.Tracing.Application.Commands.CommandHandler, commandHandlerName }, + { TelemetryTags.Tracing.Application.Commands.CommandHandlerType, handlerType?.FullName }, + }; + + if (_activeCommandsCounter.Enabled) + { + _activeCommandsCounter.Add(1, tags); + } + + if (_totalCommandsNumber.Enabled) + { + _totalCommandsNumber.Add(1, tags); + } + + _timer = Stopwatch.StartNew(); + } + + public void FinishExecuting() + { + var commandName = typeof(TCommand).Name; + var handlerType = typeof(TCommand) + .Assembly.GetTypes() + .FirstOrDefault(t => + t.GetInterfaces() + .Any(i => + i.IsGenericType + && i.GetGenericTypeDefinition() == typeof(ICommandHandler<,>) + && i.GetGenericArguments()[0] == typeof(TCommand) + ) + ); + var commandHandlerName = handlerType?.Name; + + var tags = new TagList + { + { TelemetryTags.Tracing.Application.Commands.Command, commandName }, + { TelemetryTags.Tracing.Application.Commands.CommandType, typeof(TCommand).FullName }, + { TelemetryTags.Tracing.Application.Commands.CommandHandler, commandHandlerName }, + { TelemetryTags.Tracing.Application.Commands.CommandHandlerType, handlerType?.FullName }, + }; + + if (_activeCommandsCounter.Enabled) + { + _activeCommandsCounter.Add(-1, tags); + } + + if (!_handlerDuration.Enabled) + return; + + var elapsedTimeSeconds = _timer.Elapsed.Seconds; + + _handlerDuration.Record(elapsedTimeSeconds, tags); + + if (_successCommandsNumber.Enabled) + { + _successCommandsNumber.Add(1, tags); + } + } + + public void FailedCommand() + { + var commandName = typeof(TCommand).Name; + var handlerType = typeof(TCommand) + .Assembly.GetTypes() + .FirstOrDefault(t => + t.GetInterfaces() + .Any(i => + i.IsGenericType + && i.GetGenericTypeDefinition() == typeof(ICommandHandler<,>) + && i.GetGenericArguments()[0] == typeof(TCommand) + ) + ); + var commandHandlerName = handlerType?.Name; + + var tags = new TagList + { + { TelemetryTags.Tracing.Application.Commands.Command, commandName }, + { TelemetryTags.Tracing.Application.Commands.CommandType, typeof(TCommand).FullName }, + { TelemetryTags.Tracing.Application.Commands.CommandHandler, commandHandlerName }, + { TelemetryTags.Tracing.Application.Commands.CommandHandlerType, handlerType?.FullName }, + }; + + if (_failedCommandsNumber.Enabled) + { + _failedCommandsNumber.Add(1, tags); + } + } +} diff --git a/src/BuildingBlocks/OpenTelemetryCollector/CoreDiagnostics/Query/QueryHandlerActivity.cs b/src/BuildingBlocks/OpenTelemetryCollector/CoreDiagnostics/Query/QueryHandlerActivity.cs new file mode 100644 index 00000000..3d5b0372 --- /dev/null +++ b/src/BuildingBlocks/OpenTelemetryCollector/CoreDiagnostics/Query/QueryHandlerActivity.cs @@ -0,0 +1,47 @@ +using System.Diagnostics; +using BuildingBlocks.Core.CQRS; +using BuildingBlocks.OpenTelemetryCollector.DiagnosticsProvider; + +namespace BuildingBlocks.OpenTelemetryCollector.CoreDiagnostics.Query; + +public class QueryHandlerActivity(IDiagnosticsProvider diagnosticsProvider) +{ + public async Task Execute( + Func> action, + CancellationToken cancellationToken + ) + { + var queryName = typeof(TQuery).Name; + var handlerType = typeof(TQuery) + .Assembly.GetTypes() + .FirstOrDefault(t => + t.GetInterfaces() + .Any(i => + i.IsGenericType + && i.GetGenericTypeDefinition() == typeof(IQueryHandler<,>) + && i.GetGenericArguments()[0] == typeof(TQuery) + ) + ); + var queryHandlerName = handlerType?.Name; + + // usually we use class/methodName + var activityName = $"{ObservabilityConstant.Components.QueryHandler}.{queryHandlerName}/{queryName}"; + + return await diagnosticsProvider.ExecuteActivityAsync( + new CreateActivityInfo + { + Name = activityName, + ActivityKind = ActivityKind.Consumer, + Tags = new Dictionary + { + { TelemetryTags.Tracing.Application.Queries.Query, queryName }, + { TelemetryTags.Tracing.Application.Queries.QueryType, typeof(TQuery).FullName }, + { TelemetryTags.Tracing.Application.Queries.QueryHandler, queryHandlerName }, + { TelemetryTags.Tracing.Application.Queries.QueryHandlerType, handlerType?.FullName }, + }, + }, + action, + cancellationToken + ); + } +} diff --git a/src/BuildingBlocks/OpenTelemetryCollector/CoreDiagnostics/Query/QueryHandlerMetrics.cs b/src/BuildingBlocks/OpenTelemetryCollector/CoreDiagnostics/Query/QueryHandlerMetrics.cs new file mode 100644 index 00000000..eaea5dde --- /dev/null +++ b/src/BuildingBlocks/OpenTelemetryCollector/CoreDiagnostics/Query/QueryHandlerMetrics.cs @@ -0,0 +1,156 @@ +using System.Diagnostics; +using System.Diagnostics.Metrics; +using BuildingBlocks.Core.CQRS; +using BuildingBlocks.OpenTelemetryCollector.DiagnosticsProvider; + +namespace BuildingBlocks.OpenTelemetryCollector.CoreDiagnostics.Query; + +public class QueryHandlerMetrics +{ + private readonly UpDownCounter _activeQueriesCounter; + private readonly Counter _totalQueriesNumber; + private readonly Counter _successQueriesNumber; + private readonly Counter _failedQueriesNumber; + private readonly Histogram _handlerDuration; + + private Stopwatch _timer; + + public QueryHandlerMetrics(IDiagnosticsProvider diagnosticsProvider) + { + _activeQueriesCounter = diagnosticsProvider.Meter.CreateUpDownCounter( + TelemetryTags.Metrics.Application.Commands.ActiveCount, + unit: "{active_queries}", + description: "Number of queries currently being handled" + ); + + _totalQueriesNumber = diagnosticsProvider.Meter.CreateCounter( + TelemetryTags.Metrics.Application.Commands.TotalExecutedCount, + unit: "{total_queries}", + description: "Total number of executed query that sent to query handlers" + ); + + _successQueriesNumber = diagnosticsProvider.Meter.CreateCounter( + TelemetryTags.Metrics.Application.Commands.SuccessCount, + unit: "{success_queries}", + description: "Number queries that handled successfully" + ); + + _failedQueriesNumber = diagnosticsProvider.Meter.CreateCounter( + TelemetryTags.Metrics.Application.Commands.FaildCount, + unit: "{failed_queries}", + description: "Number queries that handled with errors" + ); + + _handlerDuration = diagnosticsProvider.Meter.CreateHistogram( + TelemetryTags.Metrics.Application.Commands.HandlerDuration, + unit: "s", + description: "Measures the duration of query handler" + ); + } + + public void StartExecuting() + { + var queryName = typeof(TQuery).Name; + var handlerType = typeof(TQuery) + .Assembly.GetTypes() + .FirstOrDefault(t => + t.GetInterfaces() + .Any(i => + i.IsGenericType + && i.GetGenericTypeDefinition() == typeof(IQueryHandler<,>) + && i.GetGenericArguments()[0] == typeof(TQuery) + ) + ); + var queryHandlerName = handlerType?.Name; + + var tags = new TagList + { + { TelemetryTags.Tracing.Application.Queries.Query, queryName }, + { TelemetryTags.Tracing.Application.Queries.QueryType, typeof(TQuery).FullName }, + { TelemetryTags.Tracing.Application.Queries.QueryHandler, queryHandlerName }, + { TelemetryTags.Tracing.Application.Queries.QueryHandlerType, handlerType?.FullName }, + }; + + if (_activeQueriesCounter.Enabled) + { + _activeQueriesCounter.Add(1, tags); + } + + if (_totalQueriesNumber.Enabled) + { + _totalQueriesNumber.Add(1, tags); + } + + _timer = Stopwatch.StartNew(); + } + + public void FinishExecuting() + { + var queryName = typeof(TQuery).Name; + var handlerType = typeof(TQuery) + .Assembly.GetTypes() + .FirstOrDefault(t => + t.GetInterfaces() + .Any(i => + i.IsGenericType + && i.GetGenericTypeDefinition() == typeof(IQueryHandler<,>) + && i.GetGenericArguments()[0] == typeof(TQuery) + ) + ); + var queryHandlerName = handlerType?.Name; + + var tags = new TagList + { + { TelemetryTags.Tracing.Application.Queries.Query, queryName }, + { TelemetryTags.Tracing.Application.Queries.QueryType, typeof(TQuery).FullName }, + { TelemetryTags.Tracing.Application.Queries.QueryHandler, queryHandlerName }, + { TelemetryTags.Tracing.Application.Queries.QueryHandlerType, handlerType?.FullName }, + }; + + if (_activeQueriesCounter.Enabled) + { + _activeQueriesCounter.Add(-1, tags); + } + + if (!_handlerDuration.Enabled) + return; + + var elapsedTimeSeconds = _timer.Elapsed.Seconds; + + _handlerDuration.Record(elapsedTimeSeconds, tags); + + if (_successQueriesNumber.Enabled) + { + _successQueriesNumber.Add(1, tags); + } + } + + public void FailedCommand() + { + var queryName = typeof(TQuery).Name; + var handlerType = typeof(TQuery) + .Assembly.GetTypes() + .FirstOrDefault(t => + t.GetInterfaces() + .Any(i => + i.IsGenericType + && i.GetGenericTypeDefinition() == typeof(IQueryHandler<,>) + && i.GetGenericArguments()[0] == typeof(TQuery) + ) + ); + var queryHandlerName = handlerType?.Name; + + var tags = new TagList + { + { TelemetryTags.Tracing.Application.Queries.Query, queryName }, + { TelemetryTags.Tracing.Application.Queries.QueryType, typeof(TQuery).FullName }, + { TelemetryTags.Tracing.Application.Queries.QueryHandler, queryHandlerName }, + { TelemetryTags.Tracing.Application.Queries.QueryHandlerType, handlerType?.FullName }, + }; + + if (_failedQueriesNumber.Enabled) + { + _failedQueriesNumber.Add(1, tags); + } + } +} diff --git a/src/BuildingBlocks/OpenTelemetryCollector/CreateActivityInfo.cs b/src/BuildingBlocks/OpenTelemetryCollector/CreateActivityInfo.cs new file mode 100644 index 00000000..bbaa8ab8 --- /dev/null +++ b/src/BuildingBlocks/OpenTelemetryCollector/CreateActivityInfo.cs @@ -0,0 +1,12 @@ +using System.Diagnostics; + +namespace BuildingBlocks.OpenTelemetryCollector; + +public class CreateActivityInfo +{ + public required string Name { get; set; } + public IDictionary Tags { get; set; } = new Dictionary(); + public string? ParentId { get; set; } + public ActivityContext? Parent { get; set; } + public required ActivityKind ActivityKind = ActivityKind.Internal; +} diff --git a/src/BuildingBlocks/OpenTelemetryCollector/DiagnosticsProvider/CustomeDiagnosticsProvider.cs b/src/BuildingBlocks/OpenTelemetryCollector/DiagnosticsProvider/CustomeDiagnosticsProvider.cs new file mode 100644 index 00000000..abbcc7f3 --- /dev/null +++ b/src/BuildingBlocks/OpenTelemetryCollector/DiagnosticsProvider/CustomeDiagnosticsProvider.cs @@ -0,0 +1,132 @@ +using System.Diagnostics; +using System.Diagnostics.Metrics; +using System.Reflection; +using Microsoft.Extensions.Options; + +namespace BuildingBlocks.OpenTelemetryCollector.DiagnosticsProvider; + +public class CustomeDiagnosticsProvider(IMeterFactory meterFactory, IOptions options) + : IDiagnosticsProvider +{ + private readonly Version? _version = Assembly.GetCallingAssembly().GetName().Version; + private ActivitySource? _activitySource; + private ActivityListener? _listener; + private Meter? _meter; + + public string InstrumentationName { get; } = options.Value.InstrumentationName ?? throw new ArgumentException("InstrumentationName cannot be null or empty."); + + // https://learn.microsoft.com/en-us/dotnet/core/diagnostics/distributed-tracing-instrumentation-walkthroughs + public ActivitySource ActivitySource + { + get + { + if (_activitySource != null) + return _activitySource; + + _activitySource = new(InstrumentationName, _version?.ToString()); + + _listener = new ActivityListener + { + ShouldListenTo = x => true, + Sample = (ref ActivityCreationOptions _) => ActivitySamplingResult.AllDataAndRecorded, + }; + ActivitySource.AddActivityListener(_listener); + + return _activitySource; + } + } + + // https://learn.microsoft.com/en-us/dotnet/core/diagnostics/metrics-instrumentation + public Meter Meter + { + get + { + if (_meter != null) + return _meter; + + _meter = meterFactory.Create(InstrumentationName, _version?.ToString()); + + return _meter; + } + } + + public async Task ExecuteActivityAsync( + CreateActivityInfo createActivityInfo, + Func action, + CancellationToken cancellationToken = default + ) + { + if (!options.Value.TracingEnabled) + { + await action(null, cancellationToken); + + return; + } + + using var activity = + ActivitySource + .CreateActivity( + name: $"{InstrumentationName}.{createActivityInfo.Name}", + kind: createActivityInfo.ActivityKind, + parentContext: createActivityInfo.Parent ?? default, + idFormat: ActivityIdFormat.W3C, + tags: createActivityInfo.Tags + ) + ?.Start() ?? Activity.Current; + + try + { + await action(activity!, cancellationToken); + activity?.SetOkStatus(); + } + catch (System.Exception ex) + { + activity?.SetErrorStatus(ex); + throw; + } + } + + public async Task ExecuteActivityAsync( + CreateActivityInfo createActivityInfo, + Func> action, + CancellationToken cancellationToken = default + ) + { + if (!options.Value.TracingEnabled) + { + return await action(null, cancellationToken); + } + + using var activity = + ActivitySource + .CreateActivity( + name: $"{InstrumentationName}.{createActivityInfo.Name}", + kind: createActivityInfo.ActivityKind, + parentContext: createActivityInfo.Parent ?? default, + idFormat: ActivityIdFormat.W3C, + tags: createActivityInfo.Tags + ) + ?.Start() ?? Activity.Current; + + try + { + var result = await action(activity!, cancellationToken); + + activity?.SetOkStatus(); + + return result; + } + catch (System.Exception ex) + { + activity?.SetErrorStatus(ex); + throw; + } + } + + public void Dispose() + { + _listener?.Dispose(); + _meter?.Dispose(); + _activitySource?.Dispose(); + } +} diff --git a/src/BuildingBlocks/OpenTelemetryCollector/DiagnosticsProvider/IDiagnosticsProvider.cs b/src/BuildingBlocks/OpenTelemetryCollector/DiagnosticsProvider/IDiagnosticsProvider.cs new file mode 100644 index 00000000..32cb70dd --- /dev/null +++ b/src/BuildingBlocks/OpenTelemetryCollector/DiagnosticsProvider/IDiagnosticsProvider.cs @@ -0,0 +1,23 @@ +using System.Diagnostics; +using System.Diagnostics.Metrics; + +namespace BuildingBlocks.OpenTelemetryCollector.DiagnosticsProvider; + +public interface IDiagnosticsProvider : IDisposable +{ + string InstrumentationName { get; } + ActivitySource ActivitySource { get; } + Meter Meter { get; } + + Task ExecuteActivityAsync( + CreateActivityInfo createActivityInfo, + Func action, + CancellationToken cancellationToken = default + ); + + Task ExecuteActivityAsync( + CreateActivityInfo createActivityInfo, + Func> action, + CancellationToken cancellationToken = default + ); +} diff --git a/src/BuildingBlocks/OpenTelemetryCollector/Extensions.cs b/src/BuildingBlocks/OpenTelemetryCollector/Extensions.cs new file mode 100644 index 00000000..04bf73ba --- /dev/null +++ b/src/BuildingBlocks/OpenTelemetryCollector/Extensions.cs @@ -0,0 +1,358 @@ +using System.Diagnostics; +using System.Reflection; +using BuildingBlocks.OpenTelemetryCollector.CoreDiagnostics.Commands; +using BuildingBlocks.OpenTelemetryCollector.CoreDiagnostics.Query; +using BuildingBlocks.OpenTelemetryCollector.DiagnosticsProvider; +using BuildingBlocks.Web; +using Grafana.OpenTelemetry; +using MassTransit.Logging; +using MassTransit.Monitoring; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http.Features; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Npgsql; +using OpenTelemetry; +using OpenTelemetry.Exporter; +using OpenTelemetry.Logs; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; + +namespace BuildingBlocks.OpenTelemetryCollector; + +// https://learn.microsoft.com/en-us/dotnet/core/diagnostics/observability-otlp-example +// https://learn.microsoft.com/en-us/dotnet/core/diagnostics/observability-prgrja-example +// https://learn.microsoft.com/en-us/dotnet/core/diagnostics/observability-prgrja-example +// https://blog.codingmilitia.com/2023/09/05/observing-dotnet-microservices-with-opentelemetry-logs-traces-metrics/ +public static class Extensions +{ + public static WebApplicationBuilder AddCustomObservability(this WebApplicationBuilder builder) + { + + Activity.DefaultIdFormat = ActivityIdFormat.W3C; + builder.Services.AddSingleton(); + builder.AddCoreDiagnostics(); + + builder.Services.AddValidateOptions(); + var observabilityOptions = builder.Services.GetOptions(nameof(ObservabilityOptions)); + + // InstrumentationName property option is mandatory and can't be empty + ArgumentException.ThrowIfNullOrEmpty(observabilityOptions.InstrumentationName); + ObservabilityConstant.InstrumentationName = observabilityOptions.InstrumentationName; + + if (observabilityOptions is { MetricsEnabled: false, TracingEnabled: false, LoggingEnabled: false }) + { + return builder; + } + + void ConfigureResourceBuilder(ResourceBuilder resourceBuilder) + { + resourceBuilder.AddAttributes([new("service.environment", builder.Environment.EnvironmentName)]); + + resourceBuilder.AddService( + serviceName: observabilityOptions.ServiceName ?? builder.Environment.ApplicationName, + serviceVersion: Assembly.GetCallingAssembly().GetName().Version?.ToString() ?? "unknown", + serviceInstanceId: Environment.MachineName + ); + } + + if (observabilityOptions.LoggingEnabled) + { + // logging + // opentelemtry logging works with .net default logging providers and doesn't work for `serilog`, in serilog we should enable `WriteToProviders=true` + builder.Logging.AddOpenTelemetry(options => + { + var resourceBuilder = ResourceBuilder.CreateDefault(); + ConfigureResourceBuilder(resourceBuilder); + options.SetResourceBuilder(resourceBuilder); + + options.IncludeFormattedMessage = true; + options.IncludeScopes = true; + // this allows the state value passed to the logger.Log method to be parsed, in case it isn't a collection of KeyValuePair, which is the case when we use things like logger.LogInformation. + options.ParseStateValues = true; + // which means the message wouldn't have the placeholders replaced + options.IncludeFormattedMessage = true; + + // add some metadata to exported logs + options.SetResourceBuilder( + ResourceBuilder + .CreateDefault() + .AddService( + observabilityOptions.ServiceName ?? builder.Environment.ApplicationName, + serviceVersion: Assembly.GetCallingAssembly().GetName().Version?.ToString() ?? "unknown", + serviceInstanceId: Environment.MachineName + ) + ); + + options.AddLoggingExporters(observabilityOptions); + }); + } + + if (observabilityOptions is { MetricsEnabled: false, TracingEnabled: false }) + { + return builder; + } + + OpenTelemetryBuilder otel = null!; + + if (observabilityOptions.MetricsEnabled || observabilityOptions.TracingEnabled) + { + // metrics and tracing + otel = builder.Services.AddOpenTelemetry(); + otel.ConfigureResource(ConfigureResourceBuilder); + } + + if (observabilityOptions.MetricsEnabled) + { + otel.WithMetrics(metrics => + { + metrics + .AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddProcessInstrumentation() + .AddRuntimeInstrumentation() + .AddMeter(InstrumentationOptions.MeterName) + .AddMeter(observabilityOptions.InstrumentationName) + // metrics provides by ASP.NET Core in .NET 8 + .AddView( + "http.server.request.duration", + new ExplicitBucketHistogramConfiguration + { + Boundaries = [0, 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10], + } + ) + .AddMeter("System.Runtime") + .AddMeter("Microsoft.AspNetCore.Hosting") + .AddMeter("Microsoft.AspNetCore.Server.Kestrel"); + + AddMetricsExporter(observabilityOptions, metrics); + }); + } + + if (observabilityOptions.TracingEnabled) + { + otel.WithTracing(tracing => + { + if (builder.Environment.IsDevelopment()) + { + // We want to view all traces in development + tracing.SetSampler(new AlwaysOnSampler()); + } + + tracing + .SetErrorStatusOnException() + .AddAspNetCoreInstrumentation(options => + { + options.RecordException = true; + }) + .AddGrpcClientInstrumentation() + .AddHttpClientInstrumentation(instrumentationOptions => + { + instrumentationOptions.RecordException = true; + }) + .AddEntityFrameworkCoreInstrumentation(instrumentationOptions => + { + instrumentationOptions.SetDbStatementForText = true; + }) + .AddSource(DiagnosticHeaders.DefaultListenerName) + .AddNpgsql() + // `AddSource` for adding custom activity sources + .AddSource(observabilityOptions.InstrumentationName) + // metrics provides by ASP.NET Core in .NET 8 + .AddSource("Microsoft.AspNetCore.Hosting") + .AddSource("Microsoft.AspNetCore.Server.Kestrel"); + + AddTracingExporter(observabilityOptions, tracing); + }); + } + + return builder; + } + + + public static WebApplication UseCustomObservability(this WebApplication app) + { + var options = app.Services.GetRequiredService>().Value; + + app.Use( + async (context, next) => + { + var metricsFeature = context.Features.Get(); + if (metricsFeature != null && context.Request.Path is { Value: "/metrics" or "/health" }) + { + metricsFeature.MetricsDisabled = true; + } + + await next(context); + } + ); + + if (options.UsePrometheusExporter) + { + // export application metrics in `/metrics` endpoint and should scrape in the Prometheus config file and `scrape_configs` + // https://github.com/open-telemetry/opentelemetry-dotnet/tree/e330e57b04fa3e51fe5d63b52bfff891fb5b7961/src/OpenTelemetry.Exporter.Prometheus.AspNetCore + app.UseOpenTelemetryPrometheusScrapingEndpoint(); // http://localhost:4000/metrics + } + + return app; + } + + private static void AddTracingExporter(ObservabilityOptions observabilityOptions, TracerProviderBuilder tracing) + { + if (observabilityOptions.UseJaegerExporter) + { + ArgumentNullException.ThrowIfNull(observabilityOptions.JaegerOptions); + // https://github.com/open-telemetry/opentelemetry-dotnet/tree/e330e57b04fa3e51fe5d63b52bfff891fb5b7961/docs/trace/getting-started-jaeger + // `OpenTelemetry.Exporter.Jaeger` package and `AddJaegerExporter` to use Http endpoint (http://localhost:14268/api/traces) is deprecated, and we should use `OpenTelemetry.Exporter.OpenTelemetryProtocol` and `AddOtlpExporter` with OTLP port `4317` on Jaeger + // tracing.AddJaegerExporter( + // x => x.Endpoint = new Uri(observabilityOptions.JaegerOptions.HttpExporterEndpoint)); // http://localhost:14268/api/traces + tracing.AddOtlpExporter(x => + { + x.Endpoint = new Uri(observabilityOptions.JaegerOptions.OTLPGrpcExporterEndpoint); + x.Protocol = OtlpExportProtocol.Grpc; + }); + } + + if (observabilityOptions.UseZipkinExporter) + { + ArgumentNullException.ThrowIfNull(observabilityOptions.ZipkinOptions); + // https://github.com/open-telemetry/opentelemetry-dotnet/tree/e330e57b04fa3e51fe5d63b52bfff891fb5b7961/src/OpenTelemetry.Exporter.Zipkin + tracing.AddZipkinExporter(x => + x.Endpoint = new Uri(observabilityOptions.ZipkinOptions.HttpExporterEndpoint) + ); // "http://localhost:9411/api/v2/spans" + } + + if (observabilityOptions.UseConsoleExporter) + { + tracing.AddConsoleExporter(); + } + + if (observabilityOptions.UseOTLPExporter) + { + ArgumentNullException.ThrowIfNull(observabilityOptions.OTLPOptions); + tracing.AddOtlpExporter(x => + { + x.Endpoint = new Uri(observabilityOptions.OTLPOptions.OTLPGrpcExporterEndpoint); + x.Protocol = OtlpExportProtocol.Grpc; + }); + } + + if (observabilityOptions.UseAspireOTLPExporter) + { + // we can just one `AddOtlpExporter` and in development use `aspire-dashboard` OTLP endpoint address as `OTLPExporterEndpoint` and in production we can use `otel-collector` OTLP endpoint address + ArgumentNullException.ThrowIfNull(observabilityOptions.OTLPOptions); + tracing.AddOtlpExporter(x => + { + x.Endpoint = new Uri(observabilityOptions.AspireDashboardOTLPOptions.OTLPGrpcExporterEndpoint); + x.Protocol = OtlpExportProtocol.Grpc; + }); + } + + if (observabilityOptions.UseGrafanaExporter) + { + // https://github.com/grafana/grafana-opentelemetry-dotnet/blob/main/docs/configuration.md#aspnet-core + // https://github.com/grafana/grafana-opentelemetry-dotnet/ + // https://github.com/grafana/grafana-opentelemetry-dotnet/blob/main/docs/configuration.md#sending-to-an-agent-or-collector-via-otlp + // https://grafana.com/docs/grafana-cloud/monitor-applications/application-observability/instrument/dotnet/ + tracing.UseGrafana(); + } + } + + private static void AddMetricsExporter(ObservabilityOptions observabilityOptions, MeterProviderBuilder metrics) + { + if (observabilityOptions.UsePrometheusExporter) + { + // https://github.com/open-telemetry/opentelemetry-dotnet/tree/e330e57b04fa3e51fe5d63b52bfff891fb5b7961/src/OpenTelemetry.Exporter.Prometheus.AspNetCore + // for exporting app metrics to `/metrics` endpoint + metrics.AddPrometheusExporter(o => o.DisableTotalNameSuffixForCounters = true); // http://localhost:4000/metrics + } + + if (observabilityOptions.UseConsoleExporter) + { + metrics.AddConsoleExporter(); + } + + if (observabilityOptions.UseOTLPExporter) + { + ArgumentNullException.ThrowIfNull(observabilityOptions.OTLPOptions); + metrics.AddOtlpExporter(x => + { + x.Endpoint = new Uri(observabilityOptions.OTLPOptions.OTLPGrpcExporterEndpoint); + x.Protocol = OtlpExportProtocol.Grpc; + }); + } + + if (observabilityOptions.UseAspireOTLPExporter) + { + // we can just one `AddOtlpExporter` and in development use `aspire-dashboard` OTLP endpoint address as `OTLPExporterEndpoint` and in production we can use `otel-collector` OTLP endpoint address + ArgumentNullException.ThrowIfNull(observabilityOptions.OTLPOptions); + metrics.AddOtlpExporter(x => + { + x.Endpoint = new Uri(observabilityOptions.AspireDashboardOTLPOptions.OTLPGrpcExporterEndpoint); + x.Protocol = OtlpExportProtocol.Grpc; + }); + } + + if (observabilityOptions.UseGrafanaExporter) + { + // https://github.com/grafana/grafana-opentelemetry-dotnet/blob/main/docs/configuration.md#aspnet-core + // https://github.com/grafana/grafana-opentelemetry-dotnet/ + // https://github.com/grafana/grafana-opentelemetry-dotnet/blob/main/docs/configuration.md#sending-to-an-agent-or-collector-via-otlp + // https://grafana.com/docs/grafana-cloud/monitor-applications/application-observability/instrument/dotnet/ + metrics.UseGrafana(); + } + } + + private static void AddLoggingExporters( + this OpenTelemetryLoggerOptions openTelemetryLoggerOptions, + ObservabilityOptions observabilityOptions + ) + { + if (observabilityOptions.UseOTLPExporter) + { + ArgumentNullException.ThrowIfNull(observabilityOptions.OTLPOptions); + openTelemetryLoggerOptions.AddOtlpExporter(options => + { + options.Endpoint = new Uri(observabilityOptions.OTLPOptions.OTLPGrpcExporterEndpoint); + options.Protocol = OtlpExportProtocol.Grpc; + }); + } + + if (observabilityOptions.UseAspireOTLPExporter) + { + // we can just one `AddOtlpExporter` and in development use `aspire-dashboard` OTLP endpoint address as `OTLPExporterEndpoint` and in production we can use `otel-collector` OTLP endpoint address + ArgumentNullException.ThrowIfNull(observabilityOptions.OTLPOptions); + openTelemetryLoggerOptions.AddOtlpExporter(x => + { + x.Endpoint = new Uri(observabilityOptions.AspireDashboardOTLPOptions.OTLPGrpcExporterEndpoint); + x.Protocol = OtlpExportProtocol.Grpc; + }); + } + + if (observabilityOptions.UseGrafanaExporter) + { + // https://github.com/grafana/grafana-opentelemetry-dotnet/ + // https://github.com/grafana/grafana-opentelemetry-dotnet/blob/main/docs/configuration.md#aspnet-core + // https://grafana.com/docs/grafana-cloud/monitor-applications/application-observability/instrument/dotnet/ + openTelemetryLoggerOptions.UseGrafana(); + } + + if (observabilityOptions.UseConsoleExporter) + { + openTelemetryLoggerOptions.AddConsoleExporter(); + } + } + + private static WebApplicationBuilder AddCoreDiagnostics(this WebApplicationBuilder builder) + { + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + + return builder; + } +} diff --git a/src/BuildingBlocks/OpenTelemetryCollector/ObservabilityConstant.cs b/src/BuildingBlocks/OpenTelemetryCollector/ObservabilityConstant.cs new file mode 100644 index 00000000..319a97c9 --- /dev/null +++ b/src/BuildingBlocks/OpenTelemetryCollector/ObservabilityConstant.cs @@ -0,0 +1,16 @@ +namespace BuildingBlocks.OpenTelemetryCollector; + +public static class ObservabilityConstant +{ + public static string InstrumentationName = default!; + + public static class Components + { + public const string CommandHandler = "CommandHandler"; + public const string QueryHandler = "QueryHandler"; + public const string EventStore = "EventStore"; + public const string Producer = "Producer"; + public const string Consumer = "Consumer"; + public const string EventHandler = "EventHandler"; + } +} diff --git a/src/BuildingBlocks/OpenTelemetryCollector/ObservabilityOptions.cs b/src/BuildingBlocks/OpenTelemetryCollector/ObservabilityOptions.cs new file mode 100644 index 00000000..dca919a2 --- /dev/null +++ b/src/BuildingBlocks/OpenTelemetryCollector/ObservabilityOptions.cs @@ -0,0 +1,47 @@ +namespace BuildingBlocks.OpenTelemetryCollector; + +public class ObservabilityOptions +{ + public string InstrumentationName { get; set; } = default!; + public string? ServiceName { get; set; } + public bool MetricsEnabled { get; set; } = true; + public bool TracingEnabled { get; set; } = true; + public bool LoggingEnabled { get; set; } = true; + public bool UsePrometheusExporter { get; set; } = true; + public bool UseOTLPExporter { get; set; } = true; + public bool UseAspireOTLPExporter { get; set; } = true; + public bool UseGrafanaExporter { get; set; } + public bool UseConsoleExporter { get; set; } + public bool UseJaegerExporter { get; set; } + public bool UseZipkinExporter { get; set; } + public ZipkinOptions ZipkinOptions { get; set; } = default!; + public JaegerOptions JaegerOptions { get; set; } = default!; + public OTLPOptions OTLPOptions { get; set; } = default!; + public AspireDashboardOTLPOptions AspireDashboardOTLPOptions { get; set; } = default!; +} + +// https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry.Exporter.Zipkin/README.md +public class ZipkinOptions +{ + /// + /// Gets or sets endpoint address to receive telemetry + /// + public string HttpExporterEndpoint { get; set; } = "http://localhost:9411/api/v2/spans"; +} + +public class JaegerOptions +{ + public string OTLPGrpcExporterEndpoint { get; set; } = "http://localhost:14317"; + public string HttpExporterEndpoint { get; set; } = "http://localhost:14268/api/traces"; +} + +public class OTLPOptions +{ + public string OTLPGrpcExporterEndpoint { get; set; } = "http://localhost:4317"; + public string OTLPHttpExporterEndpoint { get; set; } = "http://localhost:4318"; +} + +public class AspireDashboardOTLPOptions +{ + public string OTLPGrpcExporterEndpoint { get; set; } = "http://localhost:4319"; +} diff --git a/src/BuildingBlocks/OpenTelemetryCollector/TelemetryTags.cs b/src/BuildingBlocks/OpenTelemetryCollector/TelemetryTags.cs new file mode 100644 index 00000000..7cf27874 --- /dev/null +++ b/src/BuildingBlocks/OpenTelemetryCollector/TelemetryTags.cs @@ -0,0 +1,265 @@ +namespace BuildingBlocks.OpenTelemetryCollector; + +/// +/// Telemetry tags use for adding tags to activities as tag name +/// +public static class TelemetryTags +{ + // https://opentelemetry.io/docs/specs/semconv/general/trace/ + // https://opentelemetry.io/docs/specs/semconv/general/attribute-naming/ + public static class Tracing + { + // https://opentelemetry.io/docs/specs/semconv/resource/#service + // https://opentelemetry.io/docs/specs/semconv/attributes-registry/peer/#peer-attributes + public static class Service + { + public const string PeerService = "peer.service"; + public const string Name = "service.name"; + public const string InstanceId = "service.instance.id"; + public const string Version = "service.version"; + public const string NameSpace = "service.namespace"; + } + + // https://opentelemetry.io/docs/specs/semconv/attributes-registry/messaging/#general-messaging-attributes + // https://opentelemetry.io/docs/specs/semconv/messaging/messaging-spans/ + public static class Messaging + { + // https://opentelemetry.io/docs/specs/semconv/attributes-registry/messaging/#messaging-operation-type + public static class OperationType + { + public const string Key = "messaging.operation.type"; + public const string Receive = "receive"; + public const string Send = "send"; + public const string Process = "process"; + } + + // https://opentelemetry.io/docs/specs/semconv/attributes-registry/messaging/#messaging-system + public static class System + { + public const string Key = "messaging.system"; + public const string ActiveMQ = "activemq"; + public const string RabbitMQ = "rabbitmq"; + public const string AwsSqs = "aws_sqs"; + public const string EventGrid = "eventgrid"; + public const string EventHubs = "eventhubs"; + public const string GcpPubSub = "gcp_pubsub"; + public const string Kafka = "kafka"; + public const string Pulsar = "pulsar"; + public const string ServiceBus = "servicebus"; + } + + public const string Destination = "messaging.destination"; + public const string DestinationKind = "messaging.destination_kind"; + public const string Url = "messaging.url"; + public const string MessageId = "messaging.message_id"; + public const string ConversationId = "messaging.conversation_id"; + public const string CorrelationId = "messaging.correlation_id"; + public const string CausationId = "messaging.causation_id"; + public const string Operation = "messaging.operation"; + public const string OperationName = "messaging.operation.name"; + public const string DestinationName = "messaging.destination.name"; + public const string ConsumerGroup = "messaging.consumer.group.name"; + public const string DestinationPartition = "messaging.destination.partition.id"; + + // https://opentelemetry.io/docs/specs/semconv/attributes-registry/messaging/#rabbitmq-attributes + // https://opentelemetry.io/docs/specs/semconv/messaging/rabbitmq/ + public static class RabbitMQ + { + public const string RoutingKey = "messaging.rabbitmq.destination.routing_key"; + public const string DeliveryTag = "messaging.rabbitmq.message.delivery_tag"; + + public static IDictionary ProducerTags( + string serviceName, + string topicName, + string routingKey, + string? deliveryTag = null + ) => + new Dictionary + { + { System.Key, System.Kafka }, + { DeliveryTag, deliveryTag }, + { Destination, topicName }, + { OperationType.Key, OperationType.Send }, + { Service.Name, serviceName }, + { RoutingKey, routingKey }, + }; + + public static IDictionary ConsumerTags( + string serviceName, + string topicName, + string routingKey, + string? consumerGroup = null + ) => + new Dictionary + { + { System.Key, System.Kafka }, + { Destination, topicName }, + { OperationType.Key, OperationType.Receive }, + { Service.Name, serviceName }, + { ConsumerGroup, consumerGroup }, + { RoutingKey, routingKey }, + }; + } + + // https://opentelemetry.io/docs/specs/semconv/attributes-registry/messaging/#kafka-attributes + // https://opentelemetry.io/docs/specs/semconv/messaging/kafka/ + public static class Kafka + { + public const string MessageKey = "messaging.kafka.message.key"; + public const string Tombstone = "messaging.kafka.message.tombstone"; + public const string Offset = "messaging.kafka.offset"; + + public static IDictionary ProducerTags( + string serviceName, + string topicName, + string messageKey + ) => + new Dictionary + { + { System.Key, System.Kafka }, + { Destination, topicName }, + { OperationType.Key, OperationType.Send }, + { Service.Name, serviceName }, + { MessageKey, messageKey }, + }; + + public static IDictionary ConsumerTags( + string serviceName, + string topicName, + string messageKey, + string partitionName, + string consumerGroup + ) => + new Dictionary + { + { System.Key, System.Kafka }, + { Destination, topicName }, + { OperationType.Key, OperationType.Receive }, + { Service.Name, serviceName }, + { MessageKey, messageKey }, + { DestinationPartition, partitionName }, + { ConsumerGroup, consumerGroup }, + }; + } + } + + // https://opentelemetry.io/docs/specs/semconv/database/database-spans/#common-attributes + // https://opentelemetry.io/docs/specs/semconv/database/postgresql/#attributes + public static class Db + { + public const string System = "db.system"; + public const string ConnectionString = "db.connection_string"; + public const string User = "db.user"; + public const string MsSqlInstanceName = "db.mssql.instance_name"; + public const string Name = "db.name"; + public const string Statement = "db.statement"; + public const string Operation = "db.operation"; + public const string Instance = "db.instance"; + public const string Url = "db.url"; + public const string CassandraKeyspace = "db.cassandra.keyspace"; + public const string RedisDatabaseIndex = "db.redis.database_index"; + public const string MongoDbCollection = "db.mongodb.collection"; + } + + // https://opentelemetry.io/docs/specs/semconv/exceptions/exceptions-spans/#exception-event + public static class Exception + { + public const string EventName = "exception"; + public const string Type = "exception.type"; + public const string Message = "exception.message"; + public const string Stacktrace = "exception.stacktrace"; + } + + // https://opentelemetry.io/docs/specs/semconv/attributes-registry/otel/#otel-attributes + public static class Otel + { + public const string StatusCode = "otel.status_code"; + public const string StatusDescription = "otel.status_description"; + } + + public static class Message + { + public const string Type = "message.type"; + public const string Id = "message.id"; + } + + public static class Application + { + public static string AppService = $"{ObservabilityConstant.InstrumentationName}.appservice"; + public static string Consumer = $"{ObservabilityConstant.InstrumentationName}.consumer"; + public static string Producer = $"{ObservabilityConstant.InstrumentationName}.producer"; + + public static class Commands + { + public static string Command = $"{ObservabilityConstant.InstrumentationName}.command"; + public static string CommandType = $"{Command}.type"; + public static string CommandHandler = $"{Command}.handler"; + public static string CommandHandlerType = $"{CommandHandler}.type"; + } + + public static class Queries + { + public static string Query = $"{ObservabilityConstant.InstrumentationName}.query"; + public static string QueryType = $"{Query}.type"; + public static string QueryHandler = $"{Query}.handler"; + public static string QueryHandlerType = $"{QueryHandler}.type"; + } + + public static class Events + { + public static string Event = $"{ObservabilityConstant.InstrumentationName}.event"; + public static string EventType = $"{Event}.type"; + public static string EventHandler = $"{Event}.handler"; + public static string EventHandlerType = $"{EventHandler}.type"; + } + } + } + + // https://opentelemetry.io/docs/specs/semconv/general/metrics/ + // https://opentelemetry.io/docs/specs/semconv/general/attribute-naming/ + public static class Metrics + { + public static class Application + { + public static string AppService = $"{ObservabilityConstant.InstrumentationName}.appservice"; + public static string Consumer = $"{ObservabilityConstant.InstrumentationName}.consumer"; + public static string Producer = $"{ObservabilityConstant.InstrumentationName}.producer"; + + public static class Commands + { + public static string Command = $"{ObservabilityConstant.InstrumentationName}.command"; + public static string CommandType = $"{Command}.type"; + public static string CommandHandler = $"{Command}.handler"; + public static string SuccessCount = $"{CommandHandler}.success.count"; + public static string FaildCount = $"{CommandHandler}.failed.count"; + public static string ActiveCount = $"{CommandHandler}.active.count"; + public static string TotalExecutedCount = $"{CommandHandler}.total.count"; + public static string HandlerDuration = $"{CommandHandler}.duration"; + } + + public static class Queries + { + public static string Query = $"{ObservabilityConstant.InstrumentationName}.query"; + public static string QueryType = $"{Query}.type"; + public static string QueryHandler = $"{Query}.handler"; + public static string SuccessCount = $"{QueryHandler}.success.count"; + public static string FaildCount = $"{QueryHandler}.failed.count"; + public static string ActiveCount = $"{QueryHandler}.active.count"; + public static string TotalExecutedCount = $"{QueryHandler}.total.count"; + public static string HandlerDuration = $"{QueryHandler}.duration"; + } + + public static class Events + { + public static string Event = $"{ObservabilityConstant.InstrumentationName}.event"; + public static string EventType = $"{Event}.type"; + public static string EventHandler = $"{Event}.handler"; + public static string SuccessCount = $"{EventHandler}.success.count"; + public static string FaildCount = $"{EventHandler}.failed.count"; + public static string ActiveCount = $"{EventHandler}.active.count"; + public static string TotalExecutedCount = $"{EventHandler}.total.count"; + public static string HandlerDuration = $"{EventHandler}.duration"; + } + } + } +} diff --git a/src/Services/Booking/src/Booking.Api/appsettings.docker.json b/src/Services/Booking/src/Booking.Api/appsettings.docker.json index 8ad2a7d8..1ab06604 100644 --- a/src/Services/Booking/src/Booking.Api/appsettings.docker.json +++ b/src/Services/Booking/src/Booking.Api/appsettings.docker.json @@ -38,21 +38,11 @@ "LogOptions": { "Level": "information", "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", - "Elastic": { - "Enabled": true, - "ElasticServiceUrl": "elasticsearch:9200" - }, "File": { "Enabled": false, "Path": "logs/logs.txt", "Interval": "day" }, - "Sentry": { - "Enabled": false, - "Dsn": "", - "MinimumBreadcrumbLevel": "information", - "MinimumEventLevel":"error" - } }, "AllowedHosts": "*" } diff --git a/src/Services/Booking/src/Booking.Api/appsettings.json b/src/Services/Booking/src/Booking.Api/appsettings.json index d5084e8d..abfdd412 100644 --- a/src/Services/Booking/src/Booking.Api/appsettings.json +++ b/src/Services/Booking/src/Booking.Api/appsettings.json @@ -1,67 +1,78 @@ { - "AppOptions": { - "Name": "Booking-Service" - }, - "LogOptions": { - "Level": "information", - "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", - "Elastic": { - "Enabled": true, - "ElasticServiceUrl": "http://localhost:9200" + "AppOptions": { + "Name": "Booking-Service" }, - "File": { - "Enabled": false, - "Path": "logs/logs.txt", - "Interval": "day" + "LogOptions": { + "Level": "information", + "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", + "File": { + "Enabled": false, + "Path": "logs/logs.txt", + "Interval": "day" + }, }, - "Sentry": { - "Enabled": false, - "Dsn": "", - "MinimumBreadcrumbLevel": "information", - "MinimumEventLevel":"error" - } - }, - "Jwt": { - "Authority": "http://localhost:6005", - "Audience": "booking-api", - "RequireHttpsMetadata": false, - "MetadataAddress": "http://localhost:6005/.well-known/openid-configuration" - }, - "RabbitMqOptions": { - "HostName": "localhost", - "ExchangeName": "booking", - "UserName": "guest", - "Password": "guest", - "Port": 5672 - }, - "Grpc": { - "FlightAddress": "https://localhost:5003", - "PassengerAddress": "https://localhost:5012" - }, - "PolicyOptions": { - "Retry": { - "RetryCount": 3, - "SleepDuration": 1 - }, - "CircuitBreaker": { - "RetryCount": 5, - "BreakDuration" : 30 - } - }, - "EventStoreOptions": { - "ConnectionString": "esdb://localhost:2113?tls=false" - }, - "MongoOptions": { - "ConnectionString": "mongodb://localhost:27017", - "DatabaseName": "booking-db" - }, - "HealthOptions": { - "Enabled": false - }, - "PersistMessageOptions": { - "Interval": 30, - "Enabled": true, - "ConnectionString": "Server=localhost;Port=5432;Database=persist_message;User Id=postgres;Password=postgres;Include Error Detail=true" - }, - "AllowedHosts": "*" + "Jwt": { + "Authority": "http://localhost:6005", + "Audience": "booking-api", + "RequireHttpsMetadata": false, + "MetadataAddress": "http://localhost:6005/.well-known/openid-configuration" + }, + "RabbitMqOptions": { + "HostName": "localhost", + "ExchangeName": "booking", + "UserName": "guest", + "Password": "guest", + "Port": 5672 + }, + "Grpc": { + "FlightAddress": "https://localhost:5003", + "PassengerAddress": "https://localhost:5012" + }, + "PolicyOptions": { + "Retry": { + "RetryCount": 3, + "SleepDuration": 1 + }, + "CircuitBreaker": { + "RetryCount": 5, + "BreakDuration": 30 + } + }, + "EventStoreOptions": { + "ConnectionString": "esdb://localhost:2113?tls=false" + }, + "MongoOptions": { + "ConnectionString": "mongodb://localhost:27017", + "DatabaseName": "booking-db" + }, + "HealthOptions": { + "Enabled": false + }, + "PersistMessageOptions": { + "Interval": 30, + "Enabled": true, + "ConnectionString": "Server=localhost;Port=5432;Database=persist_message;User Id=postgres;Password=postgres;Include Error Detail=true" + }, + "ObservabilityOptions": { + "InstrumentationName": "booking_service", + "OTLPOptions": { + "OTLPGrpExporterEndpoint": "http://localhost:4317" + }, + "AspireDashboardOTLPOptions": { + "OTLPGrpExporterEndpoint": "http://localhost:4319" + }, + "ZipkinOptions": { + "HttpExporterEndpoint": "http://localhost:9411/api/v2/spans" + }, + "JaegerOptions": { + "OTLPGrpcExporterEndpoint": "http://localhost:14317", + "HttpExporterEndpoint": "http://localhost:14268/api/traces" + }, + "UsePrometheusExporter": true, + "UseOTLPExporter": true, + "UseAspireOTLPExporter": true, + "UseGrafanaExporter": false, + "ServiceName": "Booking Service" + }, + "AllowedHosts": "*" } diff --git a/src/Services/Booking/src/Booking/Extensions/Infrastructure/InfrastructureExtensions.cs b/src/Services/Booking/src/Booking/Extensions/Infrastructure/InfrastructureExtensions.cs index 18f8ba8d..919b6f5a 100644 --- a/src/Services/Booking/src/Booking/Extensions/Infrastructure/InfrastructureExtensions.cs +++ b/src/Services/Booking/src/Booking/Extensions/Infrastructure/InfrastructureExtensions.cs @@ -9,7 +9,7 @@ using BuildingBlocks.MassTransit; using BuildingBlocks.Mongo; using BuildingBlocks.OpenApi; -using BuildingBlocks.OpenTelemetry; +using BuildingBlocks.OpenTelemetryCollector; using BuildingBlocks.PersistMessageProcessor; using BuildingBlocks.ProblemDetails; using BuildingBlocks.Web; @@ -73,7 +73,7 @@ public static WebApplicationBuilder AddInfrastructure(this WebApplicationBuilder builder.Services.AddCustomMapster(typeof(BookingRoot).Assembly); builder.Services.AddCustomHealthCheck(); builder.Services.AddCustomMassTransit(env, typeof(BookingRoot).Assembly); - builder.Services.AddCustomOpenTelemetry(); + builder.AddCustomObservability(); builder.Services.AddTransient(); // ref: https://github.com/oskardudycz/EventSourcing.NetCore/tree/main/Sample/EventStoreDB/ECommerce @@ -91,7 +91,7 @@ public static WebApplication UseInfrastructure(this WebApplication app) var env = app.Environment; var appOptions = app.GetOptions(nameof(AppOptions)); - app.MapPrometheusScrapingEndpoint(); + app.UseCustomObservability(); app.UseCustomProblemDetails(); app.UseSerilogRequestLogging(options => diff --git a/src/Services/Flight/src/Flight.Api/appsettings.docker.json b/src/Services/Flight/src/Flight.Api/appsettings.docker.json index 5f211e82..d0daf016 100644 --- a/src/Services/Flight/src/Flight.Api/appsettings.docker.json +++ b/src/Services/Flight/src/Flight.Api/appsettings.docker.json @@ -3,20 +3,10 @@ "LogOptions": { "Level": "information", "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", - "Elastic": { - "Enabled": true, - "ElasticServiceUrl": "elasticsearch:9200" - }, "File": { "Enabled": false, "Path": "logs/logs.txt", "Interval": "day" - }, - "Sentry": { - "Enabled": false, - "Dsn": "", - "MinimumBreadcrumbLevel": "information", - "MinimumEventLevel": "error" } }, "PostgresOptions": { diff --git a/src/Services/Flight/src/Flight.Api/appsettings.json b/src/Services/Flight/src/Flight.Api/appsettings.json index 971e4d44..0f38f149 100644 --- a/src/Services/Flight/src/Flight.Api/appsettings.json +++ b/src/Services/Flight/src/Flight.Api/appsettings.json @@ -1,53 +1,64 @@ { - "AppOptions": { - "Name": "Flight-Service" - }, - "LogOptions": { - "Level": "information", - "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", - "Elastic": { - "Enabled": true, - "ElasticServiceUrl": "http://localhost:9200" - }, - "File": { - "Enabled": false, - "Path": "logs/logs.txt", - "Interval": "day" - }, - "Sentry": { - "Enabled": false, - "Dsn": "", - "MinimumBreadcrumbLevel": "information", - "MinimumEventLevel": "error" - } - }, - "PostgresOptions": { - "ConnectionString": "Server=localhost;Port=5432;Database=flight;User Id=postgres;Password=postgres;Include Error Detail=true" - }, - "MongoOptions": { - "ConnectionString": "mongodb://localhost:27017", - "DatabaseName": "flight-db" - }, - "Jwt": { - "Authority": "http://localhost:6005", - "Audience": "flight-api", - "RequireHttpsMetadata": false, - "MetadataAddress": "http://localhost:6005/.well-known/openid-configuration" - }, - "RabbitMqOptions": { - "HostName": "localhost", - "ExchangeName": "flight", - "UserName": "guest", - "Password": "guest", - "Port": 5672 - }, - "PersistMessageOptions": { - "Interval": 30, - "Enabled": true, - "ConnectionString": "Server=localhost;Port=5432;Database=persist_message;User Id=postgres;Password=postgres;Include Error Detail=true" - }, - "HealthOptions": { - "Enabled": false - }, - "AllowedHosts": "*" + "AppOptions": { + "Name": "Flight-Service" + }, + "LogOptions": { + "Level": "information", + "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", + "File": { + "Enabled": false, + "Path": "logs/logs.txt", + "Interval": "day" + } + }, + "PostgresOptions": { + "ConnectionString": "Server=localhost;Port=5432;Database=flight;User Id=postgres;Password=postgres;Include Error Detail=true" + }, + "MongoOptions": { + "ConnectionString": "mongodb://localhost:27017", + "DatabaseName": "flight-db" + }, + "Jwt": { + "Authority": "http://localhost:6005", + "Audience": "flight-api", + "RequireHttpsMetadata": false, + "MetadataAddress": "http://localhost:6005/.well-known/openid-configuration" + }, + "RabbitMqOptions": { + "HostName": "localhost", + "ExchangeName": "flight", + "UserName": "guest", + "Password": "guest", + "Port": 5672 + }, + "PersistMessageOptions": { + "Interval": 30, + "Enabled": true, + "ConnectionString": "Server=localhost;Port=5432;Database=persist_message;User Id=postgres;Password=postgres;Include Error Detail=true" + }, + "HealthOptions": { + "Enabled": false + }, + "ObservabilityOptions": { + "InstrumentationName": "flight_service", + "OTLPOptions": { + "OTLPGrpExporterEndpoint": "http://localhost:4317" + }, + "AspireDashboardOTLPOptions": { + "OTLPGrpExporterEndpoint": "http://localhost:4319" + }, + "ZipkinOptions": { + "HttpExporterEndpoint": "http://localhost:9411/api/v2/spans" + }, + "JaegerOptions": { + "OTLPGrpcExporterEndpoint": "http://localhost:14317", + "HttpExporterEndpoint": "http://localhost:14268/api/traces" + }, + "UsePrometheusExporter": true, + "UseOTLPExporter": true, + "UseAspireOTLPExporter": true, + "UseGrafanaExporter": false, + "ServiceName": "Flight Service" + }, + "AllowedHosts": "*" } diff --git a/src/Services/Flight/src/Flight/Extensions/Infrastructure/InfrastructureExtensions.cs b/src/Services/Flight/src/Flight/Extensions/Infrastructure/InfrastructureExtensions.cs index fd06f53b..d0c5f733 100644 --- a/src/Services/Flight/src/Flight/Extensions/Infrastructure/InfrastructureExtensions.cs +++ b/src/Services/Flight/src/Flight/Extensions/Infrastructure/InfrastructureExtensions.cs @@ -9,7 +9,7 @@ using BuildingBlocks.MassTransit; using BuildingBlocks.Mongo; using BuildingBlocks.OpenApi; -using BuildingBlocks.OpenTelemetry; +using BuildingBlocks.OpenTelemetryCollector; using BuildingBlocks.PersistMessageProcessor; using BuildingBlocks.ProblemDetails; using BuildingBlocks.Web; @@ -78,7 +78,7 @@ public static WebApplicationBuilder AddInfrastructure(this WebApplicationBuilder builder.Services.AddCustomMapster(typeof(FlightRoot).Assembly); builder.Services.AddHttpContextAccessor(); builder.Services.AddCustomMassTransit(env, typeof(FlightRoot).Assembly); - builder.Services.AddCustomOpenTelemetry(); + builder.AddCustomObservability(); builder.Services.AddCustomHealthCheck(); builder.Services.AddGrpc(options => @@ -97,7 +97,7 @@ public static WebApplication UseInfrastructure(this WebApplication app) var env = app.Environment; var appOptions = app.GetOptions(nameof(AppOptions)); - app.MapPrometheusScrapingEndpoint(); + app.UseCustomObservability(); app.UseCustomProblemDetails(); app.UseSerilogRequestLogging(options => diff --git a/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetFlightByIdTests.cs b/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetFlightByIdTests.cs index c0d1fd88..0df0609a 100644 --- a/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetFlightByIdTests.cs +++ b/src/Services/Flight/tests/IntegrationTest/Flight/Features/GetFlightByIdTests.cs @@ -9,9 +9,7 @@ namespace Integration.Test.Flight.Features; -using global::Flight.Flights.Features.CreatingFlight.V1; using global::Flight.Flights.Features.GettingFlightById.V1; -using Thrift.Protocol; public class GetFlightByIdTests : FlightIntegrationTestBase { diff --git a/src/Services/Flight/tests/UnitTest/Aircraft/Features/CreateAircraftTests/CreateAircraftCommandHandlerTests.cs b/src/Services/Flight/tests/UnitTest/Aircraft/Features/CreateAircraftTests/CreateAircraftCommandHandlerTests.cs index 6c299414..10c9f3ff 100644 --- a/src/Services/Flight/tests/UnitTest/Aircraft/Features/CreateAircraftTests/CreateAircraftCommandHandlerTests.cs +++ b/src/Services/Flight/tests/UnitTest/Aircraft/Features/CreateAircraftTests/CreateAircraftCommandHandlerTests.cs @@ -1,6 +1,3 @@ -using System; -using System.Threading; -using System.Threading.Tasks; using FluentAssertions; using Unit.Test.Common; using Unit.Test.Fakes; @@ -8,7 +5,6 @@ namespace Unit.Test.Aircraft.Features.CreateAircraftTests; -using global::Flight.Aircrafts.Dtos; using global::Flight.Aircrafts.Features.CreatingAircraft.V1; [Collection(nameof(UnitTestFixture))] diff --git a/src/Services/Flight/tests/UnitTest/Airport/Features/CreateAirportTests/CreateAirportCommandHandlerTests.cs b/src/Services/Flight/tests/UnitTest/Airport/Features/CreateAirportTests/CreateAirportCommandHandlerTests.cs index f430026c..d6a4137c 100644 --- a/src/Services/Flight/tests/UnitTest/Airport/Features/CreateAirportTests/CreateAirportCommandHandlerTests.cs +++ b/src/Services/Flight/tests/UnitTest/Airport/Features/CreateAirportTests/CreateAirportCommandHandlerTests.cs @@ -1,6 +1,3 @@ -using System; -using System.Threading; -using System.Threading.Tasks; using FluentAssertions; using Unit.Test.Common; using Unit.Test.Fakes; diff --git a/src/Services/Flight/tests/UnitTest/Common/DbContextFactory.cs b/src/Services/Flight/tests/UnitTest/Common/DbContextFactory.cs index b3d30c7e..f11753a8 100644 --- a/src/Services/Flight/tests/UnitTest/Common/DbContextFactory.cs +++ b/src/Services/Flight/tests/UnitTest/Common/DbContextFactory.cs @@ -1,5 +1,3 @@ -using System; -using System.Collections.Generic; using Flight.Data; using Flight.Flights.Enums; using Flight.Seats.Enums; diff --git a/src/Services/Flight/tests/UnitTest/Common/UnitTestFixture.cs b/src/Services/Flight/tests/UnitTest/Common/UnitTestFixture.cs index 57efaa65..102d7559 100644 --- a/src/Services/Flight/tests/UnitTest/Common/UnitTestFixture.cs +++ b/src/Services/Flight/tests/UnitTest/Common/UnitTestFixture.cs @@ -1,4 +1,3 @@ -using System; using Flight.Data; using MapsterMapper; using Xunit; diff --git a/src/Services/Flight/tests/UnitTest/Flight/FlightMappingTests.cs b/src/Services/Flight/tests/UnitTest/Flight/FlightMappingTests.cs index 78a69574..4c1e26e2 100644 --- a/src/Services/Flight/tests/UnitTest/Flight/FlightMappingTests.cs +++ b/src/Services/Flight/tests/UnitTest/Flight/FlightMappingTests.cs @@ -1,5 +1,3 @@ -using System; -using System.Collections.Generic; using Flight.Flights.Dtos; using MapsterMapper; using Unit.Test.Common; @@ -10,12 +8,10 @@ namespace Unit.Test.Flight; [Collection(nameof(UnitTestFixture))] public class FlightMappingTests { - private readonly UnitTestFixture _fixture; private readonly IMapper _mapper; public FlightMappingTests(UnitTestFixture fixture) { - _fixture = fixture; _mapper = fixture.Mapper; } diff --git a/src/Services/Flight/tests/UnitTest/Seat/Features/CreateSeatCommandHandlerTests.cs b/src/Services/Flight/tests/UnitTest/Seat/Features/CreateSeatCommandHandlerTests.cs index 5f85681b..ad9d85ae 100644 --- a/src/Services/Flight/tests/UnitTest/Seat/Features/CreateSeatCommandHandlerTests.cs +++ b/src/Services/Flight/tests/UnitTest/Seat/Features/CreateSeatCommandHandlerTests.cs @@ -1,6 +1,3 @@ -using System; -using System.Threading; -using System.Threading.Tasks; using FluentAssertions; using Unit.Test.Common; using Unit.Test.Fakes; diff --git a/src/Services/Flight/tests/UnitTest/Seat/SeatMappingTests.cs b/src/Services/Flight/tests/UnitTest/Seat/SeatMappingTests.cs index 1f749102..46526654 100644 --- a/src/Services/Flight/tests/UnitTest/Seat/SeatMappingTests.cs +++ b/src/Services/Flight/tests/UnitTest/Seat/SeatMappingTests.cs @@ -1,5 +1,3 @@ -using System; -using System.Collections.Generic; using Flight.Seats.Dtos; using MapsterMapper; using Unit.Test.Common; diff --git a/src/Services/Identity/src/Identity.Api/appsettings.docker.json b/src/Services/Identity/src/Identity.Api/appsettings.docker.json index d040ecb0..967ec5dc 100644 --- a/src/Services/Identity/src/Identity.Api/appsettings.docker.json +++ b/src/Services/Identity/src/Identity.Api/appsettings.docker.json @@ -21,20 +21,10 @@ "LogOptions": { "Level": "information", "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", - "Elastic": { - "Enabled": true, - "ElasticServiceUrl": "elasticsearch:9200" - }, "File": { "Enabled": false, "Path": "logs/logs.txt", "Interval": "day" - }, - "Sentry": { - "Enabled": false, - "Dsn": "", - "MinimumBreadcrumbLevel": "information", - "MinimumEventLevel":"error" } }, "AllowedHosts": "*" diff --git a/src/Services/Identity/src/Identity.Api/appsettings.json b/src/Services/Identity/src/Identity.Api/appsettings.json index 80f62ff9..f144a556 100644 --- a/src/Services/Identity/src/Identity.Api/appsettings.json +++ b/src/Services/Identity/src/Identity.Api/appsettings.json @@ -1,46 +1,57 @@ { - "AppOptions": { - "Name": "Identity-Service" - }, - "PostgresOptions": { - "ConnectionString": "Server=localhost;Port=5432;Database=identity;User Id=postgres;Password=postgres;Include Error Detail=true" - }, - "AuthOptions": { - "IssuerUri": "http://localhost:6005" - }, - "RabbitMqOptions": { - "HostName": "localhost", - "ExchangeName": "identity", - "UserName": "guest", - "Password": "guest", - "Port": 5672 - }, - "LogOptions": { - "Level": "information", - "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", - "Elastic": { - "Enabled": true, - "ElasticServiceUrl": "http://localhost:9200" - }, - "File": { - "Enabled": false, - "Path": "logs/logs.txt", - "Interval": "day" - }, - "Sentry": { - "Enabled": false, - "Dsn": "", - "MinimumBreadcrumbLevel": "information", - "MinimumEventLevel":"error" - } - }, - "HealthOptions": { - "Enabled": false - }, - "PersistMessageOptions": { - "Interval": 30, - "Enabled": true, - "ConnectionString": "Server=localhost;Port=5432;Database=persist_message;User Id=postgres;Password=postgres;Include Error Detail=true" - }, - "AllowedHosts": "*" + "AppOptions": { + "Name": "Identity-Service" + }, + "PostgresOptions": { + "ConnectionString": "Server=localhost;Port=5432;Database=identity;User Id=postgres;Password=postgres;Include Error Detail=true" + }, + "AuthOptions": { + "IssuerUri": "http://localhost:6005" + }, + "RabbitMqOptions": { + "HostName": "localhost", + "ExchangeName": "identity", + "UserName": "guest", + "Password": "guest", + "Port": 5672 + }, + "LogOptions": { + "Level": "information", + "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", + "File": { + "Enabled": false, + "Path": "logs/logs.txt", + "Interval": "day" + } + }, + "HealthOptions": { + "Enabled": false + }, + "PersistMessageOptions": { + "Interval": 30, + "Enabled": true, + "ConnectionString": "Server=localhost;Port=5432;Database=persist_message;User Id=postgres;Password=postgres;Include Error Detail=true" + }, + "ObservabilityOptions": { + "InstrumentationName": "identity_service", + "OTLPOptions": { + "OTLPGrpExporterEndpoint": "http://localhost:4317" + }, + "AspireDashboardOTLPOptions": { + "OTLPGrpExporterEndpoint": "http://localhost:4319" + }, + "ZipkinOptions": { + "HttpExporterEndpoint": "http://localhost:9411/api/v2/spans" + }, + "JaegerOptions": { + "OTLPGrpcExporterEndpoint": "http://localhost:14317", + "HttpExporterEndpoint": "http://localhost:14268/api/traces" + }, + "UsePrometheusExporter": true, + "UseOTLPExporter": true, + "UseAspireOTLPExporter": true, + "UseGrafanaExporter": false, + "ServiceName": "Identity Service" + }, + "AllowedHosts": "*" } diff --git a/src/Services/Identity/src/Identity/Extensions/Infrastructure/InfrastructureExtensions.cs b/src/Services/Identity/src/Identity/Extensions/Infrastructure/InfrastructureExtensions.cs index 8960e461..e58a084d 100644 --- a/src/Services/Identity/src/Identity/Extensions/Infrastructure/InfrastructureExtensions.cs +++ b/src/Services/Identity/src/Identity/Extensions/Infrastructure/InfrastructureExtensions.cs @@ -6,7 +6,7 @@ using BuildingBlocks.Mapster; using BuildingBlocks.MassTransit; using BuildingBlocks.OpenApi; -using BuildingBlocks.OpenTelemetry; +using BuildingBlocks.OpenTelemetryCollector; using BuildingBlocks.PersistMessageProcessor; using BuildingBlocks.ProblemDetails; using BuildingBlocks.Web; @@ -74,7 +74,7 @@ public static WebApplicationBuilder AddInfrastructure(this WebApplicationBuilder builder.Services.AddCustomHealthCheck(); builder.Services.AddCustomMassTransit(env, typeof(IdentityRoot).Assembly); - builder.Services.AddCustomOpenTelemetry(); + builder.AddCustomObservability(); builder.AddCustomIdentityServer(); @@ -93,7 +93,7 @@ public static WebApplication UseInfrastructure(this WebApplication app) var env = app.Environment; var appOptions = app.GetOptions(nameof(AppOptions)); - app.MapPrometheusScrapingEndpoint(); + app.UseCustomObservability(); app.UseForwardedHeaders(); diff --git a/src/Services/Passenger/src/Passenger.Api/appsettings.docker.json b/src/Services/Passenger/src/Passenger.Api/appsettings.docker.json index f55e0f81..5aa591db 100644 --- a/src/Services/Passenger/src/Passenger.Api/appsettings.docker.json +++ b/src/Services/Passenger/src/Passenger.Api/appsettings.docker.json @@ -28,20 +28,10 @@ "LogOptions": { "Level": "information", "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", - "Elastic": { - "Enabled": true, - "ElasticServiceUrl": "elasticsearch:9200" - }, "File": { "Enabled": false, "Path": "logs/logs.txt", "Interval": "day" - }, - "Sentry": { - "Enabled": false, - "Dsn": "", - "MinimumBreadcrumbLevel": "information", - "MinimumEventLevel":"error" } }, "AllowedHosts": "*" diff --git a/src/Services/Passenger/src/Passenger.Api/appsettings.json b/src/Services/Passenger/src/Passenger.Api/appsettings.json index 1ec2f4f2..951ae6dd 100644 --- a/src/Services/Passenger/src/Passenger.Api/appsettings.json +++ b/src/Services/Passenger/src/Passenger.Api/appsettings.json @@ -1,53 +1,64 @@ { - "AppOptions": { - "Name": "Passenger-Service" - }, - "PostgresOptions": { - "ConnectionString": "Server=localhost;Port=5432;Database=passenger;User Id=postgres;Password=postgres;Include Error Detail=true" - }, - "MongoOptions": { - "ConnectionString": "mongodb://localhost:27017", - "DatabaseName": "passenger-db" - }, - "Jwt": { - "Authority": "http://localhost:6005", - "Audience": "passenger-api", - "RequireHttpsMetadata": false, - "MetadataAddress": "http://localhost:6005/.well-known/openid-configuration" - }, - "RabbitMqOptions": { - "HostName": "localhost", - "ExchangeName": "passenger", - "UserName": "guest", - "Password": "guest", - "Port": 5672 - }, - "LogOptions": { - "Level": "information", - "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", - "Elastic": { - "Enabled": true, - "ElasticServiceUrl": "http://localhost:9200" - }, - "File": { - "Enabled": false, - "Path": "logs/logs.txt", - "Interval": "day" - }, - "Sentry": { - "Enabled": false, - "Dsn": "", - "MinimumBreadcrumbLevel": "information", - "MinimumEventLevel":"error" - } - }, - "HealthOptions": { - "Enabled": false - }, - "PersistMessageOptions": { - "Interval": 30, - "Enabled": true, - "ConnectionString": "Server=localhost;Port=5432;Database=persist_message;User Id=postgres;Password=postgres;Include Error Detail=true" - }, - "AllowedHosts": "*" + "AppOptions": { + "Name": "Passenger-Service" + }, + "PostgresOptions": { + "ConnectionString": "Server=localhost;Port=5432;Database=passenger;User Id=postgres;Password=postgres;Include Error Detail=true" + }, + "MongoOptions": { + "ConnectionString": "mongodb://localhost:27017", + "DatabaseName": "passenger-db" + }, + "Jwt": { + "Authority": "http://localhost:6005", + "Audience": "passenger-api", + "RequireHttpsMetadata": false, + "MetadataAddress": "http://localhost:6005/.well-known/openid-configuration" + }, + "RabbitMqOptions": { + "HostName": "localhost", + "ExchangeName": "passenger", + "UserName": "guest", + "Password": "guest", + "Port": 5672 + }, + "LogOptions": { + "Level": "information", + "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", + "File": { + "Enabled": false, + "Path": "logs/logs.txt", + "Interval": "day" + } + }, + "HealthOptions": { + "Enabled": false + }, + "PersistMessageOptions": { + "Interval": 30, + "Enabled": true, + "ConnectionString": "Server=localhost;Port=5432;Database=persist_message;User Id=postgres;Password=postgres;Include Error Detail=true" + }, + "ObservabilityOptions": { + "InstrumentationName": "passenger_service", + "OTLPOptions": { + "OTLPGrpExporterEndpoint": "http://localhost:4317" + }, + "AspireDashboardOTLPOptions": { + "OTLPGrpExporterEndpoint": "http://localhost:4319" + }, + "ZipkinOptions": { + "HttpExporterEndpoint": "http://localhost:9411/api/v2/spans" + }, + "JaegerOptions": { + "OTLPGrpcExporterEndpoint": "http://localhost:14317", + "HttpExporterEndpoint": "http://localhost:14268/api/traces" + }, + "UsePrometheusExporter": true, + "UseOTLPExporter": true, + "UseAspireOTLPExporter": true, + "UseGrafanaExporter": false, + "ServiceName": "Passenger Service" + }, + "AllowedHosts": "*" } diff --git a/src/Services/Passenger/src/Passenger/Extensions/Infrastructure/InfrastructureExtensions.cs b/src/Services/Passenger/src/Passenger/Extensions/Infrastructure/InfrastructureExtensions.cs index cbcadd8e..a7cbe48a 100644 --- a/src/Services/Passenger/src/Passenger/Extensions/Infrastructure/InfrastructureExtensions.cs +++ b/src/Services/Passenger/src/Passenger/Extensions/Infrastructure/InfrastructureExtensions.cs @@ -9,7 +9,7 @@ using BuildingBlocks.MassTransit; using BuildingBlocks.Mongo; using BuildingBlocks.OpenApi; -using BuildingBlocks.OpenTelemetry; +using BuildingBlocks.OpenTelemetryCollector; using BuildingBlocks.PersistMessageProcessor; using BuildingBlocks.ProblemDetails; using BuildingBlocks.Web; @@ -26,7 +26,6 @@ namespace Passenger.Extensions.Infrastructure; - public static class InfrastructureExtensions { public static WebApplicationBuilder AddInfrastructure(this WebApplicationBuilder builder) @@ -38,27 +37,31 @@ public static WebApplicationBuilder AddInfrastructure(this WebApplicationBuilder builder.Services.AddScoped(); builder.Services.AddScoped(); - builder.Services.Configure(options => - { - options.SuppressModelStateInvalidFilter = true; - }); + builder.Services.Configure( + options => + { + options.SuppressModelStateInvalidFilter = true; + }); var appOptions = builder.Services.GetOptions(nameof(AppOptions)); Console.WriteLine(FiggleFonts.Standard.Render(appOptions.Name)); - builder.Services.AddRateLimiter(options => - { - options.GlobalLimiter = PartitionedRateLimiter.Create(httpContext => - RateLimitPartition.GetFixedWindowLimiter( - partitionKey: httpContext.User.Identity?.Name ?? httpContext.Request.Headers.Host.ToString(), - factory: partition => new FixedWindowRateLimiterOptions - { - AutoReplenishment = true, - PermitLimit = 10, - QueueLimit = 0, - Window = TimeSpan.FromMinutes(1) - })); - }); + builder.Services.AddRateLimiter( + options => + { + options.GlobalLimiter = PartitionedRateLimiter.Create( + httpContext => + RateLimitPartition.GetFixedWindowLimiter( + partitionKey: httpContext.User.Identity?.Name ?? + httpContext.Request.Headers.Host.ToString(), + factory: partition => new FixedWindowRateLimiterOptions + { + AutoReplenishment = true, + PermitLimit = 10, + QueueLimit = 0, + Window = TimeSpan.FromMinutes(1) + })); + }); builder.Services.AddPersistMessageProcessor(); builder.Services.AddCustomDbContext(); @@ -76,11 +79,13 @@ public static WebApplicationBuilder AddInfrastructure(this WebApplicationBuilder builder.Services.AddHttpContextAccessor(); builder.Services.AddCustomHealthCheck(); builder.Services.AddCustomMassTransit(env, typeof(PassengerRoot).Assembly); - builder.Services.AddCustomOpenTelemetry(); - builder.Services.AddGrpc(options => - { - options.Interceptors.Add(); - }); + builder.AddCustomObservability(); + + builder.Services.AddGrpc( + options => + { + options.Interceptors.Add(); + }); return builder; } @@ -91,13 +96,16 @@ public static WebApplication UseInfrastructure(this WebApplication app) var env = app.Environment; var appOptions = app.GetOptions(nameof(AppOptions)); - app.MapPrometheusScrapingEndpoint(); + app.UseCustomObservability(); app.UseCustomProblemDetails(); - app.UseSerilogRequestLogging(options => - { - options.EnrichDiagnosticContext = LogEnrichHelper.EnrichFromRequest; - }); + + app.UseSerilogRequestLogging( + options => + { + options.EnrichDiagnosticContext = LogEnrichHelper.EnrichFromRequest; + }); + app.UseCorrelationId(); app.UseMigration(); app.UseCustomHealthCheck(); diff --git a/src/Services/Passenger/tests/IntegrationTest/Passenger/Features/GetPassengerByIdTests.cs b/src/Services/Passenger/tests/IntegrationTest/Passenger/Features/GetPassengerByIdTests.cs index 3ca8e953..59ab0a58 100644 --- a/src/Services/Passenger/tests/IntegrationTest/Passenger/Features/GetPassengerByIdTests.cs +++ b/src/Services/Passenger/tests/IntegrationTest/Passenger/Features/GetPassengerByIdTests.cs @@ -10,8 +10,6 @@ namespace Integration.Test.Passenger.Features; using global::Passenger.Passengers.Features.GettingPassengerById.V1; -using Humanizer; -using Thrift.Protocol; public class GetPassengerByIdTests : PassengerIntegrationTestBase {