sl 1.1.0 copy "sl: ^1.1.0" to clipboard
sl: ^1.1.0 copied to clipboard

A structured logging library.

sl #

A structured logging library.

Setup #

import 'package:sl/sl.dart';

final logger = Logger(
  handler: LogTextHandler(level: .debug),
);

Basic Logging #

logger.debug('connecting to database...');
logger.info('application started');
logger.warn('memory usage is high');
logger.error('failed to process request');

Structured Attributes #

logger.info('user profile updated', attrs: [
  .string('username', 'alice'),
  .int('age', 30),
  .double('height', 1.75),
  .bool('verified', true),
]);

Attribute Groups #

logger.info('request metadata', attrs: [
  .group('http', [
    .string('method', 'POST'),
    .int('status', 201),
  ]),
]);

Errors and Stack Traces #

try {
  throw StateError('connection timed out');
} catch (e, stack) {
  logger.error('database operation failed', attrs: [
    .error(e),
    .stackTrace(stack),
  ]);
}

Contextual Loggers #

Create child loggers that inherit and merge parent attributes:

final dbLogger = logger.withAttrs([
  .string('component', 'database'),
]);

dbLogger.info('executing query'); 
// Output: INFO  [database] executing query

Logger Groups #

final groupedLogger = logger.withGroup('request').withAttrs([
  .string('id', '123'),
]);

groupedLogger.info('processing', attrs: [
  .string('path', '/users'),
]);
  • LogJsonHandler output:

    {
      "time": "2026-06-28T12:00:00.000Z",
      "level": "INFO",
      "msg": "processing",
      "request": {
        "id": "123",
        "path": "/users"
      }
    }
    
  • LogTextHandler output:

    INFO  processing request.id=123 request.path=/users
    

Bridging Standard Logging #

To capture and proxy logs from Dart's standard logging package:

import 'package:logging/logging.dart' as logging;
import 'package:sl/sl.dart';

// Captures root logger logs and forwards them to our logger
final detach = StdLoggerBridge().attach(logger);

// Stop bridging later:
detach();

Context Support #

Log records can carry a Context (from package:ctx) to pass request metadata, trace IDs, and scoped data to handlers and middlewares.

Explicit Context #

Pass a Context instance directly to any log method using the optional ctx: parameter:

final context = const Context.empty().withValue('trace_id', 'trace-12345');

logger.info('processing request', ctx: context);

Zone Context Propagation #

When logging inside context.run(...), Logger automatically captures Context.current if no explicit ctx: parameter is passed:

final context = const Context.empty().withValue('trace_id', 'trace-12345');

context.run(() {
  // `logger.info()` automatically receives `Context.current`
  logger.info('processing request'); 
});

Middlewares #

Log handlers accept middlewares to transform log records before writing. This is useful for extracting values from a Context and appending them as structured attributes:

final logger = Logger(
  handler: LogTextHandler(
    middlewares: [
      (context, record) {
        if (context.value('trace_id') case final String traceId) {
          return record.copyWith(
            attrs: [...record.attrs, .string('trace_id', traceId)],
          );
        }
        return record;
      },
    ],
  ),
);

Source Locations #

To automatically capture and include the calling source code location:

final logger = Logger(
  handler: LogTextHandler(addSource: true),
);

LogTextHandler output:

INFO  application started source=package:my_app/main.dart:42

LogJsonHandler output:

{
  "time": "2026-06-27T02:00:00.000Z",
  "level": "INFO",
  "msg": "started",
  "source": {
    "file": "package:my_app/main.dart",
    "line": 42,
    "function": "main"
  }
}

Warning Capturing stack traces is relatively expensive. It is not recommended for production environments where logging performance is critical.

Handlers #

Text Output (LogTextHandler) #

final logger = Logger(
  handler: LogTextHandler(
    level: .debug,
    scopeKey: 'component', // optional, formats value in brackets [value]
    theme: .ansi, // optional, enables ANSI colors
  ),
);

Output:

INFO  [database] query completed duration_ms=45

JSON Output (LogJsonHandler) #

final logger = Logger(
  handler: LogJsonHandler(level: .info),
);

Output:

{"time":"2026-06-17T18:45:00.000Z","level":"INFO","msg":"query completed","duration_ms":45}

Multi Handler (LogMultiHandler) #

Duplicates and routes log records to multiple downstream handlers:

final logger = Logger(
  handler: LogMultiHandler([
    LogJsonHandler(level: .info),
    externalHandler, // e.g. sending logs to a file or a remote service
  ]),
);
0
likes
150
points
312
downloads

Documentation

API reference

Publisher

verified publisherpusk.software

Weekly Downloads

A structured logging library.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

ctx, logging, stack_trace

More

Packages that depend on sl