Package Exports
- @arv-bedrock/logger
Readme
Bedrock Logger
A powerful Nest.js logger middleware that supports both structured JSON logging (Loki-optimized) and pretty console output.
Features
- Request/Response logging with detailed information
- Error tracking and logging
- TypeScript support
- Nest middleware compatible
- Request ID propagation across services
- Support for both Loki (JSON) and Pretty formats
Installation
npm i @arv-bedrock/logger
Usage
import { Logger, LoggerInterceptor, LoggerOptions, LogLevel, setupHttpInterceptor } from '@arv-bedrock/logger';
import { HttpService } from '@nestjs/axios';
const app = await NestFactory.create(AppModule);
// Create logger instance
// Add logger into file main.ts
const options: LoggerOptions = {
level: LogLevel.INFO, // Minimum log level
format: 'loki', // 'loki' or 'pretty'
timestamp: true, // Include timestamps
serviceName: 'smart-utilities' // Service name for identification
};
const logger = new Logger(options);
// Create and use the logger interceptor
const interceptor = new LoggerInterceptor(logger);
app.use(interceptor.logRequest.bind(interceptor));
// **(optional) If you use httpService from @nestjs/axios add this code it will intercept your axios request and response
const httpService = app.get(HttpService);
setupHttpInterceptor(logger, httpService);
// Direct logging
logger.debug('Debug message');
logger.info('Info message');
logger.warn('Warning message');
logger.error('Error message', new Error('Something went wrong'));
Configuration
LoggerOptions
interface LoggerOptions {
level?: LogLevel; // DEBUG, INFO, WARN, ERROR (default: INFO)
timestamp?: boolean; // Include timestamps (default: true)
format?: 'loki' | 'pretty'; // Log format (default: 'loki')
serviceName?: string; // Service name for identification
maxBodySize?: number; // Maximum response body size in bytes (default: 1MB)
}
Request ID Tracking
The logger automatically handles request IDs for tracing requests across services:
- Checks for existing 'x-request-id' in request headers
- If not found, generates a new UUID
- Adds request ID to response headers
- Uses the same ID throughout request/response logging
Example of request ID header:
X-Request-ID: de021845-08ec-4158-8e83-d8f1022931a5
Log Formats
Loki Format (Default)
Outputs structured JSON logs optimized for Grafana Loki ingestion:
{
"labels": {
"level": "INFO",
"service": "smart-utilities",
"timestamp": "2025-03-08T17:53:27.164Z",
"request_id": "de021845-08ec-4158-8e83-d8f1022931a5",
"method": "GET",
"path": "/api/example"
},
"message": "Incoming GET /api/example",
"data": {
"requestId": "de021845-08ec-4158-8e83-d8f1022931a5",
"method": "GET",
"path": "/api/example",
"params": {},
"query": {},
"headers": {},
"timestamp": 1741456407164,
"type": "request"
}
}
Pretty Format
Human-readable colored output for local development:
[2025-03-08T17:53:27.164Z] [smart-utilities] [INFO] [de021845-08ec] Incoming GET /api/example
Response Body Handling
The logger intelligently handles response bodies:
Size Limit:
- By default, response bodies larger than 1MB are excluded from logs
- Configurable via
maxBodySize
option (in bytes) - When body is excluded, logs will show:
[Content Excluded: <size> bytes]
Binary Content:
- Automatically excludes binary content types (images, PDFs, etc.)
- Supported binary types:
- application/octet-stream
- application/pdf
- application/vnd.ms-excel
- application/zip
- image/*
- audio/*
- video/*
Example configuration with custom body size limit:
const logger = new Logger({
maxBodySize: 512 * 1024, // Set 512KB limit
format: 'pretty',
serviceName: 'my-service'
});
Querying Logs in Grafana Loki
Basic Queries
- Filter by status code:
{serviceName="smart-utilities"} | json | data_statusCode = 200
- Filter by request method and path:
{serviceName="smart-utilities"} | json | data_method = "GET" and data_path = "/api/example"
- Search in time range:
{serviceName="smart-utilities"} | json
| data_timestamp > unix_timestamp("2025-03-08T17:53:27.164Z")
| data_timestamp < unix_timestamp("2025-03-08T17:53:28.519Z")
Trace Queries
Follow request across services:
{app=~".*"} | json | request_id = "de021845-08ec-4158-8e83-d8f1022931a5"
Advanced JSON Queries
Query nested JSON response data:
{serviceName="smart-utilities"} | json | data_body := unwrap data.body | json data_body
| paymentStatus[*].label = "รอการถอดถอนมาตร"
Error Handling
The logger automatically handles errors and prevents duplicate error logs. Each error is logged only once with:
- Error message and type
- Stack trace
- Request context
- Response status code
License
MIT