loq 0.0.1 copy "loq: ^0.0.1" to clipboard
loq: ^0.0.1 copied to clipboard

Structured logging for Dart. Pipeline architecture with pluggable handlers, context propagation via Zones, and OpenTelemetry-ready. Works everywhere — server, Flutter, CLI, web.

loq #

Structured logging for Dart. Pipeline architecture, OTel-ready, works everywhere.

import 'package:loq/loq.dart';

final log = Logger('my_service');
log.info('request handled', fields: {'path': '/api', 'status': 200});

Why loq? #

Most Dart logging packages give you string messages with levels. Loq gives you structured key-value fields that flow through a processor pipeline to pluggable handlers — console, JSON, OpenTelemetry, Crashlytics, or your own.

Before (unstructured):

INFO: 2026-04-09: Payment processed for order abc-123, amount $99.95

After (structured with loq):

{"time":"2026-04-09T12:34:56.789Z","level":"info","msg":"payment processed","logger":"payments","orderId":"abc-123","amount":99.95}

Structured logs are searchable, filterable, and directly consumable by observability backends like Grafana, Datadog, and Elastic.

Features #

  • Structured fields — attach typed key-value data to every log
  • Pipeline architecture — Logger → Processors → Handlers
  • Bound loggerslogger.withFields() returns a new logger with inherited context
  • Zone-based context — fields flow through async calls automatically
  • Early-out filtering — skip all work when a level is disabled
  • Pure Dart — no platform dependencies, works on server, Flutter, CLI, web
  • OTel-ready — designed to bridge into OpenTelemetry (adapter coming soon)

Quick start #

import 'package:loq/loq.dart';

void main() {
  // Optional: configure handlers and processors
  LogConfig.configure(
    handlers: [ConsoleHandler(minLevel: Level.debug)],
    zoneAccessor: defaultZoneAccessor,
  );

  final log = Logger('app');
  log.info('started', fields: {'port': 8080});
}

Bound loggers #

Attach context that flows through every subsequent log call:

final log = Logger('api');
final reqLog = log.withFields({'requestId': 'abc-123', 'userId': 42});

reqLog.info('handling request');       // includes requestId, userId
reqLog.warn('slow query', fields: {'ms': 340});  // includes all three

Zone context #

Attach fields that automatically propagate through async code — no need to pass loggers around:

withLogContext({'traceId': 'xyz', 'tenantId': 'acme'}, () async {
  final log = Logger('db');
  log.info('query executed');  // includes traceId and tenantId
  await someAsyncWork();
  log.info('done');            // still includes them
});

Error logging #

try {
  await riskyOperation();
} catch (e, st) {
  log.error('operation failed', error: e, stackTrace: st, fields: {
    'orderId': order.id,
  });
}

Processors #

Processors form a chain that transforms, enriches, or filters records before they reach handlers:

LogConfig.configure(
  processors: [
    redact({'password', 'token'}),   // replace sensitive values
    filterByLevel(Level.info),        // drop debug/trace in production
    sample(10),                       // pass ~1 in 10 records (for high-volume)
  ],
  handlers: [JsonHandler()],
);

Handlers #

Handlers are the output backends. Loq ships with ConsoleHandler (dev) and JsonHandler (production). Write your own by implementing the Handler interface:

class MyHandler implements Handler {
  @override
  bool isEnabled(Level level) => level >= Level.warn;

  @override
  void handle(Record record) {
    // Send to your backend
  }

  @override
  Future<void> flush() async {}

  @override
  Future<void> close() async {}
}

JSON output #

LogConfig.configure(handlers: [JsonHandler()]);

final log = Logger('api');
log.info('request completed', fields: {'path': '/users', 'status': 200});

// Output:
// {"time":"2026-04-09T12:34:56.789Z","level":"info","msg":"request completed","logger":"api","path":"/users","status":200}

Ecosystem (planned) #

Package Description
loq Core structured logging (this package)
loq_otel OpenTelemetry log bridge via Dartastic
loq_flutter Flutter lifecycle, navigation context
loq_crashlytics Firebase Crashlytics adapter
loq_sentry Sentry adapter

Design influences #

Loq's architecture follows patterns proven by Go's slog, Python's structlog, and .NET's Serilog: a frontend/backend split with a processor chain between them.

License #

MIT. See LICENSE.

0
likes
0
points
208
downloads

Publisher

unverified uploader

Weekly Downloads

Structured logging for Dart. Pipeline architecture with pluggable handlers, context propagation via Zones, and OpenTelemetry-ready. Works everywhere — server, Flutter, CLI, web.

Homepage
Repository (GitHub)
View/report issues

Topics

#logging #structured-logging #observability #opentelemetry

License

unknown (license)

More

Packages that depend on loq