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

# Formato de resposta da API e exemplos de JSON

> Leia as respostas da API do LogBrew para listas de telemetria, páginas de cursor, eventos ao vivo, alterações, sucessos e erros.

Esta página mostra um exemplo de cada família de respostas da
[API de telemetria](/pt-BR/reference/telemetry-api). Todos os valores são
fictícios. Para códigos de erro e recuperação, consulte
[Erros da API](/pt-BR/reference/api-errors).

## Leia uma resposta

Leia cada resposta nesta ordem:

1. Leia o status HTTP.
2. Confira se o corpo tem o formato definido pela rota.
3. Confira se cada `project_id` está dentro do escopo de projetos solicitado.
4. Mantenha os valores canônicos de enum e os identificadores sem alteração.
5. Siga `next_action` somente quando o cliente aceitar o `code` e o
   `target` dele.
6. Trate `null`, um campo omitido e uma lista vazia como estados diferentes.

Um `200 OK` pode conter uma lista vazia. Uma lista de logs vazia significa que
nenhum log correspondeu à requisição. Isso não significa que problemas, traces
ou ações também estejam vazios. Não junte sinais só porque os horários estão
próximos. Siga um trace somente quando a resposta trouxer o `trace_id` exato
dele.

Um `404` e uma lista vazia são resultados diferentes. Uma rota de lista retorna
`[]` quando nenhum item corresponde. Uma rota de detalhe retorna `404` com
`code: not_found` quando não encontra um item que a conta possa ler. Nenhum dos
dois resultados prova que a ingestão falhou.

## O que enviar

A utilidade das respostas depende da telemetria que você envia. Envie estes
valores em cada envelope ou configuração de SDK:

* `release` e `environment`.
* Nomes estáveis para serviços, ações e métricas.
* Contexto de trace quando logs, spans, ações e problemas pertencem à mesma
  requisição.
* Valores canônicos de gravidade: `info`, `warning`, `error` e `critical`.
* Atributos que ajudam na depuração, sem segredos nem dados pessoais
  desnecessários.

Consulte [Integração do SDK](/pt-BR/guides/sdk-ingestion) e
[Controlar dados capturados](/pt-BR/guides/safe-capture).

## Resposta da ingestão

Os SDKs públicos leem a resposta de `POST /v1/events` por você. O código da
aplicação não precisa tratá-la.

### Resposta de lote do SDK

Um lote do SDK bem-sucedido retorna `200 OK` com a contagem aceita de cada
fluxo:

```json theme={null}
{
  "issues": 1,
  "logs": 2,
  "trace_spans": 3,
  "actions": 1,
  "metrics": 1,
  "already_accepted": 0,
  "context_updated": true,
  "next": "review accepted telemetry in logs, issues, traces, actions, metrics, or live feed",
  "next_action": {
    "code": "review_ingested_telemetry",
    "target": "telemetry_reads"
  }
}
```

| Campo | Significado |
| - | - |
| `issues`, `logs`, `trace_spans`, `actions`, `metrics` | Eventos deste lote que o LogBrew aceitou. |
| `already_accepted` | Eventos cujo ID o LogBrew já tinha aceitado antes. O LogBrew não os armazena de novo. |
| `context_updated` | `true` quando o lote atualizou o contexto de versão ou de ambiente. |

As contagens cobrem só este lote. Uma nova tentativa de um lote que o LogBrew
já aceitou retorna `0` para cada fluxo e o número de eventos em
`already_accepted`. Mantenha os IDs originais dos eventos ao tentar novamente.

### Resposta do envelope nativo

`POST /api/telemetry/ingest` retorna `200 OK` com a contagem de itens aceitos
de cada fluxo:

```json theme={null}
{
  "issues": 0,
  "logs": 1,
  "trace_spans": 0,
  "actions": 1,
  "already_accepted": 0,
  "next": "review accepted telemetry in logs, issues, traces, actions, or live feed",
  "next_action": {
    "code": "review_ingested_telemetry",
    "target": "telemetry_reads"
  }
}
```

A resposta nativa não tem os campos `metrics` nem `context_updated`. Não os
adicione. `already_accepted` conta os itens cujo `id` o LogBrew já tinha
aceitado para o projeto. Consulte o
[envelope nativo direto](/pt-BR/guides/sdk-ingestion#required-envelope-fields).

### Erros de ingestão

Um `401` com `code: ingest_key_invalid` significa que o bearer token de
ingestão foi revogado, expirou ou não vale para o projeto. Em
`POST /v1/events`, um bearer token ausente, ou um que não seja uma chave de
ingestão, retorna `401` com `code: unauthorized`. Use o bearer token de
ingestão atual do projeto. Não tente novamente com o bearer token da conta.

Um lote do SDK rejeitado retorna `422` com `code: validation_failed`:

```json theme={null}
{
  "error": "SDK event ids must be unique within a batch",
  "code": "validation_failed",
  "next": "send release/environment context plus issue, log, span, action, or metric events from a current LogBrew SDK",
  "next_action": {
    "code": "fix_request",
    "target": "request"
  }
}
```

Outros valores de `error` incluem `SDK event batch requires at least one event`
e `SDK event type is not supported by this ingest route`. Confira a versão do
SDK e a configuração do transporte. Não envie um lote vazio. Não altere tipos
nem IDs de eventos só para o lote passar na validação.

Uma requisição com um método diferente de `POST` retorna `405` com
`code: method_not_allowed`. Um corpo JSON ilegível retorna `code: invalid_json`.

## Formato de resposta das listas de telemetria

Por padrão, as rotas de lista retornam um array JSON simples. Uma lista vazia
bem-sucedida é `[]`.

Com `pagination=cursor`, a rota retorna um envelope. A chave da coleção
corresponde ao sinal:

| Rota | Chave da coleção |
| - | - |
| `/api/logs` | `logs` |
| `/api/telemetry/issues` | `issues` |
| `/api/telemetry/issues/{issue_id}/events` | `events`, com um `issue_id` no nível superior |
| `/api/telemetry/actions` | `actions` |
| `/api/telemetry/metrics` | `metrics` |
| `/api/telemetry/releases` | `releases` |
| `/api/telemetry/traces` | `traces`, com um `naming_quality` no nível superior |

`next_cursor` é um objeto com os campos de continuação, ou `null` na última
página. As linhas vêm da mais recente para a mais antiga. Consulte
[paginação por cursor](/pt-BR/reference/telemetry-api-filters#cursor-pagination).

### <span id="log-response">Resposta de log</span>

Uma página de cursor de logs com `limit=1`:

```json theme={null}
{
  "logs": [
    {
      "id": "150d1288-bec2-49ec-a036-3f7ac55f1b2d",
      "project_id": "123e4567-e89b-12d3-a456-426614174000",
      "level": "warning",
      "severity": "warning",
      "triage": {
        "effective_severity": "warning",
        "ignored": false,
        "rule_applied": false
      },
      "source": "runtime",
      "message": "checkout retry scheduled",
      "attributes": { "route": "/checkout" },
      "occurred_at": "2026-06-01T12:00:00Z",
      "environment": "production",
      "release": "api@1.2.3",
      "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
      "span_id": "00f067aa0ba902b7",
      "service_name": "checkout-api",
      "sdk_name": "@logbrew/node",
      "sdk_version": "0.1.8",
      "next_action": {
        "code": "inspect_trace",
        "target": "trace_summary"
      }
    }
  ],
  "next_cursor": {
    "time": "2026-06-01T12:00:00Z",
    "id": "150d1288-bec2-49ec-a036-3f7ac55f1b2d"
  }
}
```

Os logs incluem `level` por compatibilidade e `severity` para exibição. Os
dois têm o valor canônico. `triage` tem o resultado de uma regra de gravidade.
Consulte [respostas de regras de gravidade](#severity-rule-responses).

`trace_id` e `span_id` são `null` quando o log não tem vínculo com um trace.
Nesse caso, `next_action` é `inspect_related_logs` com o destino
`telemetry_logs`. Logs, problemas e ações usam os mesmos 2 pares de
`next_action`.

`GET /api/logs/{log_id}` retorna um log no mesmo formato.

### <span id="issue-response">Resposta de problema</span>

`GET /api/telemetry/issues/{issue_id}` retorna um problema agrupado. A lista
retorna os mesmos objetos. Este exemplo usa a versão de resposta padrão, a 1:

```json theme={null}
{
  "id": "9b2b4b3a-bd4e-4f85-a0f6-48118f037c17",
  "project_id": "123e4567-e89b-12d3-a456-426614174000",
  "fingerprint": "payment-error",
  "severity": "error",
  "triage": {
    "effective_severity": "error",
    "ignored": false,
    "rule_applied": false
  },
  "title": "PaymentError",
  "message": "payment provider timed out",
  "stack_trace": null,
  "attributes": {},
  "environment": "production",
  "release": "checkout@1.2.3",
  "service_name": "checkout-api",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "span_id": "00f067aa0ba902b7",
  "next_action": {
    "code": "inspect_trace",
    "target": "trace_summary"
  },
  "status": "unresolved",
  "occurrence_count": 2,
  "first_seen_at": "2026-07-13T07:00:00Z",
  "last_seen_at": "2026-07-13T08:00:00Z"
}
```

Na versão 1, `status` é `unresolved`, `resolved` ou `ignored`. Em um problema
arquivado, `triage.ignored` é `true`. Para os pares de `next_action` e as
leituras que vêm depois deles, consulte
[Investigar um problema](/pt-BR/guides/investigate-an-issue).

`first_seen_at` e `last_seen_at` são os horários da primeira ocorrência e da
mais recente. Eles não mudam quando o status muda.

Alguns campos só aparecem quando o LogBrew tem os dados:

| Campo | Quando aparece |
| - | - |
| `span_id` | O problema tem vínculo com um span. Caso contrário, o campo é omitido. |
| `diagnostics` | A ocorrência mais recente tem um tipo de exceção ou breadcrumbs. Consulte [histórico de ocorrências do problema](#issue-occurrence-history). |
| `symbolication` | Só em `GET /api/telemetry/issues/{issue_id}`, quando o problema tem a identificação de um artefato da versão. Consulte [Source maps de JavaScript](/pt-BR/guides/source-maps). |

`symbolication.status` é `resolved`, `invalid_metadata`,
`artifact_not_found`, `source_not_resolved` ou `unavailable`. A lista, as
mudanças de status e as mudanças de regra não retornam `symbolication`.

Com `response_version=2`, o problema tem os mesmos campos, com estas
mudanças:

| Campo | Valor na versão 2 |
| - | - |
| `status` | `unresolved`, `resolved` ou `archived`. A versão 1 mostra `archived` como `ignored`. |
| `priority` | `high`, `medium` ou `low`. |
| `priority_source` | `manual` quando uma pessoa definiu a prioridade. `derived` quando a prioridade segue a gravidade efetiva. |

```json theme={null}
{
  "id": "9b2b4b3a-bd4e-4f85-a0f6-48118f037c17",
  "status": "archived",
  "severity": "error",
  "priority": "low",
  "priority_source": "manual"
}
```

Este exemplo mostra só alguns campos. Uma prioridade derivada é `high` para
`error` e `critical`, `medium` para `warning` e `low` para `info`. Ela usa
`triage.effective_severity`, então uma regra de gravidade do problema pode
mudá-la.

Com `response_version=3`, o problema tem todos os campos da versão 2 e
`assignee`. `assignee` é `null` quando o problema não tem responsável:

```json theme={null}
{
  "id": "9b2b4b3a-bd4e-4f85-a0f6-48118f037c17",
  "status": "unresolved",
  "priority": "high",
  "priority_source": "derived",
  "assignee": {
    "user_id": "5d6e7f80-1a2b-4c3d-8e4f-5a6b7c8d9e0f",
    "name": "Ada Example",
    "email": "ada@example.com"
  }
}
```

| Campo | Significado |
| - | - |
| `assignee.user_id` | ID de usuário do responsável. Envie-o como `assignee` em um filtro ou em uma alteração. |
| `assignee.name` | Nome do responsável, ou `null` quando a conta não tem nome. |
| `assignee.email` | Endereço de e-mail do responsável. |

Um problema aparece sem responsável quando o membro atribuído não pode mais
ler o projeto.

Com `response_version=4`, `assignee` também tem `type`. Um responsável `user`
tem `user_id`, `name` e `email`, como na versão 3. Um responsável `team` tem
`team_id`, `slug` e `name`. A versão 3 mostra uma equipe responsável como
`null`. A CLI solicita a versão 4:

```json theme={null}
{
  "assignee": {
    "type": "team",
    "team_id": "7c1d2e3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
    "slug": "payments",
    "name": "Payments"
  }
}
```

Qualquer outro `response_version` retorna `422` com
`code: validation_failed`. Uma página de cursor usa a mesma versão para todos
os problemas em `issues`.

### <span id="assignee-list-response">Resposta da lista de responsáveis</span>

`GET /api/telemetry/issues/assignees?project_id=<project_id>` retorna todas as
contas que podem receber problemas atribuídos no projeto:

```json theme={null}
{
  "project_id": "123e4567-e89b-12d3-a456-426614174000",
  "assignees": [
    {
      "user_id": "5d6e7f80-1a2b-4c3d-8e4f-5a6b7c8d9e0f",
      "name": "Ada Example",
      "email": "ada@example.com"
    },
    {
      "user_id": "0f1e2d3c-4b5a-4968-8776-655443322110",
      "name": null,
      "email": "sam@example.com"
    }
  ]
}
```

Adicione `response_version=2` para receber também `teams`: todas as equipes
da organização do projeto, com `team_id`, `slug` e `name`.

Se a conta não puder ler o projeto, a rota retorna `404` com
`code: not_found`.

### <span id="action-response">Resposta de ação</span>

```json theme={null}
{
  "id": "d8ee3a6f-3918-440b-96cb-14166419399a",
  "project_id": "123e4567-e89b-12d3-a456-426614174000",
  "name": "checkout_failed",
  "distinct_id": "user_123",
  "session_id": "session_456",
  "occurred_at": "2026-06-01T12:00:00Z",
  "properties": { "surface": "checkout" },
  "environment": "production",
  "release": "checkout@1.2.3",
  "service_name": "checkout-api",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "span_id": "00f067aa0ba902b7",
  "next_action": {
    "code": "inspect_trace",
    "target": "trace_summary"
  }
}
```

`distinct_id` acompanha um ator ou uma sessão. Trate `distinct_id` e
`session_id` como identificadores opacos. `session_id` e `trace_id` são `null`
quando não foram capturados. `span_id` é omitido quando não foi capturado. Uma
ação não tem gravidade. Consulte
[Captura de eventos de produto](/pt-BR/guides/product-events).

### Resposta de métrica

```json theme={null}
{
  "id": "6f1c2d3e-4a5b-4c6d-8e7f-901234567890",
  "event_id": "metric-1",
  "project_id": "123e4567-e89b-12d3-a456-426614174000",
  "name": "http.server.duration",
  "kind": "histogram",
  "value": 12.5,
  "unit": "ms",
  "temporality": "delta",
  "attributes": {},
  "occurred_at": "2026-07-13T08:00:00Z",
  "environment": "production",
  "release": "checkout@1.2.3",
  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
  "span_id": "00f067aa0ba902b7",
  "service_name": "checkout-api",
  "sdk_name": "@logbrew/node",
  "sdk_version": "0.1.8"
}
```

Cada item é uma amostra. Não use o número de amostras como contagem de eventos
ou de usuários. `unit`, `temporality`, `trace_id` e `span_id` são `null`
quando não foram capturados. Um valor `null` não é zero.

### Resposta de versão

```json theme={null}
{
  "project_id": "123e4567-e89b-12d3-a456-426614174000",
  "release": "api@1.2.3",
  "environment": "production",
  "service_name": "checkout-api",
  "issue_count": 3,
  "log_count": 824,
  "trace_span_count": 421,
  "action_count": 19,
  "metric_count": 87,
  "first_seen_at": "2026-06-01T12:00:00Z",
  "last_seen_at": "2026-06-01T12:15:00Z",
  "trace_health": {
    "status": "errors_observed",
    "trace_count": 42,
    "error_trace_count": 3,
    "error_rate_basis_points": 714
  },
  "next_action": {
    "code": "inspect_release_issues",
    "target": "telemetry_issues"
  }
}
```

Uma linha cobre um projeto, uma versão, um ambiente e um serviço. As contagens
dela descrevem só essa linha.

`trace_health.status` é `unknown` quando a linha não tem traces. Nos outros
casos, é `no_errors_observed` ou `errors_observed`. `error_rate_basis_points`
é a parcela de traces com um span de erro, de `0` a `10000`. Não é uma taxa
de erro de todas as requisições.

`next_action` aponta para o primeiro tipo de sinal que tem dados, nesta ordem:

| `code` | `target` |
| - | - |
| `inspect_release_issues` | `telemetry_issues` |
| `inspect_release_traces` | `trace_explorer` |
| `inspect_release_logs` | `telemetry_logs` |
| `inspect_release_actions` | `telemetry_actions` |
| `inspect_release_metrics` | `telemetry_metrics` |
| `review_release_telemetry` | `telemetry_reads` |

Consulte [Versões](/pt-BR/concepts/releases).

### Resposta da descoberta de traces

`GET /api/telemetry/traces?pagination=cursor` retorna uma linha para cada
trace, mais um resumo `naming_quality` da página retornada:

```json theme={null}
{
  "traces": [
    {
      "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
      "project_ids": ["123e4567-e89b-12d3-a456-426614174000"],
      "root_span_name": "POST /checkout",
      "root_service_name": "checkout-api",
      "root_operation": "http.server",
      "span_count": 3,
      "error_span_count": 1,
      "service_count": 1,
      "started_at": "2026-06-01T12:00:00Z",
      "duration_ms": 45,
      "services": ["checkout-api"],
      "releases": ["checkout@1.2.3"],
      "environments": ["production"],
      "next_action": {
        "code": "inspect_trace",
        "target": "trace_summary"
      }
    }
  ],
  "next_cursor": null,
  "naming_quality": {
    "evaluated_traces": 1,
    "meaningful_name_traces": 1,
    "generic_name_traces": 0,
    "unmatched_route_traces": 0,
    "generic_operation_traces": 0,
    "truncated": false,
    "next_action": null
  }
}
```

`naming_quality` cobre só a página retornada. Não é uma pontuação da conta
inteira. `truncated: true` significa que existe outra página. Quando a página
tem um nome genérico, uma rota sem correspondência ou uma operação genérica,
`next_action` é `improve_trace_naming` com o destino `sdk_configuration`. Sem
`pagination=cursor`, a rota retorna um array simples de traces, sem
`naming_quality`.

`next_cursor` contém `time` e `trace_id`. Envie-os como `cursor_time` e
`cursor_trace_id`.

`GET /api/telemetry/traces/{trace_id}` retorna os spans de um trace.
`GET /api/telemetry/traces/{trace_id}/summary` retorna o span raiz, os spans
de erro, os serviços, a duração e o caminho mais lento, sem os atributos
brutos dos spans. Um `404` no resumo significa que nenhum trace correspondeu
ao escopo completo. Não remova os filtros para tentar novamente. Consulte
[respostas de spans e resumo de trace](#trace-spans-and-summary-responses).

### Listas vazias e itens inexistentes

Uma leitura de lista pode não ter correspondências. Uma leitura de detalhe tem
outro contrato:

| Requisição | Sucesso | Nenhum item legível |
| - | - | - |
| `GET /api/logs/{log_id}` | `200` com um [log](#log-response) | `404` com `code: not_found` |
| `GET /api/telemetry/issues/{issue_id}` | `200` com um [problema](#issue-response) | `404` com `code: not_found` |
| `GET /api/telemetry/issues/{issue_id}/events` | `200` com ocorrências | `404` com `code: not_found` na primeira página |
| `GET /api/telemetry/traces/{trace_id}` | `200` com spans | `200` com `[]` |
| `GET /api/telemetry/traces/{trace_id}/summary` | `200` com um resumo | `404` com `code: not_found` |

Um log inexistente retorna este `404`:

```json theme={null}
{
  "error": "log not found",
  "code": "not_found",
  "next": "check the resource id or filters and retry",
  "next_action": {
    "code": "check_resource",
    "target": "resource"
  }
}
```

Um problema inexistente usa `"error": "issue not found"`. Um resumo de trace
inexistente usa `"error": "trace not found"`. Um ID desconhecido e um ID que a
conta não pode ler retornam a mesma resposta.

Uma lista com um `project_id` que a conta não pode ler retorna `200` com uma
lista vazia. Confira o ID do projeto antes de informar que não há dados.

### Seleções de projetos rejeitadas

As listas de logs, problemas, ações, métricas, versões e traces aceitam um
projeto com `project_id` ou de 2 a 50 projetos com `project_ids`. O catálogo
de atributos de logs aceita os mesmos seletores. O histórico de ocorrências do
problema não os aceita.

Uma requisição com `project_id` e `project_ids` ao mesmo tempo retorna `422`:

```json theme={null}
{
  "error": "project_id and project_ids are mutually exclusive",
  "code": "validation_failed",
  "next": "use project_id for one project, project_ids=uuid,uuid for two to fifty projects, or omit both for all readable projects",
  "next_action": {
    "code": "fix_request",
    "target": "request"
  }
}
```

`project_ids` com um UUID inválido, um ID repetido, ou com menos de 2 ou mais
de 50 IDs também retorna `422` com `code: validation_failed`.

Se a conta não puder ler um dos projetos de um conjunto `project_ids`, a
requisição inteira retorna `404`. Ela não retorna os outros projetos como
resultado parcial:

```json theme={null}
{
  "error": "project selection not found",
  "code": "not_found",
  "next": "refresh readable projects and retry with only project IDs you can read",
  "next_action": {
    "code": "check_resource",
    "target": "resource"
  }
}
```

Mostre o erro, não uma lista vazia nem uma contagem zero. Leia a lista de
projetos de novo. Não remova um projeto sem avisar e não tente novamente com
todos os projetos. Uma credencial delegada, como uma conexão MCP, retorna
`403` com `code: forbidden` para um projeto que a conexão não cobre. Consulte
[escopo de projetos](/pt-BR/reference/telemetry-api-filters#project-scope).

### <span id="cursor-errors">Erros de cursor</span>

Logs, problemas, ações, métricas e ocorrências de problemas usam `cursor_time`
e `cursor_id`. Um cursor rejeitado retorna `422` com `code: validation_failed`.
Esses erros não significam que a lista está vazia.

| Requisição | `error` |
| - | - |
| `pagination=cursor` com só 1 dos 2 campos do cursor | `cursor_time and cursor_id must be sent together` |
| `cursor_time` que não é um timestamp RFC3339 | `cursor_time must be an RFC3339 timestamp` |
| Campos de cursor sem `pagination=cursor`, ou com outro valor de `pagination` | `pagination must be cursor when cursor pagination is requested` |

Por exemplo:

```json theme={null}
{
  "error": "cursor_time and cursor_id must be sent together",
  "code": "validation_failed",
  "next": "send pagination=cursor alone for the first page, then send cursor_time and cursor_id together from next_cursor",
  "next_action": {
    "code": "fix_request",
    "target": "request"
  }
}
```

Copie o `next_cursor` completo da página anterior. Não troque `cursor_time`
pelo horário atual. Se você perdeu o cursor, comece de novo com
`pagination=cursor` e os filtros originais. Um parâmetro de consulta desconhecido ou
um valor do tipo errado retorna `422` com `"error": "invalid query parameters"`.

### Respostas com cursor de versões

Um cursor de versões tem 5 campos. Uma requisição bem-sucedida sem
correspondências retorna `200`:

```json theme={null}
{
  "releases": [],
  "next_cursor": null
}
```

Quando `next_cursor` não for `null`, envie os 5 valores na próxima requisição:

| Campo de `next_cursor` | Parâmetro de consulta |
| - | - |
| `time` | `cursor_time` |
| `project_id` | `cursor_project_id` |
| `release` | `cursor_release` |
| `environment` | `cursor_environment` |
| `service_name` | `cursor_service_name` |

`cursor_project_id` marca uma posição. Ele não substitui `project_id` nem
`project_ids`. Mantenha os parâmetros originais de projeto e de filtro.
Codifique cada valor para URL.

Com `pagination=cursor`, um cursor incompleto ou um valor em branco de versão,
ambiente ou serviço retorna `422` com
`"error": "all release cursor fields must be sent together"`. Um
`cursor_time` inválido e a falta de `pagination=cursor` retornam os mesmos
erros dos [outros cursores](#cursor-errors).

### Erros da descoberta de traces

Estes erros valem para `GET /api/telemetry/traces`. Cada um retorna `422` com
`code: validation_failed`. Uma requisição rejeitada não é um resultado vazio.

| Requisição | `error` |
| - | - |
| `status` diferente de `error` ou `ok` | `trace status must be error or ok` |
| `min_duration_ms` abaixo de `0` | `minimum trace duration must not be negative` |
| Só 1 campo de cursor, ou um `cursor_trace_id` em branco | `cursor_time and cursor_trace_id must be sent together` |
| `cursor_time` que não é um timestamp RFC3339 | `cursor_time must be an RFC3339 timestamp` |
| Campos de cursor sem `pagination=cursor` | `pagination must be cursor when cursor pagination is requested` |

Para incluir traces com os dois status, omita `status`. Para a próxima página,
copie `next_cursor.time` para `cursor_time` e `next_cursor.trace_id` para
`cursor_trace_id`. Não envie `cursor_id` em uma página de traces. Consulte
[filtros de trace](/pt-BR/reference/telemetry-api-filters#trace-filters).

### <span id="issue-occurrence-history">Histórico de ocorrências do problema</span>

`GET /api/telemetry/issues/{issue_id}/events` lê as ocorrências de um problema
agrupado. Use o bearer token da conta e o ID do problema agrupado. A rota
aceita só `pagination`, `cursor_time`, `cursor_id` e `limit`. Ela não aceita
filtros de projeto, tempo, versão, ambiente ou gravidade.

```bash theme={null}
curl --get "https://api.logbrew.co/api/telemetry/issues/$ISSUE_ID/events" \
  --header "Authorization: Bearer $LOGBREW_ACCOUNT_BEARER" \
  --data-urlencode "pagination=cursor" \
  --data-urlencode "limit=1"
```

Uma primeira página com uma ocorrência e um cursor de continuação:

```json theme={null}
{
  "issue_id": "d1776d70-763c-47b5-a8f1-76f593221e2b",
  "events": [
    {
      "id": "db619770-1f7c-4bd5-8310-9f171df8af47",
      "issue_id": "d1776d70-763c-47b5-a8f1-76f593221e2b",
      "project_id": "123e4567-e89b-12d3-a456-426614174000",
      "severity": "error",
      "title": "Checkout failed",
      "message": "Checkout could not complete",
      "stack_trace": null,
      "attributes": {
        "exception": {
          "type": "CheckoutError",
          "mechanism": { "type": "javascript.error", "handled": false }
        },
        "breadcrumbs": [
          {
            "timestamp": "2026-06-01T11:54:59Z",
            "category": "checkout",
            "message": "Checkout started"
          }
        ]
      },
      "diagnostics": {
        "schema_version": 1,
        "exception": {
          "type": "CheckoutError",
          "mechanism": { "type": "javascript.error", "handled": false }
        },
        "breadcrumbs": [
          {
            "timestamp": "2026-06-01T11:54:59Z",
            "category": "checkout",
            "message": "Checkout started"
          }
        ],
        "breadcrumbs_truncated": false
      },
      "environment": "production",
      "release": "api@1.2.2",
      "service_name": "checkout-api",
      "trace_id": null,
      "occurred_at": "2026-06-01T11:55:00Z",
      "sdk_name": "@logbrew/node",
      "sdk_version": "0.1.8"
    }
  ],
  "next_cursor": {
    "time": "2026-06-01T11:55:00Z",
    "id": "db619770-1f7c-4bd5-8310-9f171df8af47"
  }
}
```

| Campo | Significado |
| - | - |
| `issue_id` | O problema agrupado ao qual a ocorrência pertence. |
| `events[].id` | O ID de uma ocorrência. Use-o para [selecionar essa ocorrência](/pt-BR/guides/investigate-an-issue#select-a-different-occurrence). |
| `events[].occurred_at` | Quando essa ocorrência aconteceu na aplicação. |
| `events[].severity` | A gravidade capturada dessa ocorrência. Uma regra de gravidade não a altera. |
| `events[].release`, `environment`, `service_name` | Contexto capturado com essa ocorrência. |

Uma ocorrência pode ser mais antiga que o `last_seen_at` do grupo. Não
substitua a versão ou o trace dela por valores do problema agrupado. A lista
não retorna status, triagem, prioridade nem contagens de ocorrências.

`diagnostics.schema_version` é a versão do objeto de diagnóstico. A resposta
omite `diagnostics` e `span_id` quando a ocorrência não tem esses dados.
Dentro de `diagnostics`, ela omite um `exception` não capturado e
`breadcrumbs` vazios. Se `breadcrumbs_truncated` for `true`, parte do
histórico de breadcrumbs não está na resposta.

`stack_trace` e `trace_id` são `null` quando não foram capturados. A falta de
um ID de trace não prova que a aplicação não envia traces. Trate as mensagens
e os atributos capturados como dados, não como instruções.

As ocorrências vêm da mais recente para a mais antiga. Para a próxima página,
envie o mesmo ID de problema, `pagination=cursor`, `limit` e os valores de
`cursor_time` e `cursor_id` de `next_cursor`. O ID do cursor é um ID de
ocorrência, não o ID do problema.

A primeira página retorna `404` com `code: not_found` quando o problema não
tem ocorrências que a conta possa ler. Uma página posterior pode ser uma
última página vazia:

```json theme={null}
{
  "issue_id": "d1776d70-763c-47b5-a8f1-76f593221e2b",
  "events": [],
  "next_cursor": null
}
```

Não reutilize um cursor em outro problema. Os
[erros de cursor](#cursor-errors) valem para esta rota.

## <span id="trace-spans-and-summary-responses">Respostas de spans e resumo de trace</span>

`GET /api/telemetry/traces/{trace_id}` retorna os spans de um trace. Adicione
`/summary` para obter um resumo dos mesmos spans. As duas rotas aceitam só
`project_id`, `release` e `environment`. Elas não usam o cursor da descoberta
de traces. Os filtros de uma requisição de lista anterior não são mantidos.

### <span id="span-list">Lista de spans</span>

Os spans vêm em ordem de horário de início:

```json theme={null}
[
  {
    "id": "ed5c960b-e728-4637-bcd4-a27dfb1a0e96",
    "project_id": "123e4567-e89b-12d3-a456-426614174000",
    "trace_id": "6e0c63257de34c92bdb0c8f1e9278a50",
    "span_id": "b37ac82563149fed",
    "parent_span_id": null,
    "name": "POST /checkout",
    "operation": "http.server",
    "status": "error",
    "started_at": "2026-06-01T12:00:00Z",
    "duration_ms": 823,
    "attributes": {},
    "environment": "production",
    "release": "api@1.2.3",
    "service_name": "checkout-api",
    "sdk_name": "@logbrew/node",
    "sdk_version": "0.1.8"
  },
  {
    "id": "0c2f7a51-4e8d-4b6a-9f13-2d7e5c8b1a90",
    "project_id": "123e4567-e89b-12d3-a456-426614174000",
    "trace_id": "6e0c63257de34c92bdb0c8f1e9278a50",
    "span_id": "7a085853722dc6d2",
    "parent_span_id": "b37ac82563149fed",
    "name": "POST /v1/charges",
    "operation": "http.client",
    "status": "error",
    "started_at": "2026-06-01T12:00:00.100Z",
    "duration_ms": 640,
    "attributes": {},
    "environment": "production",
    "release": "api@1.2.3",
    "service_name": "checkout-api",
    "sdk_name": "@logbrew/node",
    "sdk_version": "0.1.8"
  }
]
```

`status: "error"` descreve a operação capturada, não a leitura da API.
`parent_span_id: null` significa que o span não tem ID de pai. `status: null`
significa que o span não informou um status.

### Resumo do trace

O resumo dos mesmos 2 spans:

```json theme={null}
{
  "trace_id": "6e0c63257de34c92bdb0c8f1e9278a50",
  "span_count": 2,
  "error_span_count": 2,
  "service_count": 1,
  "project_count": 1,
  "started_at": "2026-06-01T12:00:00Z",
  "duration_ms": 823,
  "root_span": {
    "span_id": "b37ac82563149fed",
    "parent_span_id": null,
    "name": "POST /checkout",
    "operation": "http.server",
    "status": "error",
    "started_at": "2026-06-01T12:00:00Z",
    "duration_ms": 823,
    "service_name": "checkout-api"
  },
  "slowest_child_span": {
    "span_id": "7a085853722dc6d2",
    "parent_span_id": "b37ac82563149fed",
    "name": "POST /v1/charges",
    "operation": "http.client",
    "status": "error",
    "started_at": "2026-06-01T12:00:00.100Z",
    "duration_ms": 640,
    "service_name": "checkout-api"
  },
  "slowest_path": [
    {
      "span_id": "b37ac82563149fed",
      "parent_span_id": null,
      "name": "POST /checkout",
      "operation": "http.server",
      "status": "error",
      "started_at": "2026-06-01T12:00:00Z",
      "duration_ms": 823,
      "service_name": "checkout-api"
    },
    {
      "span_id": "7a085853722dc6d2",
      "parent_span_id": "b37ac82563149fed",
      "name": "POST /v1/charges",
      "operation": "http.client",
      "status": "error",
      "started_at": "2026-06-01T12:00:00.100Z",
      "duration_ms": 640,
      "service_name": "checkout-api"
    }
  ],
  "error_spans": [
    {
      "span_id": "b37ac82563149fed",
      "parent_span_id": null,
      "name": "POST /checkout",
      "operation": "http.server",
      "status": "error",
      "started_at": "2026-06-01T12:00:00Z",
      "duration_ms": 823,
      "service_name": "checkout-api"
    },
    {
      "span_id": "7a085853722dc6d2",
      "parent_span_id": "b37ac82563149fed",
      "name": "POST /v1/charges",
      "operation": "http.client",
      "status": "error",
      "started_at": "2026-06-01T12:00:00.100Z",
      "duration_ms": 640,
      "service_name": "checkout-api"
    }
  ],
  "services": [
    {
      "service_name": "checkout-api",
      "span_count": 2,
      "error_span_count": 2,
      "max_duration_ms": 823
    }
  ],
  "releases": ["api@1.2.3"],
  "environments": ["production"]
}
```

| Campo | Significado |
| - | - |
| `duration_ms` | Tempo entre o primeiro início de span e o último fim de span. Não é a soma das durações dos spans. |
| `root_span` | O span mais antigo cujo pai não está no trace. É um ponto de partida, não uma causa comprovada. |
| `slowest_child_span` | O span mais longo que tem um ID de pai, ou `null`. |
| `slowest_path` | A cadeia conhecida de spans pai, da raiz até `slowest_child_span`. É `[]` quando `slowest_child_span` é `null`. |
| `error_spans` | Os spans de erro mais longos, no máximo 5. `error_span_count` pode ser maior. |

Nenhuma das duas rotas retorna cursor ou campo de truncamento. Não adicione um
valor `truncated` que a resposta não contém.

### Nenhum span correspondente

Quando nenhum span corresponde ao ID do trace e ao escopo, a lista de spans
retorna `200` com `[]`. O resumo retorna `404` com
`"error": "trace not found"` e `code: not_found`. Confira o ID do trace e o
escopo. Não remova os filtros para fazer um resultado aparecer. Nenhum dos
dois resultados prova que a aplicação não enviou telemetria.

## <span id="live-event-response-format">Formato de resposta dos eventos ao vivo</span>

O feed ao vivo envia eventos novos. Ele não reenvia eventos que o cliente
perdeu enquanto estava desconectado. Use as rotas de lista para ler os itens
existentes.

### Crie um ticket

Envie `POST /api/feed/ticket` com o bearer token da conta. A requisição não
tem corpo.

```bash theme={null}
curl --request POST "https://api.logbrew.co/api/feed/ticket" \
  --header "Authorization: Bearer $LOGBREW_ACCOUNT_BEARER"
```

Uma resposta `200 OK` traz o ticket no campo `ticket`:

```json theme={null}
{
  "ticket": "<feed-ticket>",
  "expires_in_seconds": 60,
  "next": "connect with GET /api/feed/live?ticket=<ticket> before the ticket expires",
  "next_action": {
    "code": "connect_live_feed",
    "target": "live_feed"
  }
}
```

O ticket é uma credencial de curta duração. Não grave o ticket em logs nem o
coloque no prompt de um agente. Abra a conexão antes do fim de
`expires_in_seconds`. A expiração limita quando a conexão pode começar, não
quanto tempo ela fica aberta.

Um `401` significa que o login da conta não é válido. Entre de novo antes de
solicitar um ticket. Um método diferente de `POST` retorna `405` com
`code: method_not_allowed`.

### Abra a conexão

Conecte um cliente WebSocket a
`wss://api.logbrew.co/api/feed/live?ticket=<feed-ticket>`. Codifique o ticket
para URL. Não coloque o bearer token da conta nem o de ingestão na URL. Um
`401` significa que o ticket ou o login da conta não é válido. Crie um novo
ticket depois de entrar de novo.

| Resposta | Causa | Próximo passo |
| - | - | - |
| `422` com `"error": "feed ticket is required"` | O parâmetro de consulta `ticket` está ausente ou em branco. | Crie um ticket e conecte-se com ele. |
| `401` com `code: unauthorized` | O ticket expirou ou não é válido. | Crie um novo ticket. Não tente de novo com o mesmo ticket. |
| `code: invalid_websocket_upgrade` | A requisição não é um upgrade de WebSocket válido. | Use um cliente WebSocket. |
| `405` com `code: method_not_allowed` | A requisição não usa `GET`. | Use `GET` para a conexão. |

Espere antes de reconectar depois de um erro. Não reconecte em um loop sem
pausa.

### Leia as mensagens

Cada mensagem é um envelope `{ "type": "...", "data": ... }`. Leia `type`
antes de interpretar `data`. Ignore os tipos que o cliente não aceita.

| Tipo de evento | Conteúdo |
| - | - |
| `native_log` | Dados de log, no formato da [resposta de log](#log-response). |
| `native_issue` | Dados do problema agrupado, no formato da [resposta de problema](#issue-response) da versão 1. |
| `native_trace_span` | Um span, no formato de um item da [lista de spans](#span-list). |
| `native_action` | Dados da ação de produto, no formato da [resposta de ação](#action-response). |
| `project_created`, `project_updated`, `project_catalog_changed` | Dados do projeto. Leia a lista de projetos de novo quando ela mudar. |
| `usage_updated`, `usage_limit_warning`, `usage_limit_blocked` | Uso da conta, no formato de [uso da conta](/pt-BR/reference/account-api#account-usage). |

```json theme={null}
{
  "type": "native_log",
  "data": {
    "id": "150d1288-bec2-49ec-a036-3f7ac55f1b2d",
    "project_id": "123e4567-e89b-12d3-a456-426614174000",
    "level": "warning",
    "severity": "warning",
    "triage": {
      "effective_severity": "warning",
      "ignored": false,
      "rule_applied": false
    },
    "source": "runtime",
    "message": "checkout retry scheduled",
    "attributes": { "route": "/checkout" },
    "occurred_at": "2026-06-01T12:00:00Z",
    "environment": "production",
    "release": "api@1.2.3",
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
    "span_id": "00f067aa0ba902b7",
    "service_name": "checkout-api",
    "sdk_name": "@logbrew/node",
    "sdk_version": "0.1.8",
    "next_action": {
      "code": "inspect_trace",
      "target": "trace_summary"
    }
  }
}
```

Um evento `native_issue` usa a versão 1 da resposta de problema: um problema
arquivado aparece como `ignored`, e o evento não tem prioridade. Métricas e
versões não são tipos de evento ao vivo. Leia-as pelas rotas de lista delas.
O ticket não seleciona um projeto. Confira o `project_id` de cada evento antes
de mostrá-lo na visão de um projeto. `logbrew watch --json` usa este feed.
Consulte a [referência da CLI](/pt-BR/reference/cli).

### Trate uma conexão fechada

| Código de fechamento | Motivo | Próximo passo |
| - | - | - |
| `1013` | `live feed fell behind; reconnect to resync` | Espere e reconecte com um novo ticket. Leia as rotas de lista de novo para obter os itens que você perdeu. |
| `1008` | `live feed access changed; sign in again` | Pare de reconectar. Entre de novo antes de criar um novo ticket. |

Outras desconexões podem vir sem um motivo do LogBrew. Depois de reconectar,
leia as rotas de lista de novo e associe os itens pelo ID.

## <span id="issue-status-response-examples">Exemplos de resposta de status do problema</span>

`PATCH /api/telemetry/issues/{issue_id}` com `{ "status": "resolved" }`
retorna `200 OK` com o problema agrupado atualizado, no mesmo formato da
[resposta de problema](#issue-response). O parâmetro de consulta `response_version`
escolhe a versão. A rota não retorna um indicador de sucesso.

O corpo define 1 ou mais destes campos: `status`, `priority` e `assignee`.
`status` aceita `unresolved`, `resolved` ou `archived`. `ignored` é um nome
antigo de `archived`. Consulte
[Atualizar um problema](/pt-BR/reference/telemetry-api#update-one-issue).

Confira `id`, `status` e `priority` retornados antes de mostrar sucesso. Não
monte o resultado com os valores enviados. Uma mudança de status não exclui
ocorrências nem altera `first_seen_at` e `last_seen_at`. Ela não altera
`severity` nem uma regra de gravidade.

Uma alteração rejeitada retorna `422` com `code: validation_failed`:

```json theme={null}
{
  "error": "issue status must be unresolved, resolved, or archived",
  "code": "validation_failed",
  "next": "use status=unresolved, status=resolved, or status=archived",
  "next_action": {
    "code": "fix_request",
    "target": "request"
  }
}
```

| Resultado | Causa |
| - | - |
| `422`, `issue update requires status, priority, or assignee` | O corpo não tem nenhum dos 3 campos. |
| `422`, `issue priority must be high, medium, or low` | O valor de prioridade não é aceito. |
| `422`, `issue assignee must be me, none, a user ID, or team:<team_id>` | O valor de responsável não é aceito. |
| `422`, `issue assignee cannot read this project` | O responsável não tem acesso ao projeto. O LogBrew não altera nada. |
| `422`, `issue assignee team is not a team of this project's organization` | A equipe não pertence à organização do projeto. O LogBrew não altera nada. |
| `403` com `code: forbidden` | A conta não pode gerenciar problemas no projeto. |
| `404` com `code: not_found` | A conta não pode ler o problema, ou o problema não existe. |

Um campo que já tem o valor solicitado não muda. Depois de um timeout ou de uma
resposta perdida, envie a mesma requisição de novo ou leia o problema primeiro.
Não envie uma alteração diferente antes de ler o estado atual. Consulte
[Escritas](/pt-BR/reference/api-errors#writes).

`POST /api/telemetry/issues/bulk` retorna `200 OK` com 1 resultado para cada
ID de problema solicitado, na ordem da requisição. Cada problema encontrado usa
o formato da versão 3. Um resultado `not_found` tem `issue: null`:

```json theme={null}
{
  "project_id": "123e4567-e89b-12d3-a456-426614174000",
  "results": [
    {
      "issue_id": "9b2b4b3a-bd4e-4f85-a0f6-48118f037c17",
      "outcome": "updated",
      "issue": {
        "id": "9b2b4b3a-bd4e-4f85-a0f6-48118f037c17",
        "status": "archived",
        "priority": "high",
        "priority_source": "derived",
        "assignee": null
      }
    },
    {
      "issue_id": "3f1c2d4e-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
      "outcome": "not_found",
      "issue": null
    }
  ]
}
```

Este exemplo mostra só alguns campos do problema. `outcome` é `updated`,
`unchanged` ou `not_found`. Uma requisição repetida retorna `unchanged` e não
altera nada. Consulte
[Atualizar problemas em lote](/pt-BR/reference/telemetry-api#update-issues-in-bulk).

Uma requisição em lote falha por inteiro nestes casos:

| Resultado | Causa |
| - | - |
| `422`, `issue_ids must name 1 to 100 issues` | A lista está vazia ou tem mais de 100 IDs. |
| `422`, `issue_ids must not contain duplicates` | Um ID aparece mais de uma vez. |
| `422` com `code: invalid_json` | O corpo tem um campo desconhecido. |
| `403` com `code: forbidden` | A conta não pode gerenciar problemas no projeto. |
| `404`, `project not found` | A conta não pode ler o projeto. |

## Escopo das requisições de análise

As rotas de análise, a rota de séries de métricas e a rota de volume de sinais
leem um projeto e um período. Toda requisição precisa de `project_id` e
`since`. `since` aceita uma duração compacta, como `24h` ou `7d`, ou um
timestamp RFC3339. `until` aceita um timestamp RFC3339 e, por padrão, é o
horário da requisição. O período inclui `since`, exclui `until` e não pode
passar de 31 dias.

`service_name`, `release` e `environment` são filtros exatos opcionais. Cada
valor precisa ter de 1 a 256 caracteres depois que o LogBrew remove os espaços
das pontas. A rota de comparação de segmentos coloca esses filtros dentro de
cada segmento, não no nível superior.

Se a conta não puder ler o projeto, essas rotas retornam `200 OK` com
contagens zeradas. Elas não retornam `404`. Um resultado vazio não confirma o
acesso ao projeto. Compare `project_id` com os projetos que a conta pode ler.
Uma requisição por uma conexão MCP que não inclui o projeto retorna `403` e
`forbidden`.

| Rota | Valores de `response_version` | Padrão |
| - | - | - |
| `GET /api/telemetry/analytics/overview` | `1`, `2` ou `3` | `1` |
| `GET /api/telemetry/analytics/properties` | `1` ou `2` | `1` |
| `POST /api/telemetry/analytics/segments/compare` | `1` ou `2` | `1` |
| `POST /api/telemetry/analytics/retention` | `1` ou `2` | `1` |
| `POST /api/telemetry/analytics/lifecycle` | `1` ou `2` | `1` |
| `POST /api/telemetry/analytics/funnel` | Não aceito | Esquema `1` |
| `POST /api/telemetry/analytics/paths` | Não aceito | Esquema `1` |
| `GET /api/telemetry/metrics/series` | Não aceito | Esquema `1` |
| `GET /api/telemetry/summary/volume` | `1` | `1` |

Cada resposta começa com `schema_version`, `query` e `purpose`. `query` repete
o escopo efetivo e omite os filtros que você não enviou. `purpose` é um texto
simples que explica o que a rota responde.

Uma taxa é omitida quando o denominador dela é zero. Uma taxa omitida não é
`0` nem `null`. Leia `coverage` antes de confiar em uma taxa.

### <span id="shared-scope-errors">Erros de escopo comuns</span>

Estes erros usam HTTP `422` e `validation_failed`:

| Causa | `error` |
| - | - |
| Sem `project_id` | `product analytics project_id is required` |
| Sem `since` | `product analytics since is required` |
| `since` não é uma duração nem um timestamp RFC3339 | `invalid since value` |
| `until` não é um timestamp RFC3339 | `product analytics until must be an RFC3339 timestamp` |
| `since` não é anterior a `until` | `product analytics since must be earlier than until` |
| O período tem mais de 31 dias | `product analytics range must not exceed 31 days` |
| Um filtro vazio, ou um filtro com mais de 256 caracteres | `product analytics context filters must be non-empty and at most 256 characters` |

Por exemplo, uma requisição sem `project_id` retorna:

```json theme={null}
{
  "error": "product analytics project_id is required",
  "code": "validation_failed",
  "next": "choose one owned project and send its project_id",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

As rotas de séries de métricas e de volume de sinais usam as mesmas regras de
escopo, com textos próprios de `error`. As seções delas, mais abaixo, listam
esses erros.

Um parâmetro de consulta desconhecido retorna `422` com a resposta de
[parâmetros de consulta inválidos](/pt-BR/reference/api-errors#invalid-query-parameters).
Um campo JSON desconhecido, a falta de um campo JSON obrigatório ou um valor de
enum não aceito retorna `invalid_json`. Consulte
[JSON inválido](/pt-BR/reference/api-errors#invalid-json). Uma requisição com o
método HTTP errado retorna `405` e `method_not_allowed`. O texto de `next`
dela informa o método e os campos aceitos. Consulte
[Método não aceito](/pt-BR/reference/api-errors#unsupported-method).

## Resposta da visão geral de análise de produto

`GET /api/telemetry/analytics/overview` mostra a atividade de um projeto:
volume de ações, usuários, sessões, uma série temporal, as principais ações e
as visualizações de página, visualizações de tela e interações classificadas.
Use essa rota para encontrar os nomes exatos de eventos das outras rotas de
análise.

Envie `response_version=3`. As versões 1 e 2 retornam as mesmas contagens, mas
o valor de `estimation.method` delas é um nome mais antigo. A versão 1 não
confere o tipo de identidade ao contar usuários identificados. As versões 2 e
3 contam só identidades do tipo `user` e adicionam contagens de identidades
anônimas e `subject_coverage`.

Esta requisição lê uma hora em intervalos de cinco minutos e retorna duas
linhas em cada lista de principais itens:

```bash theme={null}
curl --get "https://api.logbrew.co/api/telemetry/analytics/overview" \
  --header "Authorization: Bearer $LOGBREW_ACCOUNT_BEARER" \
  --data-urlencode "project_id=<project_id>" \
  --data-urlencode "since=2026-06-01T11:00:00Z" \
  --data-urlencode "until=2026-06-01T12:00:00Z" \
  --data-urlencode "interval=5m" \
  --data-urlencode "top_limit=2" \
  --data-urlencode "response_version=3"
```

### Visão geral bem-sucedida

Neste resultado fictício, o projeto tem 120 ações em dois dos doze intervalos.
Vinte ações vêm de identidades anônimas. Todas as ações têm um ID de sessão.
Metade das ações tem um ID de trace.

```json theme={null}
{
  "schema_version": 3,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T11:00:00Z",
    "until": "2026-06-01T12:00:00Z",
    "interval": "5m",
    "interval_seconds": 300,
    "top_limit": 2
  },
  "purpose": "Shows what people do in one project through action volume, active identified users, separately labeled anonymous subjects, explicit sessions, activity over time, top actions, and versioned page-view, screen-view, interaction, surface, and exact event-name breakdowns. Exact classified event names can be used as ordered funnel steps. It never infers people from anonymous events or relabels arbitrary unclassified telemetry as product behavior.",
  "analysis_level": "user_and_session",
  "summary": {
    "actions": 120,
    "active_identified_users": 18,
    "active_anonymous_subjects": 7,
    "sessions": 24,
    "distinct_action_names": 3,
    "actions_per_identified_user": 5.555555555555555,
    "actions_per_session": 5.0
  },
  "coverage": {
    "identified_actions": 100,
    "anonymous_actions": 20,
    "subject_coverage": {
      "index_version": 1,
      "identified_user_events": 100,
      "anonymous_subject_events": 20,
      "legacy_unknown_kind_events": 0,
      "missing_subject_events": 0,
      "historical_unindexed_events": 0
    },
    "sessionized_actions": 120,
    "traced_actions": 60,
    "identification_rate": 0.8333333333333334,
    "sessionization_rate": 1.0,
    "trace_link_rate": 0.5,
    "expected_buckets": 12,
    "returned_points": 2,
    "returned_top_actions": 2,
    "top_actions_truncated": true,
    "first_seen_at": "2026-06-01T11:00:10Z",
    "last_seen_at": "2026-06-01T11:09:50Z",
    "limitations": [
      "Typed anonymous subjects are counted separately and never contribute to active identified-user counts.",
      "Actions without a trace ID cannot link product behavior directly to trace investigation."
    ]
  },
  "estimation": {
    "unique_counts_are_approximate": true,
    "method": "approximate_distinct",
    "description": "Active identified-user, anonymous-subject, session, distinct action-name, distinct surface, and distinct exact event-name counts are approximate distinct counts. Event totals and capture-coverage counts are exact within the selected, fully evaluated query window."
  },
  "series": [
    {
      "bucket_start": "2026-06-01T11:00:00Z",
      "bucket_end": "2026-06-01T11:05:00Z",
      "actions": 50,
      "active_identified_users": 8,
      "sessions": 10,
      "identified_actions": 40,
      "sessionized_actions": 50,
      "traced_actions": 25
    },
    {
      "bucket_start": "2026-06-01T11:05:00Z",
      "bucket_end": "2026-06-01T11:10:00Z",
      "actions": 70,
      "active_identified_users": 12,
      "sessions": 14,
      "identified_actions": 60,
      "sessionized_actions": 70,
      "traced_actions": 35
    }
  ],
  "top_actions": [
    {
      "name": "checkout_started",
      "actions": 50,
      "active_identified_users": 12,
      "sessions": 14,
      "share_of_actions": 0.4166666666666667
    },
    {
      "name": "purchase_completed",
      "actions": 40,
      "active_identified_users": 9,
      "sessions": 10,
      "share_of_actions": 0.3333333333333333
    }
  ],
  "classified_activity": {
    "summary": {
      "events": 110,
      "page_views": 50,
      "screen_views": 20,
      "interactions": 40,
      "distinct_surfaces": 4,
      "distinct_event_names": 5,
      "active_identified_users": 17,
      "active_anonymous_subjects": 6,
      "sessions": 23
    },
    "coverage": {
      "classified_actions": 60,
      "unclassified_actions": 60,
      "action_classification_rate": 0.5,
      "surfaced_events": 110,
      "named_events": 110,
      "identified_events": 90,
      "subject_coverage": {
        "index_version": 1,
        "identified_user_events": 90,
        "anonymous_subject_events": 20,
        "legacy_unknown_kind_events": 0,
        "missing_subject_events": 0,
        "historical_unindexed_events": 0
      },
      "sessionized_events": 110,
      "traced_events": 55,
      "surface_rate": 1.0,
      "event_name_rate": 1.0,
      "identification_rate": 0.8181818181818182,
      "sessionization_rate": 1.0,
      "trace_link_rate": 0.5,
      "expected_buckets": 12,
      "returned_points": 2,
      "returned_top_surfaces": 2,
      "returned_top_events": 2,
      "top_surfaces_truncated": true,
      "top_events_truncated": true,
      "first_seen_at": "2026-06-01T11:00:20Z",
      "last_seen_at": "2026-06-01T11:09:40Z",
      "limitations": [
        "Only events carrying supported version-1 analytics annotations appear in classified activity; arbitrary actions and technical spans are not relabeled.",
        "Historical or unannotated actions contribute to the action summary but not to classified screen-view or interaction breakdowns.",
        "Classified events with typed anonymous subjects are counted separately and never contribute to identified-user counts.",
        "Classified events without a trace ID cannot link product behavior directly to trace investigation."
      ]
    },
    "series": [
      {
        "bucket_start": "2026-06-01T11:00:00Z",
        "bucket_end": "2026-06-01T11:05:00Z",
        "events": 45,
        "page_views": 20,
        "screen_views": 10,
        "interactions": 15
      },
      {
        "bucket_start": "2026-06-01T11:05:00Z",
        "bucket_end": "2026-06-01T11:10:00Z",
        "events": 65,
        "page_views": 30,
        "screen_views": 10,
        "interactions": 25
      }
    ],
    "top_surfaces": [
      {
        "kind": "page_view",
        "surface": "/checkout/:step",
        "events": 40,
        "active_identified_users": 12,
        "sessions": 14,
        "share_of_classified_events": 0.36363636363636365
      },
      {
        "kind": "screen_view",
        "surface": "Checkout",
        "events": 20,
        "active_identified_users": 9,
        "sessions": 10,
        "share_of_classified_events": 0.18181818181818182
      }
    ],
    "top_events": [
      {
        "kind": "page_view",
        "event_name": "/checkout/:step",
        "events": 40,
        "active_identified_users": 12,
        "sessions": 14,
        "share_of_classified_events": 0.36363636363636365
      },
      {
        "kind": "interaction",
        "event_name": "checkout_started",
        "events": 30,
        "active_identified_users": 10,
        "sessions": 12,
        "share_of_classified_events": 0.2727272727272727
      }
    ]
  },
  "next_action": {
    "code": "build_product_funnel",
    "target": "/api/telemetry/analytics/funnel",
    "reason": "Use two through eight exact keys from classified_activity.top_events to measure ordered conversion and drop-off for explicit sessions or opaque identified users."
  }
}
```

### Leia a visão geral

As cinco contagens de `subject_coverage` somam o total de eventos da seção
delas. Só `identified_user_events` conta para usuários. `anonymous_actions` é
`summary.actions` menos `identified_actions`.

`series` contém só os intervalos com atividade. `expected_buckets` é o número
de intervalos possíveis no período. Não desenhe um intervalo ausente como um
zero medido, a menos que o gráfico informe essa regra. Os intervalos se
alinham a limites fixos em UTC. Um período que começa no meio de um intervalo
inclui esse intervalo parcial.

`classified_activity` conta visualizações de página, visualizações de tela e
interações. Visualizações de tela e interações também são ações.
Visualizações de página não são. Não some `summary.actions` a
`classified_activity.summary.events`.

Copie `kind` e `event_name` de `classified_activity.top_events` para etapas de
funil, seletores de retenção, seletores de ciclo de vida, âncoras de caminhos
e alvos de segmentos. Um valor `true` em `top_events_truncated` significa que
existem nomes com volume menor. Aumente `top_limit` até 20 para ver mais.

`analysis_level` é `no_data`, `event_only`, `user_level` ou
`user_and_session`. Se o projeto não tiver ações nem eventos classificados,
`next_action.code` é `capture_product_activity`. Consulte
[Análise de produto](/pt-BR/concepts/product-analytics#use-the-analytics-api).

### <span id="overview-errors">Erros da visão geral</span>

Além dos [erros de escopo comuns](#shared-scope-errors), a visão geral retorna
`422` e `validation_failed` para estes valores:

| Valor | `error` |
| - | - |
| `response_version` diferente de `1`, `2` ou `3` | `product analytics response_version must be 1, 2, or 3` |
| `top_limit` fora da faixa de `1` a `20` | `product analytics top_limit must be between 1 and 20` |
| `interval` diferente de `auto`, `1m`, `5m`, `15m`, `1h`, `6h` ou `1d` | `product analytics interval is not supported` |
| Um `interval` explícito que geraria mais de 500 intervalos | `product analytics interval would exceed 500 buckets` |

O `interval` padrão é `auto`. Ele escolhe a menor largura de intervalo que gera
no máximo 300 intervalos. O `top_limit` padrão é `10`.

## <span id="ordered-funnel-response">Resposta de funil ordenado</span>

`POST /api/telemetry/analytics/funnel` mede a conclusão ordenada de 2 a 8
etapas. Copie cada `kind` e `event_name` exatos de
`classified_activity.top_events` na visão geral. Um nome de ação parecido não
é uma correspondência. Este corpo de requisição conta as sessões que
visualizam `/pricing` e depois concluem o cadastro em até uma hora:

```json theme={null}
{
  "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
  "since": "2026-08-01T00:00:00Z",
  "until": "2026-08-02T00:00:00Z",
  "environment": "production",
  "analysis_unit": "session",
  "conversion_window_seconds": 3600,
  "steps": [
    { "kind": "page_view", "event_name": "/pricing" },
    { "kind": "interaction", "event_name": "signup_completed" }
  ]
}
```

`analysis_unit` é `session` ou `identified_user`. O padrão é `session`. O
`kind` de cada etapa é `page_view`, `screen_view` ou `interaction`. A rota de
funil não aceita `response_version`.

### Funil bem-sucedido

Uma resposta `200 OK`:

```json theme={null}
{
  "schema_version": 1,
  "query": {
    "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
    "since": "2026-08-01T00:00:00Z",
    "until": "2026-08-02T00:00:00Z",
    "environment": "production",
    "analysis_unit": "session",
    "conversion_window_seconds": 3600
  },
  "purpose": "Shows where explicit sessions or typed opaque user subjects enter, progress, and drop off across two through eight versioned page-view, screen-view, or interaction events. Steps must occur in order with strictly increasing timestamps inside the selected conversion window; raw session and subject identifiers are never returned.",
  "summary": {
    "candidate_units": 60,
    "entered_units": 50,
    "completed_units": 15,
    "entry_rate": 0.8333333333333334,
    "overall_conversion_rate": 0.3
  },
  "coverage": {
    "classified_events": 200,
    "named_events": 180,
    "unnamed_events": 20,
    "unit_identified_events": 160,
    "selected_step_events": 120,
    "usable_selected_step_events": 100,
    "excluded_selected_step_events": 20,
    "event_name_rate": 0.9,
    "selected_unit_coverage_rate": 0.8333333333333334,
    "limitations": [
      "Only supported version-1 classified events with exact derived names participate; arbitrary actions and technical spans are never relabeled.",
      "A unit reaches later steps only when timestamps strictly increase and the final match remains inside conversion_window_seconds from its first match.",
      "Historical or surface-less classified events without a derived event name cannot match exact funnel steps.",
      "Requested-step events without an explicit session ID are excluded from ordered unit counts.",
      "Session funnels count visits or app sessions, not unique people; use analysis_unit=identified_user only when typed user-subject coverage is sufficient."
    ]
  },
  "steps": [
    {
      "position": 1,
      "kind": "page_view",
      "event_name": "/pricing",
      "units": 50,
      "conversion_from_first": 1.0,
      "drop_off_to_next_units": 35,
      "drop_off_to_next_rate": 0.7
    },
    {
      "position": 2,
      "kind": "interaction",
      "event_name": "signup_completed",
      "units": 15,
      "conversion_from_previous": 0.3,
      "conversion_from_first": 0.3
    }
  ],
  "next_action": {
    "code": "compare_funnel_contexts",
    "target": "/api/telemetry/analytics/funnel",
    "reason": "Compare the same exact steps across bounded releases, environments, or services to locate material conversion changes."
  }
}
```

As taxas são frações de 0 a 1. Leia `coverage` antes de confiar em uma taxa.
`selected_unit_coverage_rate` é a parcela dos eventos das etapas selecionadas
que o LogBrew conseguiu usar. A resposta não retorna identidades brutas.
Consulte
[Análise de produto](/pt-BR/concepts/product-analytics#measure-a-funnel).

### Leia a conversão e a cobertura

`entry_rate` é `entered_units` dividido por `candidate_units`: 50 de 60.
`overall_conversion_rate` é `completed_units` dividido por `entered_units`:
15 de 50, ou 30%. Não é 15 dividido por todos os candidatos. Essas contagens
não explicam por que as unidades pararam.

A cobertura conta eventos, não sessões. Aqui, 120 eventos correspondem a uma
etapa, e 20 deles não têm ID de sessão. O resultado exclui esses 20 eventos
das contagens de sessões. Não os trate como 20 sessões que falharam.

A primeira etapa não tem `conversion_from_previous`. A última etapa não tem
`drop_off_to_next_units` nem `drop_off_to_next_rate`.

Uma unidade só chega a uma etapa posterior quando os horários das etapas
aumentam estritamente. Eventos com o mesmo timestamp não podem cumprir duas
etapas seguidas. A etapa final precisa ocorrer em até
`conversion_window_seconds` depois da primeira etapa.

O modo de sessão conta sessões, não pessoas. Use `identified_user` só para
eventos que trazem um ID de identidade opaco do tipo `user`. Esse modo pode
juntar eventos de sessões diferentes dentro da janela de conversão. Mantenha a
mesma unidade e as mesmas etapas ao comparar resultados.

O `conversion_window_seconds` padrão é 24 horas ou a duração do período, o que
for menor. O máximo é a duração do período em segundos inteiros, arredondada
para cima.

### Resultados de funil vazios

Uma resposta vazia bem-sucedida ainda lista as etapas solicitadas com `units`
zerado. Se não houver unidades candidatas, `summary` omite `entry_rate` e
`overall_conversion_rate`. A rota não retorna `404` só porque nenhum evento
corresponde.

Leia `coverage` e `next_action` para encontrar a causa:

| `next_action.code` | Causa |
| - | - |
| `capture_product_activity` | Não existem eventos classificados no escopo. |
| `choose_captured_funnel_steps` | Nenhum evento corresponde a uma etapa solicitada. |
| `sessionize_product_activity` | Existem eventos das etapas, mas nenhum tem ID de sessão. |
| `identify_product_users` | Existem eventos das etapas, mas nenhum tem uma identidade do tipo `user`. |
| `verify_funnel_entry` | Nenhuma unidade entrou na etapa 1. |
| `investigate_funnel_drop_off` | Unidades entraram, mas nenhuma concluiu todas as etapas. |
| `compare_funnel_contexts` | Pelo menos uma unidade concluiu o funil. |

### Requisições de funil rejeitadas

Além dos [erros de escopo comuns](#shared-scope-errors), estas requisições
retornam `422` e `validation_failed`. Menos de 2 ou mais de 8 etapas:

```json theme={null}
{
  "error": "product analytics funnel requires two through eight ordered steps",
  "code": "validation_failed",
  "next": "send a steps array containing 2 through 8 exact classified event selectors",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

Um `conversion_window_seconds` igual a `0`, ou um valor maior que a duração do
período:

```json theme={null}
{
  "error": "product analytics funnel conversion window must fit inside the query range",
  "code": "validation_failed",
  "next": "use conversion_window_seconds from 1 through the selected range length",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

Um `event_name` vazio, com mais de 256 caracteres ou com um caractere de
controle retorna
`product analytics funnel event_name must be non-empty, control-free, and at most 256 characters`.
Uma etapa `interaction` também precisa ter um nome de ação válido. Caso
contrário, o erro é `product analytics interaction event_name must be a bounded stable action name`.

Corrija a requisição antes de enviá-la de novo. Não remova etapas nem mude a
unidade de análise só para obter um resultado não vazio.

## Análise por evento exato e análise automática

Retenção e ciclo de vida aceitam dois formatos de requisição. Use
`response_version` para escolher o formato que responde à sua pergunta:

| Análise | `response_version` | Seletores de evento |
| - | - | - |
| Retenção para eventos exatos | `1`, ou omitido | Envie `start_event` e `return_event`. |
| Ciclo de vida para um evento exato | `1`, ou omitido | Envie `event`. |
| Retenção ou ciclo de vida automáticos | `2` | Não envie seletor de evento. |

Um seletor exato contém `kind` e `event_name`. `kind` é `page_view`,
`screen_view` ou `interaction`. Copie `event_name` de
`classified_activity.top_events`. Não deduza um nome de evento pelo rótulo de
um botão.

Os dois formatos contam só usuários: IDs de identidade opacos do tipo `user`.
Identidades anônimas e eventos sem um ID de identidade utilizável não contam
como usuários. As respostas nunca retornam IDs de identidade.

Os intervalos fixos são `hour`, `day`, `week` e `thirty_day`. São durações
fixas. `thirty_day` equivale a 30 dias, não a um mês do calendário. Se você
omitir `interval`, a API usa `hour` para um período de até 48 horas e `day`
para um período maior.

### Requisição de retenção por evento exato

Envie este corpo para `POST /api/telemetry/analytics/retention`. Ele pergunta
se os usuários concluem outra compra depois da primeira compra deles no
período:

```json theme={null}
{
  "project_id": "11111111-1111-4111-8111-111111111111",
  "since": "2026-06-01T00:00:00Z",
  "until": "2026-06-03T00:00:00Z",
  "response_version": 1,
  "interval": "day",
  "interval_count": 1,
  "mode": "return_on",
  "cohort_mode": "first_in_range",
  "start_event": { "kind": "interaction", "event_name": "checkout_completed" },
  "return_event": { "kind": "interaction", "event_name": "checkout_completed" }
}
```

O primeiro evento inicial correspondente no período marca o ponto de partida
de cada usuário. Um retorno precisa ocorrer estritamente depois desse ponto de
partida e antes de `until`. Os dois seletores podem ser o mesmo evento.

| Campo | Valores | Padrão |
| - | - | - |
| `interval_count` | De `1` a `31` períodos | `10` |
| `mode` | `return_on` conta um retorno dentro de cada período exato. `return_on_or_after` conta um retorno no início de cada período ou depois dele. | `return_on` |
| `cohort_mode` | `first_in_range` | `first_in_range` |

### Retenção por evento exato bem-sucedida

Neste exemplo fictício, dois usuários concluem uma compra. O primeiro conclui
uma compra às 12:00 de 1º de junho e de novo às 13:00. O segundo conclui uma
compra às 12:00 de 2 de junho. Às 13:00 de 2 de junho, o segundo usuário
visualiza uma página, mas não conclui outra compra.

```json theme={null}
{
  "schema_version": 1,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T00:00:00Z",
    "until": "2026-06-03T00:00:00Z",
    "start_event": { "kind": "interaction", "event_name": "checkout_completed" },
    "return_event": { "kind": "interaction", "event_name": "checkout_completed" },
    "interval": "day",
    "interval_seconds": 86400,
    "interval_count": 1,
    "mode": "return_on",
    "cohort_mode": "first_in_range"
  },
  "purpose": "Measures whether typed opaque user subjects return after their first matching start event inside the selected half-open query range. Returns must occur strictly after each subject's anchor. return_on measures one fixed subject-relative period; return_on_or_after measures from that period's threshold through the exclusive query upper bound. Eligibility-aware denominators prevent immature subjects from being reported as churned, cohorts are fixed buckets aligned to since, and raw subject identifiers are never returned.",
  "summary": {
    "cohort_subjects": 2,
    "subjects_returned_after_start": 1,
    "return_rate_after_start": 0.5,
    "non_empty_cohorts": 2,
    "periods_with_eligible_subjects": 1,
    "fully_observed_periods": 0
  },
  "coverage": {
    "classified_events": 4,
    "named_events": 4,
    "unnamed_events": 0,
    "identified_events": 4,
    "start_events": 3,
    "usable_start_events": 3,
    "excluded_start_events": 0,
    "return_events": 3,
    "usable_return_events": 3,
    "excluded_return_events": 0,
    "event_name_rate": 1.0,
    "start_identity_coverage_rate": 1.0,
    "return_identity_coverage_rate": 1.0,
    "limitations": [
      "Only application-supplied opaque subject IDs explicitly typed as users are counted. Anonymous, legacy-untyped, historical-unindexed, invalid, or absent subjects are excluded rather than inferred as people.",
      "first_in_range anchors each subject at its first matching start inside the selected range; it does not prove that event was the subject's first-ever historical start.",
      "Cohort buckets are fixed-width and aligned to the query's since value. hour, day, week, and thirty_day mean fixed elapsed durations; thirty_day is not a calendar month.",
      "Returns must match the exact selected kind and derived event name, occur strictly after the subject anchor, and remain before the exclusive query upper bound.",
      "This resource does not provide recurring-start cohorts, group retention, arbitrary property breakdowns, custom return ranges, or lifetime first-event lookup.",
      "return_on includes only subjects whose complete exact period ends by until; later subjects are excluded from that period's denominator."
    ]
  },
  "curve": [
    {
      "period": 0,
      "threshold_seconds": 0,
      "window_end_seconds": 86400,
      "eligible_subjects": 1,
      "retained_subjects": 1,
      "weighted_retention_rate": 1.0,
      "fully_observed_cohorts": 1,
      "fully_observed_cohort_average_rate": 1.0,
      "all_subjects_eligible": false
    }
  ],
  "cohorts": [
    {
      "cohort": 0,
      "started_at": "2026-06-01T00:00:00Z",
      "ended_at": "2026-06-02T00:00:00Z",
      "subjects": 1,
      "subjects_returned_after_start": 1,
      "periods": [
        {
          "period": 0,
          "eligible_subjects": 1,
          "retained_subjects": 1,
          "retention_rate": 1.0,
          "all_subjects_eligible": true
        }
      ]
    },
    {
      "cohort": 1,
      "started_at": "2026-06-02T00:00:00Z",
      "ended_at": "2026-06-03T00:00:00Z",
      "subjects": 1,
      "subjects_returned_after_start": 0,
      "periods": [
        {
          "period": 0,
          "eligible_subjects": 0,
          "retained_subjects": 0,
          "all_subjects_eligible": false
        }
      ]
    }
  ],
  "next_action": {
    "code": "extend_retention_observation_window",
    "target": "/api/telemetry/analytics/retention",
    "reason": "Move since earlier, until later, or request fewer periods when a fully observed long-term comparison is required."
  }
}
```

### Leia a retenção

A cobertura conta os quatro eventos classificados, mas só três correspondem a
cada seletor de compra. A visualização de página não conta como retorno. Um
dos dois usuários repete a compra, então `return_rate_after_start` é `0.5`.

Só o primeiro usuário tem um dia inteiro de observação depois do ponto de
partida. Ele volta dentro desse dia, então a taxa da curva é `1.0`. O segundo
usuário tem só 12 horas de observação. Ele não é elegível para o período 0,
então a célula da segunda coorte omite `retention_rate`. Não conte esse
usuário como perdido.

`weighted_retention_rate` divide todos os usuários retidos por todos os
usuários elegíveis. `fully_observed_cohort_average_rate` é a média simples das
taxas das coortes em que todos os usuários são elegíveis. As coortes são
intervalos fixos que começam em `since`. `cohorts` contém só as coortes que
têm usuários.

Com `mode: "return_on_or_after"`, a curva omite `window_end_seconds`.

### Retenção automática

Envie `response_version: 2`, sem `start_event` nem `return_event`. Toda
visualização de página, visualização de tela e interação compatível conta como
início e como retorno. Essa versão escolhe um conjunto de eventos. Ela não
escolhe um formato de captura do SDK.

```json theme={null}
{
  "project_id": "11111111-1111-4111-8111-111111111111",
  "since": "2026-06-01T00:00:00Z",
  "until": "2026-06-03T00:00:00Z",
  "response_version": 2,
  "interval": "day",
  "interval_count": 1,
  "mode": "return_on",
  "cohort_mode": "first_in_range"
}
```

A resposta tem os mesmos formatos de `summary`, `curve`, `cohorts` e
`next_action` da resposta por evento exato. Este trecho mostra os campos que
mudam. Neste exemplo, os mesmos dois usuários têm três eventos e nenhuma
visualização de página:

```json theme={null}
{
  "schema_version": 2,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T00:00:00Z",
    "until": "2026-06-03T00:00:00Z",
    "activity_scope": "all_classified_activity",
    "interval": "day",
    "interval_seconds": 86400,
    "interval_count": 1,
    "mode": "return_on",
    "cohort_mode": "first_in_range"
  },
  "purpose": "Measures whether typed opaque user subjects perform any later supported classified product activity after their first such activity inside the selected half-open range. It does not choose or infer a top event. Returns must occur strictly after the anchor, anonymous and unidentified subjects remain excluded from user counts, eligibility-aware denominators prevent immature subjects from being reported as churned, and raw identifiers are never returned.",
  "coverage": {
    "classified_events": 3,
    "named_events": 3,
    "unnamed_events": 0,
    "identified_events": 3,
    "start_events": 3,
    "usable_start_events": 3,
    "excluded_start_events": 0,
    "return_events": 3,
    "usable_return_events": 3,
    "excluded_return_events": 0,
    "event_name_rate": 1.0,
    "start_identity_coverage_rate": 1.0,
    "return_identity_coverage_rate": 1.0,
    "limitations": [
      "Only application-supplied opaque subject IDs explicitly typed as users are counted. Anonymous, legacy-untyped, historical-unindexed, invalid, or absent subjects are excluded rather than inferred as people.",
      "first_in_range anchors each subject at its first supported classified activity in the range; it does not prove that activity was the subject's first-ever product activity.",
      "Cohort buckets are fixed-width and aligned to the query's since value. hour, day, week, and thirty_day mean fixed elapsed durations; thirty_day is not a calendar month.",
      "Returns are any supported classified activity strictly after the subject anchor and before the exclusive query upper bound; no event is ranked, selected, or inferred.",
      "This resource does not provide recurring-start cohorts, group retention, arbitrary property breakdowns, custom return ranges, or lifetime first-event lookup.",
      "return_on includes only subjects whose complete exact period ends by until; later subjects are excluded from that period's denominator."
    ]
  }
}
```

No modo automático, `start_events` e `return_events` são iguais a
`classified_events`. Essas contagens são de eventos, não de usuários.

### Retenção sem usuários elegíveis

Um resultado bem-sucedido pode não ter usuários em nenhuma coorte. Este trecho
mostra um período solicitado sem coortes:

```json theme={null}
{
  "schema_version": 2,
  "summary": {
    "cohort_subjects": 0,
    "subjects_returned_after_start": 0,
    "non_empty_cohorts": 0,
    "periods_with_eligible_subjects": 0,
    "fully_observed_periods": 0
  },
  "curve": [
    {
      "period": 0,
      "threshold_seconds": 0,
      "window_end_seconds": 86400,
      "eligible_subjects": 0,
      "retained_subjects": 0,
      "fully_observed_cohorts": 0,
      "all_subjects_eligible": false
    }
  ],
  "cohorts": []
}
```

Leia `coverage` e `next_action`. Eles distinguem um escopo sem eventos
classificados (`capture_product_activity`) de eventos sem usuários
(`identify_product_users` ou `identify_returning_users`). Uma taxa ausente não
é um zero medido.

### Erros de retenção

Além dos [erros de escopo comuns](#shared-scope-errors), estas requisições
retornam `422` e `validation_failed`:

| Causa | `error` |
| - | - |
| Versão 1 sem os dois seletores, versão 2 com um seletor, ou outra versão | `product analytics retention activity selection is contradictory` |
| `interval_count` fora da faixa de `1` a `31` | `product analytics retention interval_count must be between 1 and 31` |
| O número de intervalos de coorte vezes `interval_count` passa de 500 | `product analytics retention interval and interval_count would exceed 500 cohort matrix cells` |

O limite de células depende do período consultado e dos períodos de retenção,
não do número de usuários. Um período de 30 dias com `interval: "hour"` tem
720 intervalos de coorte. Com `interval_count: 1`, são 720 células, mais que
500:

```json theme={null}
{
  "error": "product analytics retention interval and interval_count would exceed 500 cohort matrix cells",
  "code": "validation_failed",
  "next": "choose a wider interval, a shorter time range, or fewer retention periods",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

Para usar a retenção automática, remova os dois seletores. Não altere o SDK
para corrigir esta requisição de leitura.

### Requisição de ciclo de vida por evento exato

Envie este corpo para `POST /api/telemetry/analytics/lifecycle`. Ele
classifica os usuários por um evento, não por toda a atividade do projeto:

```json theme={null}
{
  "project_id": "11111111-1111-4111-8111-111111111111",
  "since": "2026-06-01T00:00:00Z",
  "until": "2026-06-03T00:00:00Z",
  "response_version": 1,
  "interval": "day",
  "history_period_count": 2,
  "event": { "kind": "interaction", "event_name": "checkout_completed" }
}
```

`history_period_count` define quantos períodos completos antes de `since` o
LogBrew lê como histórico. Ele aceita de `2` a `31`. O padrão é `2`. Um
usuário pode estar inativo para este evento enquanto faz outras atividades.

### Ciclo de vida por evento exato bem-sucedido

Este exemplo fictício usa dois dias de histórico e dois dias de análise. As
letras só identificam os usuários do exemplo. A resposta não retorna IDs de
usuário.

| Data (UTC) | Usuários que concluem uma compra |
| - | - |
| 30 de maio, histórico | B |
| 31 de maio, histórico | A e D |
| 1º de junho, análise | A, B e C |
| 2 de junho, análise | A e B |

C também visualiza uma página em 2 de junho. Esse evento não corresponde ao
seletor de compra.

```json theme={null}
{
  "schema_version": 1,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T00:00:00Z",
    "until": "2026-06-03T00:00:00Z",
    "history_since": "2026-05-30T00:00:00Z",
    "event": { "kind": "interaction", "event_name": "checkout_completed" },
    "interval": "day",
    "interval_seconds": 86400,
    "history_period_count": 2,
    "expected_buckets": 2
  },
  "purpose": "Classifies typed opaque user subjects for one exact product event in each fixed analysis period. new_within_observed_history means active now with no earlier matching event inside the bounded history window; returning means active now and in the immediately previous period; resurrected means active now, inactive in the previous period, and active earlier in observed history; dormant means active in the previous period but not now. These states are disjoint, incomplete buckets are marked, and raw subject identifiers are never returned.",
  "summary": {
    "observed_subjects": 4,
    "analysis_active_subjects": 3,
    "history_only_subjects": 1,
    "returned_buckets": 2,
    "fully_observed_buckets": 2,
    "latest_fully_observed_period": 1,
    "buckets_with_resurrection": 1,
    "buckets_with_dormancy": 2
  },
  "coverage": {
    "analysis_classified_events": 6,
    "analysis_named_events": 6,
    "analysis_unnamed_events": 0,
    "analysis_identified_events": 6,
    "selected_events": 5,
    "usable_selected_events": 5,
    "usable_selected_sessionized_events": 5,
    "usable_selected_trace_linked_events": 5,
    "excluded_selected_events": 0,
    "history_selected_events": 3,
    "usable_history_selected_events": 3,
    "excluded_history_selected_events": 0,
    "event_name_rate": 1.0,
    "selected_identity_coverage_rate": 1.0,
    "selected_sessionization_rate": 1.0,
    "selected_trace_link_rate": 1.0,
    "history_identity_coverage_rate": 1.0,
    "limitations": [
      "Only application-supplied opaque subject IDs explicitly typed as users are counted. Anonymous, legacy-untyped, historical-unindexed, invalid, or absent subjects are excluded rather than inferred as people.",
      "new_within_observed_history means no earlier selected event between history_since and the current bucket. It does not prove that a subject is a lifetime-new user.",
      "Observed history contains exactly 2 complete fixed periods before since; activity before history_since is intentionally unknown.",
      "Buckets are fixed-width and aligned to since. hour, day, week, and thirty_day mean fixed elapsed durations; thirty_day is not a calendar month.",
      "Returning, resurrected, and dormant compare only the selected exact kind and derived event name. They do not infer intent, identity merges, or causality.",
      "This resource does not provide arbitrary property breakdowns, reusable cohorts, group lifecycle, lifetime first-event lookup, or per-subject lists."
    ]
  },
  "buckets": [
    {
      "period": 0,
      "started_at": "2026-06-01T00:00:00Z",
      "ended_at": "2026-06-02T00:00:00Z",
      "fully_observed": true,
      "active_subjects": 3,
      "new_within_observed_history_subjects": 1,
      "returning_subjects": 1,
      "resurrected_subjects": 1,
      "dormant_subjects": 1,
      "previous_active_subjects": 2,
      "new_share_of_active": 0.3333333333333333,
      "returning_share_of_active": 0.3333333333333333,
      "resurrected_share_of_active": 0.3333333333333333,
      "dormant_share_of_previous_active": 0.5,
      "net_active_change": 1
    },
    {
      "period": 1,
      "started_at": "2026-06-02T00:00:00Z",
      "ended_at": "2026-06-03T00:00:00Z",
      "fully_observed": true,
      "active_subjects": 2,
      "new_within_observed_history_subjects": 0,
      "returning_subjects": 2,
      "resurrected_subjects": 0,
      "dormant_subjects": 1,
      "previous_active_subjects": 3,
      "new_share_of_active": 0.0,
      "returning_share_of_active": 1.0,
      "resurrected_share_of_active": 0.0,
      "dormant_share_of_previous_active": 0.3333333333333333,
      "net_active_change": -1
    }
  ],
  "next_action": {
    "code": "investigate_lifecycle_loss",
    "target": "/api/telemetry/analytics/paths",
    "reason": "The latest complete bucket lost more prior active subjects than it added through new-within-observed-history and resurrected activity; compare bounded journeys around the selected event."
  }
}
```

### Leia o ciclo de vida

Em 1º de junho, A é recorrente, B é reativado, C é novo e D está inativo. Em
2 de junho, A e B são recorrentes, e C está inativo para a compra, apesar da
visualização de página. A variação líquida em 2 de junho é `2 - 3 = -1`.

Em cada intervalo, os usuários novos, recorrentes e reativados somam
`active_subjects`. `returning_subjects` mais `dormant_subjects` é igual a
`previous_active_subjects`. `net_active_change` é `active_subjects` menos
`previous_active_subjects`.

Não some as contagens diárias de ativos para obter usuários distintos. Aqui,
as contagens diárias somam 5, mas `analysis_active_subjects` é 3. Quatro
usuários distintos aparecem entre o histórico e a análise.

`fully_observed` é `false` em um intervalo final que termina depois de
`until`. As contagens dele podem mudar quando o período inteiro puder ser
observado. O `next_action` sugere uma investigação. Ele não mostra uma causa.

### Ciclo de vida automático

Envie `response_version: 2`, sem o seletor `event`. Toda visualização de
página, visualização de tela e interação compatível conta como atividade:

```json theme={null}
{
  "project_id": "11111111-1111-4111-8111-111111111111",
  "since": "2026-06-01T00:00:00Z",
  "until": "2026-06-03T00:00:00Z",
  "response_version": 2,
  "interval": "day",
  "history_period_count": 2
}
```

A resposta tem os mesmos formatos de `summary`, `buckets` e `next_action` da
resposta por evento exato. Este trecho mostra os campos que mudam:

```json theme={null}
{
  "schema_version": 2,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T00:00:00Z",
    "until": "2026-06-03T00:00:00Z",
    "history_since": "2026-05-30T00:00:00Z",
    "activity_scope": "all_classified_activity",
    "interval": "day",
    "interval_seconds": 86400,
    "history_period_count": 2,
    "expected_buckets": 2
  },
  "purpose": "Classifies typed opaque user subjects by any supported classified product activity in each fixed period. It does not choose or infer a top event. new_within_observed_history, returning, resurrected, and dormant remain disjoint; anonymous and unidentified subjects are excluded from user counts, incomplete buckets are marked, and raw identifiers are never returned."
}
```

No modo automático, `coverage.selected_events` é igual a
`coverage.analysis_classified_events`. O quinto item de `limitations` é
`Returning, resurrected, and dormant compare any supported classified product activity; no event is ranked, selected, or inferred.`

### Ciclo de vida sem usuários

Se nem o período de análise nem o histórico tiverem usuários utilizáveis,
`buckets` fica vazio e `summary` omite `latest_fully_observed_period`:

```json theme={null}
{
  "schema_version": 2,
  "summary": {
    "observed_subjects": 0,
    "analysis_active_subjects": 0,
    "history_only_subjects": 0,
    "returned_buckets": 0,
    "fully_observed_buckets": 0,
    "buckets_with_resurrection": 0,
    "buckets_with_dormancy": 0
  },
  "buckets": []
}
```

Usuários que aparecem só no histórico ainda podem gerar intervalos com
usuários inativos quando o período de análise não tem atividade.

### Erros de ciclo de vida

Além dos [erros de escopo comuns](#shared-scope-errors), estas requisições
retornam `422` e `validation_failed`:

| Causa | `error` |
| - | - |
| Versão 1 sem `event`, versão 2 com `event`, ou outra versão | `product analytics lifecycle activity selection is contradictory` |
| `history_period_count` fora da faixa de `2` a `31` | `product analytics lifecycle history_period_count must be between 2 and 31` |
| Períodos de histórico com mais de 62 dias no total | `product analytics lifecycle history must not exceed 62 days` |
| Mais de 100 intervalos de análise | `product analytics lifecycle interval would exceed 100 analysis buckets` |

Por exemplo, dez períodos de histórico `week` precisam de 70 dias:

```json theme={null}
{
  "error": "product analytics lifecycle history must not exceed 62 days",
  "code": "validation_failed",
  "next": "use fewer history periods or a narrower fixed interval",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

### Leia o escopo de análise selecionado

As respostas por evento exato têm `schema_version: 1`. O `query` delas repete
os seletores e omite `activity_scope`. As respostas automáticas têm
`schema_version: 2` e `query.activity_scope: "all_classified_activity"`. Elas
omitem os seletores. Um seletor diferente pode mudar o resultado sem nenhuma
mudança na atividade capturada.

## Resposta de série de métricas

`GET /api/telemetry/metrics/series` lê um nome exato de métrica em um projeto.
Copie o nome de `GET /api/telemetry/metrics`. Esta requisição agrupa um
contador delta por serviço:

```bash theme={null}
curl --get "https://api.logbrew.co/api/telemetry/metrics/series" \
  --header "Authorization: Bearer $LOGBREW_ACCOUNT_BEARER" \
  --data-urlencode "project_id=<project_id>" \
  --data-urlencode "name=jobs.completed" \
  --data-urlencode "since=2026-06-01T12:00:00Z" \
  --data-urlencode "until=2026-06-01T12:15:00Z" \
  --data-urlencode "interval=5m" \
  --data-urlencode "group_by=service_name"
```

### Série de métricas bem-sucedida

Esta resposta fictícia contém uma série de contador delta. Três amostras com
os valores `2`, `3` e `5` ocorrem no primeiro intervalo. Duas amostras com os
valores `1` e `4` ocorrem no último intervalo. Nenhuma amostra ocorre no
intervalo do meio, então a resposta não tem ponto para ele.

```json theme={null}
{
  "schema_version": 1,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "name": "jobs.completed",
    "since": "2026-06-01T12:00:00Z",
    "until": "2026-06-01T12:15:00Z",
    "interval": "5m",
    "interval_seconds": 300,
    "group_by": "service_name",
    "series_limit": 10
  },
  "purpose": "Shows how one metric changes over time without changing its meaning: gauges use sampled state, delta counters use change volume and rate, histograms use distributions, and cumulative streams stay raw when reset-safe change is ambiguous.",
  "coverage": {
    "samples": 5,
    "series": 1,
    "returned_series": 1,
    "points": 2,
    "expected_buckets_per_series": 3,
    "first_seen_at": "2026-06-01T12:00:10Z",
    "last_seen_at": "2026-06-01T12:14:50Z",
    "truncated": false
  },
  "series": [
    {
      "identity": {
        "kind": "counter",
        "unit": "{job}",
        "temporality": "delta",
        "group_by": "service_name",
        "group_value": "checkout-worker"
      },
      "status": "ready",
      "aggregation": {
        "code": "delta_sum",
        "description": "Primary value is the sum of recorded changes in each bucket; rate_per_second normalizes that change by bucket width."
      },
      "sample_count": 5,
      "points": [
        {
          "bucket_start": "2026-06-01T12:00:00Z",
          "bucket_end": "2026-06-01T12:05:00Z",
          "sample_count": 3,
          "value": 10.0,
          "last": 5.0,
          "min": 2.0,
          "max": 5.0,
          "average": 3.3333333333333335,
          "sum": 10.0,
          "rate_per_second": 0.03333333333333333,
          "trace_exemplars": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
        },
        {
          "bucket_start": "2026-06-01T12:10:00Z",
          "bucket_end": "2026-06-01T12:15:00Z",
          "sample_count": 2,
          "value": 5.0,
          "last": 4.0,
          "min": 1.0,
          "max": 4.0,
          "average": 2.5,
          "sum": 5.0,
          "rate_per_second": 0.016666666666666666,
          "trace_exemplars": []
        }
      ]
    }
  ],
  "next_action": {
    "code": "inspect_metric_change",
    "target": "trace_summary",
    "reason": "Open a trace exemplar from an unusual bucket to connect the metric change to spans, errors, logs, and release context."
  }
}
```

### Leia uma série de métricas

O primeiro ponto registra 10 tarefas concluídas, não 10 amostras.
`rate_per_second` divide essa variação pelo intervalo de 300 segundos. `last`
é a última variação registrada, não a soma. Consulte
[significados da agregação de métricas](/pt-BR/concepts/telemetry#read-the-metric-value).

O tipo e a temporalidade de uma série definem o `aggregation.code` e as
estatísticas de cada ponto. Um ponto omite as estatísticas que não se
aplicam. Uma estatística ausente não é zero.

| Tipo e temporalidade | `status` | `aggregation.code` | `value` | Outras estatísticas |
| - | - | - | - | - |
| `gauge`, `instant` | `ready` | `gauge_last` | Última amostra | `last`, `min`, `max`, `average` |
| `counter`, `delta` | `ready` | `delta_sum` | Soma das variações | `last`, `min`, `max`, `average`, `sum`, `rate_per_second` |
| `histogram`, `delta` | `ready` | `distribution_p95` | p95 aproximado | `min`, `max`, `average`, `sum`, `p50`, `p95`, `p99` |
| Qualquer tipo, `cumulative` | `limited` | `raw_cumulative_last` | Última amostra bruta | `last`, `min`, `max` |
| Qualquer outro par | `limited` | `raw_last` | Última amostra bruta | `last`, `min`, `max` |

`limited` é uma resposta bem-sucedida, não um erro. Ela adiciona
`aggregation.limitation`, que explica por que o LogBrew mostra só valores
brutos. `ready` não prova que a captura está completa.

Leia `coverage` antes de desenhar um gráfico:

* `samples` conta as amostras de todas as séries correspondentes, incluindo
  séries que a resposta não retorna.
* `series` conta as séries correspondentes. `returned_series` e `points`
  contam os dados retornados.
* `truncated` é `true` quando `series_limit` removeu séries de volume menor.
* `expected_buckets_per_series` é o número de intervalos possíveis no
  período.

Não adicione um ponto para um intervalo sem amostras. Não insira um zero nem
copie o valor anterior. Cada ponto retorna até 3 `trace_exemplars`. Um
exemplar de trace vincula uma amostra a um trace. Ele não explica todas as
amostras do intervalo. Se nenhum ponto tiver um exemplar de trace,
`next_action.target` é `metric_samples`.

### Escopo e erros da série de métricas

`project_id`, `name` e `since` são obrigatórios. `name` pode ter no máximo 200
caracteres. `interval` é `auto`, `1m`, `5m`, `15m`, `1h`, `6h` ou `1d`. O
padrão é `auto`, que escolhe a menor largura de intervalo com no máximo 300
intervalos. Uma largura explícita não pode gerar mais de 500 intervalos.

`group_by` é `none`, `service_name`, `release` ou `environment`. O padrão é
`none`. Sem agrupamento, tipos, unidades e temporalidades diferentes ficam em
séries separadas. `series_limit` aceita de `1` a `20`. O padrão é `10`.

Um resultado vazio retorna `200` com `series: []` e `samples` zerado. O objeto
`coverage` omite `first_seen_at` e `last_seen_at`. Isso não prova que a
aplicação nunca enviou a métrica. Confira o projeto, o nome da métrica e o
período.

Omitir `name` retorna `422`:

```json theme={null}
{
  "error": "metric series name is required",
  "code": "validation_failed",
  "next": "send the exact metric name returned by /api/telemetry/metrics",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

Intervalos de um minuto ao longo de sete dias retornam `422`:

```json theme={null}
{
  "error": "metric series interval would exceed 500 buckets",
  "code": "validation_failed",
  "next": "use interval=auto or select a wider interval",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

Outros erros `422` são `metric series group_by is not supported`,
`metric series interval is not supported` e
`metric series_limit must be between 1 and 20`.

## Resposta da análise de caminhos

`POST /api/telemetry/analytics/paths` encontra os eventos nomeados antes ou
depois de um evento selecionado, na mesma sessão. O evento selecionado é a
âncora. Copie o `kind` e o `event_name` dele de
`classified_activity.top_events`. A rota retorna `schema_version: 1`. Ela não
aceita `response_version` nem `analysis_unit`.

```json theme={null}
{
  "project_id": "11111111-1111-4111-8111-111111111111",
  "since": "2026-06-01T11:00:00Z",
  "until": "2026-06-01T12:00:00Z",
  "direction": "following",
  "anchor": { "kind": "page_view", "event_name": "/checkout" },
  "depth": 2,
  "collapse_repeated": true,
  "path_limit": 2
}
```

`direction` e `anchor` são obrigatórios.

### Caminhos bem-sucedidos

Neste resultado fictício, quatro sessões contêm a âncora. Os dois caminhos
retornados representam três dessas sessões. Um caminho com classificação
menor não é retornado.

```json theme={null}
{
  "schema_version": 1,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T11:00:00Z",
    "until": "2026-06-01T12:00:00Z",
    "direction": "following",
    "anchor": { "kind": "page_view", "event_name": "/checkout" },
    "depth": 2,
    "collapse_repeated": true,
    "path_limit": 2
  },
  "purpose": "Shows the highest-volume named product-event sequences immediately before or after one exact version-1 page view, screen view, or interaction inside explicit sessions. Following paths use the earliest matching anchor in each session; preceding paths use the latest. Optional exact property predicates classify only the anchor, while surrounding events preserve the real session journey. Results aggregate exact bounded sequences and never return raw session or subject identifiers.",
  "summary": {
    "anchored_sessions": 4,
    "represented_sessions": 3,
    "unrepresented_sessions": 1,
    "returned_paths": 2,
    "paths_truncated": true
  },
  "coverage": {
    "classified_events": 12,
    "named_events": 12,
    "unnamed_events": 0,
    "sessionized_events": 10,
    "unsessionized_events": 2,
    "anchor_events": 5,
    "usable_anchor_events": 4,
    "excluded_anchor_events": 1,
    "traced_anchor_events": 1,
    "event_name_rate": 1.0,
    "sessionization_rate": 0.8333333333333334,
    "anchor_session_coverage_rate": 0.8,
    "anchor_trace_link_rate": 0.2,
    "ordered_event_cap_per_session": 1024,
    "limitations": [
      "Paths include only supported version-1 classified events with exact derived names; arbitrary actions, technical spans, and raw identity values are excluded.",
      "Paths stay inside application-supplied session boundaries and the selected half-open time range; activity beyond either boundary is not inferred.",
      "Each session retains at most 1024 direction-nearest named events before anchoring, so exceptionally noisy sessions can be omitted or truncated.",
      "Classified events without an explicit opaque session ID cannot participate in session paths.",
      "Trace exemplars prove only that a matching anchor carried the same trace ID. They do not prove root cause, and deeper investigation depends on retained spans for that trace.",
      "Some matching anchors lack trace IDs, so trace-linked path evidence covers only the reported traced_anchor_events population."
    ]
  },
  "paths": [
    {
      "rank": 1,
      "sessions": 2,
      "share_of_anchored_sessions": 0.5,
      "traced_sessions": 1,
      "trace_link_rate": 0.5,
      "trace_exemplars": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"],
      "nodes": [
        { "relative_position": 0, "kind": "page_view", "event_name": "/checkout" },
        { "relative_position": 1, "kind": "interaction", "event_name": "checkout.submitted" },
        { "relative_position": 2, "kind": "interaction", "event_name": "checkout.completed" }
      ]
    },
    {
      "rank": 2,
      "sessions": 1,
      "share_of_anchored_sessions": 0.25,
      "traced_sessions": 0,
      "trace_link_rate": 0.0,
      "trace_exemplars": [],
      "nodes": [
        { "relative_position": 0, "kind": "page_view", "event_name": "/checkout" },
        { "relative_position": 1, "kind": "interaction", "event_name": "checkout.failed" }
      ]
    }
  ],
  "next_action": {
    "code": "inspect_path_trace",
    "target": "/api/telemetry/traces/{trace_id}/investigation",
    "reason": "Open an exemplar from the material path to connect the product journey to retained spans, issues, logs, actions, metrics, and release context as evidence rather than a root-cause claim."
  }
}
```

### Leia os caminhos

`share_of_anchored_sessions` divide as sessões de um caminho pelas quatro
sessões com âncora. As parcelas são 50% e 25%, não 67% e 33%.
`unrepresented_sessions` conta as sessões com âncora que nenhum caminho
retornado representa. `paths_truncated: true` significa que o resultado está
incompleto.

A cobertura conta eventos, não sessões. Aqui, cinco eventos correspondem à
âncora, mas um não tem ID de sessão. Esse evento não pode entrar em um
caminho. Cada caminho retorna até 3 exemplares de trace. Use um ID de trace da
sua própria resposta. Um vínculo com um trace não mostra o que causou uma ação
do usuário ou uma falha.

| Campo | Significado |
| - | - |
| `following` | Começa na primeira âncora correspondente de cada sessão. A âncora tem a posição `0`. Os nós seguintes têm posições positivas. |
| `preceding` | Termina na última âncora correspondente de cada sessão. Os nós anteriores têm posições negativas. A âncora tem a posição `0`. |
| `depth` | Número de nós ao lado da âncora, sem contar a âncora. De `1` a `8`. O padrão é `4`. Um caminho pode ter menos nós. |
| `collapse_repeated` | Junta nós consecutivos com o mesmo tipo e o mesmo nome. O padrão é `true`. |
| `path_limit` | Número máximo de caminhos retornados, ordenados pela contagem de sessões. De `1` a `20`. O padrão é `10`. |

Os nós ficam em ordem cronológica nas duas direções. Um caminho não é uma
reprodução completa da sessão. O LogBrew lê no máximo 1024 eventos nomeados
por sessão antes de escolher a âncora: os eventos mais antigos para
`following` e os mais recentes para `preceding`. Uma âncora fora desse limite
pode ser omitida.

### <span id="filter-the-anchor-by-property">Filtre a âncora por propriedade</span>

Envie até quatro `property_filters`, cada um com um `key` e um `value`
exatos. Copie a chave do [catálogo de propriedades](#analytics-property-catalog).
Os filtros valem só para a âncora, não para os eventos ao redor dela. Os
valores diferenciam maiúsculas de minúsculas. Quando há filtros, `query` os
repete, e `coverage.anchor_property_filters` informa:

| Campo | Significado |
| - | - |
| `context_events` | Eventos de âncora no escopo antes dos filtros de propriedade. |
| `property_ready_events` | Eventos de âncora que têm todas as chaves solicitadas. |
| `missing_property_events` | Eventos de âncora sem uma ou mais chaves solicitadas. |
| `matching_events` | Eventos de âncora cujos valores correspondem a todos os filtros. |
| `nonmatching_value_events` | Eventos de âncora que têm todas as chaves, mas um valor diferente. |
| `property_ready_rate` | `property_ready_events` dividido por `context_events`. |
| `match_rate` | `matching_events` dividido por `property_ready_events`. |

Chaves ausentes e valores diferentes pedem correções diferentes. Não some os
dois. O objeto é omitido quando a requisição não tem filtro de propriedade.

### Caminhos vazios e requisições rejeitadas

Um array `paths` vazio pode ser uma resposta `200` bem-sucedida. Leia
`summary`, `coverage` e `next_action`. Estes códigos distinguem as causas:
`capture_product_activity`, `choose_captured_path_anchor`,
`capture_anchor_properties`, `improve_anchor_property_coverage`,
`verify_anchor_property_values`, `sessionize_product_activity` e
`narrow_or_move_path_anchor`.

Além dos [erros de escopo comuns](#shared-scope-errors), estas requisições
retornam `422` e `validation_failed`:

| Causa | `error` |
| - | - |
| `depth` fora da faixa de `1` a `8` | `product analytics path depth must be between 1 and 8` |
| `path_limit` fora da faixa de `1` a `20` | `product analytics path_limit must be between 1 and 20` |
| Mais de quatro filtros de propriedade | `product analytics paths accept at most four exact anchor property filters` |
| Uma chave que não está no catálogo de propriedades | `product analytics path property keys must be supported privacy-safe keys` |
| A mesma chave duas vezes | `product analytics path property keys must be unique` |
| Um valor vazio, um valor com mais de 256 caracteres ou um caractere de controle | `product analytics path property values must be non-empty, control-free, and at most 256 characters` |

Por exemplo, `depth: 0` retorna:

```json theme={null}
{
  "error": "product analytics path depth must be between 1 and 8",
  "code": "validation_failed",
  "next": "use depth from 1 through 8 adjacent named events",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

## <span id="analytics-property-catalog">Catálogo de propriedades de análise</span>

`GET /api/telemetry/analytics/properties` lista as chaves de propriedade dos
eventos de produto classificados de um projeto. Use as chaves em
[comparações de segmentos](#analytics-segment-comparison) e em filtros de
âncora de caminhos. O catálogo retorna chaves e contagens. Ele nunca retorna
valores de propriedades nem identidades.

### Leia as chaves de propriedade disponíveis

Envie `project_id` e `since`. Você também pode enviar `until`,
`service_name`, `release`, `environment`, `limit` e `response_version`.
`limit` aceita de `1` a `50` chaves. O padrão é `20`. Envie
`response_version=2` para obter o valor público de `estimation.method`.

```bash theme={null}
curl --get "https://api.logbrew.co/api/telemetry/analytics/properties" \
  --header "Authorization: Bearer $LOGBREW_ACCOUNT_BEARER" \
  --data-urlencode "project_id=<project_id>" \
  --data-urlencode "since=2026-06-01T00:00:00Z" \
  --data-urlencode "until=2026-06-02T00:00:00Z" \
  --data-urlencode "limit=20" \
  --data-urlencode "response_version=2"
```

### Catálogo de propriedades bem-sucedido

Neste resultado fictício, existem 100 eventos classificados. Cinco deles foram
capturados antes do índice de propriedades atual.

```json theme={null}
{
  "schema_version": 2,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T00:00:00Z",
    "until": "2026-06-02T00:00:00Z",
    "limit": 20
  },
  "purpose": "Discovers bounded privacy-safe runtime, framework, operating-system, device, application, and custom-tag keys captured on classified product events. It reports migration, capture, privacy-filtering, and per-key coverage without returning property values or identities, so humans and agents can build exact segment comparisons without guessing which dimensions exist.",
  "summary": {
    "classified_events": 100,
    "available_property_keys": 3,
    "returned_properties": 3
  },
  "coverage": {
    "indexed_events": 95,
    "unindexed_events": 5,
    "complete_index_events": 95,
    "incomplete_index_events": 0,
    "privacy_filtered_events": 4,
    "events_with_properties": 90,
    "index_coverage_rate": 0.95,
    "property_capture_rate": 0.9,
    "properties_truncated": false,
    "values_returned": false,
    "limitations": [
      "Property discovery returns keys and aggregate counts only; property values and identity columns are never returned.",
      "Property filters use exact case-sensitive bounded string equality and combine with logical AND inside each segment.",
      "Historical events written before the current property index are excluded from property descriptors and exact property filters.",
      "Direct-identity, credential-like, and network-address custom tag keys were intentionally excluded from the analytics property index."
    ]
  },
  "estimation": {
    "count_accuracy": "approximate",
    "method": "approximate_distinct",
    "description": "Available property-key and per-key distinct-value counts are approximate distinct counts. Classified-event, index-coverage, privacy-filtering, and per-key event counts are exact within the selected fully evaluated window."
  },
  "properties": [
    {
      "key": "resource.runtime.name",
      "source": "standard_context",
      "value_type": "string",
      "events": 90,
      "coverage_rate": 0.9,
      "distinct_values": 2
    },
    {
      "key": "resource.application.version",
      "source": "standard_context",
      "value_type": "string",
      "events": 70,
      "coverage_rate": 0.7,
      "distinct_values": 4
    },
    {
      "key": "tag.plan",
      "source": "custom_tag",
      "value_type": "string",
      "events": 60,
      "coverage_rate": 0.6,
      "distinct_values": 3
    }
  ],
  "next_action": {
    "code": "compare_property_segments",
    "target": "/api/telemetry/analytics/segments/compare",
    "reason": "Use exact returned keys with locally known values to compare behavior while preserving identity and property-value privacy."
  }
}
```

### Interprete o catálogo

`source` é `standard_context` para uma chave de contexto padrão, como
`resource.runtime.name`, ou `custom_tag` para uma chave que começa com `tag.`.
`value_type` é sempre `string`. `properties` vem ordenado por `events`, do
maior para o menor.

`tag.plan` está em 60 de 100 eventos classificados. Ela tem cerca de 3
valores distintos. A descrição da chave não mostra esses valores. Use valores
que você conhece da sua aplicação. Não deduza um valor a partir de uma
contagem. Um evento pode ter várias chaves, então não some as contagens de
`events` por chave.

| Campo | Significado |
| - | - |
| `summary.classified_events` | Eventos classificados no escopo. É o denominador de cada `coverage_rate`. |
| `summary.available_property_keys` | Número estimado de chaves distintas, não o número de linhas retornadas. |
| `coverage.unindexed_events` | Eventos capturados antes do índice de propriedades atual. Eles não podem contribuir com chaves. |
| `coverage.incomplete_index_events` | Eventos com parte do contexto malformada ou truncada. As chaves válidas deles ainda contam. |
| `coverage.privacy_filtered_events` | Eventos dos quais o LogBrew removeu chaves sensíveis de tags personalizadas. Não é uma contagem de chaves. |
| `coverage.properties_truncated` | `true` quando existem mais chaves que `limit`. Restrinja o escopo ou aumente `limit` até 50. |
| `coverage.values_returned` | Sempre `false`. |

Um array `properties` vazio não prova que o projeto não tem eventos de
produto. Leia `summary`, `coverage` e `next_action`.

### Erros do catálogo de propriedades

Além dos [erros de escopo comuns](#shared-scope-errors), `limit=0` ou
`limit=51` retorna `422`:

```json theme={null}
{
  "error": "product analytics property limit must be between 1 and 50",
  "code": "validation_failed",
  "next": "use limit=1 through limit=50",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

Um `response_version` diferente de `1` ou `2` retorna
`product analytics response_version must be 1 or 2`. O LogBrew confere
`response_version` antes dos outros valores.

Uma requisição `POST` retorna `405`:

```json theme={null}
{
  "error": "Method not allowed",
  "code": "method_not_allowed",
  "next": "send GET /api/telemetry/analytics/properties with required project_id and since plus optional until, service_name, release, environment, limit, or response_version query parameters",
  "next_action": { "code": "use_supported_method", "target": "api_method" }
}
```

## <span id="analytics-segment-comparison">Comparação de segmentos de análise</span>

`POST /api/telemetry/analytics/segments/compare` compara com que frequência
sessões ou usuários chegam a um evento exato em 2 a 4 segmentos de um
projeto. Um segmento seleciona eventos por serviço, versão, ambiente e valores
de propriedades. O primeiro segmento é a referência.

### Defina a comparação

Envie este corpo JSON com a autenticação da conta e
`Content-Type: application/json`. Aqui, `basic` e `premium` são valores de
plano da aplicação de exemplo, não planos do LogBrew:

```json theme={null}
{
  "project_id": "11111111-1111-4111-8111-111111111111",
  "since": "2026-06-01T11:00:00Z",
  "until": "2026-06-01T12:00:00Z",
  "interval": "1h",
  "analysis_unit": "session",
  "response_version": 2,
  "target": { "kind": "interaction", "event_name": "checkout_completed" },
  "segments": [
    {
      "key": "basic",
      "label": "Basic plan",
      "service_name": "checkout-api",
      "environment": "production",
      "property_filters": [{ "key": "tag.plan", "value": "basic" }]
    },
    {
      "key": "premium",
      "label": "Premium plan",
      "service_name": "checkout-api",
      "environment": "production",
      "property_filters": [{ "key": "tag.plan", "value": "premium" }]
    }
  ]
}
```

`target` e `segments` são obrigatórios. `analysis_unit` é `session` ou
`identified_user`. O padrão é `session`, que conta sessões, não pessoas.
`interval` aceita os mesmos valores da visão geral. O padrão é `auto`.

Cada segmento precisa de um `key` único, um `label` e um conjunto de filtros
diferente:

* `key`: de 1 a 32 bytes. Comece com uma letra ASCII minúscula ou um dígito.
  Use só letras ASCII minúsculas, dígitos, `_` e `-`.
* `label`: de 1 a 80 caracteres, sem caracteres de controle.
* `service_name`, `release`, `environment`: opcionais. Cada valor tem de 1 a
  256 caracteres, sem caracteres de controle.
* `property_filters`: de 0 a 4 filtros. Cada chave pode aparecer uma vez em um
  segmento. Um evento precisa corresponder a todos os filtros do segmento. Os
  valores diferenciam maiúsculas de minúsculas e têm de 1 a 256 caracteres. O
  LogBrew remove os espaços do início e do fim.

Um segmento sem filtros seleciona toda a atividade classificada do projeto no
período. Os segmentos podem se sobrepor. Um rótulo ou uma chave diferente não
torna válidos dois conjuntos de filtros idênticos.

### Comparação de segmentos bem-sucedida

Neste resultado fictício, a referência chega ao checkout em 10 de 50 sessões.
O segmento premium chega a ele em 18 de 60 sessões.

```json theme={null}
{
  "schema_version": 2,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "since": "2026-06-01T11:00:00Z",
    "until": "2026-06-01T12:00:00Z",
    "interval": "1h",
    "interval_seconds": 3600,
    "analysis_unit": "session",
    "target": { "kind": "interaction", "event_name": "checkout_completed" },
    "segments": [
      {
        "key": "basic",
        "label": "Basic plan",
        "service_name": "checkout-api",
        "release": null,
        "environment": "production",
        "property_filters": [{ "key": "tag.plan", "value": "basic" }]
      },
      {
        "key": "premium",
        "label": "Premium plan",
        "service_name": "checkout-api",
        "release": null,
        "environment": "production",
        "property_filters": [{ "key": "tag.plan", "value": "premium" }]
      }
    ]
  },
  "purpose": "Compares how often explicit sessions or typed opaque user subjects reach one exact versioned page-view, screen-view, or interaction outcome across two through four named service, release, environment, and exact safe-property segments. It distinguishes missing property capture from nonmatching values, returns time trends and descriptive differences from the first segment, and never returns identities or claims causality or statistical significance.",
  "summary": {
    "segment_count": 2,
    "baseline_segment_key": "basic",
    "segments_with_eligible_units": 2,
    "segments_with_target_events": 2,
    "segments_with_reached_units": 2
  },
  "confidence": {
    "interpretation": "descriptive_only",
    "unique_count_accuracy": "approximate",
    "estimation_method": "approximate_distinct",
    "causal_inference": "not_established",
    "statistical_significance": "not_tested",
    "segment_overlap": "possible",
    "limitations": [
      "Unique session or typed user-subject counts use bounded cardinality estimates; event and capture-coverage totals are exact within the fully evaluated window.",
      "Segments are evaluated independently and may overlap, so their totals must not be added or interpreted as a population partition.",
      "Differences and relative lift are descriptive only. They do not control for exposure, assignment, seasonality, selection bias, or other confounders.",
      "Bucket-level unique counts are recalculated inside each bucket and are not additive across the series.",
      "Session analysis compares visits or app sessions, not unique people.",
      "At least one segment has classified events without the selected unit ID; compare unit_coverage_rate before interpreting reach differences.",
      "Property predicates are exact case-sensitive string matches. Events without the current property index or every requested key are excluded from segment results and reported separately as missing_property_events.",
      "Direct-identity, credential-like, and network-address custom tag keys are excluded from the analytics property index and cannot be used for segmentation."
    ]
  },
  "segments": [
    {
      "key": "basic",
      "label": "Basic plan",
      "eligible_units": 50,
      "reached_units": 10,
      "reach_rate": 0.2,
      "usable_target_events_per_reached_unit": 1.8,
      "coverage": {
        "classified_events": 200,
        "unit_identified_events": 190,
        "excluded_events": 10,
        "unit_coverage_rate": 0.95,
        "target_events": 20,
        "usable_target_events": 18,
        "excluded_target_events": 2,
        "target_unit_coverage_rate": 0.9,
        "traced_target_events": 10,
        "target_trace_link_rate": 0.5,
        "property_filters": {
          "context_events": 500,
          "property_ready_events": 480,
          "missing_property_events": 20,
          "property_ready_rate": 0.96,
          "matching_events": 200,
          "nonmatching_value_events": 280,
          "match_rate": 0.4166666666666667
        }
      },
      "series": [
        {
          "bucket_start": "2026-06-01T11:00:00Z",
          "bucket_end": "2026-06-01T12:00:00Z",
          "classified_events": 200,
          "eligible_units": 50,
          "target_events": 20,
          "usable_target_events": 18,
          "reached_units": 10,
          "reach_rate": 0.2
        }
      ]
    },
    {
      "key": "premium",
      "label": "Premium plan",
      "eligible_units": 60,
      "reached_units": 18,
      "reach_rate": 0.3,
      "usable_target_events_per_reached_unit": 1.8888888888888888,
      "coverage": {
        "classified_events": 240,
        "unit_identified_events": 228,
        "excluded_events": 12,
        "unit_coverage_rate": 0.95,
        "target_events": 36,
        "usable_target_events": 34,
        "excluded_target_events": 2,
        "target_unit_coverage_rate": 0.9444444444444444,
        "traced_target_events": 18,
        "target_trace_link_rate": 0.5,
        "property_filters": {
          "context_events": 500,
          "property_ready_events": 480,
          "missing_property_events": 20,
          "property_ready_rate": 0.96,
          "matching_events": 240,
          "nonmatching_value_events": 240,
          "match_rate": 0.5
        }
      },
      "series": [
        {
          "bucket_start": "2026-06-01T11:00:00Z",
          "bucket_end": "2026-06-01T12:00:00Z",
          "classified_events": 240,
          "eligible_units": 60,
          "target_events": 36,
          "usable_target_events": 34,
          "reached_units": 18,
          "reach_rate": 0.3
        }
      ],
      "comparison_to_baseline": {
        "eligible_units_difference": 10,
        "reached_units_difference": 8,
        "target_events_difference": 16,
        "reach_rate_difference": 0.09999999999999998,
        "relative_reach_rate_lift": 0.4999999999999998
      }
    }
  ],
  "next_action": {
    "code": "investigate_segment_paths",
    "target": "/api/telemetry/analytics/paths",
    "reason": "Inspect paths around the target in the weakest segment, then use correlated traces to explain a material behavioral difference."
  }
}
```

### Leia as taxas e as diferenças

`eligible_units` estima as sessões ou os usuários com atividade classificada
no segmento. `reached_units` estima quantos deles chegaram ao alvo.
`reach_rate` é `reached_units` dividido por `eligible_units`. Eventos sem o ID
da unidade selecionada não contam para essas unidades.

A taxa da referência é 20%. A taxa do premium é 30%. A diferença é de 10
pontos percentuais. O aumento relativo é de 50%, não de 10%. Pequenos erros
nas casas decimais vêm da aritmética de ponto flutuante. Arredonde as taxas
para exibição, mas calcule com os valores retornados. O segmento de referência
não tem `comparison_to_baseline`. O aumento relativo é omitido quando a taxa
de alcance da referência é zero.

Em `query`, um filtro de segmento que você não enviou é `null`. Uma lista
`property_filters` vazia é omitida.

`coverage.property_filters` tem os mesmos campos da
[cobertura dos filtros de âncora de caminhos](#filter-the-anchor-by-property).
Aqui, `matching_events` é igual a `classified_events`. Mantenha separadas as
chaves ausentes e os valores diferentes. Os segmentos podem se sobrepor, e uma
sessão pode aparecer em vários intervalos. Não some contagens de unidades
entre segmentos ou intervalos.

A comparação é descritiva. `confidence.causal_inference` é `not_established`
e `confidence.statistical_significance` é `not_tested`. Uma taxa de 30% contra
20% não mostra que um plano causou mais compras.

### Erros da comparação de segmentos

Além dos [erros de escopo comuns](#shared-scope-errors), estas requisições
retornam `422` e `validation_failed`:

| Causa | `error` |
| - | - |
| Menos de 2 ou mais de 4 segmentos | `product analytics segment comparison requires two through four segments` |
| Dois segmentos com a mesma chave | `product analytics segment keys must be unique` |
| Dois segmentos com os mesmos filtros | `product analytics segment filters must be unique` |
| Uma chave que não tem de 1 a 32 bytes permitidos | `product analytics segment keys must be 1 through 32 machine-safe bytes` |
| Um rótulo vazio, longo demais ou com um caractere de controle | `product analytics segment labels must be non-empty, control-free, and at most 80 characters` |
| Um valor de filtro com um caractere de controle | `product analytics segment filters must be control-free` |
| Mais de quatro filtros de propriedade em um segmento | `product analytics segments accept at most four exact property filters` |
| Uma chave que não está no catálogo de propriedades | `product analytics segment property keys must be supported privacy-safe keys` |
| A mesma chave de propriedade duas vezes em um segmento | `product analytics segment property keys must be unique within each segment` |
| Um valor de propriedade vazio, longo demais ou com um caractere de controle | `product analytics segment property values must be non-empty, control-free, and at most 256 characters` |
| Um `response_version` diferente de `1` ou `2` | `product analytics response_version must be 1 or 2` |

Os erros de `interval` são os mesmos dos [erros da visão geral](#overview-errors).

Por exemplo, dois segmentos com chaves diferentes e filtros idênticos
retornam:

```json theme={null}
{
  "error": "product analytics segment filters must be unique",
  "code": "validation_failed",
  "next": "change at least one exact service_name, release, environment, or property filter",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

Um rótulo diferente ou outra ordem dos filtros de propriedade não muda os
eventos selecionados. Uma falha de validação não é evidência de que nenhum
evento corresponde.

Uma requisição `GET` retorna `405`:

```json theme={null}
{
  "error": "Method not allowed",
  "code": "method_not_allowed",
  "next": "send POST /api/telemetry/analytics/segments/compare with project_id, since, one exact target, two through four named segments, and optional until, interval, analysis_unit, property_filters, or response_version JSON fields",
  "next_action": { "code": "use_supported_method", "target": "api_method" }
}
```

## Resposta de volume de sinais

`GET /api/telemetry/summary/volume` conta os sinais retidos de um projeto em um
período. A rota exige `project_id` e `since`. Ela não aceita `project_ids`.

`until` não pode estar no futuro. Se você o omitir, o fim é o horário da
requisição. Um `since` compacto, como `24h`, conta para trás a partir de
`until`. `interval` é `auto`, `1m`, `5m`, `15m`, `1h`, `6h` ou `1d`. O padrão
`auto` escolhe a menor largura de intervalo com no máximo 120 intervalos. Uma
requisição não pode gerar mais de 500 intervalos. O único `response_version`
é `1`.

### Contagens de sinais

Esta resposta fictícia cobre dois intervalos de um minuto. A requisição foi
feita às 12:02 UTC, sem `until`. A conta tem uma política de retenção de 30
dias. Leia a política e a data de corte retornadas. Não presuma que esses
valores valem para a sua conta.

```json theme={null}
{
  "schema_version": 1,
  "query": {
    "project_id": "11111111-1111-4111-8111-111111111111",
    "requested_since": "2026-09-08T12:00:00Z",
    "since": "2026-09-08T12:00:00Z",
    "until": "2026-09-08T12:02:00Z",
    "interval": "1m",
    "interval_seconds": 60,
    "bucket_alignment": "query_relative_utc_half_open",
    "bucket_count": 2,
    "service_name": "checkout-api",
    "release": "api@1.2.3",
    "environment": "production"
  },
  "purpose": "Compares retained issue occurrences, log events, unique traces, action events, and metric points over one exact project and time scope. Every lane is independently scalable, uses explicit zero-filled half-open buckets, returns no source telemetry rows, and qualifies retention and sampling so different signal volumes are not mistaken for equivalent impact.",
  "series": [
    {
      "signal": "issues",
      "count_unit": "issue_occurrences",
      "total": 1,
      "peak": 1,
      "non_empty_buckets": 1,
      "points": [
        { "bucket_start": "2026-09-08T12:00:00Z", "bucket_end": "2026-09-08T12:01:00Z", "count": 1 },
        { "bucket_start": "2026-09-08T12:01:00Z", "bucket_end": "2026-09-08T12:02:00Z", "count": 0 }
      ]
    },
    {
      "signal": "logs",
      "count_unit": "log_events",
      "total": 3,
      "peak": 2,
      "non_empty_buckets": 2,
      "points": [
        { "bucket_start": "2026-09-08T12:00:00Z", "bucket_end": "2026-09-08T12:01:00Z", "count": 2 },
        { "bucket_start": "2026-09-08T12:01:00Z", "bucket_end": "2026-09-08T12:02:00Z", "count": 1 }
      ]
    },
    {
      "signal": "traces",
      "count_unit": "unique_traces_by_first_observed_span",
      "total": 1,
      "peak": 1,
      "non_empty_buckets": 1,
      "points": [
        { "bucket_start": "2026-09-08T12:00:00Z", "bucket_end": "2026-09-08T12:01:00Z", "count": 1 },
        { "bucket_start": "2026-09-08T12:01:00Z", "bucket_end": "2026-09-08T12:02:00Z", "count": 0 }
      ]
    },
    {
      "signal": "actions",
      "count_unit": "action_events",
      "total": 1,
      "peak": 1,
      "non_empty_buckets": 1,
      "points": [
        { "bucket_start": "2026-09-08T12:00:00Z", "bucket_end": "2026-09-08T12:01:00Z", "count": 1 },
        { "bucket_start": "2026-09-08T12:01:00Z", "bucket_end": "2026-09-08T12:02:00Z", "count": 0 }
      ]
    },
    {
      "signal": "metrics",
      "count_unit": "metric_points",
      "total": 2,
      "peak": 2,
      "non_empty_buckets": 1,
      "points": [
        { "bucket_start": "2026-09-08T12:00:00Z", "bucket_end": "2026-09-08T12:01:00Z", "count": 0 },
        { "bucket_start": "2026-09-08T12:01:00Z", "bucket_end": "2026-09-08T12:02:00Z", "count": 2 }
      ]
    }
  ],
  "coverage": {
    "storage_evaluation": "complete",
    "output_truncation": "not_truncated",
    "payload_shape": "aggregate_only",
    "count_precision": "exact",
    "integer_safety": "javascript_safe",
    "javascript_safe_integer_max": 9007199254740991,
    "returned_series": 5,
    "returned_points": 10,
    "max_buckets_per_series": 500,
    "retention": {
      "policy_days": 30,
      "cutoff": "2026-08-09T12:02:00Z",
      "window_clipped": false
    },
    "sampling": {
      "server": "not_applied",
      "upstream": "unknown"
    },
    "limitations": ["upstream_sampling_unknown", "release_volume_not_included"]
  }
}
```

### Leia cada contagem na própria unidade

| Sinal | O que `total` conta | Não interprete como |
| - | - | - |
| `issues` | Ocorrências de problemas retidas | Problemas agrupados ou usuários afetados |
| `logs` | Eventos de log retidos | Requisições |
| `traces` | IDs de trace únicos, contados no primeiro span retido de cada um neste período | Spans ou inícios de trace em todo o histórico |
| `actions` | Eventos de ação retidos | Usuários ou sessões |
| `metrics` | Pontos de métrica retidos | A soma dos valores das métricas |

`total` é a soma das contagens dos intervalos da série. `peak` é a maior
contagem de um intervalo. `non_empty_buckets` conta os intervalos com
contagem acima de zero. As cinco séries sempre aparecem nesta ordem. Não
junte contagens de sinais diferentes em uma única pontuação de impacto.

Os intervalos começam em `query.since`. Um intervalo inclui o início e exclui
o fim. O último intervalo pode ser mais curto que a largura escolhida. A
resposta não tem série de contagem de versões. Não interprete
`release_volume_not_included` como zero versões.

### Períodos vazios e encurtados

Se nenhum sinal corresponder, as cinco séries continuam na resposta, e os
pontos delas têm contagens zero explícitas. Uma requisição que falhou é
diferente. Não substitua um erro por um gráfico preenchido com zeros.

Compare `query.requested_since` com `query.since`. Se a retenção encurtar o
período, `coverage.retention.window_clipped` é `true` e `limitations` contém
`retention_window_clipped`. Se nada do período solicitado sobrar,
`query.bucket_count` é `0` e cada série tem um array `points` vazio. Isso não
prova que nenhum evento ocorreu nesse período.

`policy_days` é `null` e `cutoff` é omitido quando nenhum limite de retenção
se aplica. `sampling.upstream` é sempre `unknown`, mesmo quando
`storage_evaluation` é `complete`. Não afirme que a resposta conta todos os
eventos que a aplicação gerou.

### Requisições de volume de sinais rejeitadas

Estas requisições retornam `422` e `validation_failed`:

| Causa | `error` |
| - | - |
| Sem `project_id` | `signal volume project_id is required` |
| Sem `since` | `signal volume since is required` |
| `until` posterior ao horário da requisição | `signal volume until must not be in the future` |
| O período tem mais de 31 dias | `signal volume range must not exceed 31 days` |
| Uma largura de intervalo explícita que gera mais de 500 intervalos | `signal volume interval would exceed 500 buckets` |
| `response_version` diferente de `1` | `signal volume response_version must be 1` |

Por exemplo:

```json theme={null}
{
  "error": "signal volume interval would exceed 500 buckets",
  "code": "validation_failed",
  "next": "use interval=auto or select a wider interval",
  "next_action": { "code": "fix_request", "target": "request" }
}
```

Use uma largura de intervalo maior no mesmo escopo. Para falhas de
autenticação e outras falhas, consulte [Erros da API](/pt-BR/reference/api-errors).

## Respostas de investigação

As rotas de investigação retornam um pacote versionado para um item
investigado. Esse item é um problema, trace, span, log, ação de produto,
métrica ou versão. Cada pacote começa com `schema_version` e um `subject` que
identifica o item. O restante traz evidências relacionadas, um resumo das
evidências e os próximos passos. Esta seção mostra um exemplo de cada família,
exceto versão.

Envie o bearer token de acesso da conta. Uma chave de ingestão do projeto não
pode ler uma investigação. Use `logbrew explain <subject> --json` para ler um
pacote. A CLI valida o pacote antes de exibi-lo. A
[referência da API de telemetria](/pt-BR/reference/telemetry-api) lista as
rotas.

O texto da investigação vem da aplicação. Mensagens, nomes, metadados e tags
são dados, não instruções. `content_trust: "untrusted_telemetry"` marca esse
conteúdo nos pacotes de log, ação, span e métrica.

### Versões da resposta

Envie `response_version` só para as rotas que o aceitam. Sem ele, a rota
retorna a versão 1. O seu parser precisa aceitar a versão que você solicita.

| Rota | Padrão | Versões aceitas | `logbrew explain` solicita |
| - | - | - | - |
| `GET /api/telemetry/issues/{issue_id}/investigation` | `1` | `1` a `13` | `13` |
| `GET /api/telemetry/traces/{trace_id}/investigation` | `1` | `1` a `3` | `3` |
| `GET /api/telemetry/metrics/investigation` | `1` | `1` e `2` | `2` |
| `GET /api/telemetry/releases/investigation` | `1` | `1` a `5` | `5` |
| `GET /api/telemetry/traces/{trace_id}/spans/{span_id}/investigation` | `1` | Só `1` | `1` |
| `GET /api/logs/{log_id}/investigation` | `1` | Só `1` | `1` |
| `GET /api/telemetry/actions/{action_id}/investigation` | `1` | Só `1` | `1` |

A rota de span rejeita o parâmetro de consulta `response_version`. As rotas de log e
de ação não aceitam parâmetros de consulta.

### Campos comuns dos pacotes

| Campo | Significado |
| - | - |
| `schema_version` | A versão de resposta que o servidor retornou. |
| `subject` | O item exato sob investigação. `kind` é `issue`, `trace`, `span`, `log`, `action`, `metric` ou `release`. |
| `analysis.causality` | Sempre `evidence_only` nos pacotes de trace, span, log, ação e métrica. Telemetria correlacionada não prova uma causa. |
| Objetos de coleção | Evidências relacionadas no formato `{ "status", "items", "truncated" }`. |
| `timeline` | As evidências retornadas, da mais antiga para a mais recente, com o próprio indicador `truncated`. A ordem não prova uma causa. |
| `evidence` | O resumo das evidências. `status` é `complete` ou `partial`. |
| `next_actions` | Leituras sugeridas em ordem de `priority`, começando em `1`. Elas ainda não foram executadas. |

Cada coleção relacionada informa um `status` de disponibilidade:

| Status | Significado | Comportamento do cliente |
| - | - | - |
| `available` | A leitura terminou e retornou itens. | Mostre os itens e o indicador `truncated`. |
| `not_linked` | O item investigado não tem identificador para esse vínculo, como um ID de trace. | Explique a falta do vínculo. Não crie um vínculo a partir de horários. |
| `not_found` | A leitura terminou e não encontrou evidências retidas. | Mostre um resultado vazio. |
| `unavailable` | A leitura opcional falhou. O item investigado continua válido. | Mantenha o item visível. Tente novamente mais tarde. Não mostre zero itens como resultado. |

O resumo das evidências tem quatro listas ordenadas de nomes de campos
estáveis: `captured_fields`, `missing_fields`, `redacted_fields` e
`truncated_fields`. `status` só é `complete` quando as três últimas listas
estão vazias. Dado ocultado não é dado não capturado. Dado truncado não é dado
completo. Não preencha um valor ocultado ou truncado.

### Limites da investigação

Estes limites valem para uma resposta. Um indicador `truncated` ou um item em
`truncated_fields` mostra que um limite omitiu dados.

| Evidências | Limite |
| - | - |
| Itens relacionados em uma coleção | 20 |
| Spans retidos lidos para um trace | 1.000 |
| Itens da linha do tempo | 50 nos pacotes de log, ação e span. 100 nos pacotes de trace e métrica. |
| Atributos, propriedades e metadados estruturados | 64 valores escalares, 4 níveis de objetos ou arrays, 16 itens em cada array, 512 caracteres em cada string |
| Período de correlação | 5 minutos antes e depois de um log, de uma ação ou da ocorrência de problema selecionada. Para um trace ou span, 5 minutos antes do início e depois do fim, com no máximo 24 horas. |

A seção de cada família lista os próprios limites.

### Resposta de investigação de problema

Use `GET /api/telemetry/issues/{issue_id}/investigation` para ler as
evidências de uma ocorrência de um problema agrupado. O
[guia de investigação de problemas](/pt-BR/guides/investigate-an-issue) mostra
como ler as evidências em ordem. Solicite a versão 13:

```bash theme={null}
curl --fail-with-body -sS -G \
  "https://api.logbrew.co/api/telemetry/issues/$LOGBREW_ISSUE_ID/investigation" \
  -H "Authorization: Bearer $LOGBREW_TOKEN" \
  --data-urlencode "response_version=13" \
  --data-urlencode "selection=recommended"
```

Os parâmetros de consulta são `response_version`, `selection` e `occurrence_id`.
`selection` é `recommended`, `first` ou `latest`. Os valores diferenciam
maiúsculas de minúsculas. Nas versões de 2 a 13, quando o seletor é omitido,
vale `recommended`. A versão 1 retorna a ocorrência retida mais recente e não
aceita seletor. Os filtros da lista de problemas não valem para esta leitura.

<Accordion title="Exemplo de investigação de problema na versão 13">
  Esta resposta `200 OK` fictícia tem uma ocorrência de `TypeError` tratada, com
  um trace vinculado. Ela não tem requisição, breadcrumbs, logs relacionados nem
  evidências de implantação, então `evidence.status` é `partial`.

  ```json theme={null}
  {
    "schema_version": 13,
    "subject": {
      "kind": "issue", "id": "11111111-1111-4111-8111-111111111111",
      "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
      "fingerprint": "checkout-cart-total", "status": "unresolved", "severity": "error",
      "title": "TypeError",
      "message": "Cannot read properties of undefined (reading 'total')",
      "occurrence_count": 1, "first_seen_at": "2026-08-03T11:05:00Z",
      "last_seen_at": "2026-08-03T11:05:00Z"
    },
    "event": {
      "id": "22222222-2222-4222-8222-222222222222",
      "occurred_at": "2026-08-03T11:05:00Z",
      "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
      "context": {
        "schema_version": 1,
        "resource": {
          "service": null,
          "deployment": null,
          "runtime": {"name": "node", "version": "24.4.0"},
          "framework": null,
          "operating_system": {"name": "Linux", "version": "6.8", "build": null},
          "device": {"family": null, "model": null, "architecture": "arm64"},
          "application": null
        },
        "trace": {
          "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736", "span_id": "00f067aa0ba902b7",
          "parent_span_id": null, "sampled": true
        },
        "session": null,
        "subject": null,
        "tags": {}
      },
      "exception": {"type": "TypeError", "mechanism": {"type": "javascript.error", "handled": true}},
      "exception_chain": {
        "status": "captured",
        "entries": [
          {
            "id": 0,
            "parent_id": null,
            "relationship": "reported",
            "type": "TypeError",
            "message": null,
            "message_state": "redacted",
            "module": null,
            "mechanism": {"type": "javascript.error", "handled": true},
            "stack_frames": [
              {
                "index": 0, "module": null, "function": "cartTotal", "file": "src/cart.ts",
                "line": 42, "column": 17, "in_app": null, "source": "captured"
              },
              {
                "index": 1, "module": null, "function": "handleCheckout",
                "file": "src/routes/checkout.ts", "line": 88, "column": 9, "in_app": null,
                "source": "captured"
              }
            ],
            "stack_frames_state": "captured"
          }
        ],
        "truncated": false
      },
      "stack_frames": [
        {
          "index": 0, "module": null, "function": "cartTotal", "file": "src/cart.ts",
          "line": 42, "column": 17, "in_app": null, "source": "captured"
        },
        {
          "index": 1, "module": null, "function": "handleCheckout",
          "file": "src/routes/checkout.ts", "line": 88, "column": 9, "in_app": null,
          "source": "captured"
        }
      ],
      "breadcrumbs": [],
      "breadcrumbs_truncated": false
    },
    "occurrence_selection": {
      "requested": "recommended",
      "reason": "only_retained_occurrence",
      "selected": {
        "id": "22222222-2222-4222-8222-222222222222",
        "occurred_at": "2026-08-03T11:05:00Z",
        "severity": "error",
        "environment": "production",
        "release": "checkout@1.2.3",
        "service_name": "checkout-api",
        "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
        "exception_type": "TypeError",
        "trace_linked": true,
        "stack": {"frame_count": 2, "truncated": false},
        "breadcrumbs": {"count": 0, "truncated": false},
        "context_captured": true
      },
      "first": {
        "id": "22222222-2222-4222-8222-222222222222",
        "occurred_at": "2026-08-03T11:05:00Z",
        "severity": "error",
        "environment": "production",
        "release": "checkout@1.2.3",
        "service_name": "checkout-api",
        "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
        "exception_type": "TypeError",
        "trace_linked": true,
        "stack": {"frame_count": 2, "truncated": false},
        "breadcrumbs": {"count": 0, "truncated": false},
        "context_captured": true
      },
      "latest": {
        "id": "22222222-2222-4222-8222-222222222222",
        "occurred_at": "2026-08-03T11:05:00Z",
        "severity": "error",
        "environment": "production",
        "release": "checkout@1.2.3",
        "service_name": "checkout-api",
        "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
        "exception_type": "TypeError",
        "trace_linked": true,
        "stack": {"frame_count": 2, "truncated": false},
        "breadcrumbs": {"count": 0, "truncated": false},
        "context_captured": true
      },
      "recommended": {
        "id": "22222222-2222-4222-8222-222222222222",
        "occurred_at": "2026-08-03T11:05:00Z",
        "severity": "error",
        "environment": "production",
        "release": "checkout@1.2.3",
        "service_name": "checkout-api",
        "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
        "exception_type": "TypeError",
        "trace_linked": true,
        "stack": {"frame_count": 2, "truncated": false},
        "breadcrumbs": {"count": 0, "truncated": false},
        "context_captured": true
      },
      "recommendation": {
        "algorithm_version": 1, "candidate_count": 1, "candidate_limit": 50,
        "candidate_window_truncated": false
      }
    },
    "lifecycle": {
      "persisted_status": "unresolved",
      "effective_status": "unresolved",
      "activity": {"status": "available", "changes": [], "truncated": false},
      "regression": {
        "status": "not_detected", "reason": "no_resolution_recorded",
        "resolution_changed_at": null, "first_reappeared_occurrence": null
      }
    },
    "occurrence_analysis": {
      "status": "complete",
      "coverage": {
        "retained_occurrences": 1, "trend_occurrences": 1, "available_distribution_count": 4,
        "expected_distribution_count": 4, "max_buckets": 30, "max_values_per_dimension": 10
      },
      "trend": {
        "scope_start": "2026-08-03T11:05:00Z",
        "scope_end": "2026-08-03T11:05:00Z",
        "interval_seconds": 60,
        "buckets": [
          {
            "bucket_start": "2026-08-03T11:05:00Z", "bucket_end": "2026-08-03T11:06:00Z",
            "occurrence_count": 1
          }
        ]
      },
      "distributions": [
        {
          "dimension": "release",
          "distinct_value_count": 1,
          "values": [
            {
              "value": "checkout@1.2.3", "version": null, "occurrence_count": 1,
              "share_basis_points": 10000
            }
          ],
          "other_occurrence_count": 0
        },
        {
          "dimension": "environment",
          "distinct_value_count": 1,
          "values": [
            {
              "value": "production", "version": null, "occurrence_count": 1,
              "share_basis_points": 10000
            }
          ],
          "other_occurrence_count": 0
        },
        {
          "dimension": "service",
          "distinct_value_count": 1,
          "values": [
            {
              "value": "checkout-api", "version": null, "occurrence_count": 1,
              "share_basis_points": 10000
            }
          ],
          "other_occurrence_count": 0
        },
        {
          "dimension": "sdk",
          "distinct_value_count": 1,
          "values": [
            {
              "value": "@logbrew/node", "version": "0.1.11", "occurrence_count": 1,
              "share_basis_points": 10000
            }
          ],
          "other_occurrence_count": 0
        }
      ],
      "limitations": []
    },
    "grouping": {"strategy": "sdk_fingerprint", "components": ["sdk_fingerprint"], "stack": null},
    "cause": {
      "status": "evidence_only",
      "summary": null,
      "provenance": null,
      "signals": ["handled_exception", "error_trace_span"]
    },
    "fix": {
      "status": "observed_frame",
      "location": {
        "component": null, "module": null, "function": "cartTotal", "file": "src/cart.ts",
        "line": 42, "column": 17, "in_app": null
      },
      "provenance": "backend_observed"
    },
    "source_locator": {
      "status": "not_found",
      "repository_provider": null,
      "repository_full_name": null,
      "component_path": null,
      "revision": null,
      "revision_source": null,
      "repository_relative_file": null,
      "evidence": {
        "status": "partial",
        "captured_fields": ["source.service"],
        "missing_fields": ["source.component"],
        "redacted_fields": [],
        "truncated_fields": []
      }
    },
    "reproduction": {
      "status": "insufficient_evidence",
      "baseline_occurrence_id": "22222222-2222-4222-8222-222222222222",
      "evidence": {
        "status": "partial",
        "captured_fields": [
          "reproduction.baseline_occurrence", "reproduction.code_location",
          "reproduction.expected_failure"
        ],
        "missing_fields": ["reproduction.trigger"],
        "redacted_fields": [],
        "truncated_fields": []
      }
    },
    "impact": {
      "occurrence_count": 1,
      "first_seen_at": "2026-08-03T11:05:00Z",
      "last_seen_at": "2026-08-03T11:05:00Z",
      "affected_users": null,
      "user_impact": {
        "status": "not_captured",
        "known_affected_users": null,
        "count_method": "unavailable",
        "coverage": {
          "retained_occurrences": 1, "indexed_occurrences": 1,
          "historical_unindexed_occurrences": 0, "identified_user_occurrences": 0,
          "anonymous_subject_occurrences": 0, "missing_subject_occurrences": 1,
          "privacy_filtered_subject_occurrences": 0, "index_coverage_basis_points": 10000,
          "identified_user_coverage_basis_points": 0
        },
        "limitations": ["missing_subject_context"]
      },
      "reported": null
    },
    "correlations": {
      "trace": {
        "status": "available",
        "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
        "summary": {
          "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
          "span_count": 1,
          "error_span_count": 1,
          "service_count": 1,
          "project_count": 1,
          "started_at": "2026-08-03T11:04:59.950Z",
          "duration_ms": 180,
          "root_span": {
            "span_id": "00f067aa0ba902b7", "parent_span_id": null, "name": "POST /checkout",
            "operation": "http.server", "status": "error",
            "started_at": "2026-08-03T11:04:59.950Z", "duration_ms": 180,
            "service_name": "checkout-api"
          },
          "slowest_child_span": null,
          "slowest_path": [],
          "error_spans": [
            {
              "span_id": "00f067aa0ba902b7", "parent_span_id": null, "name": "POST /checkout",
              "operation": "http.server", "status": "error",
              "started_at": "2026-08-03T11:04:59.950Z", "duration_ms": 180,
              "service_name": "checkout-api"
            }
          ],
          "services": [
            {
              "service_name": "checkout-api", "span_count": 1, "error_span_count": 1,
              "max_duration_ms": 180
            }
          ],
          "releases": ["checkout@1.2.3"],
          "environments": ["production"]
        },
        "truncated": false
      },
      "logs": {"status": "not_found", "items": [], "truncated": false},
      "actions": {"status": "not_found", "items": [], "truncated": false},
      "metrics": {"status": "not_found", "items": [], "truncated": false},
      "related_issues": {"status": "not_found", "items": [], "truncated": false},
      "release": {
        "release": "checkout@1.2.3", "environment": "production",
        "service_name": "checkout-api", "deployment_status": "not_found"
      }
    },
    "evidence": {
      "status": "partial",
      "captured_fields": [
        "context", "deployment.lookup", "exception", "exception.mechanism", "exception_chain",
        "exception_chain.stack_frames", "grouping", "grouping.components",
        "grouping.strategy", "grouping.strategy_details", "lifecycle.regression",
        "lifecycle.status_history", "likely_fix_area", "occurrence.boundaries",
        "occurrence.distribution.environment", "occurrence.distribution.release",
        "occurrence.distribution.sdk", "occurrence.distribution.service",
        "occurrence.recommendation", "occurrence.selection", "occurrence.trend", "release",
        "sdk", "source_locator", "stack_frames", "trace"
      ],
      "missing_fields": [
        "affected_users", "breadcrumbs", "deployment", "impact", "likely_root_cause",
        "related_actions", "related_issues", "related_logs", "related_metrics", "request",
        "source_locator.complete"
      ],
      "redacted_fields": ["exception_chain.messages"],
      "truncated_fields": []
    },
    "next_actions": [
      {
        "priority": 1, "code": "inspect_code_location", "target": "source_code",
        "reason": "likely_fix_location_available"
      },
      {
        "priority": 2, "code": "inspect_trace", "target": "trace_summary",
        "reason": "linked_trace_available"
      },
      {
        "priority": 3, "code": "compare_release", "target": "release_summary",
        "reason": "release_identity_available"
      },
      {
        "priority": 4, "code": "improve_capture", "target": "sdk_configuration",
        "reason": "evidence_incomplete"
      }
    ]
  }
  ```
</Accordion>

| Campo | Versão | Significado |
| - | - | - |
| `subject` | 1 | O problema agrupado. `first_seen_at`, `last_seen_at` e `occurrence_count` descrevem o grupo. |
| `event` | 1 | A ocorrência selecionada: SDK, `context`, `exception`, `stack_frames` e `breadcrumbs`. Na versão 1, é `null` quando nenhuma ocorrência mais recente pode ser lida. |
| `cause` | 1 | `status` é `reported_hypothesis`, `evidence_only` ou `unknown`. `signals` lista os sinais observados. |
| `fix` | 1 | Um local no código. `status` é `reported_location`, `observed_application_frame`, `observed_frame`, `observed_underlying_exception_frame` ou `unknown`. |
| `impact` | 1 | Contagens de ocorrências e `user_impact`. `reported` traz o impacto informado pela aplicação, ou `null`. |
| `correlations` | 1 | `trace`, `logs`, `actions`, `metrics` e `release`. |
| `occurrence_selection` | 2 | O seletor solicitado, o motivo e resumos das ocorrências selecionada, primeira, mais recente e recomendada. |
| `lifecycle` | 3 | `persisted_status`, `effective_status`, a atividade de status e `regression`. `effective_status` pode ser `regressed`. |
| `occurrence_analysis` | 4 | A tendência de ocorrências e as distribuições por versão, ambiente, serviço e SDK. |
| `event.exception_chain` | 5 | Até 8 exceções vinculadas. `relationship` é `reported`, `cause`, `context`, `aggregate_member` ou `suppressed`. |
| `event.request` | 6 | `method`, `route_template` e `response_status_code`. A chave não aparece quando nenhuma requisição foi capturada. |
| `grouping` | 7 | A `strategy` de agrupamento, os `components` dela e o uso de frames da pilha. |
| `correlations.release.deployment_status` | 8 | O estado da busca pela implantação. `deployment`, `time_since_deployment_ms` e `deployment_causality` só aparecem quando uma implantação foi encontrada. |
| `correlations.related_issues` | 9 | Outros problemas no mesmo trace. |
| `source_locator` | 10 | Repositório, componente, revisão e arquivo relativo ao repositório, quando o LogBrew consegue vinculá-los. |
| `reproduction` | 11 | `status` é `ready`, `partial` ou `insufficient_evidence`. |
| `next_actions` com o código `verify_correction` | 12 | Aparece quando `reproduction.status` é `ready`. |
| `impact.user_impact.count_method` | 13 | Informa uma contagem distinta aproximada como `approximate_distinct`. Versões anteriores usam um nome de valor mais antigo. `unavailable` significa que não há contagem. |

As chaves de uma versão posterior não aparecem em uma versão anterior. Não
interprete uma chave ausente como `null`.

`subject.status` e os status de `lifecycle` informam um problema arquivado
como `ignored`. As respostas de lista e de detalhe de problemas usam
`archived` a partir da versão de resposta 2.

Limites de problemas: a recomendação lê no máximo 50 ocorrências retidas. A
tendência tem no máximo 30 intervalos. Cada distribuição retorna no máximo 10
valores. Uma pilha tem no máximo 32 frames.

#### Erros de requisição da investigação de problema

Use `selection` ou `occurrence_id`. Não envie os dois, mesmo quando eles
selecionam a mesma ocorrência:

```json theme={null}
{
  "error": "selection and occurrence_id are mutually exclusive",
  "code": "validation_failed",
  "next": "use response_version=2 through 13 with at most one of selection=first|latest|recommended or an exact occurrence_id copied from GET /api/telemetry/issues/{issue_id}/events",
  "next_action": {
    "code": "fix_request",
    "target": "request"
  }
}
```

| HTTP | `error` | Causa | Recuperação |
| - | - | - | - |
| `422` | `selection and occurrence_id are mutually exclusive` | A requisição tem os dois seletores. | Mantenha um seletor. |
| `422` | `issue occurrence selection requires response_version=2 through 13` | A requisição tem um seletor e a versão 1, ou nenhuma versão. | Envie `response_version=13`. Mantenha o seletor. |
| `422` | `issue investigation response_version must be 1 through 13` | A versão está fora da faixa. | Envie uma versão aceita. |
| `422` | `invalid query parameters` | Um parâmetro desconhecido, um UUID inválido, uma versão que não é um número inteiro ou um valor de `selection` desconhecido. | Corrija a [consulta](/pt-BR/reference/api-errors#invalid-query-parameters). |
| `404` | `issue occurrence not found` | A ocorrência não está no histórico retido deste grupo. | Copie o ID da ocorrência dos eventos deste problema. Não use `latest` ou `recommended` no lugar dele sem aprovação. |
| `404` | `issue not found` | Nenhum projeto que a conta pode ler tem este problema. | Confira a conta e o UUID do problema. Não envie o UUID de uma ocorrência como ID do problema. |

Uma ocorrência inexistente não significa que o problema não existe. Um `404`
não mostra se outra conta pode ler o problema.

### Resposta de investigação de trace

Use `GET /api/telemetry/traces/{trace_id}/investigation` para ler um trace com
o caminho da falha, o caminho mais lento e os sinais relacionados. Os parâmetros
de consulta são `response_version`, `project_id`, `release` e `environment`.
Todos são opcionais. Solicite a versão 3:

```bash theme={null}
curl --fail-with-body -sS -G \
  "https://api.logbrew.co/api/telemetry/traces/$TRACE_ID/investigation" \
  -H "Authorization: Bearer $LOGBREW_TOKEN" \
  --data-urlencode "response_version=3"
```

A versão 2 adiciona `cause` e `fix` a cada problema relacionado. A versão 3
adiciona `span_id` aos problemas, ações e métricas relacionados quando ele foi
capturado.

<Accordion title="Exemplo de investigação de trace na versão 3">
  Esta resposta fictícia tem um span raiz de servidor e um span de cliente com
  falha. O span com falha também é o span filho mais lento. Os spans não têm
  contexto estruturado, então `spans.context` fica como não capturado.

  ```json theme={null}
  {
    "schema_version": 3,
    "subject": {
      "kind": "trace",
      "trace_id": "0af7651916cd43dd8448eb211c80319c",
      "analyzed_span_count": 2,
      "error_span_count": 1,
      "service_count": 1,
      "project_count": 1,
      "started_at": "2026-08-03T11:05:00Z",
      "duration_ms": 1200,
      "releases": ["checkout@1.2.3"],
      "environments": ["production"]
    },
    "analysis": {
      "status": "errors_observed",
      "causality": "evidence_only",
      "root_span": {
        "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
        "operation": "http.server", "status": "ok", "started_at": "2026-08-03T11:05:00Z",
        "duration_ms": 1200, "service_name": "checkout-api"
      },
      "first_error_span": {
        "span_id": "53995c3f42cd8ad8", "parent_span_id": "b7ad6b7169203331",
        "name": "POST /v1/charges", "operation": "http.client", "status": "error",
        "started_at": "2026-08-03T11:05:00.100Z", "duration_ms": 900,
        "service_name": "checkout-api"
      },
      "first_error_path": [
        {
          "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
          "operation": "http.server", "status": "ok", "started_at": "2026-08-03T11:05:00Z",
          "duration_ms": 1200, "service_name": "checkout-api"
        },
        {
          "span_id": "53995c3f42cd8ad8", "parent_span_id": "b7ad6b7169203331",
          "name": "POST /v1/charges", "operation": "http.client", "status": "error",
          "started_at": "2026-08-03T11:05:00.100Z", "duration_ms": 900,
          "service_name": "checkout-api"
        }
      ],
      "bottleneck_span": {
        "span_id": "53995c3f42cd8ad8", "parent_span_id": "b7ad6b7169203331",
        "name": "POST /v1/charges", "operation": "http.client", "status": "error",
        "started_at": "2026-08-03T11:05:00.100Z", "duration_ms": 900,
        "service_name": "checkout-api"
      },
      "bottleneck_path": [
        {
          "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
          "operation": "http.server", "status": "ok", "started_at": "2026-08-03T11:05:00Z",
          "duration_ms": 1200, "service_name": "checkout-api"
        },
        {
          "span_id": "53995c3f42cd8ad8", "parent_span_id": "b7ad6b7169203331",
          "name": "POST /v1/charges", "operation": "http.client", "status": "error",
          "started_at": "2026-08-03T11:05:00.100Z", "duration_ms": 900,
          "service_name": "checkout-api"
        }
      ]
    },
    "spans": {
      "items": [
        {
          "id": "33333333-3333-4333-8333-333333333333",
          "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
          "span_id": "b7ad6b7169203331",
          "parent_span_id": null,
          "name": "POST /checkout",
          "operation": "http.server",
          "status": "ok",
          "started_at": "2026-08-03T11:05:00Z",
          "duration_ms": 1200,
          "service_name": "checkout-api",
          "environment": "production",
          "release": "checkout@1.2.3",
          "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
          "context": null,
          "roles": ["root", "error_path", "bottleneck_path", "slow"]
        },
        {
          "id": "44444444-4444-4444-8444-444444444444",
          "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
          "span_id": "53995c3f42cd8ad8",
          "parent_span_id": "b7ad6b7169203331",
          "name": "POST /v1/charges",
          "operation": "http.client",
          "status": "error",
          "started_at": "2026-08-03T11:05:00.100Z",
          "duration_ms": 900,
          "service_name": "checkout-api",
          "environment": "production",
          "release": "checkout@1.2.3",
          "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
          "context": null,
          "roles": ["first_error", "error_path", "bottleneck", "bottleneck_path", "error", "slow"]
        }
      ],
      "truncated": false
    },
    "correlations": {
      "window": {
        "since": "2026-08-03T11:00:00Z",
        "until": "2026-08-03T11:10:01.200Z",
        "scopes": [
          {
            "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "environment": "production",
            "release": "checkout@1.2.3"
          }
        ],
        "truncated": false
      },
      "issues": {"status": "not_found", "items": [], "truncated": false},
      "logs": {
        "status": "available",
        "items": [
          {
            "id": "55555555-5555-4555-8555-555555555555",
            "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "severity": "error",
            "source": "payments", "message": "Charge request failed",
            "occurred_at": "2026-08-03T11:05:01Z", "service_name": "checkout-api",
            "span_id": "53995c3f42cd8ad8", "environment": "production",
            "release": "checkout@1.2.3"
          }
        ],
        "truncated": false
      },
      "actions": {"status": "not_found", "items": [], "truncated": false},
      "metrics": {"status": "not_found", "items": [], "truncated": false}
    },
    "timeline": {
      "items": [
        {
          "id": "b7ad6b7169203331", "kind": "span", "occurred_at": "2026-08-03T11:05:00Z",
          "name": "POST /checkout", "service_name": "checkout-api",
          "span_id": "b7ad6b7169203331", "severity": null, "status": "ok",
          "duration_ms": 1200
        },
        {
          "id": "53995c3f42cd8ad8", "kind": "span", "occurred_at": "2026-08-03T11:05:00.100Z",
          "name": "POST /v1/charges", "service_name": "checkout-api",
          "span_id": "53995c3f42cd8ad8", "severity": null, "status": "error",
          "duration_ms": 900
        },
        {
          "id": "55555555-5555-4555-8555-555555555555", "kind": "log",
          "occurred_at": "2026-08-03T11:05:01Z", "name": "Charge request failed",
          "service_name": "checkout-api", "span_id": "53995c3f42cd8ad8", "severity": "error",
          "status": null, "duration_ms": null
        }
      ],
      "truncated": false
    },
    "evidence": {
      "status": "partial",
      "captured_fields": [
        "correlations.window", "related_actions", "related_issues", "related_logs",
        "related_metrics", "spans.sdk", "timeline", "trace.parentage", "trace.root",
        "trace.spans"
      ],
      "missing_fields": ["spans.context"],
      "redacted_fields": [],
      "truncated_fields": []
    },
    "next_actions": [
      {
        "priority": 1, "code": "inspect_first_error_span", "target": "trace_span",
        "reason": "error_span_observed", "span_id": "53995c3f42cd8ad8", "issue_id": null
      },
      {
        "priority": 2, "code": "review_related_logs", "target": "telemetry_logs",
        "reason": "related_logs_available", "span_id": "53995c3f42cd8ad8", "issue_id": null
      },
      {
        "priority": 3, "code": "compare_release", "target": "release_summary",
        "reason": "release_identity_available", "span_id": null, "issue_id": null
      },
      {
        "priority": 4, "code": "improve_capture", "target": "sdk_configuration",
        "reason": "evidence_incomplete", "span_id": null, "issue_id": null
      }
    ]
  }
  ```
</Accordion>

| Campo | Significado |
| - | - |
| `subject` | Totais do trace, a partir dos spans analisados. |
| `analysis.status` | `errors_observed`, `latency_focus` ou `no_error_observed`. |
| `analysis.first_error_path` | A cadeia conhecida de spans pai, da raiz até o span de erro mais antigo. |
| `analysis.bottleneck_path` | A cadeia conhecida de spans pai até o span filho mais lento. |
| `spans.items[].roles` | Por que o span está na prévia: `root`, `first_error`, `error_path`, `bottleneck`, `bottleneck_path`, `error` ou `slow`. |
| `correlations.window` | O período e os escopos de implantação usados nas leituras relacionadas. |
| `correlations.issues`, `logs`, `actions`, `metrics` | Sinais com o mesmo ID de trace no período. |

`trace.parentage` fica como não capturado quando um span indica um pai que o
LogBrew não reteve. A prévia de spans tem no máximo 64 spans. Cada caminho de
análise tem no máximo 64 spans. As leituras relacionadas usam no máximo 8
escopos de implantação.

Um próximo passo com o destino `trace_span` indica um `span_id` deste pacote.
Para ler esse span, chame a rota de span com o `project_id`, o `environment` e
o `release` do span.

### Resposta de investigação de span

Use `GET /api/telemetry/traces/{trace_id}/spans/{span_id}/investigation` para
ler uma operação de um trace. Envie `project_id`, `environment` e `release`.
Os três são obrigatórios. Copie-os do span selecionado. Não envie o `id` da
linha do span como `span_id`.

```bash theme={null}
curl --fail-with-body -sS -G \
  "https://api.logbrew.co/api/telemetry/traces/$TRACE_ID/spans/$SPAN_ID/investigation" \
  -H "Authorization: Bearer $LOGBREW_TOKEN" \
  --data-urlencode "project_id=$PROJECT_ID" \
  --data-urlencode "environment=production" \
  --data-urlencode "release=checkout@1.2.3"
```

<Accordion title="Exemplo de investigação de span">
  Esta resposta fictícia descreve o span de cliente com falha do exemplo de
  trace. Um log de erro tem o mesmo ID de span. O span demorou mais que o
  percentil 95 aproximado dos spans semelhantes retidos.

  ```json theme={null}
  {
    "schema_version": 1,
    "subject": {
      "kind": "span",
      "id": "44444444-4444-4444-8444-444444444444",
      "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
      "trace_id": "0af7651916cd43dd8448eb211c80319c",
      "span_id": "53995c3f42cd8ad8",
      "parent_span_id": "b7ad6b7169203331",
      "name": "POST /v1/charges",
      "operation": "http.client",
      "status": "error",
      "started_at": "2026-08-03T11:05:00.100Z",
      "duration_ms": 900,
      "service_name": "checkout-api",
      "environment": "production",
      "release": "checkout@1.2.3",
      "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
      "content_trust": "untrusted_telemetry"
    },
    "context": null,
    "payload": {
      "metadata": {
        "values": {"provider": "example-pay"},
        "included_leaf_count": 1,
        "redacted": false,
        "truncated": false
      },
      "events": [],
      "links": [],
      "included_leaf_count": 1,
      "redacted": false,
      "truncated": false
    },
    "analysis": {
      "status": "error_evidence",
      "causality": "evidence_only",
      "observations": ["subject_error", "exact_span_error_log", "subject_at_or_above_peer_p95"]
    },
    "topology": {
      "status": "available",
      "root": {
        "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
        "operation": "http.server", "status": "ok", "started_at": "2026-08-03T11:05:00Z",
        "duration_ms": 1200, "service_name": "checkout-api"
      },
      "parent": {
        "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
        "operation": "http.server", "status": "ok", "started_at": "2026-08-03T11:05:00Z",
        "duration_ms": 1200, "service_name": "checkout-api"
      },
      "ancestors": [
        {
          "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
          "operation": "http.server", "status": "ok", "started_at": "2026-08-03T11:05:00Z",
          "duration_ms": 1200, "service_name": "checkout-api"
        }
      ],
      "children": [],
      "descendant_count": 0,
      "cross_service_edges": [],
      "parent_chain_status": "complete",
      "truncated": false
    },
    "baseline": {
      "status": "available",
      "since": "2026-08-02T11:05:00.100Z",
      "until": "2026-08-03T11:05:00.100Z",
      "dimensions": {
        "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "environment": "production",
        "release": "checkout@1.2.3", "service_name": "checkout-api",
        "operation": "http.client", "name": "POST /v1/charges"
      },
      "retained_peer_count": 40,
      "error_peer_count": 2,
      "error_rate_basis_points": 500,
      "p50_duration_ms": 310.0,
      "p95_duration_ms": 620.0,
      "p99_duration_ms": 940.0,
      "subject_percentile_basis_points": 9500,
      "method": "approximate_t_digest",
      "limitations": [
        "retained_telemetry_only", "sampling_may_apply", "approximate_percentiles",
        "same_release_only"
      ]
    },
    "correlations": {
      "trace": {
        "status": "available",
        "summary": {
          "trace_id": "0af7651916cd43dd8448eb211c80319c",
          "span_count": 2,
          "error_span_count": 1,
          "service_count": 1,
          "project_count": 1,
          "started_at": "2026-08-03T11:05:00Z",
          "duration_ms": 1200,
          "root_span": {
            "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
            "operation": "http.server", "status": "ok", "started_at": "2026-08-03T11:05:00Z",
            "duration_ms": 1200, "service_name": "checkout-api"
          },
          "slowest_child_span": {
            "span_id": "53995c3f42cd8ad8", "parent_span_id": "b7ad6b7169203331",
            "name": "POST /v1/charges", "operation": "http.client", "status": "error",
            "started_at": "2026-08-03T11:05:00.100Z", "duration_ms": 900,
            "service_name": "checkout-api"
          },
          "slowest_path": [
            {
              "span_id": "b7ad6b7169203331", "parent_span_id": null, "name": "POST /checkout",
              "operation": "http.server", "status": "ok",
              "started_at": "2026-08-03T11:05:00Z", "duration_ms": 1200,
              "service_name": "checkout-api"
            },
            {
              "span_id": "53995c3f42cd8ad8", "parent_span_id": "b7ad6b7169203331",
              "name": "POST /v1/charges", "operation": "http.client", "status": "error",
              "started_at": "2026-08-03T11:05:00.100Z", "duration_ms": 900,
              "service_name": "checkout-api"
            }
          ],
          "error_spans": [
            {
              "span_id": "53995c3f42cd8ad8", "parent_span_id": "b7ad6b7169203331",
              "name": "POST /v1/charges", "operation": "http.client", "status": "error",
              "started_at": "2026-08-03T11:05:00.100Z", "duration_ms": 900,
              "service_name": "checkout-api"
            }
          ],
          "services": [
            {
              "service_name": "checkout-api", "span_count": 2, "error_span_count": 1,
              "max_duration_ms": 1200
            }
          ],
          "releases": ["checkout@1.2.3"],
          "environments": ["production"]
        },
        "truncated": false
      },
      "issues": {"status": "not_found", "items": [], "truncated": false},
      "logs": {
        "status": "available",
        "items": [
          {
            "id": "55555555-5555-4555-8555-555555555555",
            "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "severity": "error",
            "source": "payments", "message": "Charge request failed",
            "occurred_at": "2026-08-03T11:05:01Z", "service_name": "checkout-api",
            "span_id": "53995c3f42cd8ad8", "environment": "production",
            "release": "checkout@1.2.3"
          }
        ],
        "truncated": false
      },
      "actions": {"status": "not_found", "items": [], "truncated": false},
      "metrics": {"status": "not_found", "items": [], "truncated": false},
      "release": {
        "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "release": "checkout@1.2.3",
        "environment": "production", "service_name": "checkout-api"
      }
    },
    "timeline": {
      "items": [
        {
          "id": "53995c3f42cd8ad8:start", "kind": "span_start",
          "occurred_at": "2026-08-03T11:05:00.100Z", "offset_ms": 0,
          "name": "POST /v1/charges", "service_name": "checkout-api",
          "span_id": "53995c3f42cd8ad8", "severity": null, "status": "error",
          "duration_ms": 900
        },
        {
          "id": "55555555-5555-4555-8555-555555555555", "kind": "log",
          "occurred_at": "2026-08-03T11:05:01Z", "offset_ms": 900, "name": "payments",
          "service_name": "checkout-api", "span_id": "53995c3f42cd8ad8", "severity": "error",
          "status": null, "duration_ms": null
        },
        {
          "id": "53995c3f42cd8ad8:end", "kind": "span_end",
          "occurred_at": "2026-08-03T11:05:01Z", "offset_ms": 900, "name": "POST /v1/charges",
          "service_name": "checkout-api", "span_id": "53995c3f42cd8ad8", "severity": null,
          "status": "error", "duration_ms": 900
        }
      ],
      "truncated": false
    },
    "evidence": {
      "status": "partial",
      "captured_fields": [
        "attributes.metadata.provider", "baseline", "correlations.actions",
        "correlations.issues", "correlations.logs", "correlations.metrics",
        "correlations.trace", "subject.content_trust", "subject.deployment",
        "subject.identity", "subject.sdk", "subject.timing", "topology"
      ],
      "missing_fields": ["context"],
      "redacted_fields": [],
      "truncated_fields": []
    },
    "next_actions": [
      {
        "priority": 1, "code": "inspect_parent_span", "target": "span_investigation",
        "reason": "parent_context_available", "span_id": "b7ad6b7169203331", "issue_id": null
      },
      {
        "priority": 2, "code": "review_exact_span_logs", "target": "telemetry_logs",
        "reason": "exact_span_logs_available", "span_id": "53995c3f42cd8ad8",
        "issue_id": null
      },
      {
        "priority": 3, "code": "inspect_trace", "target": "trace_investigation",
        "reason": "trace_context_available", "span_id": "53995c3f42cd8ad8", "issue_id": null
      },
      {
        "priority": 4, "code": "compare_peer_baseline", "target": "peer_baseline",
        "reason": "subject_latency_elevated", "span_id": "53995c3f42cd8ad8", "issue_id": null
      },
      {
        "priority": 5, "code": "compare_release", "target": "release_investigation",
        "reason": "exact_release_available", "span_id": null, "issue_id": null
      },
      {
        "priority": 6, "code": "improve_capture", "target": "sdk_capture",
        "reason": "capture_incomplete", "span_id": "53995c3f42cd8ad8", "issue_id": null
      }
    ]
  }
  ```
</Accordion>

| Campo | Significado |
| - | - |
| `payload` | O `metadata` do span, até 8 `events` e até 8 `links`. Os três dividem um limite de 64 valores. |
| `analysis.observations` | `subject_error`, `child_error`, `exact_span_error_log`, `related_issue`, `subject_at_or_above_peer_p95` ou `subject_at_or_above_peer_p99`. |
| `topology` | `root`, `parent`, `ancestors`, os `children` diretos, `descendant_count` e `cross_service_edges`. |
| `topology.parent_chain_status` | `root`, `complete`, `missing`, `cycle`, `truncated` ou `unavailable`. |
| `baseline` | Spans anteriores com o mesmo projeto, ambiente, versão, serviço, operação e nome. |
| `correlations.logs` | Logs com o mesmo ID de trace e o mesmo ID de span. |
| `correlations.issues`, `actions`, `metrics` | Sinais com o mesmo ID de trace no mesmo projeto, ambiente e versão. |
| `timeline[].offset_ms` | Milissegundos desde o início do span. Um valor negativo indica um momento anterior ao span. |

A linha de base lê as 24 horas antes do início do span. `since` é inclusivo e
`until` é exclusivo. `error_rate_basis_points: 500` significa 5%.
`subject_percentile_basis_points: 9500` significa que 95% dos spans
semelhantes retidos não demoraram mais que este span. Os percentis são
aproximados. Mantenha `baseline.limitations` junto com os valores. Uma linha de
base `not_found` não tem spans semelhantes retidos. Uma linha de base
`unavailable` é uma leitura que falhou, não uma contagem zero.

`parent_chain_status: "complete"` significa que a cadeia retida chega a uma
raiz. Isso não prova que o LogBrew reteve todos os spans da requisição. A
topologia retorna no máximo 64 ancestrais, 50 filhos diretos e 50 ligações
entre serviços.

| HTTP | `error` | Recuperação |
| - | - | - |
| `422` | `trace_id must be a non-zero 32-character hexadecimal value` | Copie o `trace_id` de uma resposta de trace do LogBrew. |
| `422` | `span_id must be a non-zero 16-character hexadecimal value` | Copie o `span_id` de uma resposta de trace do LogBrew. |
| `422` | `environment and release must be non-empty exact span scope values` | Copie o escopo do span selecionado. |
| `422` | `invalid query parameters` | Envie `project_id`, `environment` e `release`, e nenhuma outra chave. |
| `404` | `span not found` | Confira os IDs, o projeto, o ambiente e a versão. |

### Resposta de investigação de log

Use `GET /api/logs/{log_id}/investigation` para ler um log e as evidências
relacionadas. Esta rota não tem parâmetros de consulta. Copie o ID do log de uma
lista de logs.

```bash theme={null}
curl --fail-with-body -sS \
  "https://api.logbrew.co/api/logs/$LOG_ID/investigation" \
  -H "Authorization: Bearer $LOGBREW_TOKEN"
```

A leitura pode retornar evidências fora dos filtros da lista de logs. As
leituras relacionadas usam o projeto, o ambiente e a versão do log, e 5
minutos antes e depois do log. Os logs próximos também usam o mesmo serviço.
Eles não precisam de ID de trace. As leituras pelo trace exato precisam do ID
de trace do log e podem incluir outros serviços. O resumo do trace usa o mesmo
ID de trace e o mesmo escopo, sem o período.

<Accordion title="Exemplo de investigação de log">
  Esta resposta fictícia tem um log de aviso sem contexto de trace e um log
  próximo. A resposta não cria um vínculo de trace a partir dos horários.

  ```json theme={null}
  {
    "schema_version": 1,
    "subject": {
      "kind": "log",
      "id": "66666666-6666-4666-8666-666666666666",
      "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
      "severity": "warning",
      "content_trust": "untrusted_telemetry",
      "source": "inventory",
      "message": "Inventory update delayed",
      "occurred_at": "2026-08-03T12:00:00Z",
      "service_name": "checkout-api",
      "environment": "production",
      "release": "checkout@1.2.3",
      "sdk": {"name": "@logbrew/node", "version": "0.1.11"}
    },
    "context": null,
    "attributes": {
      "values": {"retry_count": 2},
      "included_leaf_count": 1,
      "redacted": false,
      "truncated": false
    },
    "analysis": {
      "status": "warning_evidence",
      "causality": "evidence_only",
      "observations": ["subject_warning"]
    },
    "correlations": {
      "trace": {
        "status": "not_linked", "trace_id": null, "span_id": null, "exact_span": null,
        "summary": null, "truncated": false
      },
      "issues": {"status": "not_linked", "items": [], "truncated": false},
      "trace_logs": {"status": "not_linked", "items": [], "truncated": false},
      "nearby_logs": {
        "status": "available",
        "items": [
          {
            "id": "77777777-7777-4777-8777-777777777777",
            "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "severity": "info",
            "source": "inventory", "message": "Inventory retry started",
            "occurred_at": "2026-08-03T11:59:58Z", "service_name": "checkout-api",
            "trace_id": null, "span_id": null, "environment": "production",
            "release": "checkout@1.2.3", "relationship": "nearby_scope"
          }
        ],
        "truncated": false
      },
      "actions": {"status": "not_linked", "items": [], "truncated": false},
      "metrics": {"status": "not_linked", "items": [], "truncated": false},
      "release": {
        "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "release": "checkout@1.2.3",
        "environment": "production", "service_name": "checkout-api"
      }
    },
    "timeline": {
      "items": [
        {
          "id": "77777777-7777-4777-8777-777777777777", "kind": "log",
          "relationship": "nearby_scope", "occurred_at": "2026-08-03T11:59:58Z",
          "name": "inventory", "message": "Inventory retry started",
          "service_name": "checkout-api", "span_id": null, "severity": "info", "status": null,
          "duration_ms": null
        },
        {
          "id": "66666666-6666-4666-8666-666666666666", "kind": "log",
          "relationship": "subject", "occurred_at": "2026-08-03T12:00:00Z",
          "name": "inventory", "message": "Inventory update delayed",
          "service_name": "checkout-api", "span_id": null, "severity": "warning",
          "status": null, "duration_ms": null
        }
      ],
      "truncated": false
    },
    "evidence": {
      "status": "partial",
      "captured_fields": [
        "attributes", "attributes.retry_count", "correlations.nearby_logs",
        "correlations.release", "subject.content_trust", "subject.environment", "subject.id",
        "subject.message", "subject.occurred_at", "subject.project_id", "subject.release",
        "subject.sdk.name", "subject.sdk.version", "subject.service_name", "subject.severity",
        "subject.source", "timeline"
      ],
      "missing_fields": ["context", "correlations.trace.trace_id"],
      "redacted_fields": [],
      "truncated_fields": []
    },
    "next_actions": [
      {
        "priority": 1, "code": "review_nearby_logs", "target": "telemetry_logs",
        "reason": "nearby_logs_available", "issue_id": null, "trace_id": null,
        "span_id": null
      },
      {
        "priority": 2, "code": "improve_capture", "target": "sdk_configuration",
        "reason": "evidence_incomplete", "issue_id": null, "trace_id": null, "span_id": null
      },
      {
        "priority": 3, "code": "compare_release", "target": "release_investigation",
        "reason": "release_identity_available", "issue_id": null, "trace_id": null,
        "span_id": null
      }
    ]
  }
  ```
</Accordion>

| Campo | Significado |
| - | - |
| `attributes` | Os atributos estruturados, com limites. `values` não inclui `context`, que fica no campo `context` de nível superior. |
| `analysis.status` | `critical_evidence`, `error_evidence`, `warning_evidence` ou `no_failure_observed`. |
| `correlations.trace` | O ID de trace, o ID de span, `exact_span` e o `summary` do trace. |
| `correlations.trace_logs` | Logs com o mesmo ID de trace. `relationship` é `exact_trace`. |
| `correlations.nearby_logs` | Logs do mesmo serviço no período. `relationship` é `nearby_scope`. Não inclui o log investigado nem os logs do trace exato. |
| `correlations.issues`, `actions`, `metrics` | Sinais com o mesmo ID de trace. |
| `correlations.release` | O escopo de versão para uma investigação de versão. Não contém uma comparação. |
| `timeline[].relationship` | `subject`, `exact_span`, `exact_trace` ou `nearby_scope`. |

Um ID de trace pode estar presente quando o status do trace é `not_found` ou
`unavailable`. Um resumo de trace disponível não garante um `exact_span`.

### Resposta de investigação de ação

Use `GET /api/telemetry/actions/{action_id}/investigation` para ler uma ação
de produto, o status informado dela e as evidências relacionadas. Esta rota
não tem parâmetros de consulta. As leituras relacionadas usam o mesmo período e os
mesmos escopos de uma investigação de log.

```bash theme={null}
curl --fail-with-body -sS \
  "https://api.logbrew.co/api/telemetry/actions/$ACTION_ID/investigation" \
  -H "Authorization: Bearer $LOGBREW_TOKEN"
```

`correlations`, `timeline` e `next_actions` usam os formatos da investigação
de log. As ações relacionadas não incluem a ação investigada.

<Accordion title="Exemplo de investigação de ação">
  Esta resposta fictícia descreve uma ação de checkout que falhou, feita por um
  usuário conectado. A ação não tem ID de trace.

  ```json theme={null}
  {
    "schema_version": 1,
    "subject": {
      "kind": "action",
      "id": "14141414-1414-4141-8141-141414141414",
      "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
      "name": "checkout.submit",
      "status": "failure",
      "content_trust": "untrusted_telemetry",
      "occurred_at": "2026-08-03T11:05:00Z",
      "service_name": "checkout-api",
      "environment": "production",
      "release": "checkout@1.2.3",
      "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
      "subject_classification": "user",
      "session_captured": true
    },
    "context": null,
    "properties": {
      "values": {"plan": "team", "step": "payment"},
      "included_leaf_count": 2,
      "redacted": false,
      "truncated": false
    },
    "analysis": {
      "status": "subject_failure",
      "causality": "evidence_only",
      "observations": ["subject_failure"]
    },
    "correlations": {
      "trace": {
        "status": "not_linked", "trace_id": null, "span_id": null, "exact_span": null,
        "summary": null, "truncated": false
      },
      "issues": {"status": "not_linked", "items": [], "truncated": false},
      "trace_logs": {"status": "not_linked", "items": [], "truncated": false},
      "nearby_logs": {"status": "not_found", "items": [], "truncated": false},
      "actions": {"status": "not_linked", "items": [], "truncated": false},
      "metrics": {"status": "not_linked", "items": [], "truncated": false},
      "release": {
        "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "release": "checkout@1.2.3",
        "environment": "production", "service_name": "checkout-api"
      }
    },
    "timeline": {
      "items": [
        {
          "id": "14141414-1414-4141-8141-141414141414", "kind": "action",
          "relationship": "subject", "occurred_at": "2026-08-03T11:05:00Z",
          "name": "checkout.submit", "message": null, "service_name": "checkout-api",
          "span_id": null, "severity": null, "status": "failure", "duration_ms": null
        }
      ],
      "truncated": false
    },
    "evidence": {
      "status": "partial",
      "captured_fields": [
        "correlations.nearby_logs", "correlations.release", "properties.metadata",
        "properties.metadata.plan", "properties.metadata.step", "subject.content_trust",
        "subject.environment", "subject.id", "subject.name", "subject.occurred_at",
        "subject.project_id", "subject.release", "subject.sdk.name", "subject.sdk.version",
        "subject.service_name", "subject.session_captured", "subject.status",
        "subject.subject_classification", "timeline"
      ],
      "missing_fields": ["context", "correlations.trace.trace_id"],
      "redacted_fields": ["subject.distinct_id", "subject.session_id"],
      "truncated_fields": []
    },
    "next_actions": [
      {
        "priority": 1, "code": "inspect_analytics_paths", "target": "analytics_paths",
        "reason": "session_captured", "issue_id": null, "trace_id": null, "span_id": null
      },
      {
        "priority": 2, "code": "improve_capture", "target": "sdk_configuration",
        "reason": "evidence_incomplete", "issue_id": null, "trace_id": null, "span_id": null
      },
      {
        "priority": 3, "code": "compare_release", "target": "release_investigation",
        "reason": "release_identity_available", "issue_id": null, "trace_id": null,
        "span_id": null
      }
    ]
  }
  ```
</Accordion>

| Campo | Significado |
| - | - |
| `subject.status` | `queued`, `running`, `success`, `failure` ou `null` quando nenhum status compatível foi capturado. |
| `subject.subject_classification` | `user`, `anonymous`, `legacy_unknown`, `missing`, `historical_unindexed` ou `unsupported`. |
| `subject.session_captured` | Se a ação tinha uma sessão. A resposta nunca retorna o ID da sessão. |
| `properties` | O objeto `metadata` da ação, com limites. |
| `analysis.status` | `subject_failure`, `correlated_failure_evidence`, `in_progress`, `success_observed` ou `status_not_captured`. |

A resposta nunca retorna identificadores da identidade nem da sessão. O resumo
das evidências sempre lista `subject.distinct_id` como ocultado, e
`subject.session_id` quando uma sessão foi capturada. Por isso, todo pacote de
ação é `partial` e inclui `improve_capture`. Não remova controles de
privacidade para atender a esse próximo passo.

### Resposta de investigação de métrica

Use `GET /api/telemetry/metrics/investigation` para ler um nome de métrica em
um projeto e um período. A resposta traz a série atual, uma comparação com o
período anterior de mesma duração, a amostra mais recente, exemplares de trace
e as implantações concluídas. A versão 2 adiciona a descrição da métrica a
partir da amostra retida mais recente. A versão 1 sempre informa
`description_status: "not_captured"`.

```bash theme={null}
curl --fail-with-body -sS -G \
  "https://api.logbrew.co/api/telemetry/metrics/investigation" \
  -H "Authorization: Bearer $LOGBREW_TOKEN" \
  --data-urlencode "project_id=$PROJECT_ID" \
  --data-urlencode "name=http.server.duration" \
  --data-urlencode "since=2026-08-02T12:00:00Z" \
  --data-urlencode "until=2026-08-03T12:00:00Z" \
  --data-urlencode "interval=5m" \
  --data-urlencode "group_by=service_name" \
  --data-urlencode "environment=production" \
  --data-urlencode "series_limit=12" \
  --data-urlencode "response_version=2"
```

`project_id`, `name` e `since` são obrigatórios. `since` é inclusivo e `until`
é exclusivo. Por padrão, `until` é o momento atual. A comparação também lê o
período anterior de mesma duração.

<Accordion title="Exemplo de investigação de métrica na versão 2">
  Este histograma fictício tem 5 amostras em dois intervalos de 5 minutos. O
  intervalo mais recente tem p95 de 48 ms. O intervalo mais recente do período
  anterior tem p95 de 24 ms.

  ```json theme={null}
  {
    "schema_version": 2,
    "subject": {
      "kind": "metric", "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
      "name": "http.server.duration", "description_status": "captured",
      "description": "Duration of one completed server request."
    },
    "query": {
      "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "name": "http.server.duration",
      "since": "2026-08-02T12:00:00Z", "until": "2026-08-03T12:00:00Z", "interval": "5m",
      "interval_seconds": 300, "group_by": "service_name", "environment": "production",
      "series_limit": 12
    },
    "purpose": "Explains one metric's latest application-supplied description and bounded change, compares the immediately preceding equal window, exposes one privacy-bounded latest-sample capture context, exact trace/span exemplars, and nearby completed deployments, and keeps every correlation evidence-only rather than claiming an anomaly or root cause.",
    "content_trust": "untrusted_telemetry",
    "analysis": {
      "status": "change_observed",
      "causality": "evidence_only",
      "focus": {
        "comparison_index": 0, "selection": "largest_absolute_relative_change",
        "direction": "increased", "absolute_change": 24.0, "relative_change_percent": 100.0
      }
    },
    "coverage": {
      "samples": 5, "series": 1, "returned_series": 1, "points": 2,
      "expected_buckets_per_series": 288, "first_seen_at": "2026-08-03T11:00:10Z",
      "last_seen_at": "2026-08-03T11:09:50Z", "truncated": false
    },
    "series": [
      {
        "identity": {
          "kind": "histogram", "unit": "ms", "temporality": "delta",
          "group_by": "service_name", "group_value": "checkout-api"
        },
        "status": "ready",
        "aggregation": {
          "code": "distribution_p95",
          "description": "Primary value is the approximate p95 of raw observations in each bucket; p50, p99, range, average, count, and sum preserve distribution context."
        },
        "sample_count": 5,
        "points": [
          {
            "bucket_start": "2026-08-03T11:00:00Z", "bucket_end": "2026-08-03T11:05:00Z",
            "sample_count": 2, "value": 42.0, "min": 42.0, "max": 42.0, "average": 42.0,
            "sum": 84.0, "p50": 42.0, "p95": 42.0, "p99": 42.0, "trace_exemplars": []
          },
          {
            "bucket_start": "2026-08-03T11:05:00Z",
            "bucket_end": "2026-08-03T11:10:00Z",
            "sample_count": 3,
            "value": 48.0,
            "min": 48.0,
            "max": 48.0,
            "average": 48.0,
            "sum": 144.0,
            "p50": 48.0,
            "p95": 48.0,
            "p99": 48.0,
            "trace_exemplars": ["4bf92f3577b34da6a3ce929d0e0e4736"]
          }
        ]
      }
    ],
    "comparison": {
      "status": "available",
      "method": "adjacent_equal_window_latest_bucket",
      "previous_since": "2026-08-01T12:00:00Z",
      "previous_until": "2026-08-02T12:00:00Z",
      "items": [
        {
          "identity": {
            "kind": "histogram", "unit": "ms", "temporality": "delta",
            "group_by": "service_name", "group_value": "checkout-api"
          },
          "aggregation": "distribution_p95",
          "current": {
            "bucket_start": "2026-08-03T11:05:00Z", "bucket_end": "2026-08-03T11:10:00Z",
            "sample_count": 3, "value": 48.0
          },
          "previous": {
            "bucket_start": "2026-08-02T11:55:00Z", "bucket_end": "2026-08-02T12:00:00Z",
            "sample_count": 2, "value": 24.0
          },
          "direction": "increased",
          "absolute_change": 24.0,
          "relative_change_percent": 100.0
        }
      ],
      "truncated": false,
      "limitation": "Each item compares the latest non-empty semantic bucket in adjacent equal-length windows. It is an observed value change, not seasonality-aware anomaly detection or evidence that a deployment caused the change."
    },
    "latest_sample": {
      "status": "available",
      "sample": {
        "id": "dddddddd-dddd-4ddd-8ddd-dddddddddddd",
        "kind": "histogram",
        "value": 48.0,
        "unit": "ms",
        "temporality": "delta",
        "occurred_at": "2026-08-03T11:09:50Z",
        "service_name": "checkout-api",
        "environment": "production",
        "release": "checkout@1.2.3",
        "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
        "span_id": "00f067aa0ba902b7",
        "sdk": {"name": "@logbrew/node", "version": "0.1.11"},
        "context": null,
        "metadata": {"values": {}, "included_leaf_count": 0, "redacted": false, "truncated": false}
      }
    },
    "exemplars": {
      "status": "available",
      "coverage": {
        "matching_samples": 5, "trace_linked_samples": 1, "span_linked_samples": 1,
        "returned_exemplars": 1
      },
      "items": [
        {
          "id": "dddddddd-dddd-4ddd-8ddd-dddddddddddd",
          "value": 48.0,
          "occurred_at": "2026-08-03T11:09:50Z",
          "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
          "span_id": "00f067aa0ba902b7",
          "service_name": "checkout-api",
          "environment": "production",
          "release": "checkout@1.2.3",
          "sdk": {"name": "@logbrew/node", "version": "0.1.11"}
        }
      ],
      "truncated": false
    },
    "deployments": {
      "status": "available",
      "items": [
        {
          "deployment_id": "deploy-123", "release": "checkout@1.2.3",
          "environment": "production", "service_name": "checkout-api", "status": "succeeded",
          "started_at": "2026-08-03T11:02:00Z", "finished_at": "2026-08-03T11:03:00Z",
          "commit_sha": "0123456789abcdef"
        }
      ],
      "truncated": false
    },
    "timeline": {
      "items": [
        {
          "id": "deploy-123", "kind": "deployment_finished",
          "occurred_at": "2026-08-03T11:03:00Z", "value": null, "trace_id": null,
          "span_id": null, "release": "checkout@1.2.3", "service_name": "checkout-api"
        },
        {
          "id": "dddddddd-dddd-4ddd-8ddd-dddddddddddd", "kind": "metric_exemplar",
          "occurred_at": "2026-08-03T11:09:50Z", "value": 48.0,
          "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736", "span_id": "00f067aa0ba902b7",
          "release": "checkout@1.2.3", "service_name": "checkout-api"
        }
      ],
      "truncated": false
    },
    "evidence": {
      "status": "partial",
      "captured_fields": [
        "metric.current_window_coverage", "metric.deployment_overlays", "metric.description",
        "metric.identity", "metric.latest_sample", "metric.latest_sample.kind",
        "metric.latest_sample.occurred_at", "metric.latest_sample.scope",
        "metric.latest_sample.sdk.name", "metric.latest_sample.sdk.version",
        "metric.latest_sample.span_id", "metric.latest_sample.trace_id",
        "metric.latest_sample.value", "metric.prior_window_comparison", "metric.query_scope",
        "metric.series_semantics", "metric.span_exemplars", "metric.trace_exemplars"
      ],
      "missing_fields": ["metric.latest_sample.context", "metric.latest_sample.metadata"],
      "redacted_fields": [],
      "truncated_fields": []
    },
    "next_actions": [
      {
        "priority": 1,
        "code": "inspect_exact_span",
        "target": "span_investigation",
        "reason": "Inspect the exact span that emitted a retained metric exemplar, then review its failure, latency, log, issue, action, and trace evidence.",
        "context": {
          "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
          "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736", "span_id": "00f067aa0ba902b7",
          "environment": "production", "release": "checkout@1.2.3",
          "service_name": "checkout-api"
        }
      },
      {
        "priority": 2,
        "code": "review_deployment",
        "target": "release_investigation",
        "reason": "Review release-scoped telemetry for a completed deployment inside the compared evidence window without treating temporal proximity as causality.",
        "context": {
          "project_id": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa", "trace_id": null,
          "span_id": null, "environment": "production", "release": "checkout@1.2.3",
          "service_name": "checkout-api"
        }
      }
    ]
  }
  ```
</Accordion>

| Campo | Significado |
| - | - |
| `subject.description_status` | `captured`, `not_captured` ou `unavailable`. |
| `query` | A consulta normalizada. `service_name`, `release` e `environment` só aparecem quando foram enviados. |
| `analysis.status` | `no_samples`, `change_observed`, `no_change_observed`, `baseline_not_found` ou `comparison_unavailable`. |
| `analysis.focus` | O item da comparação com a maior variação relativa, ou com a maior variação absoluta quando não há variação relativa. `null` quando nenhum item é comparável. |
| `series[].aggregation.code` | `gauge_last`, `delta_sum`, `distribution_p95`, `raw_cumulative_last` ou `raw_last`. |
| `comparison.status` | `available`, `partial`, `not_found`, `unavailable` ou `no_current_samples`. |
| `comparison.items[]` | O intervalo não vazio mais recente de cada período, para a mesma identidade de série. |
| `latest_sample` | A amostra bruta mais recente, com SDK, `context`, `metadata` e o vínculo de trace. |
| `exemplars` | Amostras brutas com ID de trace. `coverage` conta as amostras vinculadas. |
| `deployments` | Implantações concluídas entre o início do período anterior e `until`. |
| `next_actions[]` | `code`, `target`, um `reason` em texto simples e um escopo `context` para a próxima leitura. |

`relative_change_percent` é `(current - previous) / abs(previous) * 100`. Ele
é `null` quando o valor anterior é zero ou está ausente.
`expected_buckets_per_series` conta os intervalos possíveis, não os intervalos
com dados. Não desenhe intervalos vazios como zero. Uma implantação perto de
uma variação não prova que ela causou a variação.

Um projeto que a conta não pode ler retorna `200 OK` com
`analysis.status: "no_samples"`, não `404`. Um resultado vazio não descreve
outros tipos de sinal.

Limites de métricas: o período tem no máximo 31 dias. Cada série tem no máximo
500 intervalos. `series_limit` vai de 1 a 20, com padrão 10. A resposta
retorna no máximo 20 exemplares e 20 implantações.

| HTTP | `error` | Recuperação |
| - | - | - |
| `422` | `metric investigation response_version must be 1 or 2` | Omita `response_version` ou envie `2`. |
| `422` | `metric series project_id is required` | Envie o ID de um projeto que a conta pode ler. |
| `422` | `metric series name is required` | Copie o nome da lista de métricas. |
| `422` | `metric series since is required` | Envie um valor como `24h` ou um timestamp RFC 3339. |
| `422` | `metric series range must not exceed 31 days` | Use um período menor. |
| `422` | `metric series interval would exceed 500 buckets` | Use `interval=auto` ou um intervalo maior. |
| `422` | `metric series_limit must be between 1 and 20` | Envie um valor de 1 a 20. |

`interval` é `auto`, `1m`, `5m`, `15m`, `1h`, `6h` ou `1d`. `group_by` é
`none`, `service_name`, `release` ou `environment`. Outros valores retornam
`422`.

### Erros de investigação

| HTTP | Rota | `error` |
| - | - | - |
| `404` | Log | `log not found` |
| `404` | Ação | `action not found` |
| `404` | Trace | `trace not found` |
| `422` | Trace | `trace investigation response_version must be 1, 2, or 3` |
| `400` | Log, ação, problema | `invalid URL path parameters` quando o ID no caminho não é um UUID |
| `422` | Problema, trace, span, métrica | `invalid query parameters` para uma chave desconhecida ou um valor do tipo errado |

Um `404` significa que nenhum projeto que a conta pode ler tem o registro.
Cada rota também retorna `401` sem autenticação válida e `405` para um método
diferente de `GET`. Consulte [Erros da API](/pt-BR/reference/api-errors) para
ver as respostas de
[recurso não encontrado](/pt-BR/reference/api-errors#resource-not-found),
[caminho](/pt-BR/reference/api-errors#invalid-path-value),
[autenticação](/pt-BR/reference/api-errors#authentication-failure) e
[método](/pt-BR/reference/api-errors#unsupported-method).

Uma leitura opcional de evidências pode falhar dentro de uma resposta
`200 OK`. Nesse caso, a coleção informa `unavailable`. Não a mostre como
`not_found` nem como zero registros.

## <span id="severity-values">Valores de gravidade</span>

Os valores de gravidade exibidos às pessoas são `info`, `warning`, `error` e
`critical`. SDKs e runtimes podem enviar aliases comuns, como `trace`,
`debug`, `warn` ou `fatal`. As respostas REST e ao vivo sempre retornam o valor
canônico. Por exemplo, o LogBrew aceita `warn` na entrada e retorna `warning`.
A ingestão rejeita valores de gravidade desconhecidos.

| Alias | Valor canônico |
| - | - |
| `trace`, `debug` | `info` |
| `warn` | `warning` |
| `fatal` | `critical` |

## <span id="severity-rule-responses">Respostas de regras de gravidade</span>

Uma regra de gravidade muda como o LogBrew mostra um log ou um problema. Ela
não muda a gravidade que a aplicação capturou. Logs e problemas retornam um
objeto `triage`:

| Campo | Significado |
| - | - |
| `effective_severity` | A gravidade a exibir. Sem regra, é igual a `severity`. |
| `ignored` | `true` quando uma regra de log ignora o log, ou quando o problema está arquivado. |
| `rule_applied` | `true` quando uma regra de gravidade ou o estado ignorado se aplica. `false` é o padrão, não um dado ausente. |

Use `triage.effective_severity` para exibir a gravidade. Mantenha `severity`
como o valor capturado. Por padrão, a lista de logs omite os logs ignorados.
Para incluí-los, envie `status=ignored` ou `status=all` em `GET /api/logs`.

A conta precisa de permissão para gerenciar problemas no projeto. Acesso de
leitura não basta. Sem essa permissão, uma mudança de regra retorna `403` com
`code: forbidden`.

### Altere uma regra de log

`PUT /api/logs/{log_id}/triage-rule` define a regra para o log e para os logs
posteriores com a mesma assinatura. O corpo precisa de `severity` e de
`ignored`:

```bash theme={null}
curl --request PUT "https://api.logbrew.co/api/logs/$LOG_ID/triage-rule" \
  --header "Authorization: Bearer $LOGBREW_ACCOUNT_BEARER" \
  --header "Content-Type: application/json" \
  --data '{ "severity": "info", "ignored": true }'
```

Uma resposta `200 OK` contém o [log](#log-response) completo. O `severity`
dele continua `warning`. O `triage` mostra a regra:

```json theme={null}
{
  "severity": "warning",
  "triage": {
    "effective_severity": "info",
    "ignored": true,
    "rule_applied": true
  }
}
```

Este trecho mostra só os campos alterados. Na requisição, `severity` é
`source`, `info`, `warning`, `error` ou `critical`. `source` restaura a
gravidade capturada. Ele não torna ativo um log ignorado. Para mostrar o log
de novo, envie `"ignored": false`.

### Altere uma regra de problema

`PUT /api/telemetry/issues/{issue_id}/triage-rule` define a gravidade exibida
de um problema agrupado e das ocorrências posteriores dele. O corpo aceita só
`severity`:

```bash theme={null}
curl --request PUT "https://api.logbrew.co/api/telemetry/issues/$ISSUE_ID/triage-rule" \
  --header "Authorization: Bearer $LOGBREW_ACCOUNT_BEARER" \
  --header "Content-Type: application/json" \
  --data '{ "severity": "warning" }'
```

Uma resposta `200 OK` contém o [problema](#issue-response) completo na versão
1 da resposta. O `severity` e o `status` capturados não mudam:

```json theme={null}
{
  "severity": "error",
  "status": "unresolved",
  "triage": {
    "effective_severity": "warning",
    "ignored": false,
    "rule_applied": true
  }
}
```

Este trecho mostra só alguns campos. Uma regra não resolve, não arquiva nem
reabre um problema. Para isso, use a
[mudança de status](#issue-status-response-examples). Uma prioridade derivada
acompanha a nova gravidade efetiva. Para vê-la, leia o problema com
`response_version=2` ou `3`.

Uma gravidade não aceita retorna `422`:

```json theme={null}
{
  "error": "triage severity must be source, info, warning, error, or critical",
  "code": "validation_failed",
  "next": "use source to restore captured severity, or choose info, warning, error, or critical",
  "next_action": {
    "code": "fix_request",
    "target": "request"
  }
}
```

Um campo desconhecido no corpo, como `status` em uma regra de problema,
retorna `422` com `code: invalid_json`. Um log ou problema inexistente, ou que
a conta não pode ler, retorna `404` com `code: not_found`. Se a resposta se
perder, leia o log ou o problema de novo antes de reenviar a regra.

## Formato da resposta de erro

Os erros da aplicação retornam um envelope JSON. Este exemplo mostra uma
requisição rejeitada. O texto de `error` e de `next` varia conforme o erro:

```json theme={null}
{
  "error": "<what is wrong>",
  "code": "validation_failed",
  "next": "<how to fix it>",
  "next_action": {
    "code": "fix_request",
    "target": "request"
  }
}
```

Use `code` para as ramificações do programa e `next_action` para automação.
Mostre `error` e `next` às pessoas como texto simples. Não analise a redação
deles. Alguns erros adicionam campos, como `limit`, `reset_at` ou
`retry_after_seconds`. Uma resposta sem corpo JSON não tem `code` do LogBrew.
Consulte [Erros da API](/pt-BR/reference/api-errors) para ver todos os
códigos.

## Leia dados com a CLI

A CLI lê as mesmas rotas e retorna o mesmo JSON com `--json`. Comece com uma
leitura ampla e depois restrinja:

```bash theme={null}
logbrew read releases --environment production --json
logbrew read issues --release api@1.2.3 --status unresolved --json
logbrew read logs --release api@1.2.3 --since 24h --json
logbrew read actions --name checkout_failed --since 24h --json
logbrew read traces --status error --since 24h --json
logbrew read trace <trace_id> --json
```

Adicione `--pagination cursor` para receber o envelope de cursor. A CLI
solicita a versão 4 da resposta de problemas. Consulte
[Ler a próxima página](/pt-BR/reference/cli#read-the-next-page) e
[Acompanhamento ao vivo](/pt-BR/reference/cli#live-watch).


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