Libraries
    Preparing search index...

    Module @cleverbrush/log

    @cleverbrush/log

    Enterprise structured logging for TypeScript — Serilog-style message templates, CLEF format, batching sinks with circuit breaking, ambient correlation IDs.

    npm install @cleverbrush/log
    
    import {
    createLogger,
    consoleSink,
    hostnameEnricher,
    processIdEnricher,
    } from '@cleverbrush/log';

    const logger = createLogger({
    minimumLevel: 'information',
    sinks: [consoleSink({ theme: 'dark' })],
    enrichers: [hostnameEnricher(), processIdEnricher()],
    });

    logger.info('Server started on port {Port}', { Port: 3000 });
    logger.error(new Error('oops'), 'Request failed for {UserId}', { UserId: 42 });

    await logger.dispose();
    • Message Templates{Named} properties captured as structured data
    • Typed TemplatesTypedTemplate<T> via @cleverbrush/schema for compile-time checked, groupable log events
    • CLEF Format — Compact Log Event Format for Seq, ClickHouse, etc.
    • Sinks — Console, File (with rotation), Seq, ClickHouse, custom
    • Batching — All network sinks batch with retry & circuit breaking
    • Enrichers — hostname, processId, environment, application, correlationId, caller
    • Correlation IDs — UUID v7, extracted from headers, propagated via AsyncLocalStorage
    • Middleware — Request logging & correlation ID for @cleverbrush/server
    • DIconfigureLogging() for @cleverbrush/di
    • Sampling — Per-level sampling filters

    Pass a ParseStringSchemaBuilder (from @cleverbrush/schema) directly to any log method. The logger uses the raw {Property} pattern as messageTemplate so all events of the same shape are grouped in Seq, SigNoz, ClickHouse, etc., while the rendered message is interpolated as usual.

    import { s } from '@cleverbrush/schema';
    import { createLogger, consoleSink } from '@cleverbrush/log';

    // Define once — compile-time checked parameter types
    const TodoCreated = s.parseString('Todo #{TodoId} "{Title}" created by {UserId}');

    const logger = createLogger({ sinks: [consoleSink()] });

    // TypeScript enforces { TodoId, Title, UserId }
    logger.info(TodoCreated, { TodoId: 1, Title: 'Buy milk', UserId: 'u-42' });
    import { useLogging } from '@cleverbrush/log';

    // Returns [correlationIdMiddleware, requestLoggingMiddleware]
    const [correlationId, requestLogging] = useLogging(logger, {
    excludePaths: ['/health'],
    // Set to false when OTel traceparent already provides traceability
    correlationResponseHeader: false,
    });

    correlationResponseHeader: false suppresses the X-Correlation-Id response header entirely — useful when @cleverbrush/otel's tracing middleware already sets a traceparent / traceresponse header and a second ID would be redundant.

    Trace correlation, OTLP log export, and the traceEnricher (which copies the active span's traceId / spanId onto every log event) live in @cleverbrush/otel. Wire them up like this:

    import { createLogger, consoleSink } from '@cleverbrush/log';
    import { otelLogSink, traceEnricher } from '@cleverbrush/otel';

    const logger = createLogger({
    sinks: [consoleSink(), otelLogSink()],
    enrichers: [traceEnricher()],
    });

    @cleverbrush/log itself stays free of any OpenTelemetry runtime dependency.

    BSD-3-Clause

    Modules

    clickhouse