Skip to content

feat(logger): add structured logging with configurable levels and formats#94

Merged
gregpriday merged 3 commits into
developfrom
feature/issue-30-add-structured-logging
Feb 26, 2026
Merged

feat(logger): add structured logging with configurable levels and formats#94
gregpriday merged 3 commits into
developfrom
feature/issue-30-add-structured-logging

Conversation

@gregpriday
Copy link
Copy Markdown
Owner

Summary

Implements structured, configurable logging for the CopyTree CLI, replacing the legacy binary silent/debug model with a full level hierarchy, multiple output formats, and runtime reconfiguration from CLI flags.

Closes #30

Changes Made

Logger core (src/utils/logger.js)

  • Added log level hierarchy: error(0) < warn(1) < success(2) = info(2) < debug(3)
  • Added log formats: text (coloured terminal), json (NDJSON to stderr), silent (errors only)
  • Added colorize modes: auto (TTY detection), always, never
  • Routes all logs to stderr by default; stdout is reserved for program output
  • Added configure() for runtime reconfiguration from CLI flags
  • Reads COPYTREE_LOG_LEVEL and COPYTREE_LOG_FORMAT directly from process.env
  • Safe JSON serialization with fallbacks for circular refs, BigInt, and Symbol
  • Replaced custom _stripAnsi with the strip-ansi package (with string guards)

CLI (bin/copytree.js)

  • Added --log-level <error|warn|info|debug> flag (default: info)
  • Added --log-format <text|json|silent> flag (default: text)
  • Added --no-color flag to disable ANSI codes
  • Uses InvalidArgumentError for option validation (proper Commander.js pattern)

Config (config/logging.js, config/schema.json)

  • Added logging.* config section with defaults for level, format, colorize, timestamp, destination
  • Full JSON Schema validation for all logging config values

Pipeline/Stage integration

  • Stage.log() now routes through the logger (maps infologger.debug() for backward compat — stage progress was previously silent by default)
  • Pipeline.js uses this.context.logger consistently (replaced console.warn and a stray defaultLogger.warn)
  • Stream mode forces destination: 'stderr' to keep stdout clean for piped output

Tests

  • Added 27 unit tests for the real Logger class in tests/unit/utils/logger.test.js
  • Added a dedicated loggerUnitProject in jest.config.js that tests the real logger without mocking it
  • E2E tests set COPYTREE_LOG_LEVEL=error so golden file assertions remain clean

- Add missing "peer": true annotations to @babel/eslint-parser,
  @types/node, acorn, browserslist, eslint-visitor-keys, and react
  entries after post-merge npm install
…mats

- Add log levels (error/warn/info/debug) with numeric priority hierarchy
- Add log formats: text (coloured), json (NDJSON), silent (errors-only)
- Add colorize modes: auto (TTY detection), always, never
- Route all logs to stderr by default; stdout reserved for program output
- Add configure() for runtime reconfiguration from CLI flags
- Read COPYTREE_LOG_LEVEL and COPYTREE_LOG_FORMAT directly from process.env
- Add --log-level, --log-format, --no-color flags to copytree CLI
- Force destination=stderr in stream mode to keep stdout clean
- Use InvalidArgumentError for CLI option validation (not process.exit)
- Add logging defaults in config/logging.js and schema/schema.json
- Replace custom _stripAnsi with strip-ansi package (with string guards)
- Add safe JSON serialization for circular refs, BigInt, and Symbol
- Route Stage.log() through logger (info→debug for backward compat)
- Replace console.warn in Pipeline with context.logger for consistency
- Add 27 unit tests for Logger via dedicated loggerUnitProject in Jest
- Suppress log noise in E2E tests via COPYTREE_LOG_LEVEL=error env var
@gregpriday gregpriday merged commit c6f1b15 into develop Feb 26, 2026
11 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add structured logging with configurable levels and formats

1 participant