PagnovoPagnovodocs

Conceitos

Trace ID e debug

Toda resposta da API da Pagnovo — tanto de sucesso quanto de erro — carrega um header x-trace-id. Esse ID é a informação mais importante quando algo dá errado em produção.

Quando você abrir um ticket de suporte, a primeira pergunta que vamos fazer é "qual foi o trace ID?". Com ele, podemos buscar nos nossos logs distribuídos e encontrar exatamente o que aconteceu, em qual pod, em qual milissegundo, com qual estado do banco. Sem ele, ficamos correlacionando timestamps na mão.

Trate o trace ID como um artefato de debug de primeira classe: capture-o em toda resposta, registre-o no log junto com sua própria requisição e mostre-o nas mensagens de erro que aparecem para o usuário final.

Formato e propriedades

A Pagnovo não usa UUID v4 para traces. Usamos um formato curto, customizado e ordenável por tempo:

{sufixoPod}-{ts36}-{rand6hex}

Exemplo: trc-1a-lkj234-a3f1b9

Três coisas que esse formato te dá:

  1. Você consegue identificar o pod que processou a requisição pelo prefixo. Útil quando você está investigando distribuição irregular de carga ou bugs específicos de um pod.
  2. Trace IDs são ordenáveis por tempo. O segmento do meio é um timestamp em milissegundos em base 36, então ordenar trace IDs alfabeticamente te dá a ordem cronológica.
  3. A entropia é suficiente. 6 caracteres hex dão ~16M combinações por milissegundo — colisões não são preocupação no nosso volume de requisições.

Ele também é significativamente mais curto que um UUID completo (~20 chars vs 36), o que faz aparecer bonito nos logs sem quebrar linhas.

Ecoando seu próprio trace ID

Se você enviar um header x-trace-id na requisição, a Pagnovo usa esse valor em vez de gerar um novo — desde que seja uma string não-vazia com menos de 100 caracteres. Esse é o mecanismo que permite correlação end-to-end entre sistemas distribuídos.

Cenário prático:

  • Seu frontend gera um trace ID no carregamento da página
  • Ele passa o trace ID para o seu backend via header
  • Seu backend repassa o mesmo ID para a Pagnovo
  • O mesmo ID aparece nos logs do seu frontend, nos logs do seu backend, nos nossos logs e em qualquer webhook subsequente

Quando algo quebrar, você busca por um único ID em três sistemas e encontra a timeline completa.

Se você já usa OpenTelemetry, Datadog APM, Sentry ou qualquer stack moderna de observabilidade, use o span/trace ID existente como seu x-trace-id. Stacks modernas têm propagação de contexto nativa — não precisa inventar a roda.

Exemplo (Node.js, propagação manual):

TypeScript
async function callPagnovo<T>(path: string, init: RequestInit = {}): Promise<T> {
  const traceId = currentRequestContext().traceId; // do seu proprio framework
  const res = await fetch(`https://api.pagnovo.com${path}`, {
    ...init,
    headers: {
      ...init.headers,
      "x-trace-id": traceId, // <- repassa
      Authorization: `Basic ${token}`,
    },
  });
  return res.json();
}

Onde o trace ID aparece

Na resposta (sempre)

Seja a requisição bem-sucedida ou não, o trace ID está no header de resposta:

HTTP/1.1 201 Created
x-trace-id: trc-1a-lkj234-a3f1b9
content-type: application/json; charset=utf-8

Nas entregas de webhook

Todo webhook que a API entrega no seu endpoint carrega o mesmo header x-trace-id que recebemos na requisição original. Ou seja, se uma transação foi criada com o trace trc-1a-lkj234-a3f1b9, o webhook da aprovação dela chega com esse mesmo trace ID. Capture-o no seu handler de webhook e persista.

Nos nossos logs de servidor

Toda requisição à API emite no mínimo duas linhas de log estruturado em JSON do nosso lado:

JSON
{ "evt": "req_in",  "trace_id": "trc-1a-lkj234-a3f1b9", "method": "POST", "url": "/transactions/v2/purchase" }
{ "evt": "req_out", "trace_id": "trc-1a-lkj234-a3f1b9", "status": 201, "dur_ms": 264 }

Rotas internas de health-check e métricas não emitem logs de trace — são chamadas centenas de vezes por minuto e afogariam todo o resto.

Uso recomendado em produção

1. Capture o trace ID em toda resposta, sucesso ou erro.

TypeScript
const res = await fetch(url, opts);
const traceId = res.headers.get("x-trace-id");

logger.info("api_call", {
  url,
  status: res.status,
  trace_id: traceId,
});

if (!res.ok) {
  const body = await res.json();
  throw new ApiError(body.message, { statusCode: res.status, traceId, body });
}

2. Anexe-o em todo relatório de erro.

Ao mandar erros para o Sentry, Datadog ou seu logger, inclua o trace ID como tag para que você consiga pivotar de "esse usuário recebeu um 500" para "isso é o que aconteceu do lado da API":

TypeScript
sentry.captureException(err, {
  tags: { pagnovo_trace_id: err.traceId },
  extra: { responseBody: err.body },
});

3. Mostre o trace ID ao usuário final ao exibir erros.

Um discreto "Código de erro: trc-1a-lkj234-a3f1b9" na UI economiza idas e vindas em todo ticket de suporte. O usuário copia o código, você encontra a requisição imediatamente. Sem screenshot da tela de erro, sem "ontem por volta das 14h".

4. Persista o trace ID nos seus registros de transação.

Quando você gravar uma linha para uma transação ou saque criado, salve o trace ID junto com os outros campos. Meses depois, ao conciliar, você vai agradecer a si mesmo.