npm.io
2.0.2 • Published yesterday

@beecode/msh-logger

Licence
mit
Version
2.0.2
Deps
3
Size
88 kB
Vulns
0
Weekly
0

Build Status codecov GitHub license NPM

@beecode/msh-logger

Micro-service helper: logging abstraction using the Strategy Pattern

A TypeScript logging abstraction that decouples formatting from transport. Built on the Strategy Pattern with pluggable formatting strategies, transporting strategies, and ready-made presets for common setups.

Install

npm i @beecode/msh-logger

Quick Start

import { LogLevel } from '@beecode/msh-logger'
import { PresetConsoleSimpleString } from '@beecode/msh-logger/controller/preset/console-simple-string'

const logger = new PresetConsoleSimpleString({ logLevel: LogLevel.INFO })

logger.debug('This is hidden') // filtered out (below INFO)
logger.info('Server started', { port: 3000 })
logger.warn('Deprecation warning')
logger.error('Something went wrong', new Error('boom'))

Output:

2026-05-30T12:00:00.000Z - INFO: Server started { port: 3000 }
2026-05-30T12:00:00.000Z - WARN: Deprecation warning
2026-05-30T12:00:00.000Z - ERROR: Something went wrong Error: boom

Architecture

Diagram

vision-diagram

Format-Transport Separation

The logger is built on two independent, composable strategy layers:

  • FormattingStrategy — transforms log data (level, meta, category, timestamp) plus messages into structured FormattedLog[] objects.
  • TransportingStrategy — receives FormattedLog objects and writes them to a destination (console, Pino, stream, etc.).

The LoggerStrategyBase composes one of each. Presets pre-wire common combinations so you don't have to think about the two layers individually.

src/
├── business/
│   ├── model/
│   │   └── log-level.ts                         # LogLevel enum
│   └── service/
│       ├── logger-strategy.ts                    # LoggerStrategy interface
│       ├── logger-strategy/
│       │   └── base.ts                           # LoggerStrategyBase
│       ├── formatting-strategy.ts                # FormattingStrategy interface
│       ├── formatting-strategy/
│       │   ├── simple-string.ts                  # FormattingStrategySimpleString
│       │   └── json.ts                           # FormattingStrategyJson
│       ├── transporting-strategy.ts              # TransportingStrategy interface
│       └── transporting-strategy/
│           ├── console.ts                        # TransportingStrategyConsole
│           ├── pino.ts                           # TransportingStrategyPino
│           ├── stream.ts                         # TransportingStrategyStream
│           └── void.ts                           # TransportingStrategyVoid
└── controller/preset/                       # Pre-wired presets
    ├── console-simple-string.ts             # PresetConsoleSimpleString
    ├── console-json.ts                      # PresetConsoleJson
    ├── pino.ts                              # PresetPino
    └── void.ts                              # PresetVoid

Presets (convenience wrappers):

Preset Formatting Transporting
PresetConsoleSimpleString FormattingStrategySimpleString TransportingStrategyConsole
PresetConsoleJson FormattingStrategyJson TransportingStrategyConsole
PresetPino FormattingStrategyJson TransportingStrategyPino
PresetVoid — (no-op)

Log Levels

The LogLevel enum controls which messages are emitted. Higher numeric severity means more critical:

Level Value Description
LogLevel.FATAL 60 Unrecoverable — the process must terminate
LogLevel.ERROR 50 Unexpected failure — a feature failed but the process can continue
LogLevel.WARN 40 Degraded behavior — unexpected but recoverable
LogLevel.INFO 30 Business-significant events — service started, user logged in
LogLevel.DEBUG 20 Diagnostic detail — request/response payloads, branching decisions
LogLevel.TRACE 10 Fine-grained flow — function entry/exit, variable dumps

When a logger is created, it defaults to LogLevel.ERROR (most restrictive). Any log at or above the configured level is emitted; lower levels are silently dropped.

Presets

Presets are the easiest way to get started. Each pre-wires a specific formatting + transporting combination.

PresetConsoleSimpleString

Human-readable console output with timestamps. Good for local development.

import { LogLevel } from '@beecode/msh-logger'
import { PresetConsoleSimpleString } from '@beecode/msh-logger/controller/preset/console-simple-string'

const logger = new PresetConsoleSimpleString({
  logLevel: LogLevel.DEBUG,
  category: 'my-app',
  meta: { service: 'api', version: '1.0.0' },
})

Constructor params (inherits LoggerStrategyParams, omits strategies):

Param Type Default Description
logLevel LogLevel LogLevel.ERROR Minimum log level to emit
category string undefined Category label added to every log entry
meta ObjectType undefined Metadata attached to every log entry

Output format:

2026-05-30T12:00:00.000Z - INFO: [my-app] Hello world
PresetConsoleJson

JSON-formatted console output. Good for structured log ingestion.

import { LogLevel } from '@beecode/msh-logger'
import { PresetConsoleJson } from '@beecode/msh-logger/controller/preset/console-json'

const logger = new PresetConsoleJson({
  logLevel: LogLevel.INFO,
  category: 'my-app',
  meta: { service: 'api' },
})

Constructor params: same as PresetConsoleSimpleString.

Output format:

{"level":"INFO","timestamp":1748606400000,"category":"my-app","message":"Hello world"}

When meta is provided, it is spread into the JSON payload:

{"service":"api","level":"INFO","timestamp":1748606400000,"category":"my-app","message":"Hello world"}
PresetPino

Production-grade logging via Pino. Delegates formatting and transport to the Pino library.

import { LogLevel } from '@beecode/msh-logger'
import { PresetPino } from '@beecode/msh-logger/controller/preset/pino'

const logger = new PresetPino({
  logLevel: LogLevel.INFO,
})

Constructor params (PresetPinoParams):

Param Type Default Description
logLevel LogLevel LogLevel.ERROR Minimum log level to emit
category string undefined Category label added to every log entry
meta ObjectType undefined Metadata attached to every log entry
pinoLogger pino.Logger pino() Custom Pino logger instance
PresetVoid

The default no-op logger. All log calls are silently ignored — useful for testing or disabling logging entirely.

import { PresetVoid } from '@beecode/msh-logger/controller/preset/void'

const logger = new PresetVoid()

logger.info('This does nothing')
logger.error('Neither does this')

Formatting Strategies

Formatting strategies transform raw log data into FormattedLog[] objects. Each FormattedLog contains a level, message, and optional metadata.

FormattingStrategySimpleString

Human-readable format with timestamps. Produces messages like 2026-05-30T12:00:00.000Z - INFO: [category] message.

import { FormattingStrategySimpleString } from '@beecode/msh-logger/business/service/formatting-strategy/simple-string'

const formatter = new FormattingStrategySimpleString()
FormattingStrategyJson

Structured JSON format. Extracts message from objects and spreads remaining keys into metadata.

import { FormattingStrategyJson } from '@beecode/msh-logger/business/service/formatting-strategy/json'

const formatter = new FormattingStrategyJson()

Transporting Strategies

Transporting strategies receive FormattedLog objects and write them to a destination.

TransportingStrategyConsole

Writes to console.* methods, mapping log levels to the appropriate console function.

import { TransportingStrategyConsole } from '@beecode/msh-logger/business/service/transporting-strategy/console'

const transport = new TransportingStrategyConsole()
TransportingStrategyPino

Sends logs to a Pino logger instance. Optionally inject a custom Pino logger; defaults to pino().

import { TransportingStrategyPino } from '@beecode/msh-logger/business/service/transporting-strategy/pino'

const transport = new TransportingStrategyPino() // uses default pino()
// or with a custom instance:
// const transport = new TransportingStrategyPino(customPinoLogger)
TransportingStrategyStream

Writes JSON-stringified FormattedLog to any NodeJS.WritableStream. Useful for piping logs to files, HTTP streams, or custom destinations.

import { createWriteStream } from 'node:fs'
import { TransportingStrategyStream } from '@beecode/msh-logger/business/service/transporting-strategy/stream'

const stream = createWriteStream('./app.log')
const transport = new TransportingStrategyStream(stream)
TransportingStrategyVoid

No-op transport. Silently drops all logs.

import { TransportingStrategyVoid } from '@beecode/msh-logger/business/service/transporting-strategy/void'

const transport = new TransportingStrategyVoid()

Custom LoggerStrategyBase

Combine any formatting strategy with any transporting strategy to build a custom logger:

import { LogLevel } from '@beecode/msh-logger'
import { LoggerStrategyBase } from '@beecode/msh-logger/business/service/logger-strategy/base'
import { FormattingStrategyJson } from '@beecode/msh-logger/business/service/formatting-strategy/json'
import { TransportingStrategyStream } from '@beecode/msh-logger/business/service/transporting-strategy/stream'
import { createWriteStream } from 'node:fs'

const logger = new LoggerStrategyBase({
  formattingStrategy: new FormattingStrategyJson(),
  transportingStrategy: new TransportingStrategyStream(createWriteStream('./app.log')),
  logLevel: LogLevel.DEBUG,
  category: 'my-service',
  meta: { env: 'production' },
})

Constructor params (LoggerStrategyBaseParams):

Param Type Default Description
formattingStrategy FormattingStrategy (required) Strategy for formatting log data
transportingStrategy TransportingStrategy (required) Strategy for transporting formatted logs
logLevel LogLevel LogLevel.ERROR Minimum log level to emit
category string undefined Category label added to every log entry
meta ObjectType undefined Metadata attached to every log entry

Creating Child Loggers (clone)

Use clone() to create a child logger that inherits settings from a parent, with optional overrides:

import { LogLevel } from '@beecode/msh-logger'
import { PresetConsoleSimpleString } from '@beecode/msh-logger/controller/preset/console-simple-string'

const parent = new PresetConsoleSimpleString({
  logLevel: LogLevel.INFO,
  category: 'app',
  meta: { service: 'api' },
})

// Child inherits everything, overrides category and adds meta
const child = parent.clone({
  category: 'app:router',
  meta: { route: '/users' },
})

child.info('User listed')
// Meta is shallow-merged: { service: 'api', route: '/users' }

API Reference

Full API documentation is generated with TypeDoc and available in resource/doc/api/.

Public exports (from @beecode/msh-logger):

Export Kind Description
LogLevel enum Log level values: FATAL, ERROR, WARN, INFO, DEBUG, TRACE
LoggerStrategy interface Contract for all logger implementations
LoggerStrategyParams type Params for configuring loggers and clone()
ObjectType type Record<string, unknown> — metadata bag

Formatting types (from @beecode/msh-logger/business/service/formatting-strategy):

Export Kind Description
FormattedLog type Intermediate structure: { level, message, metadata? }
FormattingStrategy interface Contract for formatting strategies

Preset imports (via subpath):

Import path Export
@beecode/msh-logger/controller/preset/console-simple-string PresetConsoleSimpleString
@beecode/msh-logger/controller/preset/console-json PresetConsoleJson
@beecode/msh-logger/controller/preset/pino PresetPino
@beecode/msh-logger/controller/preset/void PresetVoid

Formatting strategy imports (via subpath):

Import path Export
@beecode/msh-logger/business/service/formatting-strategy/json FormattingStrategyJson
@beecode/msh-logger/business/service/formatting-strategy/simple-string FormattingStrategySimpleString

Transporting strategy imports (via subpath):

Import path Export
@beecode/msh-logger/business/service/transporting-strategy/console TransportingStrategyConsole
@beecode/msh-logger/business/service/transporting-strategy/pino TransportingStrategyPino
@beecode/msh-logger/business/service/transporting-strategy/stream TransportingStrategyStream
@beecode/msh-logger/business/service/transporting-strategy/void TransportingStrategyVoid

Base class import (via subpath):

Import path Export
@beecode/msh-logger/business/service/logger-strategy/base LoggerStrategyBase, LoggerStrategyBaseParams

Migrating from v1 to v2

See MIGRATION.md for a complete guide covering all breaking changes and code examples.

License

MIT