> ## Documentation Index
> Fetch the complete documentation index at: https://chatcli.edilsonfreitas.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Web Dashboard e Grafana

> O dashboard web embutido no operator (API keys, publicação atrás de um Ingress) e dashboards Grafana pré-configurados para observabilidade.

A plataforma AIOps do ChatCLI inclui um **dashboard web embutido** (SPA self-contained servida pelo operator) e **4 dashboards Grafana** (JSON no repositório) para observabilidade do pipeline de operações autônomas.

## Web Dashboard

### Visão Geral

O Web Dashboard é uma **Single Page Application** embutida diretamente no binário do operator via Go `embed.FS` — não requer Node.js, npm ou qualquer build frontend separado.

| Característica | Detalhe |
| - | - |
| **Tecnologia** | HTML/CSS/JS vanilla num único `index.html` (zero dependências externas) |
| **Empacotamento** | Go `embed.FS` — compilado no binário |
| **Porta** | `8090` no operator (chart `api.port`, env `CHATCLI_AIOPS_PORT`), Service `chatcli-operator` |
| **Tema** | Mesma linguagem visual do live dashboard do ChatCLI: paleta escura de terminal, paleta clara, tipografia monoespaçada, tiles de KPI, barra de abas segmentada. Um seletor no cabeçalho escolhe **Sistema / Escuro / Claro**; Sistema segue a preferência do SO |
| **Idioma** | Seletor no cabeçalho com **English** e **Português (BR)**; todo rótulo, cabeçalho de tabela, estado vazio, toast e prompt de confirmação é traduzido no lugar, sem recarregar. Datas e números seguem o idioma escolhido |
| **Responsivo** | Adapta-se a desktop, tablet e mobile |
| **Auto-refresh** | Intervalo configurável: Off, 10s, 30s (padrão), 1m, 2m, 5m — com botão de refresh manual |
| **Proteção de rascunho** | Um formulário em preenchimento (feedback de post-mortem, motivo de aprovação) nunca é apagado por um refresh: a contagem fica parada enquanto um campo está focado ou tem texto não salvo, o cabeçalho mostra *pausado durante a edição*, e os valores são restaurados após qualquer outra re-renderização. As linhas expandidas são identificadas pelo nome do objeto, então um post-mortem aberto continua aberto quando a lista reordena ou o intervalo de tempo muda |
| **Tabelas ordenáveis** | Clique no cabeçalho de qualquer coluna para ordenar (▲ ascendente / ▼ descendente) |
| **Ordenação estável** | Listas mantêm ordem consistente entre refreshes (incidentes, aprovações e audit mais recentes primeiro, SLOs por nome) |
| **Autenticação** | Mesma API key da API REST (header `X-API-Key`); a role da chave decide quais ações funcionam |
| **URL** | `http://&lt;operator-host&gt;:8090/` |

<Note>
  O dashboard consome a mesma API REST documentada na [API Reference](/pt/reference/api/overview). Toda operação disponível no dashboard (acknowledge, snooze, resolve, approve, reject, revisão, fechamento e feedback de post-mortem e reconhecimento de ação humana) é uma chamada REST autenticada e exige pelo menos a role `operator`; uma chave `viewer` vê tudo, mas suas ações devolvem `403`.
</Note>

### Tema e idioma

Os dois seletores ficam no cabeçalho, ao lado do controle de auto-refresh, e são acessíveis por teclado. A escolha fica guardada no navegador e é aplicada antes da primeira pintura, então um reload nunca pisca o tema errado.

| Preferência | Valores | Chave de armazenamento | Padrão |
| - | - | - | - |
| **Tema** | `system`, `dark`, `light` | `localStorage` `chatcli_dash_theme` | `system` — segue `prefers-color-scheme` |
| **Idioma** | `en`, `pt-BR` | `localStorage` `chatcli_dash_lang` | Do navegador: `pt*` → `pt-BR`, qualquer outro → `en` |

Os parâmetros de query `?theme=` e `?lang=` definem a preferência uma vez e a persistem, então um bookmark como `http://localhost:8090/?lang=pt-BR&theme=dark` abre o dashboard em português e escuro em todas as visitas seguintes. O atributo `<html lang>` acompanha o idioma, e os valores que vêm da API (severidade, estados de incidente e de plano, decisões de aprovação) mantêm o valor bruto no markup enquanto o rótulo visível é traduzido.

<Tip>
  Os nomes de produto ficam em inglês nos dois idiomas: Issue, SLO, Runbook, PostMortem, AIInsight e RemediationPlan são os nomes dos CRDs que o operator gerencia.
</Tip>

### Arquitetura

```text theme={"system"}
+-------------------------------------------------------------+
|                    Binário do Operator                       |
|                                                              |
|  +--------------------+  +-------------------------------+   |
|  |  embed.FS          |  |  Servidor HTTP (:8090)        |   |
|  |  +-- index.html    |  |  +-- /          -> SPA        |   |
|  |   (HTML, CSS, JS   |  |  +-- /api/v1/   -> API REST   |   |
|  |    e i18n num só   |  |  +-- /healthz   -> Health     |   |
|  |    arquivo)        |  |  +-- /readyz    -> Ready      |   |
|  +--------------------+  +-------------------------------+   |
|                                                              |
|  +------------------------------------------------------+    |
|  |  client do controller-runtime (leituras em cache)     |    |
|  |  Issues, AIInsights, Plans, PostMortems, SLOs, ...    |    |
|  +------------------------------------------------------+    |
+-------------------------------------------------------------+
```

A página em si (`/`) é servida sem autenticação; toda chamada de dados que ela faz vai para `/api/v1/` com a API key. No primeiro acesso o dashboard pede a chave, valida contra `/api/v1/incidents` e a guarda no `localStorage` do navegador (`chatcli_api_key`); **Trocar a chave de API** no cabeçalho a apaga.

<Note>
  O dashboard é servido pelo **operator**, na porta `api` (8090) do Service `chatcli-operator` no namespace do operator, e não pelo Service da Instance do ChatCLI. Toda réplica do operator serve o dashboard e a API, então um Service com várias réplicas pode rotear para qualquer uma delas.
</Note>

### Views do Dashboard

O dashboard tem **11 views** acessíveis por abas. Um filtro de período no cabeçalho (**Todo o período**, ou **De**/**Até**) é repassado como `from`/`to` às listas que o suportam.

<AccordionGroup>
  <Accordion title="1. Overview">
    Visão geral da plataforma com métricas agregadas, montada a partir de `/analytics/summary`, `/analytics/compliance`, `/analytics/capacity`, `/analytics/remediation-stats`, `/analytics/mttd`, `/analytics/mttr` e da lista de incidentes.

    **Componentes:**

    | Componente | Descrição |
    | - | - |
    | **Stats Cards** | 8 tiles de KPI: Issues Ativas, **Contidos (requer ação humana)**, Resolvidos, Remediações (Issues resolvidas por remediação / Issues remediadas), Taxa de Sucesso, PostMortems (com a contagem pendente de ação humana), Aprovações Pendentes, **Simulações de chaos (excluídas de MTTD/MTTR)**. O tile de Contidos ganha contorno violeta quando há issues nesse estado. |
    | **Alertas de Capacidade** | Banner com as previsões de capacidade com `Urgency: plan` (requests em 80% ou mais dos limits, ou incidentes repetidos no recurso), com recomendações |
    | **Issues por Severidade** | Gráfico de pizza com a distribuição de incidentes por severidade (Critical/High/Medium/Low) |
    | **Recursos da Plataforma** | Totais: Issues, Remediações, PostMortems, Runbooks, SLOs, Aprovações Pendentes, risk score médio |
    | **Atividade de Remediação** | Os últimos incidentes com tentativas de remediação, em linha do tempo. Um botão alterna entre mais recentes primeiro (padrão) e mais antigos primeiro; a escolha fica em `localStorage` (`chatcli_dash_remediationSort`) |
    | **Remediação por Estratégia** | Barras horizontais com a taxa de sucesso por estratégia (ex.: RestartDeployment 93%, RollbackDeployment 80%) |
    | **Conformidade e SLA** | Percentual de conformidade de SLA, violações de SLA de resposta/resolução, aprovações (auto/manual) |
    | **Tendência de MTTD e MTTR** | Médias de MTTD e MTTR e a tendência de MTTR dos últimos 10 dias |
    | **Incidentes Recentes** | Os incidentes mais recentes com estado, severidade e idade, mais uma barra de filtros igual à da aba Incidents: severidade, estado, tipo de recurso, simulações de chaos e namespace, com botão Limpar. A filtragem é feita no cliente sobre os incidentes já carregados, reaplicada a cada auto-refresh, e a seleção fica em `localStorage` (`chatcli_dash_recentFilters`). Todo cabeçalho de coluna ordena o painel (nome, severidade, estado, recurso, namespace, idade); severidade ordena por gravidade, não pelo rótulo, e a ordenação é mantida por painel entre refreshes |

    Os painéis podem ser reorganizados arrastando o cabeçalho; a ordem fica em `localStorage` (`panelOrder_overviewPanels`).
  </Accordion>

  <Accordion title="2. Incidents">
    Tabela interativa dos incidentes com filtros e ações.

    **Funcionalidades:**

    | Funcionalidade | Descrição |
    | - | - |
    | **Filtros** | Severidade, estado, tipo de recurso, simulações de chaos (ocultas por padrão), namespace, mais o período do cabeçalho. Clique em **Aplicar** |
    | **Tabela** | Colunas: Nome (com os badges `CHAOS` e `NEEDS HUMAN`), Severidade, Estado, Recurso, Namespace, Risco, Idade, ações. Mais recentes primeiro; mostra os 100 resultados mais recentes (sem paginação) |
    | **Ordenação** | Clique no cabeçalho da coluna para ordenar (asc/desc) |
    | **Expansão** | Clique na linha para expandir: descrição, recurso, tipo de sinal, origem, risk score, tentativas de remediação, resolução, horários de detecção/resolução |
    | **Preview do AI Insight** | Linhas expandidas carregam a análise de IA inline com badge de confiança, provedor/modelo, resumo da análise (primeiros 500 caracteres) e as 3 principais recomendações |
    | **Ack** | Reconhece o incidente (não aparece para Resolved ou Contained) |
    | **Adiar (Snooze)** | Pede uma duração como `30m`, `1h` ou `2h` (padrão `1h`) (não aparece para Resolved ou Contained) |
    | **Resolver** | Aparece para incidentes Escalated e Contained; pede uma nota de resolução opcional e marca a Issue como `Resolved` |

    Ack, Adiar e Resolver exigem a role `operator`. **Ack** para a escalação do incidente no nível atual (nenhum nível a mais, nenhuma repetição) e registra quem reconheceu no status da EscalationPolicy. **Adiar** segura toda notificação exceto `Resolved`, e a escalação, até o snooze terminar; um page de escalação retido sai nesse momento e o timer do nível recomeça. Veja [reconhecimento e snooze](/pt/kubernetes/aiops/notifications#reconhecimento-e-como-encerrar-uma-escalação).

    **Badges de severidade (tema escuro):**

    | Severidade | Cor |
    | - | - |
    | Critical | Vermelho (#E06C75) |
    | High | Laranja (#FF8C69) |
    | Medium | Âmbar (#FFB454) |
    | Low | Verde (#7FD962) |

    **Badges de estado (tema escuro):**

    | Estado | Cor |
    | - | - |
    | Detected | Vermelho (#E06C75) |
    | Analyzing | Âmbar (#FFB454) |
    | Remediating | Âmbar (#FFB454) |
    | **Contained** | **Violeta (#C79BFF) com animação pulsante** — há uma ação humana pendente |
    | Resolved | Verde (#7FD962) |
    | Escalated | Laranja (#FF8C69) |
    | Failed | Vermelho (#E06C75) |
  </Accordion>

  <Accordion title="3. SLOs">
    Um card por SLO, ordenados por nome, mais uma tabela **Alertas de SLO ativos** com os SLOs abaixo da meta.

    **Componentes por SLO:**

    | Componente | Descrição |
    | - | - |
    | **Card** | Serviço (ou nome do SLO), tipo de SLI, janela, valor atual vs. meta |
    | **Estado** | Badge com o estado do SLO que a API deriva (`Healthy`, `AtRisk`, `Breached`); antes do primeiro cálculo do SLO, mostra `Healthy` ou `Firing` a partir de atual vs. meta |
    | **Error Budget restante** | Barra com o error budget restante: verde (>50%), âmbar (>20%), vermelho nos demais casos |
    | **Chips de Burn Rate** | Chips de 1h, 6h, 24h e 72h com os burn rates que o controller de SLO calcula (`burnRate1h` … `burnRate72h`): vermelho acima de 14x, âmbar acima de 1x |
  </Accordion>

  <Accordion title="4. Approvals">
    Pedidos de aprovação, mais recentes primeiro, com ações de aprovar/rejeitar. O badge da aba mostra quantos estão pendentes.

    **Funcionalidades:**

    | Funcionalidade | Descrição |
    | - | - |
    | **Filtro** | Estado (Pending, Approved, Rejected, Expired) |
    | **Contexto** | Cada card mostra: nome, namespace, solicitante, ação solicitada (a primeira), recurso (a Issue), motivo (a política que o levantou, ex.: `decision-engine`) |
    | **Seu nome** | Campo obrigatório nos cards pendentes: o nome do aprovador registrado na decisão, junto com a identidade da API key. Fica lembrado no navegador (`localStorage` `chatcli_approver`) para a próxima decisão |
    | **Motivo da decisão** | Campo de texto opcional nos cards pendentes |
    | **Progresso do quorum** | Nos pedidos que precisam de mais de um aprovador: "*n* de *total* aprovações necessárias" |
    | **Aprovar / Rejeitar** | Botões nos cards pendentes; exigem a role `operator`. Cada clique registra uma decisão no pedido; a lista recarrega para mostrar o veredito do operator (quorum, change window) |
    | **Cards decididos** | Mostram aprovador, motivo e horário da decisão |

    <Note>
      Uma decisão tomada aqui é igual à chamada REST: ela fica gravada em `status.decisions` como `<seu nome> (api-key: <identidade da chave>)`, e o controller de aprovação avalia então quorum e change window. Um quorum conta cada API key uma vez, então cada aprovador precisa da própria chave; um pedido que não está mais pendente, ou que a sua chave já decidiu, devolve erro. Veja [Fluxo de Aprovação](/pt/kubernetes/aiops/approval-workflow#via-rest-api). Quando o pedido traz a annotation `platform.chatcli.io/blast-risk-level`, o card mostra um badge de blast radius colorido pelo nível.
    </Note>
  </Accordion>

  <Accordion title="5. AI Insights">
    Veja todas as análises geradas pela IA para entender como ela raciocinou sobre cada incidente.

    **Funcionalidades:**

    | Funcionalidade | Descrição |
    | - | - |
    | **Filtro** | Filtre pelo nome do incidente para ver os insights de uma issue específica |
    | **Tabela** | Colunas: Incidente, Provedor, Modelo, Confiança, Recomendações, Ações, Gerado |
    | **Confiança** | Score de confiança por cor: verde (≥85%), âmbar (70-84%), laranja/vermelho (\<70%) |
    | **Expansão** | Clique na linha para expandir: texto completo da análise, lista de recomendações, ações sugeridas com parâmetros |
    | **Análise de Logs** | O texto de análise de logs que o operator anexou à análise, quando existe |
    | **Análise de Cascata** | A análise de cascata entre serviços, quando existe |
    | **Contexto GitOps** | Contexto de Helm/ArgoCD/Flux no momento da análise, quando existe |
    | **Blast Radius** | A previsão de blast radius das ações sugeridas, quando existe |

    Esta view é essencial quando um incidente é **escalado para ação humana** -- ela mostra o que a IA encontrou, por que recomendou certas ações e quais dados de enriquecimento embasaram a análise.

    **Endpoint da API:** [`GET /api/v1/aiinsights`](/pt/reference/api/list-aiinsights)
  </Accordion>

  <Accordion title="6. Remediations">
    Acompanhe todos os planos de remediação com detalhes de execução, tanto baseados em runbook quanto agênticos.

    **Funcionalidades:**

    | Funcionalidade | Descrição |
    | - | - |
    | **Filtros** | Dropdown de estado (Pending/Executing/Verifying/Completed/Failed/RolledBack), filtro por nome do incidente |
    | **Tabela** | Colunas: Nome, Incidente, Tentativa, Estado, Modo (Runbook/Agentic), Ações/Passos, Início, Duração |
    | **Expansão** | Clique na linha para expandir: estratégia, ações planejadas, resultado, horários de início e conclusão |
    | **Detalhes agênticos** | Para planos agênticos: contagem de passos na tabela e na view de detalhe |
    | **Duração** | Calculada do início até a conclusão |

    **Modos de remediação:**

    * **Modo Runbook**: mostra a sequência de ações do runbook a partir do qual o plano foi montado
    * **Modo Agentic**: mostra a contagem de passos; use a [API Get Remediation Plan](/pt/reference/api/get-remediation-detail) para o histórico completo da conversa com a IA

    **Endpoint da API:** [`GET /api/v1/remediations`](/pt/reference/api/list-remediations)
  </Accordion>

  <Accordion title="7. Runbooks">
    Veja todos os runbooks — tanto os criados manualmente quanto os gerados pela IA.

    **Funcionalidades:**

    | Funcionalidade | Descrição |
    | - | - |
    | **Tabela** | Colunas: Nome, Tipo de Sinal, Severidade, Tipo de Recurso, Passos, Máx. Tentativas, Criado |
    | **Badge de sinal** | Badge colorido com o tipo de sinal do gatilho (oom\_kill, pod\_not\_ready, deploy\_failing etc.) |
    | **Expansão** | Clique na linha para expandir: descrição completa, critérios do gatilho e lista ordenada de passos |
    | **Detalhe dos passos** | Cada passo mostra: badge do tipo de ação, descrição e parâmetros em JSON |

    RemediationPlans não agênticos são montados a partir de um runbook. Quando uma Issue é analisada e nenhum runbook que casa com o gatilho dela (tipo de sinal, severidade, tipo de recurso) é aceito, o operator gera um a partir das ações sugeridas pela IA; depois de uma remediação agêntica bem-sucedida, ele também salva as ações que funcionaram como um runbook `agentic-…`. Runbooks gerados levam o label `platform.chatcli.io/auto-generated: "true"` e são reutilizados pelo próximo incidente parecido, em vez de começar do zero.

    **Endpoint da API:** [`GET /api/v1/runbooks`](/pt/reference/api/list-runbooks)
  </Accordion>

  <Accordion title="8. PostMortems">
    Tabela de post-mortems com detalhes expansíveis.

    **Funcionalidades:**

    | Funcionalidade | Descrição |
    | - | - |
    | **Tabela** | Colunas: Nome (com os badges `CHAOS` e `NEEDS HUMAN`), Severidade, Estado (Open/InReview/Closed), Recurso, Duração, Issue, Criado, ações |
    | **Expansão** | Clique para expandir: resumo, causa raiz, impacto, linha do tempo, ações executadas |
    | **Lições Aprendidas** | Seção com lições aprendidas (geradas pela IA) |
    | **Ações de Prevenção** | Lista de ações preventivas sugeridas |
    | **Feedback do Desenvolvedor** | Formulário inline: seu nome (obrigatório), precisão da remediação (1-5 estrelas, obrigatório), correção da causa raiz, comentários. Depois de enviado, mostra o feedback com a nota visual |
    | **Revisar** | Marca o post-mortem como `InReview` |
    | **Fechar** | Marca como `Closed` |
    | **Ack Human Action** | Substitui Revisar e Fechar enquanto o post-mortem exige ação humana (incidente contido); pede uma nota opcional e limpa a marcação para que Fechar apareça |

    Revisar, Fechar, feedback e Ack Human Action exigem a role `operator`.
  </Accordion>

  <Accordion title="9. Clusters">
    Visão geral da federação e um card por cluster registrado.

    **Tiles de resumo** (de `/clusters/global-status`): Total de Clusters, Saudáveis (conectados, todos os nodes Ready), Degradados (conectados, com a condition `Degraded`: alguns nodes não Ready), Offline.

    **Painel de Federação:**

    | Componente | Descrição |
    | - | - |
    | **Status da Federação** | Contagem de clusters conectados/desconectados e Issues locais ativas |
    | **Correlações Cross-Cluster** | Issues correlacionadas com badge de severidade, tipo de sinal, flags CASCADE/ELEVATED e o número de clusters que a correlação abrange, uma entrada por id de correlação (veja [Federação](/pt/kubernetes/aiops/federation#correlação-cross-cluster)) |

    **Componentes por cluster:**

    | Componente | Descrição |
    | - | - |
    | **Card** | Nome de exibição, badge `Healthy` ou `Offline` (de `status.connected`) |
    | **Detalhes** | Região, environment, tier, nodes, namespaces, versão do Kubernetes, issues ativas, remediações ativas |
    | **Último Health Check** | Tempo desde o último health check |

    **Endpoints da API:** [`GET /api/v1/clusters/global-status`](/pt/reference/api/global-status), [`GET /api/v1/federation/status`](/pt/reference/api/federation-status), [`GET /api/v1/federation/correlations`](/pt/reference/api/federation-correlations)
  </Accordion>

  <Accordion title="10. Políticas">
    Visão somente leitura dos quatro tipos de política que os controllers leem: ApprovalPolicy, NotificationPolicy, EscalationPolicy e IncidentSLA. As políticas são escritas via `kubectl` ou GitOps, onde são revisadas; a aba mostra o que está em vigor, por namespace ou em todos.

    | Painel | Colunas |
    | - | - |
    | **Políticas de aprovação** | Nome, namespace, ativa, quantidade de regras, totais aprovados e rejeitados |
    | **Políticas de notificação** | Nome, namespace, quantidade de canais, quantidade de regras, idade |
    | **Políticas de escalonamento** | Nome, namespace, ativa (e `padrão`), quantidade de níveis, severidades |
    | **SLAs de incidente** | Nome, namespace, severidade, metas de resposta e resolução, violações, conformidade |

    Toda coluna ordena. **Endpoints da API:** [`GET /api/v1/policies/{kind}`](/pt/reference/api/list-policies), [`GET /api/v1/policies/{kind}/{name}`](/pt/reference/api/get-policy)
  </Accordion>

  <Accordion title="11. Audit">
    Log de auditoria pesquisável (CRs AuditEvent) com exportação.

    **Funcionalidades:**

    | Funcionalidade | Descrição |
    | - | - |
    | **Busca** | Busca de texto no cliente sobre nome, tipo de evento, recurso, ator, id de correlação e detalhe |
    | **Filtros** | Tipo de evento (agrupado: Issues, Remediation, Approvals, Operations, SLO/SLA, Clusters, System), severidade, mais o período do cabeçalho |
    | **Tabela** | Colunas: Timestamp, Tipo de Evento, Severidade, Ator, Recurso, Correlação, Detalhe. Mostra os 100 eventos mais recentes que casam com os filtros |
    | **Exportar JSON** | Baixa `/api/v1/audit/export` com os filtros de tipo de evento e severidade (não o período) como arquivo JSON. A role `viewer` basta |
  </Accordion>
</AccordionGroup>

## Grafana Dashboards

O repositório traz **4 dashboards Grafana** em JSON em [`deploy/grafana/`](https://github.com/diillson/chatcli/tree/main/deploy/grafana), prontos para importação. Painéis baseados em métricas `chatcli_operator_*` precisam que o endpoint de métricas do operator seja coletado; painéis com `chatcli_grpc_*`, `chatcli_llm_*`, `chatcli_session_*`, `chatcli_server_*` e `chatcli_watcher_*` precisam também da porta de métricas do servidor ChatCLI (9090).

### 1. AIOps Overview (`aiops-overview.json`)

| Linha | Painéis |
| - | - |
| **AIOps Platform Overview** | Active Issues, Total Issues (24h), MTTR (p50 do tempo de resolução), Remediation Success Rate, Managed Instances, Notifications Sent (24h) |
| **Issues by Severity** | Issues Created Over Time (por severidade), Issues by State |
| **Remediation Performance** | Remediation Actions by Type, Remediation Duration (p50/p95/p99), Issue Resolution Duration (p50/p95) |
| **Watcher & Node Health** | Watcher Targets Monitored, Pods Ready vs Desired, Collection Errors, Pod Restarts, Watcher Alerts by Type, Collection Duration |
| **LLM & AI Performance** | LLM Requests Rate, LLM Latency (p50/p95/p99), Tokens Used, LLM Error Rate |
| **gRPC & Server** | Server Uptime, gRPC Request Rate, In-Flight Requests, gRPC Latency (p95), gRPC Error Rate |
| **Chaos Engineering** | Chaos Experiments (24h), Chaos Success Rate, Recovery Time (p50), Pods Affected by Chaos |

### 2. SLO Burn Rate (`slo-burn-rate.json`)

Variáveis de template `service` e `slo_name`.

| Linha | Painéis |
| - | - |
| **Error Budget Status** | Error Budget Remaining, Current SLI Value, Burn Rate (1h), SLO Violations (24h) |
| **Multi-Window Burn Rates** | Burn rate nas janelas de 1h, 6h, 24h e 72h, cada uma com sua linha de threshold (14.4x, 6x, 3x, 1x) |
| **SLA Compliance** | SLA Compliance %, SLA Response Time by Severity, SLA Violations Rate |
| **SLO Detail by Service** | Current SLI by Service, Error Budget by Service, SLO Violations by Service |
| **Burn Rate Analysis** | Burn rate em todas as janelas, Burn Rate vs Threshold, Time Until Budget Exhaustion |
| **SLA Deep Dive** | SLA Response/Resolution Time Distribution, SLA Compliance Trend, Violations by Type (24h) |

### 3. Incident Timeline (`incident-timeline.json`)

| Linha | Painéis |
| - | - |
| **Incident Lifecycle** | Critical Issues Detected (24h), Escalated Issues, Resolved (24h), Anomalies Processed (24h), Issues from Correlation, Escalation Levels Reached |
| **Notification Delivery** | Notifications by Channel, Notification Failures |
| **Approval Workflow** | Approval Decisions (por modo e resultado), Approval Decision Latency |
| **Federation** | Connected Clusters, Cross-Cluster Issues, Cascade Detected |
| **Incident Intelligence** | Anomaly Processing Rate, Issues Created by Correlation, Active Issues Trend, Issue Resolution Duration Distribution |
| **Notification & Escalation Analytics** | Notification Success Rate, Notification Latency by Channel, Escalation Level Distribution, Notification Failures by Reason |
| **Federation & Multi-Cluster** | Clusters by Status, Cross-Cluster Issues Rate, Cascade Events Rate |

### 4. Remediation Stats (`remediation-stats.json`)

| Linha | Painéis |
| - | - |
| **Remediation Performance** | Overall Success Rate, Total Remediations (24h), Median Remediation Duration, Auto-Approved (24h) |
| **Success Rate by Action Type** | Remediations by Action Type & Result, Success Rate per Action Type (24h), Remediation Duration Distribution |
| **Operator Health** | Operator Reconciliation Rate, Reconciliation Duration, Instance Health |
| **Approval Workflow Analytics** | Expired Approvals (24h), Approval Decision Distribution, Approval Duration by Mode, Auto-Approve Rate |
| **SLA Performance** | SLA Compliance by Severity, Response/Resolution Time by Severity (p95), SLA Violations Rate |
| **Session & Platform** | Active Sessions, Session Operations, Server Info, Server Uptime |

<Note>
  Todo painel consulta apenas métricas, labels e valores que o operator ou o servidor exporta; um teste no repositório garante isso nos quatro arquivos. Alguns painéis que vale conhecer:

  * **Expired Approvals (24h)** conta `chatcli_operator_approvals_total{result="expired"}`. Para as aprovações pendentes agora, use o tile de Aprovações Pendentes do dashboard ou `/api/v1/approvals?state=Pending`.
  * **Auto-Approved (24h)** e **Auto-Approve Rate** leem `mode="auto", result="approved"`; **Notification Success Rate** lê `result="success"`.
  * **Notification Latency by Channel** lê `chatcli_operator_notification_duration_seconds` (p50/p95 por `channel_type`).
  * **Clusters by Status** / **Connected Clusters** leem `chatcli_operator_federation_clusters_total`, um gauge definido por estado (`connected`, `degraded`, `disconnected`) a partir das registrations que existem.
  * **Critical Issues Detected (24h)** conta as Issues críticas que entraram em `Analyzing` nas últimas 24 horas.
</Note>

## Instalação dos Dashboards Grafana

### Via Grafana Sidecar (Recomendado)

Se você usa o [Helm chart do Grafana](https://github.com/grafana/helm-charts) com o sidecar de dashboards habilitado, crie um ConfigMap com os quatro arquivos e o label `grafana_dashboard: "1"`, a partir de um checkout do repositório:

```bash theme={"system"}
kubectl create configmap chatcli-grafana-dashboards -n monitoring \
  --from-file=deploy/grafana/aiops-overview.json \
  --from-file=deploy/grafana/incident-timeline.json \
  --from-file=deploy/grafana/remediation-stats.json \
  --from-file=deploy/grafana/slo-burn-rate.json \
  --dry-run=client -o yaml | kubectl apply -f -

# Label para descoberta pelo sidecar, e uma pasta para os quatro dashboards
kubectl label configmap chatcli-grafana-dashboards -n monitoring grafana_dashboard=1 --overwrite
kubectl annotate configmap chatcli-grafana-dashboards -n monitoring grafana-folder="ChatCLI AIOps" --overwrite
```

<Note>
  O sidecar do Grafana detecta ConfigMaps com o label `grafana_dashboard: "1"` e importa os dashboards sem restart. `deploy/grafana/dashboards-configmap.yaml` traz só os dois `ServiceMonitor`s que o Prometheus precisa para coletar o operator e o servidor (o do servidor seleciona `app.kubernetes.io/name: chatcli`, o label que os Services das Instances e o chart do servidor têm), com esses mesmos comandos nos comentários; ele não carrega ConfigMap de dashboards, então aplicá-lo nunca sobrescreve o criado acima. Nomeie cada arquivo JSON: apontar `--from-file` para o diretório também colocaria esse YAML dentro do ConfigMap.
</Note>

<Warning>
  Os painéis referenciam o datasource como `${DS_PROMETHEUS}`, que só a tela de importação resolve; o provisionamento pelo sidecar não resolve, e os painéis mostram `Datasource ${DS_PROMETHEUS} was not found`. Substitua o UID do seu datasource Prometheus nos arquivos antes de criar o ConfigMap, por exemplo `sed 's/\${DS_PROMETHEUS}/prometheus/g'` em cada JSON (veja o [setup de produção](/pt/cookbook/aiops-production-setup#11-dashboards-do-grafana)).
</Warning>

### Via Importação Manual

1. Vá em Grafana > **Dashboards** > **Import**
2. Faça upload do arquivo JSON ou cole o conteúdo
3. Selecione o datasource Prometheus
4. Clique em **Import**

### ServiceMonitor para Prometheus Operator

Com o Helm chart do operator, defina `serviceMonitor.enabled: true` (mais `serviceMonitor.interval`, `scrapeTimeout` e `labels` conforme necessário); o chart gera um ServiceMonitor para a porta `metrics` (8080, path `/metrics`). Escrito à mão, para um release chamado `chatcli-operator`:

```yaml theme={"system"}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: chatcli-operator
  namespace: chatcli-system
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: chatcli-operator
      app.kubernetes.io/instance: chatcli-operator
  endpoints:
    - port: metrics
      interval: 30s
      path: /metrics
  namespaceSelector:
    matchNames:
      - chatcli-system
```

O endpoint de métricas é HTTP simples, sem autenticação.

## Referência de Métricas Prometheus

O operator expõe estas métricas (além das padrão do controller-runtime) na sua porta de métricas:

| Métrica | Tipo | Labels | Descrição |
| - | - | - | - |
| `chatcli_operator_reconciliations_total` | Counter | `result` | Reconciles de Instance por resultado |
| `chatcli_operator_reconciliation_duration_seconds` | Histogram | - | Duração do reconcile de Instance |
| `chatcli_operator_managed_instances` | Gauge | - | Instances gerenciadas |
| `chatcli_operator_instance_ready` | Gauge | `name`, `namespace` | 1 quando a Instance está pronta |
| `chatcli_operator_anomalies_processed_total` | Counter | `result` | Anomalias processadas por resultado |
| `chatcli_operator_issues_created_by_correlation_total` | Counter | - | Issues criadas por correlação de anomalias |
| `chatcli_operator_issues_total` | Counter | `severity`, `state` | Transições de estado de Issues por severidade e estado |
| `chatcli_operator_issue_resolution_duration_seconds` | Histogram | - | Da detecção à resolução |
| `chatcli_operator_active_issues` | Gauge | - | Issues ainda não resolvidas |
| `chatcli_operator_remediations_total` | Counter | `action_type`, `result` | Ações de remediação por tipo e resultado (`success`, `failed`, ...) |
| `chatcli_operator_remediation_duration_seconds` | Histogram | - | Duração da execução do plano de remediação |
| `chatcli_operator_decision_engine_evaluations_total` | Counter | `mode` | Vereditos do motor de decisão |
| `chatcli_operator_decision_engine_circuit_breaker_state` | Gauge | `namespace` | 1 enquanto o circuit breaker está aberto |
| `chatcli_operator_agentic_convergence_stops_total` | Counter | `reason` | Loops agênticos parados pelo detector de convergência |
| `chatcli_operator_approvals_total` | Counter | `mode`, `result` | Resultados de aprovação (`approved`, `rejected`, `expired`) por modo |
| `chatcli_operator_approval_duration_seconds` | Histogram | `mode` | Ciclo de vida do pedido de aprovação |
| `chatcli_operator_sla_response_time_seconds` | Histogram | `severity` | Da detecção à primeira análise |
| `chatcli_operator_sla_resolution_time_seconds` | Histogram | `severity` | Da detecção à resolução |
| `chatcli_operator_sla_violations_total` | Counter | `severity`, `type` | Violações de SLA |
| `chatcli_operator_sla_compliance_percentage` | Gauge | `severity` | Percentual de conformidade de SLA |
| `chatcli_operator_slo_current_value` | Gauge | `service`, `slo_name` | Valor atual do SLI |
| `chatcli_operator_slo_error_budget_remaining` | Gauge | `service`, `slo_name` | Fração restante do error budget (0.0-1.0) |
| `chatcli_operator_slo_burn_rate` | Gauge | `service`, `slo_name`, `window` | Burn rate por janela (`1h`, `6h`, `24h`, `72h`) |
| `chatcli_operator_slo_violations_total` | Counter | `service`, `slo_name`, `severity` | Violações de SLO |
| `chatcli_operator_notifications_sent_total` | Counter | `channel_type`, `severity`, `result` | Notificações por tipo de canal e resultado |
| `chatcli_operator_notifications_failed_total` | Counter | `channel_type`, `reason` | Falhas de notificação |
| `chatcli_operator_escalation_level_reached` | Counter | `policy`, `level` | Níveis de escalonamento atingidos |
| `chatcli_operator_notification_duration_seconds` | Histogram | `channel_type` | Tempo para entregar uma notificação |
| `chatcli_operator_federation_clusters_total` | Gauge | `status` | Clusters registrados por estado: `connected`, `degraded`, `disconnected` (veja [Federação](/pt/kubernetes/aiops/federation#métricas-prometheus)) |
| `chatcli_operator_federation_cross_cluster_issues_total` | Counter | - | Correlações cross-cluster |
| `chatcli_operator_federation_cascade_detected_total` | Counter | - | Cascatas detectadas |
| `chatcli_operator_chaos_experiments_total` | Counter | `type`, `result` | Experimentos de chaos |
| `chatcli_operator_chaos_recovery_time_seconds` | Histogram | `type` | Tempo de recuperação do alvo, medido a partir do fim da injeção |
| `chatcli_operator_chaos_pods_affected_total` | Counter | `type` | Pods afetados por experimentos |

O operator não exporta métricas de tokens de LLM, custo ou capacidade; o custo de LLM por incidente está em [`GET /api/v1/analytics/cost`](/pt/reference/api/analytics-cost) e as previsões de capacidade em [`GET /api/v1/analytics/capacity`](/pt/reference/api/analytics-capacity). Métricas de requisições e tokens de LLM (`chatcli_llm_*`) vêm do servidor ChatCLI.

## Queries Prometheus Úteis

Exemplos de queries PromQL para dashboards ou alertas:

<AccordionGroup>
  <Accordion title="Tempo mediano de resolução (últimas 24h)">
    ```promql theme={"system"}
    histogram_quantile(0.5,
      rate(chatcli_operator_issue_resolution_duration_seconds_bucket[24h])
    )
    ```
  </Accordion>

  <Accordion title="Taxa de sucesso de remediação">
    ```promql theme={"system"}
    sum(rate(chatcli_operator_remediations_total{result="success"}[24h]))
    /
    sum(rate(chatcli_operator_remediations_total[24h]))
    * 100
    ```
  </Accordion>

  <Accordion title="Burn rate do SLO (alerta multi-window)">
    ```promql theme={"system"}
    # Alerta: burn rate 1h > 14.4x E burn rate 6h > 6x (modelo Google SRE)
    chatcli_operator_slo_burn_rate{window="1h"} > 14.4
    and
    chatcli_operator_slo_burn_rate{window="6h"} > 6.0
    ```
  </Accordion>

  <Accordion title="Planos segurados para um humano pelo motor de decisão">
    ```promql theme={"system"}
    sum(rate(chatcli_operator_decision_engine_evaluations_total{mode=~"approval|manual|blocked"}[1h]))
    /
    sum(rate(chatcli_operator_decision_engine_evaluations_total[1h]))
    ```
  </Accordion>

  <Accordion title="Anomalias por resultado de processamento">
    ```promql theme={"system"}
    sum by (result) (rate(chatcli_operator_anomalies_processed_total[1h]))
    ```
  </Accordion>

  <Accordion title="Taxa de falha de notificação por canal">
    ```promql theme={"system"}
    sum by (channel_type) (rate(chatcli_operator_notifications_sent_total{result="failure"}[1h]))
    /
    sum by (channel_type) (rate(chatcli_operator_notifications_sent_total[1h]))
    ```
  </Accordion>
</AccordionGroup>

## Acessar e publicar o dashboard

<Steps>
  <Step title="Verificar o operator">
    Confirme que o operator está rodando:

    ```bash theme={"system"}
    kubectl get pods -n chatcli-system -l app.kubernetes.io/name=chatcli-operator
    ```
  </Step>

  <Step title="Preview local (sem cluster)">
    Para revisar o próprio dashboard, ou testar uma mudança nele, sirva-o sobre um client fake com dados sintéticos:

    ```bash theme={"system"}
    cd operator
    make dash-preview
    ```

    Abra `http://127.0.0.1:8085/` e entre com a API key `preview`, que carrega o papel admin para que aprovações, revisões e feedback de post-mortem possam ser exercitados. O seed cobre todas as abas: issues em todos os estados, um AI insight, planos de remediação, uma aprovação pendente, um post-mortem, SLOs, clusters, eventos de auditoria e runbooks com passos. Defina `DASHPREVIEW_ADDR` para trocar o endereço. A ferramenta vive em `operator/hack/dashpreview` e nunca faz parte da imagem do operator.
  </Step>

  <Step title="Configurar as API Keys">
    O operator lê as API keys do Secret `chatcli-operator-secrets` (chave `api-keys`) no próprio namespace, com fallback para o ConfigMap `chatcli-operator-config` (mesma chave). Crie-o você mesmo como abaixo, ou deixe o chart do operator renderizá-lo (`apiKeys.create: true` com `apiKeys.entries`; as keys ficam então guardadas na release do Helm, então não faça os dois). O valor é uma lista YAML; as roles são `viewer`, `operator` e `admin` (qualquer outra role é negada):

    ```bash theme={"system"}
    # Gere cada chave com, por exemplo, `openssl rand -hex 32`
    cat > api-keys.yaml <<'EOF'
    - key: "troque-por-uma-string-aleatoria-longa"
      role: admin
      description: dashboard admin
    - key: "troque-por-outra-string-aleatoria"
      role: viewer
      description: dashboards somente leitura
    EOF

    kubectl -n chatcli-system create secret generic chatcli-operator-secrets \
      --from-file=api-keys=api-keys.yaml
    ```

    Mudanças são aplicadas em cerca de 30 segundos, sem restart. Uma edição que deixa YAML inválido mantém em vigor o último conjunto de chaves válido (o operator registra o erro no log). Sem nenhuma chave configurada, toda chamada a `/api/` devolve `401` (a página carrega, mas não consegue entrar).

    Para ler as keys de volta, por exemplo para entrar a partir de um navegador novo:

    ```bash theme={"system"}
    kubectl -n chatcli-system get secret chatcli-operator-secrets \
      -o jsonpath='{.data.api-keys}' | base64 -d
    ```
  </Step>

  <Step title="Port-forward (desenvolvimento)">
    Para acesso local durante desenvolvimento:

    ```bash theme={"system"}
    kubectl port-forward -n chatcli-system svc/chatcli-operator 8090:8090
    ```

    Acesse: `http://localhost:8090/`
  </Step>

  <Step title="Publicar com um Ingress (produção)">
    Sirva o dashboard na **raiz de um host só dele**. A página chama `/api/v1/...` e `/healthz` com caminhos absolutos, então sob um sub-path (`/chatcli` com rewrite ou strip-path) a página carrega mas todos os painéis falham; rotear `/api/v1` à parte no host compartilhado só esconde o problema e publica a API em todos os hosts daquele controller.

    ```yaml theme={"system"}
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: chatcli-dashboard
      namespace: chatcli-system
    spec:
      ingressClassName: nginx        # a classe do seu controller: nginx, kong, traefik...
      tls:
        - hosts: ["aiops.example.com"]
          secretName: aiops-tls
      rules:
        - host: aiops.example.com
          http:
            paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                    name: chatcli-operator   # <release>-chatcli-operator com outro nome de release
                    port:
                      name: api              # 8090
    ```

    * **Qualquer controller:** a regra acima não precisa de anotação do controller. Não adicione reescrita de caminho (`nginx.ingress.kubernetes.io/rewrite-target`, `konghq.com/strip-path`, um middleware `StripPrefix` do Traefik): com `path: /` não há nada a remover.
    * **TLS:** termine no Ingress como acima, ou sirva HTTPS (TLS 1.3) direto do operator com `security.apiTLS.certFile`/`keyFile` do chart (`CHATCLI_AIOPS_TLS_CERT`/`CHATCLI_AIOPS_TLS_KEY`), montando o certificado com `extraVolumes`/`extraVolumeMounts`. Um backend que serve TLS precisa da configuração de protocolo de backend do controller (no ingress-nginx, `nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"`).
    * **Cluster local (kind, k3d, Docker Desktop):** quando o ingress controller atende em `localhost`, use um nome sob `.localhost`, por exemplo `host: aiops.localhost`, e tire o bloco `tls`. Navegadores, `curl`, macOS e `systemd-resolved` mandam todo nome `*.localhost` para o endereço de loopback, então não é preciso DNS nem entrada no `/etc/hosts`.
    * **Métricas:** não publique a porta de métricas (8080) pelo mesmo Ingress: ela é HTTP puro, sem autenticação.
    * **Rate limit:** 30 requisições por minuto por host de cliente para requisições sem API key válida, 600 por minuto por key válida. Atrás de um Ingress toda requisição sem key vem do controller, então elas dividem uma cota só; o tráfego do dashboard carrega a key, então navegadores logados não dividem.
    * **CORS:** chamadas cross-origin são negadas a menos que liberadas com `security.corsAllowedOrigins` (`CHATCLI_CORS_ALLOWED_ORIGINS`); o dashboard em si é same-origin e não precisa de configuração de CORS.

    Confira: `curl -s https://aiops.example.com/healthz` responde `{"status":"ok",...}`, e `curl -s -o /dev/null -w '%{http_code}' https://aiops.example.com/api/v1/incidents` responde `401` sem key.
  </Step>
</Steps>

<Warning>
  Nunca exponha o dashboard sem API keys em produção. O modo dev (`CHATCLI_OPERATOR_DEV_MODE=true`, ou `TRUE`, `1`, `t`; chart `security.devMode`) sem chaves configuradas dá **a role admin a qualquer chamador** sem chave, incluindo operações de escrita como acknowledge, resolve, approve e reject. Use só localmente.
</Warning>

## Próximo Passo

<CardGroup cols={2}>
  <Card title="API REST Reference" icon="code" href="/pt/reference/api/overview">
    Referência completa de todos os endpoints consumidos pelo dashboard.
  </Card>

  <Card title="Capacity & Custos" icon="chart-line" href="/pt/kubernetes/aiops/capacity-cost">
    Detalhes do Capacity Planner, Noise Reducer e Cost Tracker.
  </Card>

  <Card title="AIOps Platform" icon="brain" href="/pt/kubernetes/aiops-platform">
    Arquitetura completa do pipeline de operações autônomas.
  </Card>

  <Card title="K8s Operator" icon="dharmachakra" href="/pt/kubernetes/k8s-operator">
    Configuração e deployment do operator Kubernetes.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.