structuredLogEntry function

String structuredLogEntry(
  1. Object message,
  2. LogSeverity severity, {
  3. Map<String, Object?>? payload,
  4. StackTrace? stackTrace,
})

Creates a JSON-encoded log entry that conforms with structured logging.

message is the log message. If it is a Map, it is treated as the base payload, merging with any keys explicitly provided in the payload parameter (with the parameter taking precedence). If the resulting merged map contains a "message" key, it will be extracted and used as the entry's message. If message is an empty String (or omitted via Map merging), the message field is omitted from the resulting JSON completely. For all other types, Object.toString or toJson() will be called.

payload is an optional map of additional fields to include in the log entry. These fields will be merged into the JSON root.

stackTrace is an optional stack trace to include in the log entry. It is serialized into the stack_trace field at the root of the JSON payload. Google Cloud Error Reporting automatically parses this specific field to group and track error events. See Formatting error messages for more details.

Implementation

String structuredLogEntry(
  Object message,
  LogSeverity severity, {
  Map<String, Object?>? payload,
  StackTrace? stackTrace,
}) {
  var actualMessage = message;
  var actualPayload = payload;

  if (message is Map) {
    actualPayload = {
      for (final entry in message.entries) entry.key.toString(): entry.value,
      ...?payload,
    };
    if (actualPayload.containsKey('message')) {
      actualMessage = actualPayload.remove('message') ?? '';
    } else {
      actualMessage = '';
    }
  }

  // https://cloud.google.com/logging/docs/agent/logging/configuration#special-fields
  String encode(Object innerMessage, Map<String, Object?>? innerPayload) =>
      jsonEncode(toEncodable: _toEncodableFallback, <String, dynamic>{
        ...?innerPayload,
        if (innerMessage != '') 'message': innerMessage,
        'severity': severity,
        if (stackTrace != null) 'stack_trace': formatStackTrace(stackTrace),
        if (stackTrace != null)
          'logging.googleapis.com/sourceLocation': _sourceLocation(stackTrace),
      });

  try {
    return encode(actualMessage, actualPayload);
    // ignore: avoid_catching_errors
  } on JsonUnsupportedObjectError catch (_) {
    // Fallback if there are cyclic errors parsing `payload` or `actualMessage`.
    // We omit the payload to guarantee a safe serialization.
    return encode(actualMessage.toString(), null);
  }
}