> For the complete documentation index, see [llms.txt](https://docs.ipcheck.ing/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ipcheck.ing/developer/pt-br/configuration/logging.md).

# Logging

Níveis de log, saída JSON para agregadores de logs e registro HTTP por requisição.

Ambos os processos do Node — a API de backend e o servidor de arquivos estáticos — gravam em um único [pino](https://getpino.io/) logger. Três variáveis de ambiente o controlam. As três são opcionais.

| Variável     | Valores                                 | Padrão |
| ------------ | --------------------------------------- | ------ |
| `LOG_LEVEL`  | `debug` / `info` / `warn` / `erro JSON` | `info` |
| `LOG_FORMAT` | `json`, ou qualquer outra coisa         | pretty |
| `LOG_HTTP`   | `"true"`                                | de     |

Tudo vai para stdout. Não há arquivo de log integrado — o gerenciador de processos (pm2, systemd, Docker) é quem cuida disso.

## `LOG_LEVEL`

Define a severidade mínima que será gravada. Tudo abaixo disso é descartado antes da formatação, então um nível mais silencioso é realmente barato.

* `debug` — tudo, inclusive o ruído detalhado das atualizações do conjunto de dados. Útil quando um download da MaxMind ou da CAIDA apresenta problema.
* `info` — o padrão. Linhas de inicialização, carregamentos de conjuntos de dados, planos de tarefas agendadas.
* `warn` — apenas degradação: IPs com limitação de taxa, falhas parciais do upstream, timeouts.
* `erro JSON` — apenas falhas do handler.

{% hint style="info" %}
`LOG_LEVEL` também controla o que chega ao Sentry. A ponte do Sentry é instalada dentro do logger, então uma linha suprimida pelo nível nunca se torna um log ou issue do Sentry. Veja [Monitoramento de erros](/developer/pt-br/configuration/error-monitoring.md).
{% endhint %}

## `LOG_FORMAT`

### Formato bonito (padrão)

Deixe `LOG_FORMAT` vazio e a saída passa por `pino-pretty`: colorido, uma linha por evento, carimbos de data/hora locais do host com um offset UTC, `pid` e `hostname` omitido.

```
[2026-07-14 10:23:45.221 +0800] INFO: 🚀 Servidor de backend pronto em http://localhost:11966
```

É isso que você quer para `pnpm dev` e para ler `pm2 logs` ou `docker logs` a olho nu.

### JSON

```bash
LOG_FORMAT="json"
```

A saída se torna um objeto JSON bruto por linha — o formato nativo do pino — sem cores e sem escapes ANSI:

```json
{"level":30,"time":1752459825221,"msg":"🚀 Servidor de backend pronto em http://localhost:11966"}
{"level":40,"time":1752460013887,"ip":"203.0.113.45","msg":"IP limitado por taxa"}
{"level":50,"time":1752460101044,"err":{"type":"Error","message":"O upstream respondeu 429"},"ip":"1.1.1.1","msg":"falha no handler ipinfo-io"}
```

Observações sobre os campos:

* `level` é numérico: `20` debug, `30` info, `40` warn, `50` error.
* `time` são milissegundos desde a época.
* `msg` é a mensagem legível por humanos.
* Quaisquer outras chaves são o contexto estruturado anexado pelo ponto de chamada — `ip`, `asn`, `prefixo`, `err`, e assim por diante.

Use JSON sempre que algo além de um humano for ler os logs. Os códigos de cor ANSI no modo pretty confundem a maioria dos parsers.

## `LOG_HTTP`

```bash
LOG_HTTP="true"
```

Ativa o registro por requisição para `/api/*` apenas rotas. Desativado por padrão para manter os logs do gerenciador de processos legíveis.

```
INFO: GET /api/ipinfo?ip=1.1.1.1 → 200
WARN: GET /api/report/abc → 404
```

Detalhes que vale a pena saber:

* Cada requisição registra o método, a URL, o código de status e o tempo de resposta.
* O nível corresponde ao resultado: `5xx` ou um erro lançado → `erro JSON`, `4xx` → `warn`, todo o resto → `info`.
* O middleware é montado **antes de** antes do limitador de taxa, então `429` as respostas também são registradas. Veja [Opções de Segurança](/developer/pt-br/configuration/security-options.md).
* Falhas no nível do handler são registradas independentemente desta flag — `LOG_HTTP` ele adiciona as requisições bem-sucedidas, não os erros.

{% hint style="warning" %}
As URLs das requisições contêm parâmetros de consulta, incluindo os endereços IP que os visitantes consultam. Em uma instância pública, isso é dado pessoal. Ative `LOG_HTTP` para depuração, depois desative de novo — ou certifique-se de que sua política de retenção o cubra.
{% endhint %}

## Lendo uma inicialização saudável

As linhas de inicialização têm emoji no início para que você possa examinar a inicialização de relance.

| Linha                                                                                      | Significado                                                                                      |
| ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
| `📝 Registro de requisições HTTP ativado (LOG_HTTP=true)`                                  | `LOG_HTTP` está ativado                                                                          |
| `🛡️ Limitador de taxa ativado — N requisições por …`                                      | `SECURITY_RATE_LIMIT` está definido                                                              |
| `🐢 Limitador de velocidade ativado — desacelere após N requisições`                       | `SECURITY_DELAY_AFTER` está definido                                                             |
| `📥 Bancos de dados MaxMind ausentes; tentando o download inicial …`                       | Na primeira inicialização, o GeoLite2 está sendo baixado                                         |
| `📦 Bancos de dados MaxMind carregados (…)`                                                | A geolocalização está pronta                                                                     |
| `📦 CAIDA as2org carregado (…)` / `📦 CAIDA as-rel carregado (…)`                          | Os nomes das organizações ASN e o grafo de conectividade estão prontos                           |
| `🗓️ … plano de atualização automática: próxima verificação em …`                          | Uma atualização agendada do conjunto de dados está programada                                    |
| `📦 Cache de status do serviço preparado`                                                  | A página de status do serviço tem dados                                                          |
| `🛰️ Monitoramento de backend do Sentry ativado`                                           | `SENTRY_DSN_BACKEND` está definido                                                               |
| `🚀 Servidor backend pronto em http://localhost:11966`                                     | A API está aceitando tráfego                                                                     |
| `🚀 Servidor de arquivos estáticos pronto em http://localhost:18966`                       | O SPA está sendo servido                                                                         |
| `❌ A API do MaxMind retornará 503 até que os bancos de dados sejam carregados com sucesso` | **Problema** — veja [Configuração da MaxMind](/developer/pt-br/getting-started/maxmind-setup.md) |

Ambos `🚀` as linhas dizem `localhost` porque esse é o endereço ao qual o processo se vincula dentro do próprio host ou contêiner. Isso não é uma pista sobre sua URL pública.

## Enviando logs JSON

Set `LOG_FORMAT="json"` e deixe sua plataforma coletar stdout. Nada mais no app precisa mudar.

{% tabs %}
{% tab title="Docker" %}

```bash
docker run -d -p 18966:18966 \
  -e LOG_FORMAT="json" \\
  -e LOG_LEVEL="info" \
  --log-driver=json-file \\
  --name myip \
  jason5ng32/myip:latest
```

A partir daí, qualquer driver de logging do Docker ou coletor sidecar (Vector, Fluent Bit, Promtail, o agente do Datadog) recolhe as linhas. Cada linha já é JSON válido, então não é necessário parsing multilinha ou por regex.
{% endtab %}

{% tab title="pm2" %}
{% code title=".env" %}

```bash
LOG_FORMAT="json"
LOG_LEVEL="info"
```

{% endcode %}

o pm2 grava o stdout em seus próprios arquivos de log; aponte seu coletor para esses caminhos (`pm2 info <name>` os mostra).

{% hint style="warning" %}
O pm2 tira um snapshot das variáveis de ambiente quando um processo é iniciado pela primeira vez. `pm2 restart` reaplica o snapshot antigo. Depois de alterar `.env`, faça `pm2 delete <name> && pm2 start ecosystem.config.cjs && pm2 save`.
{% endhint %}
{% endtab %}

{% tab title="Ad-hoc / jq" %}

```bash
# Apenas erros, os mais recentes primeiro
docker logs myip 2>&1 | jq -c 'select(.level >= 50)'

# Quais IPs foram limitados por taxa
docker logs myip 2>&1 | jq -r 'select(.msg == "IP limitado por taxa") | .ip' | sort | uniq -c

# Reformatar um fluxo JSON para leitura humana
docker logs myip 2>&1 | npx pino-pretty
```

{% endtab %}
{% endtabs %}

Uma configuração base razoável para produção: `LOG_FORMAT="json"`, `LOG_LEVEL="info"`, `LOG_HTTP` desativado. Adicione `LOG_HTTP="true"` temporariamente quando precisar de visibilidade por requisição.

## Páginas relacionadas

* [Monitoramento de erros](/developer/pt-br/configuration/error-monitoring.md) — como `warn` e `erro JSON` as linhas chegam ao Sentry
* [Opções de Segurança](/developer/pt-br/configuration/security-options.md) — os eventos por trás dos `IP limitado por taxa` avisos
* [Variáveis de Ambiente](/developer/pt-br/reference/environment-variables.md) — a lista completa
* [Backend](/developer/pt-br/architecture/backend.md) — onde o logger fica no caminho da requisição


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ipcheck.ing/developer/pt-br/configuration/logging.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
