Oficina fundamental 2 — Grafana: uma fonte, um painel, um painel de controle

Prática guiada17 min
Duração
20 min
Módulo
1/7
Pré-requisitos
o labo está rodando há pelo menos dois minutos (etat exibe 8/8 cibles up), Grafana aberto em http://localhost:3000 com admin / aiopsatlas2026, a oficina 1 feita (você sabe o que count(up) retorna)
Você vai construir
um painel de controle com um único painel, criado à mão na interface, salvo, relido em JSON, depois apagado
Entregável
o bloco JSON do painel tal como o Grafana o salvou (etapa 9), com três palavras destacadas: o tipo de visualização, a query, a fonte de dados

Como ler esta página. Dez etapas, um gesto de cada vez. Para cada uma: onde clicar, o que o Grafana exibe palavra por palavra, e o que observar. Os rótulos da interface estão em inglês no Grafana 13.2.2 (o do kit); eles são citados tal como aparecem, em negrito. Os números serão diferentes na sua máquina; os formatos (número de séries, valor do painel, mensagens) devem ser os mesmos. Os blocos "Para entender bem" são opcionais. Se o labo não estiver iniciado, volte à prática orientada: a seção En bref dá os comandos, incluindo o kit (https://github.com/hrhouma2/aiopsatlas-observabilite-labo-fr). Tudo o que você cria aqui é destruído na etapa 10: os três painéis de controle entregues com o kit não são tocados.

Objetivo

Na prática orientada, você digitou oito queries no Explore e olhou três painéis de controle já prontos. Você já sabe, portanto, ler o Grafana. Mas se pedirem para você adicionar um número em um painel, você sabe por onde começar? Aqui, você recomeça do zero e monta você mesmo os três objetos do Grafana, do menor ao maior: uma fonte de dados (o Grafana não armazena nada, ele consulta o Prometheus), um painel (uma query mais uma forma de desenhá-la), um painel de controle (painéis organizados em uma grade, com um nome e um endereço). Uma etapa é uma armadilha proposital: você quebra uma query para ver como o erro do Prometheus atravessa o Grafana. No final, você lê o JSON que o Grafana escreveu para você e reencontra ali os três objetos, depois apaga tudo.

O vocabulário em uma imagem

O Grafana é um porta-retrato digital. Ele não tira nenhuma foto: ele vai buscá-las com um fotógrafo (a fonte de dados: Prometheus, Loki) e as exibe. Cada foto é um painel: uma pergunta feita ao fotógrafo (a query) e um formato de exibição (um número, uma curva, um medidor). O próprio quadro, com suas fotos organizadas em uma grade, é o painel de controle: ele tem um nome, um endereço, e é salvo no banco do Grafana na forma de um documento JSON.

GrafanaBase SQL clássicaNesta oficina
fonte de dados (data source)a conexão com o bancoPrometheus (http://prometheus:9090)
query (query)SELECT …count(up)
painel (panel)uma visão salvaCibles surveillées
visualizaçãoa forma de exibir o resultadoStat (um número grande)
painel de controle (dashboard)um relatório que reúne várias visõesAtelier M1 - Cibles Prometheus
uidchave primáriaadc947c (o seu será diferente)
JSON do painelo esquema exportado do relatórioetapa 9
pasta (folder)esquema do bancoDashboards (a raiz); Labo observabilite para os três do kit

Onde clicar, e como ler uma resposta

Abra http://localhost:3000. O menu principal é o ícone de três traços no topo à esquerda: ele dá acesso a Dashboards, Explore e Connections. A trilha de navegação no topo (por exemplo Dashboards › New dashboard) sempre diz onde você está. Quando uma ação tem sucesso, o Grafana exibe por alguns segundos uma faixa no canto inferior direito (um toast): Dashboard saved, Dashboard deleted. Quando uma query falha, ele exibe uma caixa vermelha sob o campo de query, com a mensagem do Prometheus reproduzida tal como é.

Uma vez o painel de controle salvo, você vai relê-lo em JSON pela API do Grafana. No PowerShell ou em um terminal Linux, o mesmo comando:

bash
curl -s -u admin:aiopsatlas2026 http://localhost:3000/api/dashboards/uid/<uid>

<uid> é o identificador que o Grafana deu ao seu painel de controle; você vai lê-lo no endereço da página na etapa 8.

Etapa 1 — Verificar a fonte de dados

Menu principal → ConnectionsData sources. Três fontes estão listadas: Alertmanager, Loki e Prometheus (marcada default). Clique em Prometheus. A página Settings se abre, com Prometheus server URL preenchido: http://prometheus:9090. Não mude nada. Desça até o final e clique em Save & test.

text
Successfully queried the Prometheus API.
Next, you can start to visualize data by building a dashboard from scratch or by querying data in the Explore view.

A observar: a faixa verde. O Grafana acabou de enviar uma query ao Prometheus e o Prometheus respondeu. Esse é o primeiro objeto: uma fonte de dados é um endereço e um tipo. O endereço é http://prometheus:9090 e não http://localhost:9090: o Grafana roda em um contêiner, e a partir desse contêiner, o Prometheus se chama prometheus. Seu navegador, por sua vez, o alcança por localhost:9090. Dois nomes para a mesma máquina, dependendo de quem fala.

Para entender bem: quem criou essas três fontes?

Você, não. O kit as descreve em grafana/provisioning/datasources/sources.yml e o Grafana as lê na inicialização: é o provisioning. O arquivo é curto, abra-o: name: Prometheus, uid: prometheus, type: prometheus, url: http://prometheus:9090, isDefault: true. Sem esse arquivo, a primeira coisa a fazer em um Grafana novo seria Add new data source, e você digitaria essas quatro linhas à mão. O uid: prometheus vai servir novamente na etapa 9: é por ele que seu painel vai indicar sua fonte.

Etapa 2 — Consultar a fonte no Explore

Menu principal → Explore. No topo, o seletor de fonte exibe Prometheus. À direita do campo, mude para Code (e não Builder). Digite:

promql
up

depois Run query (ou Shift+Enter).

text
up{instance="alertmanager:9093", job="alertmanager"}
up{instance="alloy:12345", job="alloy"}
up{instance="api:8000", job="api", service="api"}
up{instance="cadvisor:8080", job="cadvisor"}
up{instance="grafana:3000", job="grafana"}
up{instance="localhost:9090", job="prometheus"}
up{instance="loki:3100", job="loki"}
up{instance="node-exporter:9100", job="node-exporter"}

A observar: oito linhas na legenda sob o gráfico, as oito séries da etapa 2 da oficina 1, em ordem alfabética de instance. A query é exatamente a que você digitou no Prometheus; o Grafana a transmitiu e desenhou a resposta. Explore é um rascunho: nada é salvo ali, é ali que se aperfeiçoa uma query antes de colocá-la em um painel.

Etapa 3 — A armadilha: um parêntese a menos

Ainda no Explore, substitua a query por uma versão errada, de propósito:

promql
count(up

Run query:

text
bad_data: invalid parameter "query": 1:9: parse error: unclosed left parenthesis

A observar: uma caixa vermelha sob o campo, e No data no gráfico. A mensagem não é do Grafana: parse error e a posição 1:9 são do Prometheus, que você aprendeu a ler na oficina 1. O Grafana apenas adiciona o prefixo bad_data:, a categoria de erro devolvida pela API do Prometheus. Regra: quando um painel do Grafana exibe um erro de PromQL, corrija primeiro no Prometheus (http://localhost:9090), depois copie para o Grafana. Feche o parêntese, Run query: uma única linha na legenda, que o Grafana nomeia count(up) por falta de labels (o Prometheus escrevia {}), em 8. É a query que você vai colocar no seu painel.

Etapa 4 — Criar um painel de controle vazio

Menu principal → Dashboards. A página lista uma única pasta, Labo observabilite, que contém os três painéis do kit. No topo à direita, NewNew dashboard.

text
New dashboard
Add a panel to visualize your data

A observar: a trilha de navegação diz Dashboards › New dashboard, a página está vazia, e o botão Save já está ali no topo à direita. Nada ainda foi salvo: se você fechar a aba agora, nada resta. Um painel de controle só existe a partir do momento em que é salvo (etapa 8). À direita, um painel lateral Add oferece Panel ("Drag or click to add a panel").

Etapa 5 — Adicionar um painel sem query

No painel lateral Add, clique em Panel. Um quadro aparece na grade, titulado New panel, com o texto No visualization configured. À direita, o campo Title contém New panel: substitua-o por:

text
Cibles surveillées

A observar: o título do quadro muda em tempo real. Você tem um painel, mas está vazio: nem query, nem visualização. Esse é o segundo objeto, reduzido ao mínimo: um espaço na grade e um nome. Clique em Edit visualization no painel lateral: a página Edit panel se abre, com embaixo a aba Queries 1 e, à direita, Suggestions / All visualizations.

Etapa 6 — Colocar a query

Em Queries, a linha A já está ligada a Data source: Prometheus (a fonte padrão). Mude para Code, digite no campo Enter a PromQL query…:

promql
count(up)

depois Run queries (ou Shift+Enter).

text
Suggestions
Time series · Stat · Gauge · Bar gauge · Table · State timeline · Heatmap · Histogram

A observar: o painel da direita muda: sob Suggestions, o Grafana propõe cerca de dez visualizações, e cada miniatura já exibe seu dado: count(up) e 8. O painel do topo, por sua vez, ainda diz "Run a query to visualize it here or go to all visualizations": ele tem a query, mas ainda não escolheu como desenhá-la. Query e visualização são dois ajustes separados de um mesmo painel.

Para entender bem: Builder ou Code?

Builder constrói a query com menus (escolher a métrica, adicionar um label, empilhar uma função). Code deixa você digitar. Os dois produzem a mesma string PromQL, e você pode alternar entre um e outro. Neste curso, ficamos em Code: a query que você digita aqui é palavra por palavra a do Prometheus, e você vai reencontrá-la tal como está no JSON da etapa 9 ("editorMode": "code").

Etapa 7 — Escolher a visualização

Em Suggestions, clique na miniatura Stat.

text
Stat
Value options
  Calculate | All values
  Calculation: Last *
Thresholds
  80  (rouge)
  Base  (vert)

A observar: o painel do topo agora exibe um grande 8 verde, com a pequena curva de fundo. O painel da direita lista as opções de Stat, das quais duas para conhecer: em Value options, Calculate está marcado e Calculation vale Last * (o painel mostra o último valor da série, não uma média); em Thresholds, dois patamares, Base em verde e 80 em vermelho: o valor ficaria vermelho a partir de 80. Esses limites são os que o Grafana coloca por padrão em todo painel novo; eles não fazem sentido nenhum para uma contagem de targets (você veria vermelho a partir de 80 targets), você os leria e mudaria em um painel de verdade. Aqui, deixe-os assim: o que importa é reconhecê-los no JSON.

Etapa 8 — Salvar: um nome, um endereço

No topo à direita, Save. O diálogo Save dashboard se abre, com duas abas, Details e Changes 3, e três campos: Title (New dashboard), Description, Folder (Dashboards).

A observar primeiro: apague o título e clique em Save: a palavra Required aparece em vermelho sob Title e o botão Save fica acinzentado. Um painel de controle obrigatoriamente tem um nome. Digite:

text
Atelier M1 - Cibles Prometheus

O botão volta a ficar ativo. Clique em Save.

text
Dashboard saved

A observar em seguida: a faixa Dashboard saved, depois o endereço da página:

text
http://localhost:3000/d/adc947c/atelier-m1-cibles-prometheus?orgId=1&from=now-6h&to=now&timezone=browser

Três coisas nesse endereço. adc947c é o uid, sorteado ao acaso pelo Grafana: é a identidade do painel de controle, anote-o. atelier-m1-cibles-prometheus é o título formatado como endereço; ele só serve para legibilidade. from=now-6h&to=now é o período exibido, Last 6 hours por padrão para um painel novo. O lápis no topo à direita (Edit) substituiu Save: você está em modo de leitura. Menu principal → Dashboards: seu painel está na lista, na raiz, ao lado da pasta Labo observabilite.

Para entender bem: a aba Changes 3

Antes de clicar em Save, abra Changes 3: o Grafana mostra, em JSON, a diferença entre um painel novo e o que você está salvando. O número é a quantidade de modificações que ele contou; em um painel vazio recém aberto, a aba diz Changes 1. É a primeira vez que você vê o JSON que será escrito; a etapa 9 faz você relê-lo inteiro.

Etapa 9 — Reler o JSON: os três objetos estão ali

Em um terminal, com seu uid no lugar de adc947c:

bash
curl -s -u admin:aiopsatlas2026 http://localhost:3000/api/dashboards/uid/adc947c

A resposta é um documento JSON. Sua parte meta:

json
"meta": {
  "slug": "atelier-m1-cibles-prometheus",
  "url": "/d/adc947c/atelier-m1-cibles-prometheus",
  "created": "2026-09-15T21:21:02Z",
  "version": 1,
  "folderTitle": "General"
}

E em dashboard, o array panels contém um único elemento, seu painel (resumido aos campos que importam):

json
{
  "type": "stat",
  "title": "Cibles surveillées",
  "datasource": { "type": "prometheus", "uid": "prometheus" },
  "targets": [
    {
      "datasource": { "type": "prometheus", "uid": "prometheus" },
      "editorMode": "code",
      "expr": "count(up)",
      "legendFormat": "__auto",
      "range": true,
      "refId": "A"
    }
  ],
  "fieldConfig": {
    "defaults": {
      "color": { "mode": "thresholds" },
      "thresholds": {
        "mode": "absolute",
        "steps": [
          { "color": "green", "value": 0 },
          { "color": "red", "value": 80 }
        ]
      }
    }
  },
  "options": {
    "colorMode": "value",
    "graphMode": "area",
    "reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false }
  },
  "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 },
  "id": 1,
  "pluginVersion": "13.2.2"
}

A observar: os três objetos da oficina, escritos claramente. A fonte: "datasource": { "type": "prometheus", "uid": "prometheus" }, o uid do arquivo de provisioning da etapa 1. A query: "expr": "count(up)", em targets, com "refId": "A" (a letra da linha em Queries) e "editorMode": "code". A visualização: "type": "stat", e seus ajustes da etapa 7: "calcs": ["lastNotNull"] é o Last * da tela, steps são os dois Thresholds, green na base e red em 80. gridPos diz onde está o quadro na grade: no topo à esquerda, 12 colunas de largura sobre 24, 8 linhas de altura. Um painel de controle do Grafana não é nada além disso: esse documento, salvo sob um uid. Esse é seu entregável: esse bloco, com stat, count(up) e prometheus destacados.

Para entender bem: o mesmo JSON na interface

Na página do painel de controle, Edit (o lápis) → na barra lateral direita, Options (a roda) → View all settings → aba JSON Model. É o mesmo documento, sem a parte meta, e você pode modificá-lo ali e depois Save. É também esse documento que o kit entrega para seus três painéis, em grafana/provisioning/dashboards/*.json: abra api-catalogue.json e procure "expr": você vai ler ali queries da prática orientada, exatamente no formato acima. Um painel de controle se compartilha enviando esse arquivo.

Etapa 10 — Apagar tudo, e provar

Na página do painel de controle, EditOptionsView all settings. A página Settings se abre (abas General, Annotations, Variables, Links, Versions, Permissions, JSON Model). No final, o botão vermelho Delete dashboard.

text
Delete
Do you want to delete this dashboard?
Atelier M1 - Cibles Prometheus
Type "Delete" to confirm

A observar: o botão Delete do diálogo fica acinzentado enquanto você não digitar a palavra Delete no campo. Digite-a, clique em Delete.

text
Dashboard deleted
View deleted dashboards

O Grafana te leva de volta à página inicial. Prova pela API, com seu uid:

bash
curl -s -u admin:aiopsatlas2026 http://localhost:3000/api/dashboards/uid/adc947c
json
{"message":"Dashboard not found"}

E a lista completa dos painéis de controle:

bash
curl -s -u admin:aiopsatlas2026 "http://localhost:3000/api/search?type=dash-db"

Três entradas, os três do kit, todos na pasta Labo observabilite: api-catalogue ("API catalogue — signaux dorés"), hote-conteneurs ("Hôte et conteneurs"), journaux-api ("Journaux de l'API"). O seu não está mais ali. O diálogo de exclusão dizia isso: o Grafana mantém os painéis apagados em um histórico por até doze meses (Recently deleted na página Dashboards), de onde podem ser restaurados; para o que você faz neste curso, apagado quer dizer apagado.

Verificação final

Refaça os dez gestos de memória, na ordem, e marque:

  • Connections → Data sources → Prometheus → Save & test retorna Successfully queried the Prometheus API.
  • No Explore, up em modo Code retorna 8 séries.
  • count(up retorna uma caixa vermelha bad_data: … parse error: unclosed left parenthesis; count(up) retorna {} e 8.
  • Dashboards → New → New dashboard abre uma página New dashboard vazia, com Save já visível.
  • Add → Panel cria New panel; o campo Title renomeia o quadro em tempo real.
  • count(up) depois Run queries preenche Suggestions com o valor 8 em cada miniatura.
  • A miniatura Stat exibe um grande 8; Calculation vale Last *; Thresholds: Base verde, 80 vermelho.
  • Título vazio: Required e Save acinzentado; título Atelier M1 - Cibles Prometheus: faixa Dashboard saved e um uid no endereço.
  • curl … /api/dashboards/uid/<uid> contém "type": "stat", "expr": "count(up)", "uid": "prometheus".
  • Depois de Delete dashboard, o mesmo curl retorna {"message":"Dashboard not found"} e /api/search?type=dash-db lista exatamente três painéis.

Do lado do labo, nada mudou: etat continua exibindo 10/10 services, 8/8 cibles up, 0 alertes actives. O Grafana escreveu e depois apagou uma linha no seu próprio banco; o Prometheus não viu nada passar.

Se travar

Afficher les cas où ça coince

A página de login aparece e admin / admin é recusado. A senha do kit é aiopsatlas2026 (fixada em docker-compose.yml, variável GF_SECURITY_ADMIN_PASSWORD). Na linha de comando, o mesmo par: -u admin:aiopsatlas2026; com uma senha errada, a API retorna {"message":"Invalid username or password", …, "statusCode":401}.

Save & test retorna um erro em vez da faixa verde. O Prometheus está parado ou reiniciando: etat, depois espere labo-prometheus ficar healthy e tente novamente. Se você mudou a URL por engano, restaure http://prometheus:9090 (não localhost: a partir do contêiner do Grafana, localhost é o próprio Grafana).

Explore retorna No data em up sem caixa vermelha. Olhe o seletor de fonte no topo: talvez você esteja em Loki (a prática orientada te deixou lá). Volte para Prometheus. Verifique também o período no topo à direita: ele deve terminar em now.

O campo de query recusa o que digito, ou o texto aparece duas vezes. Você está em Builder: o campo livre só existe em Code. Alterne, apague, digite novamente.

O painel continua em "Run a query to visualize it here". A query está escrita mas não foi executada: Run queries ou Shift+Enter. Se o painel Suggestions continuar vazio depois disso, a query tem um erro: a caixa vermelha está sob o campo, desça.

O Save do diálogo continua acinzentado, com Required sob o título. O título está vazio. Digite um. Se você já salvou um painel de controle com o mesmo nome em uma tentativa anterior, o Grafana aceita mesmo assim: dois painéis podem ter o mesmo título, eles têm uid diferentes. Você terá então duas entradas na lista; apague a que sobrou (etapa 10).

Não consigo encontrar o uid. Ele está no endereço, logo depois de /d/: http://localhost:3000/d/adc947c/…. Senão, curl -s -u admin:aiopsatlas2026 "http://localhost:3000/api/search?query=Atelier" retorna o campo "uid" de cada painel cujo título contém Atelier.

curl retorna {"message":"Dashboard not found"} na etapa 9 mesmo com o painel na tela. O uid foi copiado errado (maiúsculas, caractere a mais). Copie-o novamente a partir do endereço.

Apaguei um painel do kit por engano. Ele está em Dashboards → Recently deleted: restaure-o. Senão, docker compose restart grafana: o provisioning relê grafana/provisioning/dashboards/ na inicialização e recria os três painéis a partir de seus arquivos JSON (tableaux-de-bord.yml, updateIntervalSeconds: 30).

Modifiquei um painel do kit e o Save recusa. Normal: allowUiUpdates: false em tableaux-de-bord.yml. Os três painéis do kit se leem, não se sobrescrevem; salve sua versão com outro nome.