From b8016afb50fd3eaeb8d54fa4e8cad2b72fa4fab0 Mon Sep 17 00:00:00 2001 From: "Diego Ferreira L.G.Oliveira" Date: Sun, 7 Jun 2026 09:31:41 -0300 Subject: [PATCH] feat(observabilidade): adicionar dashboard de monitoramento do MongoDB - adiciona bv-mongodb-exporter (percona 0.44) ao docker-compose - adiciona bv-prometheus ao docker-compose com retencao de 15 dias - cria observabilidade/prometheus/prometheus.yaml com scrape do exporter - cria datasource Prometheus no Grafana (prometheus-bv) - cria dashboard mongodb-bv com paineis de status, conexoes, operacoes, memoria, rede, documentos, cursores e logs do container - extende Promtail para capturar e rotular logs do bv-mongodb --- docker-compose.yml | 43 +++ .../grafana/dashboards/mongodb.json | 319 ++++++++++++++++++ .../provisioning/datasources/prometheus.yaml | 13 + observabilidade/prometheus/prometheus.yaml | 11 + observabilidade/promtail/promtail.yaml | 29 ++ 5 files changed, 415 insertions(+) create mode 100644 observabilidade/grafana/dashboards/mongodb.json create mode 100644 observabilidade/grafana/provisioning/datasources/prometheus.yaml create mode 100644 observabilidade/prometheus/prometheus.yaml diff --git a/docker-compose.yml b/docker-compose.yml index 09407b1..c629c98 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -113,6 +113,48 @@ services: networks: - bv-network + bv-mongodb-exporter: + image: percona/mongodb_exporter:0.44.0 + container_name: bv-mongodb-exporter + environment: + MONGODB_URI: mongodb://${MONGO_USUARIO}:${MONGO_SENHA}@bv-mongodb:27017/?authSource=admin + command: + - --collect-all + - --web.listen-address=:9216 + ports: + - "9216:9216" + depends_on: + bv-mongodb: + condition: service_healthy + restart: unless-stopped + networks: + - bv-network + + bv-prometheus: + image: prom/prometheus:v3.4.0 + container_name: bv-prometheus + volumes: + - ./observabilidade/prometheus/prometheus.yaml:/etc/prometheus/prometheus.yml:ro + - prometheus-data:/prometheus + command: + - --config.file=/etc/prometheus/prometheus.yml + - --storage.tsdb.path=/prometheus + - --storage.tsdb.retention.time=15d + - --web.enable-lifecycle + ports: + - "9090:9090" + depends_on: + - bv-mongodb-exporter + healthcheck: + test: ["CMD-SHELL", "wget --quiet --tries=1 --spider http://localhost:9090/-/ready || exit 1"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 15s + restart: unless-stopped + networks: + - bv-network + bv-grafana: image: grafana/grafana:13.0.1 container_name: bv-grafana @@ -147,6 +189,7 @@ volumes: redis-data: loki-data: grafana-data: + prometheus-data: networks: bv-network: diff --git a/observabilidade/grafana/dashboards/mongodb.json b/observabilidade/grafana/dashboards/mongodb.json new file mode 100644 index 0000000..10bca11 --- /dev/null +++ b/observabilidade/grafana/dashboards/mongodb.json @@ -0,0 +1,319 @@ +{ + "title": "MongoDB — Monitoramento", + "uid": "mongodb-bv", + "description": "Conexões, operações, memória, rede e logs do MongoDB", + "tags": ["mongodb", "database", "bem-vindo"], + "timezone": "browser", + "refresh": "30s", + "schemaVersion": 38, + "time": { "from": "now-1h", "to": "now" }, + "editable": true, + "panels": [ + { + "id": 1, + "type": "row", + "title": "Status Geral", + "collapsed": false, + "gridPos": { "h": 1, "w": 24, "x": 0, "y": 0 } + }, + { + "id": 2, + "type": "stat", + "title": "Status MongoDB", + "gridPos": { "h": 5, "w": 4, "x": 0, "y": 1 }, + "datasource": { "type": "prometheus", "uid": "prometheus-bv" }, + "options": { + "reduceOptions": { "calcs": ["lastNotNull"] }, + "orientation": "auto", + "textMode": "auto", + "colorMode": "background", + "graphMode": "none" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { "type": "value", "options": { "1": { "text": "Online", "color": "green" }, "0": { "text": "Offline", "color": "red" } } } + ], + "thresholds": { "mode": "absolute", "steps": [{ "color": "red", "value": null }, { "color": "green", "value": 1 }] }, + "color": { "mode": "thresholds" } + } + }, + "targets": [{ "datasource": { "uid": "prometheus-bv" }, "expr": "mongodb_up", "instant": true, "legendFormat": "" }] + }, + { + "id": 3, + "type": "stat", + "title": "Conexões Ativas", + "gridPos": { "h": 5, "w": 4, "x": 4, "y": 1 }, + "datasource": { "type": "prometheus", "uid": "prometheus-bv" }, + "options": { + "reduceOptions": { "calcs": ["lastNotNull"] }, + "orientation": "auto", + "textMode": "auto", + "colorMode": "value", + "graphMode": "area" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "yellow", "value": 50 }, { "color": "red", "value": 200 }] }, + "color": { "mode": "thresholds" } + } + }, + "targets": [{ "datasource": { "uid": "prometheus-bv" }, "expr": "mongodb_ss_connections{state=\"current\"}", "instant": true, "legendFormat": "" }] + }, + { + "id": 4, + "type": "stat", + "title": "Conexões Disponíveis", + "gridPos": { "h": 5, "w": 4, "x": 8, "y": 1 }, + "datasource": { "type": "prometheus", "uid": "prometheus-bv" }, + "options": { + "reduceOptions": { "calcs": ["lastNotNull"] }, + "orientation": "auto", + "textMode": "auto", + "colorMode": "value", + "graphMode": "area" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { "mode": "absolute", "steps": [{ "color": "red", "value": null }, { "color": "yellow", "value": 10 }, { "color": "green", "value": 50 }] }, + "color": { "mode": "thresholds" } + } + }, + "targets": [{ "datasource": { "uid": "prometheus-bv" }, "expr": "mongodb_ss_connections{state=\"available\"}", "instant": true, "legendFormat": "" }] + }, + { + "id": 5, + "type": "stat", + "title": "Memória Residente", + "gridPos": { "h": 5, "w": 4, "x": 12, "y": 1 }, + "datasource": { "type": "prometheus", "uid": "prometheus-bv" }, + "options": { + "reduceOptions": { "calcs": ["lastNotNull"] }, + "orientation": "auto", + "textMode": "auto", + "colorMode": "value", + "graphMode": "area" + }, + "fieldConfig": { + "defaults": { + "unit": "decmbytes", + "thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "yellow", "value": 512 }, { "color": "red", "value": 1024 }] }, + "color": { "mode": "thresholds" } + } + }, + "targets": [{ "datasource": { "uid": "prometheus-bv" }, "expr": "mongodb_ss_mem_resident", "instant": true, "legendFormat": "" }] + }, + { + "id": 6, + "type": "gauge", + "title": "Fila de Operações Bloqueadas", + "gridPos": { "h": 5, "w": 8, "x": 16, "y": 1 }, + "datasource": { "type": "prometheus", "uid": "prometheus-bv" }, + "options": { + "reduceOptions": { "calcs": ["lastNotNull"] }, + "orientation": "auto", + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "min": 0, + "max": 100, + "thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "yellow", "value": 10 }, { "color": "red", "value": 50 }] }, + "color": { "mode": "thresholds" } + } + }, + "targets": [{ "datasource": { "uid": "prometheus-bv" }, "expr": "mongodb_ss_globalLock_currentQueue_total", "instant": true, "legendFormat": "" }] + }, + { + "id": 7, + "type": "row", + "title": "Operações", + "collapsed": false, + "gridPos": { "h": 1, "w": 24, "x": 0, "y": 6 } + }, + { + "id": 8, + "type": "timeseries", + "title": "Taxa de Operações por Tipo (ops/s)", + "gridPos": { "h": 9, "w": 24, "x": 0, "y": 7 }, + "datasource": { "type": "prometheus", "uid": "prometheus-bv" }, + "options": { + "tooltip": { "mode": "multi", "sort": "desc" }, + "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["mean", "max", "lastNotNull"] } + }, + "fieldConfig": { + "defaults": { + "unit": "ops", + "custom": { "lineWidth": 2, "fillOpacity": 10, "spanNulls": false } + } + }, + "targets": [ + { "datasource": { "uid": "prometheus-bv" }, "expr": "rate(mongodb_ss_opcounters_total{type=\"insert\"}[2m])", "legendFormat": "Insert" }, + { "datasource": { "uid": "prometheus-bv" }, "expr": "rate(mongodb_ss_opcounters_total{type=\"update\"}[2m])", "legendFormat": "Update" }, + { "datasource": { "uid": "prometheus-bv" }, "expr": "rate(mongodb_ss_opcounters_total{type=\"delete\"}[2m])", "legendFormat": "Delete" }, + { "datasource": { "uid": "prometheus-bv" }, "expr": "rate(mongodb_ss_opcounters_total{type=\"query\"}[2m])", "legendFormat": "Query" }, + { "datasource": { "uid": "prometheus-bv" }, "expr": "rate(mongodb_ss_opcounters_total{type=\"command\"}[2m])", "legendFormat": "Command" }, + { "datasource": { "uid": "prometheus-bv" }, "expr": "rate(mongodb_ss_opcounters_total{type=\"getmore\"}[2m])", "legendFormat": "Getmore" } + ] + }, + { + "id": 9, + "type": "row", + "title": "Memória e Rede", + "collapsed": false, + "gridPos": { "h": 1, "w": 24, "x": 0, "y": 16 } + }, + { + "id": 10, + "type": "timeseries", + "title": "Memória (MB)", + "gridPos": { "h": 9, "w": 12, "x": 0, "y": 17 }, + "datasource": { "type": "prometheus", "uid": "prometheus-bv" }, + "options": { + "tooltip": { "mode": "multi", "sort": "desc" }, + "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["mean", "max", "lastNotNull"] } + }, + "fieldConfig": { + "defaults": { + "unit": "decmbytes", + "custom": { "lineWidth": 2, "fillOpacity": 10, "spanNulls": false } + } + }, + "targets": [ + { "datasource": { "uid": "prometheus-bv" }, "expr": "mongodb_ss_mem_resident", "legendFormat": "Residente" }, + { "datasource": { "uid": "prometheus-bv" }, "expr": "mongodb_ss_mem_virtual", "legendFormat": "Virtual" } + ] + }, + { + "id": 11, + "type": "timeseries", + "title": "Tráfego de Rede (bytes/s)", + "gridPos": { "h": 9, "w": 12, "x": 12, "y": 17 }, + "datasource": { "type": "prometheus", "uid": "prometheus-bv" }, + "options": { + "tooltip": { "mode": "multi", "sort": "desc" }, + "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["mean", "max", "lastNotNull"] } + }, + "fieldConfig": { + "defaults": { + "unit": "Bps", + "custom": { "lineWidth": 2, "fillOpacity": 10, "spanNulls": false } + } + }, + "targets": [ + { "datasource": { "uid": "prometheus-bv" }, "expr": "rate(mongodb_ss_network_bytes_in_total[2m])", "legendFormat": "Entrada" }, + { "datasource": { "uid": "prometheus-bv" }, "expr": "rate(mongodb_ss_network_bytes_out_total[2m])", "legendFormat": "Saída" } + ] + }, + { + "id": 12, + "type": "row", + "title": "Documentos e Cursores", + "collapsed": false, + "gridPos": { "h": 1, "w": 24, "x": 0, "y": 26 } + }, + { + "id": 13, + "type": "timeseries", + "title": "Documentos por Operação (docs/s)", + "gridPos": { "h": 9, "w": 16, "x": 0, "y": 27 }, + "datasource": { "type": "prometheus", "uid": "prometheus-bv" }, + "options": { + "tooltip": { "mode": "multi", "sort": "desc" }, + "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["mean", "max", "lastNotNull"] } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "custom": { "lineWidth": 2, "fillOpacity": 10, "spanNulls": false } + } + }, + "targets": [ + { "datasource": { "uid": "prometheus-bv" }, "expr": "rate(mongodb_ss_metrics_document_total{state=\"inserted\"}[2m])", "legendFormat": "Inseridos" }, + { "datasource": { "uid": "prometheus-bv" }, "expr": "rate(mongodb_ss_metrics_document_total{state=\"returned\"}[2m])", "legendFormat": "Retornados" }, + { "datasource": { "uid": "prometheus-bv" }, "expr": "rate(mongodb_ss_metrics_document_total{state=\"updated\"}[2m])", "legendFormat": "Atualizados" }, + { "datasource": { "uid": "prometheus-bv" }, "expr": "rate(mongodb_ss_metrics_document_total{state=\"deleted\"}[2m])", "legendFormat": "Deletados" } + ] + }, + { + "id": 14, + "type": "stat", + "title": "Cursores Abertos", + "gridPos": { "h": 5, "w": 8, "x": 16, "y": 27 }, + "datasource": { "type": "prometheus", "uid": "prometheus-bv" }, + "options": { + "reduceOptions": { "calcs": ["lastNotNull"] }, + "orientation": "auto", + "textMode": "auto", + "colorMode": "value", + "graphMode": "area" + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "yellow", "value": 100 }, { "color": "red", "value": 500 }] }, + "color": { "mode": "thresholds" } + } + }, + "targets": [{ "datasource": { "uid": "prometheus-bv" }, "expr": "mongodb_ss_metrics_cursor_open{state=\"total\"}", "instant": true, "legendFormat": "" }] + }, + { + "id": 15, + "type": "timeseries", + "title": "Conexões ao Longo do Tempo", + "gridPos": { "h": 9, "w": 8, "x": 16, "y": 31 }, + "datasource": { "type": "prometheus", "uid": "prometheus-bv" }, + "options": { + "tooltip": { "mode": "multi", "sort": "desc" }, + "legend": { "displayMode": "list", "placement": "bottom" } + }, + "fieldConfig": { + "defaults": { + "unit": "short", + "custom": { "lineWidth": 2, "fillOpacity": 10, "spanNulls": false } + } + }, + "targets": [ + { "datasource": { "uid": "prometheus-bv" }, "expr": "mongodb_ss_connections{state=\"current\"}", "legendFormat": "Ativas" }, + { "datasource": { "uid": "prometheus-bv" }, "expr": "mongodb_ss_connections{state=\"available\"}", "legendFormat": "Disponíveis" } + ] + }, + { + "id": 16, + "type": "row", + "title": "Logs do MongoDB", + "collapsed": false, + "gridPos": { "h": 1, "w": 24, "x": 0, "y": 36 } + }, + { + "id": 17, + "type": "logs", + "title": "Logs do Contêiner bv-mongodb", + "gridPos": { "h": 12, "w": 24, "x": 0, "y": 37 }, + "datasource": { "type": "loki", "uid": "loki-bv" }, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": true, + "sortOrder": "Descending", + "wrapLogMessage": true + }, + "targets": [ + { + "datasource": { "uid": "loki-bv" }, + "expr": "{container=\"bv-mongodb\"}", + "legendFormat": "", + "queryType": "range" + } + ] + } + ] +} diff --git a/observabilidade/grafana/provisioning/datasources/prometheus.yaml b/observabilidade/grafana/provisioning/datasources/prometheus.yaml new file mode 100644 index 0000000..ce7d717 --- /dev/null +++ b/observabilidade/grafana/provisioning/datasources/prometheus.yaml @@ -0,0 +1,13 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + uid: prometheus-bv + type: prometheus + access: proxy + url: http://bv-prometheus:9090 + isDefault: false + jsonData: + httpMethod: POST + timeInterval: 15s + editable: false diff --git a/observabilidade/prometheus/prometheus.yaml b/observabilidade/prometheus/prometheus.yaml new file mode 100644 index 0000000..bbbf898 --- /dev/null +++ b/observabilidade/prometheus/prometheus.yaml @@ -0,0 +1,11 @@ +global: + scrape_interval: 15s + evaluation_interval: 15s + +scrape_configs: + - job_name: mongodb + static_configs: + - targets: ['bv-mongodb-exporter:9216'] + labels: + service: mongodb + container: bv-mongodb diff --git a/observabilidade/promtail/promtail.yaml b/observabilidade/promtail/promtail.yaml index 7922498..d8cd86e 100644 --- a/observabilidade/promtail/promtail.yaml +++ b/observabilidade/promtail/promtail.yaml @@ -49,3 +49,32 @@ scrape_configs: req_method: res_status: err_codigo: + + - job_name: bv-mongodb + docker_sd_configs: + - host: unix:///var/run/docker.sock + refresh_interval: 5s + filters: + - name: name + values: ["bv-mongodb"] + relabel_configs: + - source_labels: [__meta_docker_container_name] + regex: '/(.*)' + target_label: container + - source_labels: [__meta_docker_container_log_stream] + target_label: stream + + pipeline_stages: + - json: + expressions: + severity: s + component: c + msg: msg + - template: + source: severity + template: '{{if eq .Value "F"}}fatal{{else if eq .Value "E"}}error{{else if eq .Value "W"}}warn{{else if eq .Value "I"}}info{{else}}debug{{end}}' + - labels: + container: + stream: + severity: + component: