curl --request GET \
--url {scheme}://{host}:{port}/{basePath}/analytics/capacity \
--header 'X-API-Key: <api-key>'import requests
url = "{scheme}://{host}:{port}/{basePath}/analytics/capacity"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('{scheme}://{host}:{port}/{basePath}/analytics/capacity', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_PORT => "62437",
CURLOPT_URL => "{scheme}://{host}:{port}/{basePath}/analytics/capacity",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "{scheme}://{host}:{port}/{basePath}/analytics/capacity"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("{scheme}://{host}:{port}/{basePath}/analytics/capacity")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("{scheme}://{host}:{port}/{basePath}/analytics/capacity")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"apiVersion": "v1",
"kind": "CapacityForecastList",
"metadata": {
"totalCount": 2,
"page": 1,
"pageSize": 2
},
"items": [
{
"Resource": {
"kind": "Deployment",
"name": "payment-service",
"namespace": "production"
},
"CurrentUsage": {
"CPUMillicores": 400,
"MemoryBytes": 912680550
},
"Limits": {
"CPUMillicores": 500,
"MemoryBytes": 1073741824
},
"UsagePercentage": {
"CPU": 80,
"Memory": 85
},
"Trend": {
"CPUTrendPerDay": 0,
"MemoryTrendPerDay": 0,
"Direction": "insufficient_history"
},
"Forecast": {
"CPUExhaustionDate": null,
"MemoryExhaustionDate": null,
"DaysUntilCPUExhaustion": 0,
"DaysUntilMemoryExhaustion": 0,
"Recommendation": "Requests are above 80% of limits. Consider increasing limits proactively."
},
"IncidentCorrelation": {
"IncidentsInWindow": 9,
"ResourceRelatedIncidents": 4,
"ResourceIsBottleneck": true
},
"UsageSource": "requests",
"HistoryAvailable": false,
"Urgency": "plan"
},
{
"Resource": {
"kind": "Deployment",
"name": "api-gateway",
"namespace": "production"
},
"CurrentUsage": {
"CPUMillicores": 250,
"MemoryBytes": 268435456
},
"Limits": {
"CPUMillicores": 1000,
"MemoryBytes": 536870912
},
"UsagePercentage": {
"CPU": 25,
"Memory": 50
},
"Trend": {
"CPUTrendPerDay": 0,
"MemoryTrendPerDay": 0,
"Direction": "insufficient_history"
},
"Forecast": {
"CPUExhaustionDate": null,
"MemoryExhaustionDate": null,
"DaysUntilCPUExhaustion": 0,
"DaysUntilMemoryExhaustion": 0,
"Recommendation": "No usage history is collected, so no trend or exhaustion date can be projected; requests are within limits."
},
"IncidentCorrelation": {
"IncidentsInWindow": 9,
"ResourceRelatedIncidents": 1,
"ResourceIsBottleneck": false
},
"UsageSource": "requests",
"HistoryAvailable": false,
"Urgency": "none"
}
]
}
Capacidade de Analytics
Retorna um relatório de capacidade de requests versus limits para Deployments que tiveram incidentes
curl --request GET \
--url {scheme}://{host}:{port}/{basePath}/analytics/capacity \
--header 'X-API-Key: <api-key>'import requests
url = "{scheme}://{host}:{port}/{basePath}/analytics/capacity"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('{scheme}://{host}:{port}/{basePath}/analytics/capacity', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_PORT => "62437",
CURLOPT_URL => "{scheme}://{host}:{port}/{basePath}/analytics/capacity",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "{scheme}://{host}:{port}/{basePath}/analytics/capacity"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("{scheme}://{host}:{port}/{basePath}/analytics/capacity")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("{scheme}://{host}:{port}/{basePath}/analytics/capacity")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"apiVersion": "v1",
"kind": "CapacityForecastList",
"metadata": {
"totalCount": 2,
"page": 1,
"pageSize": 2
},
"items": [
{
"Resource": {
"kind": "Deployment",
"name": "payment-service",
"namespace": "production"
},
"CurrentUsage": {
"CPUMillicores": 400,
"MemoryBytes": 912680550
},
"Limits": {
"CPUMillicores": 500,
"MemoryBytes": 1073741824
},
"UsagePercentage": {
"CPU": 80,
"Memory": 85
},
"Trend": {
"CPUTrendPerDay": 0,
"MemoryTrendPerDay": 0,
"Direction": "insufficient_history"
},
"Forecast": {
"CPUExhaustionDate": null,
"MemoryExhaustionDate": null,
"DaysUntilCPUExhaustion": 0,
"DaysUntilMemoryExhaustion": 0,
"Recommendation": "Requests are above 80% of limits. Consider increasing limits proactively."
},
"IncidentCorrelation": {
"IncidentsInWindow": 9,
"ResourceRelatedIncidents": 4,
"ResourceIsBottleneck": true
},
"UsageSource": "requests",
"HistoryAvailable": false,
"Urgency": "plan"
},
{
"Resource": {
"kind": "Deployment",
"name": "api-gateway",
"namespace": "production"
},
"CurrentUsage": {
"CPUMillicores": 250,
"MemoryBytes": 268435456
},
"Limits": {
"CPUMillicores": 1000,
"MemoryBytes": 536870912
},
"UsagePercentage": {
"CPU": 25,
"Memory": 50
},
"Trend": {
"CPUTrendPerDay": 0,
"MemoryTrendPerDay": 0,
"Direction": "insufficient_history"
},
"Forecast": {
"CPUExhaustionDate": null,
"MemoryExhaustionDate": null,
"DaysUntilCPUExhaustion": 0,
"DaysUntilMemoryExhaustion": 0,
"Recommendation": "No usage history is collected, so no trend or exhaustion date can be projected; requests are within limits."
},
"IncidentCorrelation": {
"IncidentsInWindow": 9,
"ResourceRelatedIncidents": 1,
"ResourceIsBottleneck": false
},
"UsageSource": "requests",
"HistoryAvailable": false,
"Urgency": "none"
}
]
}
to − from quando os dois são válidos, senão 7 dias; a janela sempre termina no horário atual.viewer. Uma previsão é gerada para cada recurso distinto referenciado por um Issue (qualquer Issue, não só os da janela). O planner lê o recurso como um Deployment com esse nome; recursos que não são Deployments, ou que não existem mais, são ignorados silenciosamente.
Campos da previsão
| Campo | Descrição |
|---|---|
Resource | O recurso apontado pelos Issues (kind, name, namespace) |
CurrentUsage | Requests do primeiro container, usados como aproximação do uso (CPUMillicores, MemoryBytes); não são métricas ao vivo |
Limits | Limits do primeiro container |
UsagePercentage | CurrentUsage / Limits × 100 para CPU e Memory |
Trend | Direction é insufficient_history e as inclinações por dia são 0: o operator não guarda histórico de uso para ajustar uma tendência |
Forecast | Um texto Recommendation; as datas de esgotamento vêm null e as contagens de dias 0, já que nenhuma data de esgotamento é projetada |
IncidentCorrelation | Issues do namespace dentro da janela, quantos apontam para este recurso, e ResourceIsBottleneck (mais de 2) |
UsageSource | De onde vem o CurrentUsage: sempre requests |
HistoryAvailable | Sempre false: nenhuma amostra de uso é coletada |
Urgency | plan quando os requests chegam a 80% dos limits ou o recurso é um gargalo, none nos demais casos |
Resource mantém as chaves internas em minúsculas). Datas de esgotamento ausentes vêm null e contagens de dias ausentes vêm 0.{
"apiVersion": "v1",
"kind": "CapacityForecastList",
"metadata": {
"totalCount": 2,
"page": 1,
"pageSize": 2
},
"items": [
{
"Resource": {
"kind": "Deployment",
"name": "payment-service",
"namespace": "production"
},
"CurrentUsage": {
"CPUMillicores": 400,
"MemoryBytes": 912680550
},
"Limits": {
"CPUMillicores": 500,
"MemoryBytes": 1073741824
},
"UsagePercentage": {
"CPU": 80,
"Memory": 85
},
"Trend": {
"CPUTrendPerDay": 0,
"MemoryTrendPerDay": 0,
"Direction": "insufficient_history"
},
"Forecast": {
"CPUExhaustionDate": null,
"MemoryExhaustionDate": null,
"DaysUntilCPUExhaustion": 0,
"DaysUntilMemoryExhaustion": 0,
"Recommendation": "Requests are above 80% of limits. Consider increasing limits proactively."
},
"IncidentCorrelation": {
"IncidentsInWindow": 9,
"ResourceRelatedIncidents": 4,
"ResourceIsBottleneck": true
},
"UsageSource": "requests",
"HistoryAvailable": false,
"Urgency": "plan"
},
{
"Resource": {
"kind": "Deployment",
"name": "api-gateway",
"namespace": "production"
},
"CurrentUsage": {
"CPUMillicores": 250,
"MemoryBytes": 268435456
},
"Limits": {
"CPUMillicores": 1000,
"MemoryBytes": 536870912
},
"UsagePercentage": {
"CPU": 25,
"Memory": 50
},
"Trend": {
"CPUTrendPerDay": 0,
"MemoryTrendPerDay": 0,
"Direction": "insufficient_history"
},
"Forecast": {
"CPUExhaustionDate": null,
"MemoryExhaustionDate": null,
"DaysUntilCPUExhaustion": 0,
"DaysUntilMemoryExhaustion": 0,
"Recommendation": "No usage history is collected, so no trend or exhaustion date can be projected; requests are within limits."
},
"IncidentCorrelation": {
"IncidentsInWindow": 9,
"ResourceRelatedIncidents": 1,
"ResourceIsBottleneck": false
},
"UsageSource": "requests",
"HistoryAvailable": false,
"Urgency": "none"
}
]
}
Autorizações
API key sent in the X-API-Key header. Keys are read from the Secret chatcli-operator-secrets, key api-keys (fallback: ConfigMap chatcli-operator-config, key api-keys) in the operator namespace, as a YAML list of {key, role, name, description} (name is the identity recorded on approval decisions); the operator chart creates it only with apiKeys.create: true. Roles: viewer < operator < admin — any other role string is denied everywhere. Changes are picked up within about 30 seconds; deleting both the Secret and the ConfigMap revokes every key. With no keys configured every /api/ call returns 401, unless CHATCLI_OPERATOR_DEV_MODE=true, which grants admin without a key (development only).
Parâmetros de consulta
Kubernetes namespace. Empty means all namespaces.
Start of the time range (RFC3339). Unparseable values are ignored.
"2026-03-01T00:00:00Z"
End of the time range (RFC3339). Unparseable values are ignored.
"2026-03-19T23:59:59Z"