breadcrumb static method

void breadcrumb(
  1. String message, {
  2. String? category,
  3. Map<String, dynamic>? data,
  4. LogLevel level = LogLevel.info,
})

Records a breadcrumb — a trail event attached to the next captured error.

Gated at emit time by AppConfigBase.breadcrumbLevel (independent of the console logLevel — BEH-3/BEH-4): a breadcrumb whose level is below the threshold is dropped. The breadcrumb's own level comes from the optional level param; when omitted it defaults to LogLevel.info (ERH-031). Gating uses LogLevel only — never a backend level type; the LogLevelSentryLevel translation is Sentry-side (the reporter), not here (ERH-026).

The message + every value in data are redacted (fail-closed — ERH-005, ERH-017, ERH-047) before being forwarded. When no reporter is attached the (gated, redacted) breadcrumb is buffered into the bounded _earlyBreadcrumbBuffer (ERH-022/ERH-032) so the pre-attach trail is not lost; the flush-on-attach (breadcrumbs-then-errors) is wired where the reporter attaches.

Never throws into the caller — breadcrumbs are diagnostic and must not perturb the code they trace.

Implementation

static void breadcrumb(
  String message, {
  String? category,
  Map<String, dynamic>? data,
  LogLevel level = LogLevel.info,
}) {
  try {
    if (!_shouldBreadcrumb(level)) {
      return;
    }
    final redacted = _redactSensitiveData(message, data);
    final reporter = _customErrorReporter;
    if (reporter != null) {
      reporter.addBreadcrumb(
        redacted.message,
        category: category,
        data: redacted.data,
      );
    } else {
      // No reporter attached yet — buffer so the pre-attach trail survives
      // (flushed on attach, breadcrumbs-then-errors). Already redacted, so the
      // flush must NOT re-redact (ERH-032).
      _bufferEarlyBreadcrumb(BufferedBreadcrumb(
        redacted.message,
        category,
        redacted.data,
      ));
    }
  } catch (_) {
    // Diagnostics must never break the traced code path.
  }
}