Skip to content

Support for structured logging attributes #419

@chimon2000

Description

@chimon2000

Is your feature request related to a problem? Please describe.
Currently, Talker does not have a way to pass structured attributes, which limits its ability to integrate with logging services such as Sentry or Datadog. Sentry and Datadog, for example, accept a map of attributes that they displayed as structured data:

// In Sentry
FutureOr<void> error(String body, {Map<String, SentryLogAttribute>? attributes});

// In Datadog
void error(
  String message, {
  String? errorMessage,
  String? errorKind,
  StackTrace? errorStackTrace,
  Map<String, Object?> attributes = const {},
})

Describe the solution you'd like
Ideally, I should be able to log to other services by using Talker's API and adding an observer. Extend the logging methods to accept an optional attributes parameter.

void warning(
  dynamic msg, [
  Object? exception,
  StackTrace? stackTrace,
])

becomes

void warning(
  dynamic msg, [
  Object? exception,
  StackTrace? stackTrace,
  LogAttribute>? attributes
])

The attributes param is the same as Sentry's abstraction.


class LogAttribute {
  final dynamic value;
  final LogAttributeType type;

  const LogAttribute._(this.value, this.type);
}

enum LogAttributeType {
  string, boolean, integer, double
}

The TalkerObserver events could then be extended with the attributes, allowing developers to easily log to additional providers.

class _SentryTalkerObserver extends TalkerObserver {
  _SentryTalkerObserver();

  @override
  void onLog(TalkerData log) {
    _logToSentry(log);
    super.onLog(log);
  }

  void _logToSentry(TalkerData log) {
    Sentry.addBreadcrumb(Breadcrumb(message: log.message, timestamp: log.time, level: log.logLevel?.toSentryLevel()));

    switch (log.logLevel) {
      case LogLevel.error:
        Sentry.logger.error(log.generateTextMessage(), attributes: log.attributes.toSentryAttributes());
        break;
      case LogLevel.critical:
        Sentry.logger.fatal(log.generateTextMessage(), attributes: log.attributes.toSentryAttributes());
        break;
      case LogLevel.warning:
        Sentry.logger.warn(log.generateTextMessage(), attributes: log.attributes.toSentryAttributes());
        break;
      case LogLevel.debug:
      case LogLevel.verbose:
        Sentry.logger.debug(log.generateTextMessage(), attributes: log.attributes.toSentryAttributes());
        break;
      case null:
      case LogLevel.info:
        Sentry.logger.info(log.generateTextMessage(), attributes: log.attributes.toSentryAttributes());
        break;
    }
  }
}

Describe alternatives you've considered
Currently, we implement our own logger service, allowing us to define multiple strategies with different outputs. This is great, but it feels like it should be supported directly in Talker.

Additional context
n/a

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions