Logs Interceptor JS
Elven Observability Official Logger
Um coletor de logs, eventos e exceções de alta performance para apps Node.js que envia tudo ao Grafana Loki. Oferece interceptação automática de console, suporte a labels dinâmicas, envio assíncrono com buffer otimizado e integração instantânea com o Elven Stack.
Features
Alta performance com buffer assíncrono, envio em lote e compressão gzip.
Captura automática de:
console.log
,console.error
,console.warn
, etcExceções não tratadas e promises rejeitadas
Eventos personalizados via
trackEvent
Suporte a labels fixas e dinâmicas (com trace/span id via OpenTelemetry).
Buffer inteligente com envio em lote configurável.
Resiliente a falhas de rede com retry automático.
Compatível com apps simples ou complexos (web servers, workers, CLI).
Garantia de envio no encerramento do processo.
Compressão gzip para reduzir uso de banda.
Métricas em tempo real e health check integrado.
Instalação
npm install logs-interceptor
Uso Básico
import { init, logger } from "logs-interceptor";
init({
transport: {
url: "<https://loki.elvenobservability.com/loki/api/v1/push>",
tenantId: "seu-tenant", // Seu Tenant ID
authToken: "seu-token", // Seu JWT
compression: true, // Gzip habilitado
},
appName: "my-js-app",
environment: "production",
interceptConsole: true,
labels: { env: "production" },
dynamicLabels: {
hostname: () => require('os').hostname(),
memory: () => Math.round(process.memoryUsage().heapUsed / 1024 / 1024) + 'MB'
},
buffer: {
maxSize: 100,
flushInterval: 5000,
}
});
console.log("Isso será enviado ao Loki!");
logger.trackEvent("usuario_cadastrado", { user_id: 123 });
throw new Error("Erro de teste!"); // Capturado automaticamente
Opções de Configuração
Transport
url
string
Endpoint do Loki (Push API)
—
tenantId
string
Usado no header X-Scope-OrgID
—
authToken
string
Token JWT para autenticação
undefined
timeout
number
Timeout HTTP em ms
5000
maxRetries
number
Tentativas em caso de falha
3
compression
boolean
Habilita compressão gzip
true
Aplicação
appName
string
Nome da aplicação (label fixa)
—
version
string
Versão da aplicação
“1.0.0”
environment
string
Ambiente (prod, dev, staging)
“production”
labels
object
Labels fixas por log
{}
dynamicLabels
object
Labels geradas dinamicamente
{}
Buffer & Performance
buffer.maxSize
number
Logs no buffer antes de forçar envio
100
buffer.flushInterval
number
Tempo máximo antes do envio (ms)
5000
buffer.autoFlush
boolean
Flush automático habilitado
true
interceptConsole
boolean
Captura console.* automaticamente
false
enableMetrics
boolean
Coleta métricas de performance
true
Filtering & Sampling
filter.levels
array
Níveis de log permitidos
[‘debug’,’info’,’warn’,’error’,’fatal’]
filter.samplingRate
number
Taxa de amostragem (0.0-1.0)
1.0
filter.maxMessageLength
number
Tamanho máximo da mensagem
8192
Exemplo com Express.js
import express from "express";
import { init, logger } from "logs-interceptor";
init({
transport: {
url: "<https://loki.elvenobservability.com/loki/api/v1/push>",
tenantId: "seu-tenantId",
authToken: "seu-token",
compression: true,
},
appName: "express-app",
environment: "production",
interceptConsole: true,
labels: {
service: "api",
env: "production"
},
dynamicLabels: {
hostname: () => require('os').hostname(),
uptime: () => Math.round(process.uptime()) + 's'
},
});
const app = express();
app.get("/ping", (req, res) => {
console.log("ping chamado"); // Interceptado automaticamente
logger.trackEvent("api_ping", { ip: req.ip });
res.send({ message: "pong" });
});
app.get("/erro", () => {
throw new Error("Erro proposital"); // Capturado automaticamente
});
app.listen(3000, () => {
console.log("Servidor iniciado na porta 3000");
});
Auto-inicialização com NODE_OPTIONS
Para apps existentes sem modificação de código:
NODE_OPTIONS="--require logs-interceptor/preload" \\
LOGS_INTERCEPTOR_URL="<https://loki.elvenobservability.com/loki/api/v1/push>" \\
LOGS_INTERCEPTOR_TENANT_ID="seu-tenant" \\
LOGS_INTERCEPTOR_APP_NAME="minha-api" \\
LOGS_INTERCEPTOR_AUTH_TOKEN="seu-token" \\
LOGS_INTERCEPTOR_ENVIRONMENT="production" \\
node app.js
Métricas & Monitoramento
import { logger } from "logs-interceptor";
// Métricas em tempo real
const metrics = logger.getMetrics();
console.log({
logsProcessed: metrics.logsProcessed,
logsDropped: metrics.logsDropped,
flushCount: metrics.flushCount,
avgFlushTime: metrics.avgFlushTime,
errorCount: metrics.errorCount
});
// Health check
const health = logger.getHealth();
console.log({
healthy: health.healthy,
uptime: health.uptime,
bufferUtilization: health.bufferUtilization
});
Boas Práticas
Scripts curtos (CLI, cron)
Use await logger.flush()
antes do exit.
Apps web ou workers
Configuração padrão já garante envio em background.
Alta concorrência
Use maxSize: 500+
e flushInterval: 10000.
Ambientes com OpenTelemetry
Labels trace_id
e span_id
são capturados automaticamente.
Produção
Habilite compression: true
e samplingRate < 1.0
se necessário.
Troubleshooting
Logs não aparecem
tenantId
, authToken
ou URL errados
Verifique configuração e use debug: true
Logs incompletos
Processo encerrando rápido
Use await logger.flush()
antes do exit
HTTP 400
Payload malformado
Verifique se Loki está rodando na URL
Performance ruim
Buffer muito pequeno
Aumente maxSize
e flushInterval
Flush Manual
import { logger } from "logs-interceptor";
// Forçar envio imediato
await logger.flush();
// Exemplo com graceful shutdown
process.on('SIGTERM', async () => {
console.log('Shutting down gracefully...');
await logger.flush();
process.exit(0);
});
Eventos Customizados
import { logger } from "logs-interceptor";
logger.trackEvent("usuario_ativo", {
user_id: "abc123",
source: "mobile",
action: "login"
});
logger.trackEvent("compra_realizada", {
order_id: "12345",
value: 99.90,
payment_method: "credit_card"
});
No Loki aparecerá como:
[EVENT] usuario_ativo {"user_id": "abc123", "source": "mobile", "action": "login"}
Formato dos Logs no Loki
Cada log enviado inclui:
Timestamp com nanossegundos
Labels fixas e dinâmicas (ex: app, env, trace_id, span_id)
Prefixo do tipo de log (
[INFO]
,[ERROR]
,[EVENT]
, etc)Conteúdo serializado automaticamente para objetos e erros
Exemplo de payload enviado:
{
"streams": [
{
"stream": {
"app": "minha-api",
"environment": "production",
"level": "info",
"hostname": "api-01",
"trace_id": "abc123def456"
},
"values": [
["1640995200000000000", "[INFO] Usuario logado com sucesso {\\"userId\\": 123}"]
]
}
]
}
Integração com OpenTelemetry
Este logger se integra automaticamente com o OpenTelemetry, capturando os IDs de trace e span ativos no contexto atual.
Isso permite correlação perfeita entre logs e traces no Grafana Tempo, permitindo investigações completas ponta a ponta.
O que já está incluso:
trace_id
espan_id
são adicionados automaticamente como labels dinâmicasNenhuma configuração extra é necessária, desde que o app já use o OpenTelemetry
Compatível com qualquer instrumentação OpenTelemetry existente
Exemplo com traces
import { context, trace } from "@opentelemetry/api";
import { init, logger } from "logs-interceptor";
// Inicialize o OpenTelemetry antes:
const tracer = trace.getTracer("minha-lib");
init({
transport: {
url: "<https://loki.elvenobservability.com/loki/api/v1/push>",
tenantId: "elven",
authToken: "seu-token"
},
appName: "meu-app",
labels: { env: "prod" },
});
tracer.startActiveSpan("processarPedido", (span) => {
console.log("Processando pedido");
logger.info("Pedido iniciado", { orderId: 12345 });
span.end();
});
No Loki:
Cada log conterá automaticamente:
{
"trace_id": "abcdef123456789",
"span_id": "12345678",
"app": "meu-app",
"level": "info"
}
Você poderá fazer queries no Loki filtrando por trace_id
e, com isso, visualizar os logs do mesmo trace mostrado no Grafana Tempo (ou trace view da Elven Platform).
Docker & Kubernetes
Docker Compose
version: '3.8'
services:
app:
build: .
environment:
- NODE_OPTIONS=--require logs-interceptor/preload
- LOGS_INTERCEPTOR_URL=https://loki.elvenobservability.com/loki/api/v1/push
- LOGS_INTERCEPTOR_TENANT_ID=meu-tenant
- LOGS_INTERCEPTOR_AUTH_TOKEN=meu-token
- LOGS_INTERCEPTOR_APP_NAME=minha-api
- LOGS_INTERCEPTOR_ENVIRONMENT=production
Kubernetes
env:
- name: NODE_OPTIONS
value: "--require logs-interceptor/preload"
- name: LOGS_INTERCEPTOR_URL
value: "<https://loki.elvenobservability.com/loki/api/v1/push>"
- name: LOGS_INTERCEPTOR_TENANT_ID
valueFrom:
secretKeyRef:
name: elven-credentials
key: tenant-id
- name: LOGS_INTERCEPTOR_AUTH_TOKEN
valueFrom:
secretKeyRef:
name: elven-credentials
key: auth-token
Licença
Este projeto é licenciado sob a MIT License.
Contribuindo
Fork este repositório
Crie uma branch com sua melhoria
Envie um Pull Request
Toda ajuda é bem-vinda para tornar o logger ainda mais poderoso!
Feito com ❤️ pela equipe Elven Observability
Last updated
Was this helpful?