evobits

evobits · guia · aplicações · node.js

Node.js com o pacote @evobits/node

O @evobits/node liga logs, traces e erros de um serviço Node.js com uma linha, sobre o SDK oficial do OpenTelemetry, e já aplica a máscara de dado sensível antes de o dado sair da sua máquina.

Instala com
npm install @evobits/node
Node.js
22.12 ou mais novo
Rede
Só saída para otlp.evobits.com.br:443
Onde no painel
Aplicações > Serviços > Novo serviço

Copia esta página inteira em Markdown, com o texto para IA, para colar no Claude Code, no ChatGPT, no Gemini ou no assistente que vocês usam.

Exemplo de prompt
Preciso ligar o nosso serviço Node.js no evobits (logs, traces e erros).
Siga o guia que vou colar abaixo.

Nossa stack: (descreva aqui: framework, ESM ou CommonJS, como o serviço é iniciado).

Leia o guia inteiro e execute a seção "Texto para IA".
O token nunca vai escrito em arquivo: só a variável EVOBITS_TOKEN.

<COLE AQUI O TEXTO COPIADO PELO BOTÃO "COPIAR PARA IA">

01O que é monitorado

  • Requisições recebidas: cada requisição HTTP vira um span de servidor com método, rota (GET /pedidos/:id), código de resposta e duração. Fastify, Express e NestJS informam a rota.
  • Chamadas de saída: http, https e fetch (undici), com método e destino; o contexto do trace segue para o serviço chamado.
  • Banco, cache e filas: pg (e Sequelize por cima dele), Redis (ioredis e redis), MongoDB e socket.io.
  • Logs que você emite pela API de logs reexportada pelo pacote.
  • Exceções: erro lançado numa rota (vira evento de exceção no span e grupo de erro) e exceção não tratada do processo.
  • Recurso: versão do package.json, ambiente (do token), instância (nome da máquina), versão do Node e framework detectado (Fastify, Express, NestJS, Koa, Hapi ou Restify).

Desligado por padrão: o corpo das requisições nunca é lido; os spans de ruído pg-pool.connect e os spans request e handler do Fastify não são gravados (a rota continua no span do servidor); o pacote não manda métricas nem lê a linha de comando do processo.

02Como funciona

  • O pacote inicia o SDK do OpenTelemetry com as instrumentações acima e um exportador próprio: OTLP/HTTP em protobuf com gzip para https://otlp.evobits.com.br, porta 443.
  • Antes de enviar, ele aplica a mesma máscara do evobits (telefone, CPF e CNPJ, e-mail, tokens, senhas, corpo de mensagem). O evobits mascara de novo ao receber.
  • Falha de rede, 429 ou 5xx: até 3 tentativas, depois o lote é descartado. Token recusado (401 ou 403): um aviso no console, no máximo um por minuto. A telemetria nunca derruba nem segura o serviço.
  • Cota estourada: a resposta traz X-Evobits-Corte; o pacote para de enviar por 10 minutos, descarta o que sairia nesse prazo (não guarda em memória) e tenta de novo.
  • Exceção não tratada: o pacote grava um log FATAL com exception.type, exception.message e exception.stacktrace, descarrega a fila (até 3 s) e deixa o Node sair com código 1, como sempre. Se o serviço já tem tratador de uncaughtException, o pacote só registra e descarrega.
  • SIGTERM: o pacote descarrega a fila (até 3 s) e reenvia o sinal. Se o seu serviço trata o SIGTERM, chame await parar() no seu tratador.
  • Sem EVOBITS_TOKEN (ou com EVOBITS_DESLIGADO=1), o serviço roda normal, sem telemetria.

03Onde aparece

Aplicações > Serviços > meu-servico: Visão geral, Rotas, Erros, Traces, Dependências e Instâncias; Aplicações > Logs; Aplicações > Mapa. O subtítulo do serviço mostra "Node 22 · Fastify · 3 instâncias".

04Alertas

Sensor de rota (latência p50, p95, p99 ou taxa de erro) pela aba Rotas, sensor de contagem de log pelo Explorador de logs, e as regras "Erro novo em produção" e "Regressão de erro" (nascem desligadas, ligue em Alertas > Regras).

05Limites e privacidade

  • Node.js 22.12 ou mais novo (testado no 22.22). O pacote é ESM e funciona com require no Node 22.12+.
  • Lote recusado acima de 8 MB; linha de log ou span acima de 256 kB é recusado sozinho.
  • A máscara roda no pacote e de novo no evobits. Por isso o cartão "O que a máscara trocou" fica perto de zero em serviço com o pacote: o dado já saiu trocado.
  • Nome de pessoa, endereço, CEP e IP não são mascarados: crie uma regra extra na Configuração do serviço.
  • A versão 1.0.1 usa @opentelemetry/sdk-node 0.300.0, @opentelemetry/sdk-logs 3.0.0 e @opentelemetry/api 1.10.0, travadas.

06Como instalar

1. Instale o pacote.

npm install @evobits/node

2. Ponha o token no ambiente do processo (no .env que não vai para o git, no pm2, no systemd, no segredo do contêiner), nunca no código:

EVOBITS_TOKEN=eva_prd_...

3. Uma linha, antes de tudo. A primeira linha do arquivo de entrada, antes de carregar o framework.

ESM ("type": "module" ou .mjs):

import '@evobits/node/iniciar';
import Fastify from 'fastify';

CommonJS:

require('@evobits/node/iniciar');
const express = require('express');

4. Express em ESM e NestJS 12 precisam de mais um passo. Nesses dois casos o Express é carregado por import, e a rota só é lida com o gancho de módulos do OpenTelemetry registrado antes de o programa começar. Sem ele, os dados chegam, mas a rota aparece só como GET. Crie registrar.mjs ao lado do arquivo de entrada:

import { register } from 'node:module';
register('@opentelemetry/instrumentation/hook.mjs', import.meta.url);

e inicie o processo com --import:

node --import ./registrar.mjs servidor.js

(No pm2: node_args: '--import ./registrar.mjs'; no Docker: no CMD.) Fastify (ESM e CommonJS), Express em CommonJS e NestJS até a versão 11 compilado para CommonJS não precisam disso.

5. Reinicie o serviço. O primeiro dado chega em segundos, com a primeira requisição.

Express

require('@evobits/node/iniciar');
const express = require('express');
const app = express();
app.get('/clientes/:id', (req, res) => res.json({ id: req.params.id }));
app.listen(3000);

Erro lançado numa rota vira grupo de erro (o span do servidor fica com erro e evento de exceção).

Fastify

import '@evobits/node/iniciar';
import Fastify from 'fastify';
const app = Fastify();
app.get('/pedidos/:id', async (req) => ({ id: req.params.id }));
await app.listen({ port: 3000 });

NestJS

No main.ts (ou main.js), a primeira linha:

import '@evobits/node/iniciar';
import { NestFactory } from '@nestjs/core';

No NestJS 12, inicie com node --import ./registrar.mjs dist/main.js (passo 4).

Logs

Use a API de logs que o pacote reexporta, nunca outra instalação de @opentelemetry/api: duas cópias criam dois registros globais e os logs somem sem erro.

import { logs, SeverityNumber } from '@evobits/node';

const log = logs.getLogger('pedidos');
log.emit({ severityNumber: SeverityNumber.WARN, severityText: 'WARN', body: 'pedido criado sem frete', attributes: { 'pedido.id': 42 } });

Corpo em JSON (body: JSON.stringify({...})) vira atributos sozinho na busca. Para levar um erro tratado como erro agrupado, mande os atributos exception.type, exception.message e exception.stacktrace no log.

Opções no código

import { iniciar, parar } from '@evobits/node';
iniciar({ token: process.env.EVOBITS_TOKEN, versao: '2.14.1' });
// no seu tratador de SIGTERM:
await parar();

Variáveis

VariávelOpção de iniciar()Padrão
EVOBITS_TOKENtokensem token, sem telemetria
EVOBITS_ENDPOINTendpointhttps://otlp.evobits.com.br
EVOBITS_AMBIENTEambienteo do token (prd, hml, dev), depois NODE_ENV
EVOBITS_VERSAOversaoversion do package.json
EVOBITS_INSTANCIAinstancianome da máquina
OTEL_SERVICE_NAMEserviconame do package.json (só atributo: o token decide o serviço)
EVOBITS_DESLIGADO=1desligado: trueligado

A partir da versão 1.0.1 o pacote também entende as variáveis padrão do OpenTelemetry. Elas valem só quando a opção do código e a variável EVOBITS_* correspondente não existem:

Variável padrãoEquivale aObservação
OTEL_EXPORTER_OTLP_ENDPOINTEVOBITS_ENDPOINTendereço base
OTEL_EXPORTER_OTLP_HEADERSEVOBITS_TOKENlê o cabeçalho authorization=Bearer <token> (o espaço pode vir como %20)
OTEL_RESOURCE_ATTRIBUTESEVOBITS_VERSAO, EVOBITS_AMBIENTE, EVOBITS_INSTANCIAlê service.version, deployment.environment.name e service.instance.id

Para mandar a uma sonda coletora, use EVOBITS_ENDPOINT=http://<ip-da-sonda>:4318 ou OTEL_EXPORTER_OTLP_ENDPOINT=http://<ip-da-sonda>:4318.

Código compilado (TypeScript, esbuild, webpack)

Mande o source map de cada deploy para a pilha do erro mostrar o arquivo e a linha do seu código-fonte (guia "Source maps"). Se o serviço roda com node --enable-source-maps, a pilha já sai resolvida e o envio é dispensável.

07Como conferir

  1. 1Faça uma requisição ao serviço.
  2. 2O cartão Primeiro dado do Novo serviço muda para "meu-servico está mandando dados", com instância e versão.
  3. 3Em Rotas, a rota aparece com o caminho do framework (GET /pedidos/:id), não só GET.
  4. 4Um trace sem erro pode não aparecer na lista de Traces: a amostragem guarda 10 % deles. Para conferir, suba a amostragem para 100 % na Configuração e volte depois.
  5. 5No console do serviço, nenhuma linha [evobits] o evobits recusou o token.

08Problemas comuns

SintomaO que fazer
[evobits] o evobits recusou o token (HTTP 401)confira EVOBITS_TOKEN (inteiro, sem espaço, não revogado)
HTTP 403o módulo Aplicações está desligado ou sem aceite; fale com um proprietário
[evobits] sem conexão com o evobitso processo precisa de saída para otlp.evobits.com.br:443; rede fechada usa a sonda coletora
Rota aparece só como GETExpress em ESM ou NestJS 12: passo 4
Logs não aparecem, traces simo log foi emitido por outra cópia de @opentelemetry/api; importe logs de @evobits/node
Nada chegaa linha do pacote não é a primeira do arquivo de entrada, ou o processo não foi reiniciado
O serviço demora até 3 s para sair no deployé o envio final no SIGTERM, com teto de 3 s
Faixa de corte em Aplicaçõescota do mês atingida; o pacote pausa sozinho por 10 min de cada vez

09Texto para IA

Para pedir a instalação a um assistente de código (Claude Code ou afins) aberto no projeto do serviço. Troque os marcadores entre < >; o token fica só na variável EVOBITS_TOKEN.

# Tarefa: ligar o evobits (logs, traces e erros) no serviço Node.js <nome do serviço>

## Objetivo
Instrumentar este serviço Node.js com o pacote `@evobits/node`, para ele mandar logs, traces e erros ao evobits no
ambiente <ambiente>, sem mudar o comportamento do serviço.

## Contexto
- O pacote `@evobits/node` (npm) liga o OpenTelemetry com uma linha: `import '@evobits/node/iniciar'` em ESM ou
  `require('@evobits/node/iniciar')` em CommonJS, como PRIMEIRA linha do arquivo de entrada, antes do framework.
- Ele lê o token da variável de ambiente EVOBITS_TOKEN (ou, na versão 1.0.1, do cabeçalho de OTEL_EXPORTER_OTLP_HEADERS). Sem token, o serviço roda sem telemetria.
- Endereço padrão: https://otlp.evobits.com.br (não precisa configurar). Versão vem do package.json; ambiente, do token.
- Instrumenta http, fetch, Express, Fastify, NestJS, pg, Sequelize, Redis, MongoDB e socket.io. Não lê corpo de
  requisição. Mascara telefone, CPF, e-mail, tokens e senhas antes de enviar.
- Exige Node.js 22.12 ou mais novo.
- Express carregado por `import` (projeto ESM) e NestJS 12 precisam de um gancho: um arquivo `registrar.mjs` com
  `import { register } from 'node:module'; register('@opentelemetry/instrumentation/hook.mjs', import.meta.url);`
  e o processo iniciado com `node --import ./registrar.mjs <arquivo de entrada>`. Sem isso a rota vira só `GET`.
- Logs da aplicação: `import { logs, SeverityNumber } from '@evobits/node'` e
  `logs.getLogger('<nome>').emit({ severityNumber, severityText, body, attributes })`. Nunca importar `logs` de outra
  cópia de `@opentelemetry/api`.

## Passos
1. Leia o package.json: confirme Node 22.12+ (campo engines, .nvmrc, Dockerfile ou o runtime de deploy), ESM ou
   CommonJS, o framework e o arquivo de entrada (campo main, script start, Dockerfile, ecosystem do pm2).
2. Rode `npm install @evobits/node` (ou o equivalente do gerenciador do projeto).
3. Ponha `import '@evobits/node/iniciar';` (ESM) ou `require('@evobits/node/iniciar');` (CommonJS) como primeira
   linha do arquivo de entrada.
4. Se o projeto é ESM e usa Express, ou usa NestJS 12, crie `registrar.mjs` como no contexto e ajuste o comando de
   início (script start, Dockerfile, pm2 `node_args`) para `node --import ./registrar.mjs ...`.
5. Se o serviço já trata SIGTERM, acrescente `await parar()` (de `@evobits/node`) no tratador, antes de sair.
6. Documente no README ou no exemplo de variáveis (`.env.example`) a variável `EVOBITS_TOKEN=` SEM valor.
7. Se houver logger próprio que grave nome de pessoa, endereço, CEP ou IP, liste esses pontos para mim (a máscara
   fixa não cobre; eu crio uma regra extra no painel).

## Regras
- O token fica só na variável de ambiente EVOBITS_TOKEN. Nunca escreva o valor em arquivo versionado, em
  `.env.example`, em Dockerfile, em log ou na resposta. Se precisar dele para testar, peça que eu exporte a variável.
- Não mexa em nada além do pedido: sem atualizar outras dependências, sem refatorar, sem trocar o logger.
- Não leia nem envie corpo de requisição.
- Rode os testes do projeto depois da mudança.

## Como saber que deu certo
1. Com `EVOBITS_TOKEN` exportado, suba o serviço e faça uma requisição a uma rota com parâmetro.
2. O console não mostra `[evobits] o evobits recusou o token` nem `[evobits] sem conexão`.
3. No painel do evobits, o cartão "Primeiro dado" do serviço <nome do serviço> diz que ele está mandando dados, e a aba
   Rotas mostra a rota com o caminho do framework (por exemplo `GET /pedidos/:id`), não só `GET`.
4. Os testes do projeto continuam verdes e, sem a variável, o serviço sobe normal.