oklog 1.2.0 copy "oklog: ^1.2.0" to clipboard
oklog: ^1.2.0 copied to clipboard

A simple yet capable logging utility for Dart and Flutter. Just log. ok.

oklog #

pub package

A simple yet capable logging utility for Dart and Flutter. Just log. ok.

Features #

  • Six log levels: trace, debug, info, notice, warn, error
  • Colored, emoji-decorated console output via ConsoleSink and ConsoleFormatter
  • Filter logs by level via LevelFilterProcessor and by class name via NameFilterProcessor
  • Extensible pipeline: add LogProcessor instances to transform/filter, and LogSink instances to route output
  • Global log instance (OkLogger) ready to use out of the box
  • Observability support: structured events and metrics via log.obs
  • Error alerting with context: ContextBufferProcessor + ErrorAlertSink + ErrorExporter; built-in SlackErrorExporter included

Getting started #

Add the dependency to your pubspec.yaml:

dependencies:
  oklog: ^1.1.0

Then import the library:

import 'package:oklog/oklog.dart';

Usage #

Basic logging #

import 'package:oklog/oklog.dart';

void main() {
  log.level = LogLevel.trace; // show all levels

  log.trace('main', 'Trace message');
  log.debug('main', 'Debug message');
  log.info('main', 'Info message');
  log.notice('main', 'Notice message');
  log.warn('main', 'Warning message');

  try {
    throw Exception('Something went wrong!');
  } catch (e, st) {
    log.error('main', 'An error occurred.', error: e, stackTrace: st);
  }
}

Using with a class instance #

Pass this as the first argument and the class name is resolved automatically:

class MyClass {
  void myMethod() {
    log.info(this, 'Hello from MyClass');
  }
}

Attaching structured attributes #

All log methods accept an optional attrs map for structured key-value metadata:

log.debug(this, 'User action', attrs: {'userId': 123, 'action': 'login'});

Filtering by class name #

Use log.nameFilter (a NameFilterProcessor) to restrict which classes are logged:

// Only log messages from classes whose name contains 'main'
log.nameFilter.allowList = ['main'];

// Suppress log messages from classes whose name contains 'MyClass'
log.nameFilter.denyList = ['MyClass'];

// Clear filters
log.nameFilter.allowList = [];
log.nameFilter.denyList = [];

Silencing output #

log.sinks.clear(); // remove all sinks to suppress output

Changing the log level #

log.level = LogLevel.warn; // only warn and error are printed

Custom sinks #

Implement LogSink and override emit to route entries anywhere:

class FileSink extends LogSink {
  @override
  void emit(LogEntry entry) {
    if (entry is LogRecord) {
      // write to a file, remote service, etc.
    }
  }
}

log.sinks.add(FileSink());

Multiple sinks can be active at the same time. The built-in ConsoleSink is added automatically by OkLogger.

Custom formatters #

ConsoleSink accepts a LogFormatter<String> that converts a LogEntry to a string. Replace the default ConsoleFormatter to change how entries are rendered without touching sink behaviour:

class JsonFormatter extends LogFormatter<String> {
  @override
  String format(LogEntry entry) {
    if (entry is LogRecord) {
      return jsonEncode({
        'level': entry.level.name,
        'class': entry.className,
        'message': entry.message,
      });
    }
    return entry.toString();
  }
}

log.sinks
  ..clear()
  ..add(ConsoleSink(formatter: JsonFormatter()));

Custom processors #

Implement LogProcessor and return false to drop an entry from the pipeline:

class SamplingProcessor implements LogProcessor {
  @override
  bool process(LogEntry entry) => Random().nextDouble() > 0.9; // keep 10%
}

log.processors.add(SamplingProcessor());

Error alerting with context #

ContextBufferProcessor keeps a ring buffer of recent LogRecord entries. ErrorAlertSink detects error-level records and forwards them — together with that buffer — to an ErrorExporter, giving the recipient rich context about what happened before the error.

SlackErrorExporter

The built-in SlackErrorExporter sends a formatted Block Kit message to a Slack channel via an Incoming Webhook. The notification includes the error message, error object, stack trace, and the recent context logs captured by ContextBufferProcessor.

final buffer = ContextBufferProcessor();
final exporter = SlackErrorExporter(
  'https://hooks.slack.com/services/YOUR/WEBHOOK/URL',
);

log.processors.add(buffer);
log.sinks.add(ErrorAlertSink(buffer, exporter));

log.info('main', 'Application started.');
log.warn('main', 'Cache miss — fetching from origin.');
try {
  throw Exception('Database connection failed');
} catch (e, st) {
  // Sends a Slack message that includes the error plus the info/warn above.
  log.error('main', 'Unhandled error.', error: e, stackTrace: st);
}

Custom ErrorExporter

Implement the ErrorExporter interface to route error reports to any backend (Sentry, PagerDuty, a custom REST API, etc.):

class MyExporter implements ErrorExporter {
  @override
  Future<void> send(LogRecord error, List<LogRecord> contextLogs) async {
    // `error`       — the error-level LogRecord that triggered the alert
    // `contextLogs` — recent records from ContextBufferProcessor
    await myService.report(
      message: error.message,
      context: contextLogs.map((r) => r.message).toList(),
    );
  }
}

final buffer = ContextBufferProcessor();
log.processors.add(buffer);
log.sinks.add(ErrorAlertSink(buffer, MyExporter()));

Observability #

Access structured observability methods through log.obs. These are separate from severity-level logs and are designed for structured data that can later be forwarded to an external observability backend without changing call-site code.

log.obs.event #

Logs a named event with an optional payload and metadata attributes.

log.obs.event(
  this,              // source: pass `this`, a Type, or a String
  'user_signed_in',  // event name / message
  data: {'userId': '42', 'plan': 'pro'},
  attrs: {'env': 'prod'},
);

Console output:

[2026-03-13 10:00:00.000] 📡 [EVENT] MyClass: user_signed_in : {userId: 42, plan: pro} attrs: {env: prod}

log.obs.metric #

Logs a numeric measurement with an optional unit and metadata attributes.

log.obs.metric(
  this,               // source
  'request_duration', // metric name
  142,                // value
  unit: 'ms',
  attrs: {'endpoint': '/api/login'},
);

Console output:

[2026-03-13 10:00:00.000] 📊 [METRIC] MyClass: request_duration : 142 [ms] attrs: {endpoint: /api/login}

Parameter reference #

Parameter Type Required Description
source Object Yes Origin class. Pass this to resolve the runtime type automatically, or a Type or String.
message String Yes (event only) Human-readable event description.
name String Yes (metric only) Metric name (e.g. 'request_duration').
value num Yes (metric only) Numeric measurement.
unit String? No Unit label, e.g. 'ms', 'count' (metric only).
data Map<String, dynamic>? No Arbitrary payload (event only).
attrs Map<String, Object>? No Structured metadata, e.g. environment or version.

Log levels #

Level Description
trace Fine-grained diagnostic messages
debug General debugging information
info Informational messages
notice Notable events worth highlighting
warn Warnings with optional error/stack
error Errors with error object and stack
0
likes
0
points
14
downloads

Publisher

verified publisherzuvola.com

Weekly Downloads

A simple yet capable logging utility for Dart and Flutter. Just log. ok.

Repository (GitHub)
View/report issues

License

unknown (license)

More

Packages that depend on oklog