Skip to content

Logging ​

Scoped Pino logger with async context tracking, structured data, and error reporting integration.

Creating Loggers ​

typescript
import { createLogger } from '@zyno-io/dk-server-foundation';

// From a class instance (uses class name as scope)
class OrderService {
    private logger = createLogger(this);

    async process() {
        this.logger.info('Processing order');
    }
}

// From a string
const logger = createLogger('PaymentWorker');

// With default data attached to every log
const logger = createLogger(this, { region: 'us-east-1' });

Log Levels ​

typescript
logger.debug('Debug message');
logger.info('Info message');
logger.warning('Warning message');
logger.error('Error message');
logger.alert('Alert message');

Structured Data ​

typescript
// Attach data to a log entry
logger.info('Order created', { orderId: 123, total: 99.99 });

// Error with context
logger.error('Payment failed', error, { orderId: 123, provider: 'stripe' });

Scoped Loggers ​

Create child loggers with a scope prefix and optional persistent data:

typescript
const logger = createLogger(this);

// Child logger with scope
const paymentLogger = logger.scoped('payment');
paymentLogger.info('Processing');
// Output: [OrderService:payment] Processing

// Child logger with persistent data
const orderLogger = logger.scoped('order', { orderId: 123 });
orderLogger.info('Created');
// Every log includes { orderId: 123 }

setScopeData(data?) ​

Update the persistent data attached to a scoped logger:

typescript
const logger = createLogger(this);
logger.setScopeData({ userId: 456 });
logger.info('Action');
// Includes { userId: 456 }

Async Context ​

Logger automatically includes async context properties in log entries. This means request IDs, trace IDs, and other context set via setContextProp() or withContextData() flow into logs automatically.

typescript
import { withContextData } from '@zyno-io/dk-server-foundation';

await withContextData({ reqId: 'abc-123' }, async () => {
    logger.info('Handling request');
    // Log includes reqId: 'abc-123'
});

withLoggerContext(data, fn) ​

Add additional logger context for the duration of a function:

typescript
import { withLoggerContext } from '@zyno-io/dk-server-foundation';

await withLoggerContext({ jobId: 'job-456' }, async () => {
    logger.info('Processing job');
    // Log includes jobId: 'job-456'
});

Error Handling ​

When logging errors, the logger automatically:

  1. Extracts the error message and stack trace
  2. Includes any cause chain
  3. Reports to the global error reporter (Sentry, Slack) for error and alert levels
typescript
try {
    await riskyOperation();
} catch (err) {
    logger.error('Operation failed', err);
    // Error reported to Sentry, details logged to Pino
}

ExtendedLogger ​

ExtendedLogger replaces Deepkit's default Logger in the DI container. It extends Logger with:

  • Pino as the underlying transport
  • Scoped child loggers
  • Async context integration
  • Error reporting to Sentry and Slack

All injected Logger instances are ExtendedLogger instances.

Pino Instance ​

Access the raw Pino logger:

typescript
import { pinoLogger } from '@zyno-io/dk-server-foundation';

pinoLogger.info({ custom: 'data' }, 'Raw pino log');

HTTP Request Logging ​

Request logging is handled by the HTTP kernel and configured via HTTP_REQUEST_LOGGING_MODE:

ModeDescription
e2eLog at request start and end
finishLog only at request end
errorsLog only errors
noneNo request logging

Health check logging is disabled by default. Enable with HEALTHZ_ENABLE_REQUEST_LOGGING=true.

Released under the MIT License.