cenglu

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 cenglu

Get 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 production

Multiple 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

License

MIT © Wahyu Kurniawan

On this page