Utilities
Helper functions and utilities that make logging easier and more powerful.
Attribute Builder
Fluent API for building attributes:
import { attrs, New, JSONHandler } from '@omdxp/jslog';
const logger = New(new JSONHandler());
const userAttrs = attrs()
.str('username', 'alice')
.num('age', 30)
.bool('active', true)
.if(user.isPremium, 'tier', 'premium')
.build();
logger.info('User created', ...userAttrs);
Methods
const builder = attrs();
// Add attributes
builder.str(key: string, value: string);
builder.num(key: string, value: number);
builder.bool(key: string, value: boolean);
builder.time(key: string, value: Date);
builder.any(key: string, value: any);
builder.group(name: string, ...attrs: Attr[]);
// Conditional attributes
builder.if(condition: boolean, key: string, value: any);
// Build final array
const attributes = builder.build();
Correlation IDs
Track requests across your application:
import {
setCorrelationId,
getCorrelationId,
CorrelationId,
clearCorrelationId
} from '@omdxp/jslog';
// Set correlation ID for request
app.use((req, res, next) => {
setCorrelationId(generateRequestId());
next();
});
// Use in logs
logger.info('Processing request', CorrelationId());
// Get current ID
const id = getCorrelationId();
// Clear after request
app.use((req, res, next) => {
res.on('finish', () => clearCorrelationId());
next();
});
Performance Timers
Measure operation duration:
import { startTimer, Timer } from '@omdxp/jslog';
// Start a timer
const timer = startTimer('database_query');
// Do work
await queryDatabase();
// Log with elapsed time
logger.info('Query completed', timer.elapsed());
// Output: duration_ms=145
// Or get duration manually
const duration = timer.getDuration();
Timer Methods
const timer = new Timer('operation_name');
// Get elapsed time as attribute
timer.elapsed(); // Returns Attr with duration in ms
// Get raw duration
timer.getDuration(); // Returns number (milliseconds)
// Check if timer is running
timer.isRunning(); // Returns boolean
HTTP Helpers
Log HTTP requests and responses easily:
HTTP Request
import { HttpReq } from '@omdxp/jslog';
logger.info('Incoming request', ...HttpReq({
method: req.method,
url: req.url,
ip: req.ip,
userAgent: req.headers['user-agent'],
headers: req.headers
}));
HTTP Response
import { HttpRes } from '@omdxp/jslog';
logger.info('Response sent', ...HttpRes({
status: res.statusCode,
duration: Date.now() - startTime,
size: res.getHeader('content-length')
}));
SQL Query Helper
import { SqlQuery } from '@omdxp/jslog';
logger.info('Database query', ...SqlQuery({
query: 'SELECT * FROM users WHERE id = ?',
params: [userId],
duration: queryTime,
rows: result.length
}));
Data Masking
Redact sensitive information:
Email Masking
import { maskEmail, String } from '@omdxp/jslog';
logger.info('User email',
String('email', maskEmail('alice@example.com'))
);
// Output: a***@example.com
Credit Card Masking
import { maskCreditCard } from '@omdxp/jslog';
logger.info('Payment',
String('card', maskCreditCard('4532-1234-5678-9010'))
);
// Output: ****-****-****-9010
Phone Masking
import { maskPhone } from '@omdxp/jslog';
logger.info('Contact',
String('phone', maskPhone('555-123-4567'))
);
// Output: ***-***-4567
Custom Redaction
import { redact } from '@omdxp/jslog';
const redacted = redact('sensitive data', 3);
// Output: sen***
System Information
Environment Info
import { EnvInfo } from '@omdxp/jslog';
logger.info('Application started', ...EnvInfo());
// Adds: platform, arch, nodeVersion, cwd, etc.
Memory Usage
import { MemoryUsage } from '@omdxp/jslog';
logger.info('Health check', ...MemoryUsage());
// Adds: heapUsed, heapTotal, rss, external
Stack Traces
Capture stack traces for errors:
import { StackTrace } from '@omdxp/jslog';
try {
riskyOperation();
} catch (error) {
logger.error('Operation failed',
Err(error),
StackTrace()
);
}
Caller Information
Get source file and line number:
import { Caller } from '@omdxp/jslog';
logger.info('Debug point', Caller());
// Adds: file, line, function
Lazy Evaluation
Defer expensive computations:
import { lazy } from '@omdxp/jslog';
logger.debug('Stats',
lazy('expensive_data', () => {
// Only executed if DEBUG level is enabled
return computeExpensiveStats();
})
);
Safe Stringify
Safely serialize objects with circular references:
import { safeStringify } from '@omdxp/jslog';
const circular = { a: 1 };
circular.self = circular;
const json = safeStringify(circular);
// No error, circular reference handled
ID Generation
Generate unique identifiers:
import { generateRequestId, generateTraceId } from '@omdxp/jslog';
// Request ID (UUID v4)
const requestId = generateRequestId();
// Output: "550e8400-e29b-41d4-a716-446655440000"
// Trace ID (for distributed tracing)
const traceId = generateTraceId();
// Output: "1234567890abcdef"
Complete Example
Putting it all together:
import {
New,
JSONHandler,
attrs,
startTimer,
setCorrelationId,
CorrelationId,
HttpReq,
HttpRes,
maskEmail,
String,
Err
} from '@omdxp/jslog';
const logger = New(new JSONHandler());
app.use((req, res, next) => {
// Set correlation ID
setCorrelationId(generateRequestId());
// Start request timer
const timer = startTimer('request');
// Log request
logger.info('Request started',
CorrelationId(),
...HttpReq({
method: req.method,
url: req.url,
ip: req.ip
})
);
res.on('finish', () => {
// Build attributes
const responseAttrs = attrs()
.num('statusCode', res.statusCode)
.num('duration', timer.getDuration())
.if(req.user, 'userId', req.user?.id)
.if(req.user?.email, 'email', maskEmail(req.user.email))
.build();
// Log response
logger.info('Request completed',
CorrelationId(),
timer.elapsed(),
...responseAttrs
);
});
next();
});
Best Practices
Do:
- Use attribute builders for complex log entries
- Mask sensitive data (emails, credit cards, etc.)
- Add correlation IDs for request tracking
- Use timers to measure performance
- Leverage lazy evaluation for expensive computations
Don't:
- Log unmasked PII
- Create timers without using them
- Forget to clear correlation IDs
- Overuse lazy evaluation (has overhead)
See Also
- Attributes - Core attribute concepts
- Middleware - Transform and enrich logs
- Examples - Real-world examples