A lightweight, type-safe logging wrapper around Pino built by vepler for its ecosystem. While primarily designed for vepler's internal use, this library is open for public use.
- 🔒 Type-safe logging with TypeScript support
- 🌟 Singleton pattern for consistent logging across your application
- 🔄 Global context management
- 🛡️ Automatic sensitive data redaction
- 🎯 Structured logging with JSON output
- ⚡ High-performance (powered by Pino)
- 🔍 Comprehensive error object handling
- 🌊 Async flush support for graceful shutdowns
- 💫 Intuitive, flexible API that works like
console.log
but better
npm install @vepler/logger
# or
yarn add @vepler/logger
# or
pnpm add @vepler/logger
import PinoWrapper from '@vepler/logger';
// Initialize the logger (do this once at app startup)
PinoWrapper.initialize({
level: 'info',
// Optional: Add any Pino options here
});
// Set global context (e.g., in your main application setup)
PinoWrapper.setContext({
environment: process.env.NODE_ENV,
service: 'user-service'
});
// Basic logging
PinoWrapper.info('User logged in successfully', {
userId: '123',
loginMethod: 'oauth'
});
// Object-only logging
PinoWrapper.info({
userId: '123',
action: 'login',
duration: 42,
success: true
});
// Error logging
try {
// Some operation that might fail
} catch (error) {
// Several equivalent ways to log errors:
// 1. Pass the error directly
PinoWrapper.error(error);
// 2. Pass error with a message
PinoWrapper.error(error, 'Failed to process user request');
// 3. Pass error, message, and context
PinoWrapper.error(error, 'Failed to process user request', {
userId: '123',
requestId: 'abc-xyz'
});
// 4. Pass message with context containing error
PinoWrapper.error('Failed to process user request', {
error,
userId: '123',
requestId: 'abc-xyz'
});
}
// Before application shutdown
await PinoWrapper.flush();
The logger can be initialized with custom options:
PinoWrapper.initialize({
level: 'debug',
formatters: {
level: (label) => ({ level: label.toUpperCase() })
},
timestamp: pino.stdTimeFunctions.isoTime,
redact: {
paths: ['password', 'token', 'authorization', 'secret'],
remove: true
}
});
Set global context that will be included in all subsequent logs:
// Set context
PinoWrapper.setContext({
environment: 'production',
service: 'auth-service',
version: '1.0.0'
});
// Clear context when needed
PinoWrapper.clearContext();
All logging methods support multiple flexible calling patterns:
// Message only
PinoWrapper.info('System started');
// Message with context
PinoWrapper.info('User action completed', { userId: '123', action: 'signup' });
// Object-only (no message)
PinoWrapper.info({ userId: '123', event: 'login', duration: 42 });
// Error object only
PinoWrapper.error(new Error('Database connection failed'));
// Error object with message
PinoWrapper.error(new Error('Connection timeout'), 'Database error');
// Error object, message, and context
PinoWrapper.error(
new Error('Connection timeout'),
'Database error',
{ db: 'users', operation: 'query' }
);
// Message with context containing error
PinoWrapper.error('Database error', {
error: new Error('Connection timeout'),
db: 'users',
operation: 'query'
});
// Message with string error in context
PinoWrapper.error('API error', {
error: 'Rate limit exceeded',
endpoint: '/users'
});
// Object-only with error property
PinoWrapper.error({
error: new Error('Authentication failed'),
userId: '123',
attempt: 3
});
Create child loggers with additional context:
const childLogger = PinoWrapper.child({
component: 'auth',
requestId: '123'
});
Configure multiple output streams during initialization:
PinoWrapper.initialize({
transport: {
targets: [
{
target: 'pino/file',
options: {
destination: './logs/info.log',
level: 'info'
}
},
{
target: 'pino/file',
options: {
destination: './logs/error.log',
level: 'error'
}
}
]
}
});
-
Initialization
- Initialize the logger once at application startup
- Configure appropriate log levels for different environments
-
Context Management
- Use global context for environment-wide properties
- Clear context when it's no longer needed
- Don't overuse context; keep it focused on essential properties
-
Error Logging
- Choose the error logging pattern that's most readable for your use case
- Add relevant context to error logs
- Use appropriate log levels based on error severity
-
Consistency
- Choose a consistent logging style throughout your application
- For object-only logging, use descriptive property names
-
Performance
- Avoid expensive operations in log context
- Use child loggers for request-scoped logging
- Call
flush()
before application shutdown
{
"level": "ERROR",
"time": "2024-02-19T12:34:56.789Z",
"environment": "production",
"service": "user-service",
"requestId": "abc-xyz",
"error": {
"type": "Error",
"message": "Database connection failed",
"stack": "Error: Database connection failed\n at ...",
"code": "ECONNREFUSED"
},
"msg": "Failed to process user request"
}
We welcome contributions! Please feel free to submit a Pull Request.
Releases are automated using GitHub Actions. To create a new release:
- Push your changes
- GitHub Action will automatically:
- Create a new version
- Create a GitHub Release
- Publish to npm
MIT © vepler
Built with ❤️ by vepler. Powered by Pino.