Grafana: dashboards para Node.js e PostgreSQL

    Grafana transforma métricas do Prometheus em dashboards visuais que revelam o comportamento da sua aplicação em tempo real. Um dashboard bem construído responde três perguntas de imediato: o sistema está saudável? onde está o gargalo? o que mudou agora? Este guia cobre a criação de painéis práticos para APIs Node.js em produção.

    Instalar Grafana com Docker Compose

    Stack Prometheus + Grafana com configuração mínima:

    yaml
    # docker-compose.yml:
    services:
      prometheus:
        image: prom/prometheus:latest
        container_name: prometheus
        volumes:
          - ./prometheus.yml:/etc/prometheus/prometheus.yml
          - prometheus-data:/prometheus
        command:
          - '--config.file=/etc/prometheus/prometheus.yml'
          - '--storage.tsdb.retention.time=30d'
        ports:
          - "127.0.0.1:9090:9090"
        restart: unless-stopped
    
      grafana:
        image: grafana/grafana-oss:latest
        container_name: grafana
        environment:
          GF_SECURITY_ADMIN_PASSWORD: "SUA_SENHA_FORTE"
          GF_USERS_ALLOW_SIGN_UP: "false"
          GF_SERVER_ROOT_URL: "https://grafana.seudominio.com.br"
          GF_SMTP_ENABLED: "true"
          GF_SMTP_HOST: "smtp.seudominio.com.br:587"
        volumes:
          - grafana-data:/var/lib/grafana
          - ./grafana/provisioning:/etc/grafana/provisioning
        ports:
          - "127.0.0.1:3001:3000"
        restart: unless-stopped
        depends_on:
          - prometheus
    
    volumes:
      prometheus-data:
      grafana-data:
    
    # prometheus.yml — scrape da API Node.js:
    # scrape_configs:
    #   - job_name: 'nodejs-api'
    #     static_configs:
    #       - targets: ['host.docker.internal:3000']
    #     metrics_path: '/metrics'

    Dashboard de API Node.js: latência e throughput

    Queries PromQL essenciais para monitorar uma API:

    bash
    # Queries PromQL para painéis Grafana:
    
    # 1. Throughput (req/s) — Rate de requisições por endpoint:
    rate(http_request_duration_seconds_count{job="nodejs-api"}[5m])
    
    # Por endpoint (top 10 mais chamados):
    topk(10, sum by (route, method) (
      rate(http_request_duration_seconds_count[5m])
    ))
    
    # 2. Latência P50/P95/P99 — Percentis de tempo de resposta:
    histogram_quantile(0.50, sum by (le, route) (
      rate(http_request_duration_seconds_bucket{job="nodejs-api"}[5m])
    ))
    histogram_quantile(0.95, sum by (le, route) (
      rate(http_request_duration_seconds_bucket{job="nodejs-api"}[5m])
    ))
    histogram_quantile(0.99, sum by (le) (
      rate(http_request_duration_seconds_bucket{job="nodejs-api"}[5m])
    ))
    
    # 3. Taxa de erro (% de 4xx e 5xx):
    sum(rate(http_request_duration_seconds_count{status_code=~"[45].."}[5m]))
    /
    sum(rate(http_request_duration_seconds_count[5m])) * 100
    
    # 4. Erros por endpoint (para identificar rotas problemáticas):
    sum by (route, status_code) (
      rate(http_request_duration_seconds_count{status_code=~"5.."}[5m])
    )
    
    # 5. Conexões ativas Node.js:
    nodejs_active_handles_total{job="nodejs-api"}

    Painel de uso de recursos do sistema

    Métricas do Node Exporter para CPU, memória e disco:

    bash
    # Queries PromQL para recursos do servidor:
    
    # CPU usage % (por core e total):
    100 - (avg by (instance) (
      rate(node_cpu_seconds_total{mode="idle"}[5m])
    ) * 100)
    
    # Por modo (user/system/iowait):
    sum by (mode) (
      rate(node_cpu_seconds_total{instance="servidor:9100"}[5m])
    ) * 100
    
    # Memória livre %:
    (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
    
    # Memória por componente (painel tipo "stack"):
    node_memory_MemTotal_bytes - node_memory_MemFree_bytes
      - node_memory_Buffers_bytes - node_memory_Cached_bytes
    
    # Disco: uso % por filesystem:
    (
      node_filesystem_size_bytes{mountpoint="/"}
      - node_filesystem_free_bytes{mountpoint="/"}
    ) / node_filesystem_size_bytes{mountpoint="/"} * 100
    
    # I/O de disco (bytes/s):
    rate(node_disk_read_bytes_total{device="sda"}[5m])
    rate(node_disk_written_bytes_total{device="sda"}[5m])
    
    # Rede (bytes/s por interface):
    rate(node_network_receive_bytes_total{device="eth0"}[5m])
    rate(node_network_transmit_bytes_total{device="eth0"}[5m])

    Painel PostgreSQL com postgres_exporter

    Monitorar banco de dados PostgreSQL no Grafana:

    yaml
    # Instalar postgres_exporter:
    # docker-compose.yml (adicionar ao stack):
      postgres-exporter:
        image: prometheuscommunity/postgres-exporter:latest
        environment:
          DATA_SOURCE_NAME: "postgresql://monitoring:senha@postgres:5432/mydb?sslmode=disable"
        ports:
          - "127.0.0.1:9187:9187"
    
    # Queries PromQL para PostgreSQL:
    
    # Conexões ativas vs máximo:
    pg_stat_activity_count{datname="mydb", state="active"}
    pg_settings_max_connections
    
    # Transações por segundo:
    rate(pg_stat_database_xact_commit{datname="mydb"}[5m])
    rate(pg_stat_database_xact_rollback{datname="mydb"}[5m])
    
    # Cache hit ratio (deve ficar acima de 99%):
    pg_stat_database_blks_hit{datname="mydb"}
    / (
      pg_stat_database_blks_hit{datname="mydb"}
      + pg_stat_database_blks_read{datname="mydb"}
    ) * 100
    
    # Queries lentas (via pg_stat_statements):
    pg_stat_statements_mean_time_seconds
    # Ordenar por: topk(10, pg_stat_statements_mean_time_seconds)
    
    # Tamanho do banco:
    pg_database_size_bytes{datname="mydb"}
    
    # Locks esperando:
    pg_locks_count{mode="ExclusiveLock", granted="false"}

    Provisioning automático de dashboards

    Versionar dashboards como código e carregar automaticamente:

    yaml
    # Estrutura de arquivos:
    # grafana/
    #   provisioning/
    #     datasources/
    #       prometheus.yml   → configurar Prometheus como datasource
    #     dashboards/
    #       dashboard.yml    → apontar para pasta de JSON
    #   dashboards/
    #     nodejs-api.json    → dashboard exportado
    
    # grafana/provisioning/datasources/prometheus.yml:
    apiVersion: 1
    datasources:
      - name: Prometheus
        type: prometheus
        access: proxy
        url: http://prometheus:9090
        isDefault: true
        editable: false
    
    # grafana/provisioning/dashboards/dashboard.yml:
    apiVersion: 1
    providers:
      - name: 'default'
        orgId: 1
        folder: ''
        type: file
        disableDeletion: false
        updateIntervalSeconds: 30
        options:
          path: /var/lib/grafana/dashboards
    
    # Exportar dashboard existente como JSON:
    # Grafana UI → Dashboard → Share → Export → Save to file
    
    # Importar dashboard da comunidade (Grafana.com/dashboards):
    # Dashboard ID 1860 → Node Exporter Full (métricas de sistema)
    # Dashboard ID 11159 → Node.js Application Dashboard
    # Dashboard ID 9628 → PostgreSQL Database
    
    # API Grafana para importar via curl:
    curl -X POST http://admin:senha@localhost:3001/api/dashboards/import   -H 'Content-Type: application/json'   -d '{"dashboard": {...}, "overwrite": true, "folderId": 0}'

    $ runstack deploy --plan starter

    Não quer configurar manualmente?

    Não quer configurar manualmente? Implante o VPS para Node.js em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.

    Perguntas frequentes