Overview
Fast, zero-dependencies, secure logger for Node.js that doesn't suck. Built for production, not resumes.
cenglu
cenglu is a fast, zero-dependencies, secure logger for Node.js that doesn't suck. Built for production, not resumes.
Why Cenglu?
Cenglu is a production-ready logging library designed for modern Node.js applications with a focus on:
- Performance - Optimized for high throughput with minimal overhead
- Security - Built-in redaction for sensitive data (PII, credentials, API keys)
- Zero Dependencies - No external dependencies, small bundle size (< 500KB)
- Type-Safe - Written in TypeScript with comprehensive type definitions
- Extensible - Plugin system for custom behaviors
- Framework-Ready - Middleware for Express, NestJS, Fastify, and Koa
- Production-Ready - File rotation, batching, correlation IDs, distributed tracing
Quick Start
Install Cenglu using your preferred package manager:
npm install cengluGet started quickly with a basic logger:
import { createLogger } from "cenglu";
const logger = createLogger({
service: "my-app",
level: "info",
});
logger.info("Application started", { port: 3000 });For detailed installation instructions, TypeScript configuration, and import paths, see Installation Guide.
With Express
import express from "express";
import { createLogger, expressMiddleware } from "cenglu";
const app = express();
const logger = createLogger({ service: "api" });
app.use(expressMiddleware(logger));
app.get("/users/:id", (req, res) => {
// Logger is automatically attached with request context
req.logger.info("Fetching user", { userId: req.params.id });
res.json({ id: req.params.id });
});Key Features
Security-First Redaction
Automatically redact sensitive information like passwords, API keys, credit cards, and PII:
const logger = createLogger({
redaction: { enabled: true },
});
logger.info("User registered", {
password: "super-secret", // -> [REDACTED]
apiKey: "sk_live_abc123", // -> [REDACTED]
});Learn about patterns, compliance presets (PCI/GDPR/HIPAA), and advanced configuration in the Redaction Guide.
Child Loggers & Context Binding
// Child logger (shares transports/config)
const requestLogger = logger.child({ requestId: "abc-123" });
requestLogger.info("Processing request");
// Lightweight bound logger (temporary bindings)
logger.with({ userId: 123 }).info("User action", { action: "login" });Performance Timing
const done = logger.time("database-query");
await db.query("SELECT * FROM users");
done(); // Logs: "database-query completed" { durationMs: 42 }
// With additional context
done.endWithContext({ rowCount: 10 });
// Get elapsed time without logging
const ms = done.elapsed();Pretty Logs for Development
const logger = createLogger({
pretty: {
enabled: process.env.NODE_ENV !== "production"
},
});
// Outputs colored, formatted logs in dev; JSON in productionMultiple Output Formats
const logger = createLogger({
structured: {
type: "ecs", // json | ecs | datadog | splunk | logfmt
},
});Support for Elasticsearch (ECS), Datadog, Splunk, and logfmt formats. See the Formatters Guide for details.
Testing Utilities
Built-in testing utilities make it easy to test code that uses the logger:
import { createTestLogger } from "cenglu/testing";
describe("UserService", () => {
it("logs user creation", () => {
const { logger, transport } = createTestLogger();
service.createUser({ email: "test@example.com" });
expect(transport.hasLog("info", "User created")).toBe(true);
expect(transport.last()?.context?.email).toBe("test@example.com");
});
});Includes mock time control, deterministic sampling, custom matchers for Vitest/Jest, and assertion helpers. See the Testing Guide for comprehensive examples.
Community & Support
- GitHub: ayungavis/cenglu
- Issues: Report bugs
- NPM: cenglu
License
MIT © Wahyu Kurniawan