Quick Reference
Quick reference guide for common cenglu operations
Quick Reference
Quick reference cheatsheet for common cenglu operations and patterns.
For detailed guides, see Installation, Basic Usage, and Configuration.
Installation
npm install cengluBasic Usage
import { createLogger } from "cenglu";
const logger = createLogger({ service: "my-app" });
logger.info("Hello, world!");Log Levels
logger.trace("Trace level"); // 10 - Most verbose
logger.debug("Debug level"); // 20
logger.info("Info level"); // 30 - Default
logger.warn("Warning level"); // 40
logger.error("Error level"); // 50
logger.fatal("Fatal level"); // 60 - Most severeContext & Bindings
// With context
logger.info("User action", { userId: 123, action: "login" });
// Child logger (permanent bindings)
const child = logger.child({ module: "users" });
child.info("Message"); // Includes module: "users"
// Bound logger (temporary bindings)
logger.with({ requestId: "abc" }).info("Message");
// Chain bindings
logger
.with({ userId: 123 })
.with({ sessionId: "xyz" })
.info("Message");See Context & Bindings for AsyncLocalStorage, correlation IDs, and automatic context propagation.
Error Logging
// With error object
try {
await operation();
} catch (error) {
logger.error("Operation failed", error);
logger.error("Operation failed", error, { attemptCount: 3 });
}
// Without error object
logger.error("Configuration invalid", { file: "config.json" });Configuration
const logger = createLogger({
// Basic
level: "info",
service: "my-app",
env: "production",
version: "1.0.0",
// Bindings
bindings: { region: "us-east-1" },
// Pretty logs (development)
pretty: {
enabled: process.env.NODE_ENV !== "production",
},
// Structured output (production)
structured: {
type: "json", // json | ecs | datadog | splunk | logfmt
},
// See [Formatters](/docs/features/formatters) for format details
// Security
redaction: {
enabled: true,
paths: ["password", "apiKey"],
},
// Performance
sampling: {
rates: { trace: 0.1, debug: 0.5 },
},
// See [Sampling](/docs/features/sampling) for strategies and monitoring
// Distributed tracing
correlationId: () => crypto.randomUUID(),
});Redaction
// Enable default redaction
const logger = createLogger({
redaction: { enabled: true },
});
// Custom paths and patterns
redaction: {
enabled: true,
paths: ["password", "apiKey", "user.password"],
patterns: [{ pattern: /Bearer\s+\S+/g, replacement: "Bearer [REDACTED]" }],
customRedactor: (value, key) => {
// Custom logic
return undefined;
},
}See the Redaction Guide for default patterns, compliance presets (PCI/GDPR/HIPAA), and advanced usage.
Middleware
Express
import { expressMiddleware } from "cenglu";
app.use(expressMiddleware(logger, {
ignorePaths: ["/health"],
includeQuery: true,
correlationIdHeader: "x-correlation-id",
}));
app.get("/users", (req, res) => {
req.logger.info("Fetching users");
res.json({ users: [] });
});NestJS
import { nestjsMiddleware } from "cenglu";
app.use(nestjsMiddleware(logger, {
ignorePaths: ["/health"],
}));See middleware guides: Express, NestJS, Fastify, Koa
Plugins
import { samplingPlugin, rateLimitPlugin } from "cenglu";
const logger = createLogger({
plugins: [
samplingPlugin({ rates: { debug: 0.1 } }),
rateLimitPlugin({ maxLogs: 1000, windowMs: 1000 }),
],
});See Creating Plugins and Built-in Plugins for details.
Transports
See Console Transport, File Transport, and Custom Transports for detailed guides.
Console
import { createConsoleTransport } from "cenglu";
const logger = createLogger({
transports: [
createConsoleTransport({
enabled: true,
stream: process.stdout,
errorStream: process.stderr,
}),
],
});File with Rotation
import { createRotatingFileTransport } from "cenglu";
const logger = createLogger({
transports: [
createRotatingFileTransport({
enabled: true,
dir: "./logs",
separateErrors: true,
rotation: {
intervalDays: 1,
maxBytes: 10485760, // 10MB
maxFiles: 7,
compress: "gzip",
retentionDays: 30,
},
}),
],
});Performance Timing
// Basic timer
const done = logger.time("operation");
await operation();
done(); // Logs duration
// Timer with context
const timer = logger.time("query", { table: "users" });
await query();
timer.endWithContext({ rowCount: 100 });
// Get elapsed without logging
const timer = logger.time("op");
const ms = timer.elapsed();
console.log(`Took ${ms}ms`);Level Management
// Change level at runtime
logger.setLevel("debug");
// Get current level
const level = logger.getLevel(); // "debug"
// Check if level is enabled
if (logger.isLevelEnabled("debug")) {
logger.debug("Debug info", expensiveData());
}
// Conditional logging helpers
logger.ifDebug(() => {
return ["Debug info", computeExpensiveData()];
});Adapters
// Forward logs to external service
const logger = createLogger({
adapters: [
{
name: "datadog",
level: "info", // Only forward info and above
handle: async (record) => {
await datadogClient.log(record);
},
},
],
});Custom Plugin
const myPlugin = {
name: "my-plugin",
order: 50,
onRecord(record) { return { ...record, customField: "value" }; },
onWrite(record, formatted) { /* side effects */ },
async onFlush() { /* flush */ },
async onClose() { /* cleanup */ },
};
const logger = createLogger({ plugins: [myPlugin] });See Plugin System for hooks and lifecycle details.
Testing
import { createLogger } from "cenglu";
// Capture logs in tests
const logs: any[] = [];
const logger = createLogger({
adapters: [
{
name: "test",
handle: (record) => logs.push(record),
},
],
});
// Run tests
logger.info("Test message", { data: 123 });
// Assert
expect(logs).toHaveLength(1);
expect(logs[0]).toMatchObject({
level: "info",
msg: "Test message",
context: { data: 123 },
});Graceful Shutdown
process.on("SIGTERM", async () => {
console.log("Shutting down...");
// Flush pending logs
await logger.flush();
// Close transports and plugins
await logger.close();
process.exit(0);
});Common Patterns
Request Context
app.use((req, res, next) => {
req.logger = logger.child({
requestId: req.headers["x-request-id"] || uuid(),
method: req.method,
path: req.path,
});
next();
});Structured Errors
try {
await operation();
} catch (error) {
logger.error("Operation failed", error, {
operation: "create-user",
userId: 123,
attemptCount: 3,
});
}Async Context
import { LoggerContext, createRequestContext } from "cenglu";
app.use((req, res, next) => {
const context = createRequestContext({
id: uuid(),
method: req.method,
path: req.path,
});
LoggerContext.run(context, () => {
next();
});
});
// Logs automatically include context
logger.info("Processing request");Environment Variables
# Log level
LOG_LEVEL=debug
# File transport
LOG_TO_FILE=true
LOG_DIR=./logs
LOG_ROTATE_DAYS=1
LOG_MAX_BYTES=10485760
LOG_MAX_FILES=7
LOG_COMPRESS=gzip
LOG_RETENTION_DAYS=30
# Service metadata
SERVICE_NAME=my-app
SERVICE_VERSION=1.0.0
NODE_ENV=productionImport Paths
// Core
import { createLogger } from "cenglu";
// Middleware
import { expressMiddleware } from "cenglu/middleware";
import { nestjsMiddleware } from "cenglu/middleware";
// Plugins
import { samplingPlugin } from "cenglu/plugins";
// Transports
import { createFileTransport } from "cenglu/transports";
// Redaction
import { createRedactor } from "cenglu/redaction";
// Context
import { LoggerContext } from "cenglu/context";
// Format
import { formatEcs } from "cenglu/format";
// Testing
import { createTestLogger } from "cenglu/testing";Testing
import { createTestLogger } from "cenglu/testing";
// Create test logger with captured logs
const { logger, transport, time, random } = createTestLogger();
// Use in tests
logger.info("Test message", { userId: 123 });
// Assert logs
expect(transport.hasLog("info", "Test message")).toBe(true);
expect(transport.last()?.context?.userId).toBe(123);
// With custom matchers (after setup)
expect(transport).toHaveLogged("info", "Test message");
expect(transport).toHaveLoggedWithContext("userId", 123);For detailed testing guide, see Testing Documentation.