Skip to main content
Version: 0.4.2 (Previous)

📝 Logging Utilities

The Nodeblocks SDK provides pre-configured logging setup with Pino for structured logging. These utilities offer consistent logging across your application with pretty formatting and HTTP request/response logging.


🎯 Overview

Logging utilities provide a standardized logging setup using Pino, a high-performance Node.js logger. They offer structured logging with pretty formatting for development and production-ready logging for deployment.

Key Features

  • Pre-configured Logger: Ready-to-use Pino logger with pretty formatting
  • HTTP Logging: Automatic request/response logging middleware
  • Structured Logging: JSON-based logging for easy parsing
  • Performance: High-performance logging with minimal overhead
  • TypeScript Support: Full type safety for logger integration

📝 Basic Logging

nodeblocksLogger

Pre-configured Pino logger with pretty formatting and colorized output.

import { utils } from '@nodeblocks/backend-sdk';

const { nodeblocksLogger } = utils;

// Basic logging
nodeblocksLogger.info('Application started');
nodeblocksLogger.warn('Deprecated feature used');
nodeblocksLogger.error('An error occurred', { error: 'details' });

// Structured logging
nodeblocksLogger.info({
message: 'User created',
userId: 'user-123',
timestamp: new Date().toISOString()
});

Log Levels

import { utils } from '@nodeblocks/backend-sdk';

const { nodeblocksLogger } = utils;

// Available log levels
nodeblocksLogger.trace('Trace level - most detailed');
nodeblocksLogger.debug('Debug level - development info');
nodeblocksLogger.info('Info level - general information');
nodeblocksLogger.warn('Warn level - warnings');
nodeblocksLogger.error('Error level - errors');
nodeblocksLogger.fatal('Fatal level - critical errors');

🌐 HTTP Logging

nodeblocksHTTPLogger

HTTP request/response logging middleware for Express applications.

import express from 'express';
import { utils } from '@nodeblocks/backend-sdk';

const { nodeblocksHTTPLogger } = utils;

const app = express();

// Add HTTP logging middleware
app.use(nodeblocksHTTPLogger);

// Your routes
app.get('/api/users', (req, res) => {
res.json({ users: [] });
});

HTTP Log Output

The HTTP logger automatically logs:

  • Request details: Method, URL, headers, body
  • Response details: Status code, response time
  • Performance metrics: Request duration
  • Error information: Error details if requests fail

Example output:

{
"req": {
"id": "req-1",
"method": "GET",
"url": "/api/users",
"headers": {
"user-agent": "Mozilla/5.0...",
"accept": "application/json"
}
},
"res": {
"statusCode": 200,
"responseTime": 45
},
"msg": "request completed"
}

🔧 Advanced Usage

Custom Logger Configuration

import pino from 'pino';
import { utils } from '@nodeblocks/backend-sdk';

const { nodeblocksLogger } = utils;

// Extend the default logger
const customLogger = nodeblocksLogger.child({
service: 'user-service',
version: '1.0.0'
});

// Use custom logger
customLogger.info('Service started', {
port: 3000,
environment: process.env.NODE_ENV
});

Logger in Handlers

import { utils } from '@nodeblocks/backend-sdk';

const { nodeblocksLogger } = utils;

const createUserHandler = async (payload: RouteHandlerPayload) => {
const { params, logger } = payload;

// Use logger from payload or fallback to default
const log = logger || nodeblocksLogger;

log.info('Creating user', {
email: params.requestBody?.email,
timestamp: new Date().toISOString()
});

try {
// Handler logic
const user = await createUser(params.requestBody);

log.info('User created successfully', {
userId: user.id,
email: user.email
});

return ok(mergeData(payload, { user }));
} catch (error) {
log.error('Failed to create user', {
error: error.message,
email: params.requestBody?.email
});

throw error;
}
};

Conditional Logging

import { utils } from '@nodeblocks/backend-sdk';

const { nodeblocksLogger } = utils;

const getConditionalLogger = (isDevelopment: boolean) => {
if (isDevelopment) {
return nodeblocksLogger.child({ level: 'debug' });
}
return nodeblocksLogger.child({ level: 'info' });
};

// Usage
const logger = getConditionalLogger(process.env.NODE_ENV === 'development');
logger.debug('Debug info only in development');

Performance Logging

import { utils } from '@nodeblocks/backend-sdk';

const { nodeblocksLogger } = utils;

const performanceHandler = async (payload: RouteHandlerPayload) => {
const startTime = Date.now();
const log = payload.logger || nodeblocksLogger;

log.info('Starting performance-critical operation');

try {
// Expensive operation
const result = await expensiveOperation();

const duration = Date.now() - startTime;
log.info('Operation completed', {
duration,
resultSize: result.length
});

return ok(mergeData(payload, { result }));
} catch (error) {
const duration = Date.now() - startTime;
log.error('Operation failed', {
duration,
error: error.message
});

throw error;
}
};

📊 Logger Configuration

Default Configuration

The nodeblocksLogger comes pre-configured with:

{
enabled: true,
level: 'trace',
transport: {
options: {
colorize: true,
singleLine: false,
translateTime: 'SYS:standard',
},
target: 'pino-pretty',
},
}

Environment-Specific Configuration

import pino from 'pino';

const getLoggerConfig = () => {
const isDevelopment = process.env.NODE_ENV === 'development';

if (isDevelopment) {
return {
level: 'debug',
transport: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'SYS:standard',
}
}
};
}

return {
level: 'info',
// Production: no pretty formatting, structured JSON
};
};

const customLogger = pino(getLoggerConfig());

🔗 Logger Types

Logger Type

TypeScript type for logger integration:

import { primitives } from '@nodeblocks/backend-sdk';

const { Logger } = primitives;

const useLogger = (logger: Logger) => {
logger.info('Using typed logger');
logger.error('Error with logger', { error: 'details' });
};

// Usage
useLogger(nodeblocksLogger);

Logger in Payload

Handlers receive a logger in the payload:

interface RouteHandlerPayload {
// ... other properties
logger?: Logger;
}

️📐 Best Practices

1. Structured Logging

// ✅ Good: Structured logging with context
nodeblocksLogger.info({
message: 'User action performed',
userId: 'user-123',
action: 'login',
timestamp: new Date().toISOString(),
metadata: { ip: '192.168.1.1' }
});

// ❌ Avoid: Simple string logging
nodeblocksLogger.info('User logged in'); // Missing context

2. Error Logging

// ✅ Good: Comprehensive error logging
try {
await riskyOperation();
} catch (error) {
nodeblocksLogger.error({
message: 'Operation failed',
error: error.message,
stack: error.stack,
context: { userId: 'user-123' }
});
throw error;
}

// ❌ Avoid: Minimal error logging
try {
await riskyOperation();
} catch (error) {
nodeblocksLogger.error('Error'); // Missing details
}

3. Performance Logging

// ✅ Good: Performance monitoring
const startTime = Date.now();
const result = await expensiveOperation();
const duration = Date.now() - startTime;

nodeblocksLogger.info({
message: 'Operation completed',
duration,
resultSize: result.length,
operation: 'expensiveOperation'
});

4. Conditional Logging

// ✅ Good: Environment-aware logging
const logLevel = process.env.NODE_ENV === 'development' ? 'debug' : 'info';
const logger = nodeblocksLogger.child({ level: logLevel });

logger.debug('Debug info only in development');
logger.info('Info in all environments');

🔗 See Also