Skip to main content
A plataforma AIOps do ChatCLI inclui três subsistemas ao lado do pipeline de incidentes: Capacity Planner (previsão sob demanda para os recursos por trás dos seus incidentes), Noise Reducer (supressão de anomalias repetitivas, sazonais, com flapping ou de alta fadiga) e Cost Tracker (gasto de LLM por incidente, servido pela API REST).

Capacity Planner

O Capacity Planner gera um relatório de CPU e memória para cada Deployment que aparece como recurso de uma Issue. Ele não é um job em segundo plano: roda só quando GET /api/v1/analytics/capacity é chamado e não guarda histórico próprio.
O planner não lê uso real e não coleta histórico de uso. Ele não consulta metrics-server nem Prometheus (PROMETHEUS_URL não é usado aqui). O “uso atual” são os requests do primeiro container do Deployment (UsageSource: "requests"), e a porcentagem é requests dividido por limits. Sem histórico não há tendência para ajustar, então a resposta traz Trend.Direction: "insufficient_history" e HistoryAvailable: false, e nunca projeta data de esgotamento. Trate o resultado como uma checagem de requests contra limits somada a uma contagem de incidentes, não como previsão de uso.

O que Ele Calcula

Para cada recurso distinto (kind/namespace/name) entre as Issues listadas (todas, ou as do ?namespace=), o planner:
  1. Lê o Deployment com esse nome e namespace. Se não existir (o recurso é um StatefulSet, um DaemonSet, um Pod ou foi apagado), o recurso é pulado sem erro.
  2. Pega resources.limits e resources.requests de CPU e memória do primeiro container e calcula uso% = requests / limits × 100 (0 quando não há limit).
  3. Correlaciona o recurso com os incidentes do namespace dele dentro da janela (abaixo).
  4. Define uma urgência e uma recomendação a partir do que sabe: a porcentagem de requests/limits e a correlação com incidentes.
A janela padrão é de 7 dias. Quando from e to são passados juntos (RFC 3339), a janela passa a ser a diferença entre eles, e continua terminando agora.

Tendência e Urgência

Urgency só tem esses dois valores: sem histórico, nada é urgent. O banner de capacidade do dashboard lista os recursos com Urgency: "plan".

Campos da Resposta

O endpoint retorna kind: CapacityForecastList com um CapacityForecast por recurso. Os nomes de campo são os nomes Go (sem renomeação JSON), exceto a referência de recurso aninhada:

Correlação com Incidentes

Um gargalo eleva a Urgency para plan e, quando os requests estão dentro dos limits, define a recomendação.

Geração de Recomendações

A primeira regra que casar vence (o texto é sempre em inglês):

Como Usar

O endpoint exige o papel viewer (só GET). Cada chamada lista todas as Issues do escopo e, por recurso, lê um Deployment mais as Issues do namespace, então mantenha as chamadas esporádicas em clusters grandes.

Noise Reducer

O Noise Reducer roda dentro do controller de Anomaly. Ele só é consultado para uma anomalia que abriria uma Issue nova: uma anomalia cujo recurso já tem Issue ativa é antes correlacionada a ela, e uma que chega dentro do cooldown de resolução (spec.aiops.resolutionCooldownMinutes da Instance de onde a anomalia veio, padrão 10, 0 desliga) após uma resolução é suprimida antes de chegar ao Noise Reducer. As quatro checagens rodam em ordem e a primeira que disparar vence. Uma anomalia suprimida é marcada com status.correlated: true, com o motivo registrado como suppressed:<motivo>; nenhuma Issue é criada e chatcli_operator_anomalies_processed_total{result="suppressed_noise"} é incrementado. Se uma checagem falhar (por exemplo, erro num List), a anomalia não é suprimida. Os recursos são comparados pelo nome dentro do namespace da anomalia.

Estratégia 1: Supressão Repetitiva

A severidade não entra na comparação.

Estratégia 2: Padrões Sazonais

Toda anomalia não suprimida é registrada como ocorrência sazonal. Os padrões ficam por namespace no ConfigMap chatcli-seasonal-patterns, chave patterns, como um array JSON. SeasonalPattern (JSON): Algoritmo:
Hora e dia da semana vêm do relógio do pod do operator (UTC, a menos que você defina TZ no operator; a imagem inclui tzdata). A distância de horas não dá a volta na meia-noite (23:00 e 00:00 ficam a 23 horas de distância).
occurrences conta anomalias, não semanas distintas. Três anomalias do mesmo sinal e recurso no mesmo horário de um único dia bastam para suprimir as seguintes nesse horário, no mesmo dia e no mesmo dia da semana em todas as semanas seguintes. Não há score de confiança nem limpeza: os padrões ficam no ConfigMap até você editá-lo ou apagá-lo.

Estratégia 3: Detecção de Flapping

Não existe flag de flapping à parte, temporizador de espera nem alerta consolidado: cada nova anomalia é checada do mesmo jeito, e a supressão para quando sobram menos de três Issues resolvidas dentro da janela de 24 horas.

Estratégia 4: Score de Fadiga de Alertas

Na prática, bastam 7 anomalias de um recurso em 24 horas, todas já correlacionadas, com uma anomalia de referência recente, para passar do limite (35 + 30 + 20 = 85), e as anomalias seguintes desse recurso são suprimidas até a contagem cair.
A referência de recência é o último item da lista de Anomalies do namespace sem filtro, não a anomalia mais nova do recurso, então o recency_score pode refletir outro recurso. O limite > 80 é fixo e não configurável.

Cost Tracker

O Cost Tracker registra o gasto de LLM de cada incidente a partir do usage que o servidor reporta e serve o agregado pela API REST.

Custos de LLM por Provider

Toda análise (AnalyzeIssue, controller de AIInsight) e todo passo de remediação agêntica (AgenticStep, controller de Remediation) é contabilizado a partir do usage de tokens que o servidor informa na resposta, atribuído ao provider e modelo que de fato responderam (a fallback chain do servidor pode ter roteado para outro). Quando a resposta não traz usage (um servidor anterior aos campos de usage), as análises caem para caracteres divididos por quatro na entrada e na saída, e os passos agênticos registram zero tokens de entrada e o tamanho do raciocínio dividido por quatro como saída. O preço por token é resolvido nesta ordem:
  1. uma entrada para o provider no ConfigMap chatcli-cost-config do namespace da Issue (a palavra do operador do cluster);
  2. o motor de preço compartilhado (llm/pricing), as mesmas tabelas por modelo, overrides e regras de assinatura que o /cost da CLI usa (incluindo um override CHATCLI_MODEL_PRICING definido no processo do operator, por exemplo pelo extraEnv do chart), então o ledger aqui e a sessão lá concordam no preço da mesma chamada;
  3. um padrão por provider para um modelo que o motor não conhece (por exemplo CLAUDEAI 3/3/15, OPENAI 10/10/30, OPENROUTER 2/2/8, DEVIN 0,qualqueroutro0, qualquer outro 1/$3 por milhão de tokens de entrada/saída).
Só as tarifas de entrada e saída são aplicadas: descontos de leitura e escrita de cache não entram no ledger. O servidor também informa cost_usd / cost_known na própria resposta (veja modo servidor); o ledger não usa esses campos.

Configuração de Custos

Os preços podem ser sobrescritos por provider no ConfigMap chatcli-cost-config, chave pricing, uma entrada por nome de provider exatamente como o servidor o informa (CLAUDEAI, OPENAI, …). O tracker o procura no namespace da Issue sendo contabilizada, o mesmo namespace do ledger dela, então crie um em cada namespace cujos incidentes você queira precificar de outro jeito:
Uma entrada vale para todos os modelos daquele provider; não existe chave por modelo. Sem o ConfigMap, para um provider que ele não lista, ou quando o valor de pricing não é um JSON válido, valem as tarifas por modelo do motor de preço. O ConfigMap é lido a cada contabilização, então uma atualização vale a partir da próxima chamada; chamadas já registradas mantêm o preço com que foram registradas.

IncidentCost

Uma entrada no ledger por incidente, escrita pelos controllers de AIInsight e Remediation a cada chamada ao LLM:
Cada chamada é precificada uma vez, pelas tarifas do provider e modelo que a responderam, e somada ao total da entrada. Uma chamada posterior em outro modelo (por exemplo depois de um fallback) nunca reprecifica as anteriores; provider e model só nomeiam a chamada mais recente.
Exemplo de cálculo (com o override de CLAUDEAI acima):
O usage que o servidor reporta em cada resposta (usage em AnalyzeIssue e AgenticStep) é o que entra no ledger, então ele reflete contagens reais de tokens, não estimativas.
Duas chamadas registradas ao mesmo tempo no mesmo namespace não se sobrescrevem: a atualização do ledger leva a versão que leu, e um conflito de escrita é tentado de novo. Um registro que ainda falha (o limite de tamanho do ConfigMap, falta de RBAC, um ledger que não pode ser lido ou uma entrada que não pode ser decodificada) é registrado no log do controller (Failed to book the analysis cost on the ledger ou Failed to book the agentic step cost on the ledger); a análise ou o passo em si não é afetado, e uma entrada ilegível nunca é sobrescrita por uma nova.

CostSummary

Agregação num período, servida pela API REST (papel viewer, só GET), como kind: CostSummary com o resumo em spec: from e to (RFC 3339) definem um período absoluto: com os dois, é exatamente [from, to]; só com from, vai até agora; só com to, são os 30 dias que terminam em to; sem nenhum, são os últimos 30 dias. Uma entrada conta inteira quando o recordedAt dela (último registro) cai no período; entradas sem recordedAt sempre contam. Sem namespace, o resumo agrega todos os chatcli-cost-ledger do cluster. Um namespace sem ledger retorna zeros; qualquer outra falha ao ler um ledger retorna 500 (failed to read the cost ledger: ...) em vez de zeros.
Custo de downtime e retorno sobre investimento não são calculados: a plataforma não tem fonte confiável para receita por minuto ou custo-hora de engenheiro, e números construídos sobre constantes assumidas seriam enganosos. Combine totalLLMCost com a economia dos seus próprios incidentes se precisar deles.

Arquitetura de Armazenamento (ConfigMaps)

Esses subsistemas persistem os dados em ConfigMaps no namespace da Issue ou da Anomaly a que se referem (não no namespace do operator). O Capacity Planner não armazena nada.
ConfigMaps têm limite de 1MB no Kubernetes, cerca de 3.000 entradas de ledger. O operator não compacta o ledger nem os padrões sazonais: num namespace com esse volume, apague chaves antigas periodicamente, ou os novos registros falham (cada falha vai para o log, veja acima).

Formato de Armazenamento

Um ConfigMap por namespace, chatcli-cost-ledger, uma chave por incidente com o JSON do IncidentCost. O tracker o cria com o label app.kubernetes.io/managed-by: chatcli-operator, que é como o resumo de todos os namespaces encontra cada ledger:
O operator nunca compacta nem expira entradas: apague chaves, ou o ConfigMap, para zerar o ledger de um namespace.

Integrações

API REST

/api/v1/analytics/cost serve o resumo do ledger; /api/v1/analytics/capacity serve as previsões de capacidade; /api/v1/analytics/summary expõe dados de incidentes.

Web Dashboard

A view Overview tem um banner de avisos de capacidade alimentado por /analytics/capacity: ele lista os recursos com Urgency: "plan" e a recomendação de cada um. O dashboard não mostra o ledger de custos.

Grafana

O dashboard remediation-stats.json cobre o sucesso da remediação por tipo de ação. Nenhum dashboard incluído cobre capacidade ou custo de LLM.

AIOps Platform

Arquitetura completa do pipeline AIOps e como estes subsistemas se integram.