logd 0.6.0 copy "logd: ^0.6.0" to clipboard
logd: ^0.6.0 copied to clipboard

High‑precision hierarchical logging for Dart and Flutter. Engineered for architectural clarity, O(1) configuration resolution, and zero‑overhead performance.

logd #

A high‑performance hierarchical logger for Dart and Flutter. Build structured logs, control output destinations, and keep overhead minimal.

Pub Version
Pub Points
License: BSD 3‑Clause

Why logd? #

  • Hierarchical configuration – Loggers are named with dot‑separated paths (app.network.http). Settings propagate from parents to children unless overridden.
  • Zero‑boilerplate – Simple Logger.get('app') gives a fully‑configured logger.
  • Performance‑first – Lazy resolution, aggressive caching, and optional inheritance freezing keep the cost of a disabled logger essentially zero.
  • Flexible output – Choose between console, file, network, or any custom sink; format logs as plain text, boxed, structured JSON, or LLM‑optimized TOON.
  • Platform‑agnostic styling – Decouple visual intent from representation using the semantic LogTheme system.

Getting Started #

Add logd to your project:

dependencies:
  logd: ^latest_version

Then run:

dart pub get  # or flutter pub get

Quick Example #

import 'package:logd/logd.dart';

void main() {
  final logger = Logger.get('app');

  logger.info('Application started');
  logger.debug('Debug message');
  logger.warning('Low disk space');
  logger.error('Connection failed',
    error: exception,
    stackTrace: stack,
  );
}

Typical console output

[app][INFO] 2025-01-23 05:30:12.456
  --example/main.dart:12 (main)
  ----Application started

Tip: Use Logger.configure to set global log‑levels, handlers, or timestamps. logd uses Deep Equality to ensure that re-configuring with identical values results in zero performance overhead.

Core Concepts #

Hierarchical Loggers #

Loggers inherit configuration from their ancestors.

// Configure the entire app
Logger.configure('app', logLevel: LogLevel.warning);

// Override a subsystem
Logger.configure('app.network', logLevel: LogLevel.debug);

// Create a logger deep in the tree
final uiLogger = Logger.get('app.ui.button');  // inherits WARNING
final httpLogger = Logger.get('app.network.http'); // inherits DEBUG

Log levels #

Level Description
trace Diagnostic noise
debug Developer debugging
info Informational
warning Potential issue
error Failure

Advanced Features #

Custom Handlers #

Create complex pipelines of formatters and sinks:

final jsonHandler = Handler(
  formatter: JsonFormatter(),
  sink: FileSink(
    'logs/app.log',
    fileRotation: TimeRotation(
      interval: Duration(days: 1),
      timestamp: Timestamp(formatter: 'yyyy-MM-dd'),
      backupCount: 7,
      compress: true,
    ),
  ),
  filters: [LevelFilter(LogLevel.info)],  // Only info and above
);

Logger.configure('app', handlers: [jsonHandler]);

Result: JSON logs written to logs/app.log, rotated daily, keeping 7 compressed backups.

Atomic multi‑line logs #

Prevent interleaving in concurrent environments:

final buffer = logger.infoBuffer;
buffer?.writeln('=== User Session ===');
buffer?.writeln('User ID: ${user.id}');
buffer?.writeln('Login time: ${DateTime.now()}');
buffer?.writeln('IP: ${request.ip}');
buffer?.sink(); // writes atomically

Multiple Outputs #

You can either use multiple handlers:

final consoleHandler = Handler(
  formatter: StructuredFormatter(),
  decorators: const [
    BoxDecorator(),
    StyleDecorator(),
  ],
  sink: const ConsoleSink(),
  lineLength: 80,
);

final fileHandler = Handler(
  formatter: PlainFormatter(),
  sink: FileSink('logs/app.log'),
);

Logger.configure('global', handlers: [consoleHandler, fileHandler]);

Or use a multi-sink in a handler:

final multiSinkHandler = Handler(
  formatter: PlainFormatter(),
  sink: MultiSink(sinks: [
    ConsoleSinK(),
    FileSink('logs/app.log'),
    ],
  ),
);

Filtering #

Control which logs reach which handlers:

// Level-based filtering
final errorHandler = Handler(
  formatter: JsonFormatter(),
  sink: FileSink('logs/errors.log'),
  filters: [LevelFilter(LogLevel.error)],  // Errors only
);

// Regex-based filtering (exclude sensitive data)
final publicHandler = Handler(
  formatter: PlainFormatter(),
  sink: NetworkSink('https://logs.example.com'),
  filters: [
    RegexFilter(r'password|secret|token', exclude: true),
  ],
);

Timezone & Timestamp #

final timestamp = Timestamp(
  formatter: 'yyyy-MM-dd HH:mm:ss.SSS Z',
  timezone: Timezone.named('America/New_York'),
);

Logger.configure('app', timestamp: timestamp);

File Rotation #

Strategy Example
Size FileSink('logs/app.log', fileRotation: SizeRotation(maxSize: '10 MB', backupCount: 5, compress: true))
Time FileSink('logs/app.log', fileRotation: TimeRotation(interval: Duration(hours: 1), timestamp: Timestamp(formatter: 'yyyy-MM-dd_HH'), backupCount: 24))

Performance Tuning #

Logger.get('app').freezeInheritance();   // snapshot config, eliminate runtime look‑ups

Use Cases #

Development Console #

Logger.configure('global', handlers: [
  const Handler(
    formatter: StructuredFormatter(),
    decorators: [
      HierarchyDepthPrefixDecorator(indent: '│ '),
      BoxDecorator(borderStyle: BorderStyle.rounded),
      StyleDecorator(theme: LogTheme(colorScheme: LogColorScheme.darkScheme)),
    ],
    sink: ConsoleSink(),
    lineLength: 80,
  ),
]);

Production JSON #

Logger.configure('global', handlers: [
  Handler(
    formatter: JsonFormatter(),
    sink: FileSink('logs/production.log'),
    ),
]);

LLM-Native Logging (TOON) #

Optimize logs for consumption by AI agents by using the Token-Oriented Object Notation:

Logger.configure('ai.agent', handlers: [
  Handler(
    formatter: ToonFormatter(
      arrayName: 'context',
      keys: [LogField.timestamp, LogField.message],
    ),
    sink: FileSink('logs/ai_feed.toon'),
  ),
]);

Result: A highly token-efficient, flat format that LLMs can parse with minimal overhead.

Microservice Logging #

Logger.configure('api', handlers: [
  Handler(formatter: JsonFormatter(), sink: FileSink('logs/api.log')),
]);

Logger.configure('database', handlers: [
  Handler(formatter: JsonFormatter(), sink: FileSink('logs/db.log')),
]);

Logger.configure('auth', handlers: [
  Handler(
    formatter: JsonFormatter(),
    sink: NetworkSink('https://security-logs.example.com'),
    filters: [LevelFilter(LogLevel.warning)],
  ),
]);

Flutter integration #

Capture framework errors and async errors:

void main() {
  Logger.attachToFlutterErrors(); // listens to all uncaught Flutter errors

  runZonedGuarded(
    () => runApp(MyApp()),
    (error, stack) {
      Logger.get('app.crash').error(
        'Uncaught error',
        error: error,
        stackTrace: stack,
      );
    },
  );
}

Documentation #

  • Documentation Index - Overview and navigation
  • Logger Philosophy - Design principles and rationale
  • Logger Architecture - Implementation details
  • Handler Guide - Pipeline and sink customization
  • Migration Guide - Upgrading from legacy components
  • Decorator Composition - Execution priority and flow
  • Time Module - Timestamp and timezone handling
  • Roadmap - Planned features and vision

Contributing #

All contributions should follow the guidelines in CONTRIBUTING.md and, for docs, docs/CONTRIBUTING_DOCS.md.

License #

This project is licensed under the BSD 3-Clause License. See the LICENSE file for details.

Support #

  • Issues: GitHub Issues
  • Discussions: GitHub Discussions
  • Package page: logd on pub.dev
6
likes
0
points
620
downloads

Publisher

unverified uploader

Weekly Downloads

High‑precision hierarchical logging for Dart and Flutter. Engineered for architectural clarity, O(1) configuration resolution, and zero‑overhead performance.

Homepage
Repository (GitHub)
View/report issues

Topics

#logging #hierarchical #performance #structured-logging

License

unknown (license)

Dependencies

characters, flutter, meta

More

Packages that depend on logd