npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

viu-pino

v0.2.0

Published

Pino adapter for Viu logging (Kafka + Loki + HTTP API)

Downloads

26

Readme

viu-pino

npm version npm downloads License Test Coverage

TypeScript Node.js Kafka Pino

Pino adapter for Viu logging

✨ Quer ver logs? → Joga no Viu. Viu?

viu-pino é uma biblioteca TypeScript/JavaScript que integra o Pino com o sistema Viu, oferecendo dois modos de transporte:

  • HTTP (recomendado): Envia logs via API REST
  • Kafka: Envia logs diretamente para o Kafka

🚀 Features

  • Modo HTTP - Não expõe Kafka, autenticação via API Key
  • Modo Kafka - Para alta performance (legacy)
  • Circuit Breaker - Previne connection storms
  • Smart Batching - 100 logs ou 1000ms (auto-flush)
  • Correlation IDs - Rastreamento de requisições
  • Express Middleware - Integração nativa
  • TypeScript - Type-safe com definições completas
  • ESM + CommonJS - Suporte dual module
  • Pino Performance - Ultra-rápido e eficiente

📦 Instalação

npm install viu-pino
# or
yarn add viu-pino
# or
pnpm add viu-pino
# or
bun add viu-pino

🎯 Quick Start

Modo HTTP (Recomendado)

import { ViuPino, TransportMode } from 'viu-pino';

const logger = new ViuPino({
  serviceName: 'my-api',
  environment: 'production',
  transportMode: TransportMode.HTTP,
  apiUrl: 'http://localhost:3000',  // URL do backend VIU
  apiKey: 'viu_live_xxx',           // Gere no dashboard
});

await logger.initialize();

// Logging estruturado
logger.info('User logged in', { userId: '123', ip: '192.168.1.1' });
logger.error('Payment failed', new Error('Insufficient funds'), { amount: 99.90 });

Modo Kafka (Legacy/Alternativo)

import { ViuPino, TransportMode } from 'viu-pino';

const logger = new ViuPino({
  serviceName: 'my-api',
  environment: 'production',
  transportMode: TransportMode.KAFKA,
  kafkaBrokers: 'kafka.example.com:9092',
  kafkaTopic: 'logs.tenant-id',
  kafkaUsername: 'tenant_user',
  kafkaPassword: 'secure-password',
});

await logger.initialize();

logger.info('Application started', { version: '1.2.3' });

📝 Exemplos de Uso

Níveis de Log

INFO - Sem contexto

await logger.info('Application started');
await logger.info('User logged in successfully');
await logger.info('Database connection established');

INFO - Com contexto

await logger.info('User logged in', { 
  userId: '123', 
  email: '[email protected]',
  loginMethod: 'oauth'
});

await logger.info('Request processed', {
  method: 'GET',
  path: '/api/users',
  responseTime: 45,
  statusCode: 200
});

ERROR - Sem contexto (apenas mensagem)

await logger.error('Something went wrong');
await logger.error('Database connection failed');

ERROR - Com objeto Error

try {
  await processPayment(order);
} catch (err) {
  await logger.error('Payment processing failed', err as Error);
}

ERROR - Com Error + contexto adicional

try {
  await processPayment(order);
} catch (err) {
  await logger.error('Payment processing failed', err as Error, {
    orderId: order.id,
    amount: order.total,
    currency: 'BRL',
    userId: order.userId
  });
}

WARNING - Sem contexto

await logger.warn('High memory usage detected');
await logger.warn('API rate limit approaching');

WARNING - Com contexto

await logger.warn('Slow query detected', {
  query: 'SELECT * FROM users',
  duration: 2500,
  threshold: 1000
});

await logger.warn('Cache miss', {
  key: 'user:123',
  operation: 'getUserProfile',
  fallback: 'database'
});

DEBUG - Sem contexto

await logger.debug('Entering authentication flow');
await logger.debug('Cache lookup performed');

DEBUG - Com contexto

await logger.debug('Processing request', {
  headers: req.headers,
  body: req.body,
  query: req.query
});

await logger.debug('Database query executed', {
  sql: 'SELECT * FROM users WHERE id = ?',
  params: [userId],
  duration: 12
});

Outros níveis

// FATAL - Erros críticos que causam shutdown
await logger.fatal('Critical system failure', {
  error: 'Out of memory',
  freeMemory: 0
});

🔐 Produção com Autenticação SASL

import { ViuPino, TransportMode } from 'viu-pino';

const logger = new ViuPino({
  serviceName: 'my-api',
  environment: 'production',
  transportMode: TransportMode.KAFKA,
  kafkaBrokers: 'viu-kafka.example.com:9092',
  kafkaTopic: 'logs.production',
  kafkaUsername: 'viu_tenant123abc',
  kafkaPassword: 'your-secure-password',
  kafkaSaslMechanism: 'scram-sha-256',
  kafkaSecurityProtocol: 'SASL_SSL',
});

🌍 Configuração via Environment Variables

# Modo HTTP
export VIU_TRANSPORT_MODE=http
export VIU_SERVICE_NAME=my-api
export VIU_ENVIRONMENT=production
export VIU_API_URL=http://localhost:3000
export VIU_API_KEY=viu_live_xxx

# Modo Kafka
export VIU_TRANSPORT_MODE=kafka
export VIU_KAFKA_BROKERS=kafka.example.com:9092
export VIU_KAFKA_TOPIC=logs.production
export VIU_KAFKA_USERNAME=viu_tenant123abc
export VIU_KAFKA_PASSWORD=your-secure-password

🔄 Integração com Express

import express from 'express';
import { viuCorrelationMiddleware } from 'viu-pino/express';
import { ViuPino, TransportMode } from 'viu-pino';

const app = express();

// Middleware para correlation IDs
app.use(viuCorrelationMiddleware({
  serviceName: 'my-api',
  environment: 'production',
  transportMode: TransportMode.HTTP,
  apiUrl: 'http://localhost:3000',
  apiKey: 'viu_live_xxx',
}));

const logger = new ViuPino({
  serviceName: 'my-api',
  transportMode: TransportMode.HTTP,
  apiUrl: 'http://localhost:3000',
  apiKey: 'viu_live_xxx',
});

app.get('/users/:id', async (req, res) => {
  await logger.info('Fetching user', { userId: req.params.id });
  res.json({ userId: req.params.id });
});

🔗 Rastreamento e Correlation IDs

O viu-pino gera automaticamente IDs de rastreamento para todos os logs:

IDs Gerados Automaticamente

await logger.info('User action', { userId: '123' });
// Gera automaticamente:
// - correlation_id: UUID único da requisição
// - trace_id: UUID para rastreamento distribuído (reutiliza correlation_id)
// - span_id: UUID (16 chars) para operações individuais

Ordem de Prioridade para IDs

  1. Explícito via ViuPino setter: Valor definido manualmente
  2. Headers HTTP: Extraído via middleware ou setTraceHeaders()
  3. Auto-geração: UUID gerado automaticamente (padrão)

Definir Manualmente

// Definir IDs globalmente
ViuPino.correlationId = 'custom-correlation-123';
ViuPino.traceId = 'custom-trace-456';
ViuPino.spanId = 'custom-span-789';

await logger.info('Operation with custom IDs');

Detecção Automática de Headers HTTP

import { detectTraceHeaders } from 'viu-pino';

// Headers W3C Trace Context ou Zipkin B3 são detectados automaticamente
const headers = req.headers;
const traceInfo = detectTraceHeaders(headers);

if (traceInfo.correlationId) {
  ViuPino.correlationId = traceInfo.correlationId;
}
if (traceInfo.traceId) {
  ViuPino.traceId = traceInfo.traceId;
}
if (traceInfo.spanId) {
  ViuPino.spanId = traceInfo.spanId;
}

// Ou use o método helper
logger.setTraceHeaders(req.headers);

Persistência de IDs

IDs gerados automaticamente são persistidos e reutilizados entre logs:

const logger = new ViuPino({ /* config */ });

await logger.info('First log');   // Gera IDs
await logger.info('Second log');  // Reutiliza IDs
await logger.info('Third log');   // Reutiliza IDs

// Todos os 3 logs compartilham os mesmos correlation_id, trace_id, span_id

Para resetar e gerar novos IDs:

ViuPino.resetInstance();
// Próximos logs terão novos IDs

Filtragem de Context

Valores null e undefined são automaticamente removidos do contexto:

await logger.info('User event', {
  userId: '123',
  email: null,        // ← Removido
  name: 'John Doe',
  age: undefined,     // ← Removido
  status: 'active',
});

// Context enviado: { userId: '123', name: 'John Doe', status: 'active' }

Compatibilidade: W3C Trace Context, Zipkin B3, OpenTelemetry

app.get('/users/:id', async (req, res) => { logger.info('Fetching user', { userId: req.params.id }); res.json({ id: req.params.id }); });

app.listen(3000, () => { logger.info('Server started', { port: 3000 }); });


## ⚙️ Configuração

| Opção | Tipo | Descrição | Padrão |
|-------|------|-----------|--------|
| `serviceName` | string | Nome do serviço | (obrigatório) |
| `environment` | string | Ambiente | `'development'` |
| `transportMode` | `'http' \| 'kafka'` | Modo de transporte | `'http'` |
| `apiUrl` | string | URL da API (HTTP mode) | undefined |
| `apiKey` | string | API Key (HTTP mode) | undefined |
| `kafkaBrokers` | string | Endereço Kafka | `'localhost:9092'` |
| `kafkaTopic` | string | Topic Kafka | `'logs.app.raw'` |
| `kafkaUsername` | string | Username SASL | undefined |
| `kafkaPassword` | string | Password SASL | undefined |
| `kafkaSaslMechanism` | string | Mecanismo SASL | `'scram-sha-256'` |
| `kafkaSecurityProtocol` | string | Protocolo | `'SASL_SSL'` |
| `level` | string | Nível do log | `'info'` |
| `batchSize` | number | Tamanho do batch | `100` |
| `batchTimeout` | number | Timeout do batch (ms) | `1000` |

## 📈 Performance

- **Modo HTTP**: Envio imediato, retry automático
- **Modo Kafka**: Batching (100 logs ou 1000ms), compressão gzip
- **Circuit Breaker**: Evita sobrecarga em falhas
- **Pino**: Um dos loggers mais rápidos do Node.js

## 🔒 Segurança

- **Modo HTTP**: API Key no header Authorization
- **Modo Kafka**: SASL_SSL ativado por padrão
- Suporte TLS/SSL completo
- Autenticação: SCRAM-SHA-256, SCRAM-SHA-512, PLAIN

## 📦 Exports

```typescript
// Main export
import { ViuPino, ViuPinoConfig, TransportMode, createViuPino } from 'viu-pino';

// Express middleware
import { 
  viuCorrelationMiddleware, 
  getCorrelationId, 
  getTraceId, 
  getSpanId 
} from 'viu-pino/express';

🆚 HTTP vs Kafka

| Aspecto | HTTP | Kafka | |---------|------|-------| | Complexidade | Baixa | Alta | | Exposição Kafka | Não | Sim | | Autenticação | API Key | SASL | | Performance | Boa | Excelente | | Recomendado | Padrão | Alta performance |

🤝 Contributing

Contribuições são bem-vindas!

📄 License

MIT License - see LICENSE para detalhes.