DigiaLogger class
The SDK's one logging style, across core and every CEP plugin.
One instance per module, held as a const field so a call site is a method
call and nothing more. The tag becomes the console prefix and is the whole
retrieval story: a developer filters their console for DIGIA and pastes.
Never reword the prefix; grepping for it is the only way a support
ticket carries our logs.
<badge> [<TAG>] [<LEVEL>]: [<campaignKey>] <Message> (key=value, key=value)
π΄ [DIGIA] [ERROR]: [canvas_new_nudge] Payload parse failed
π‘ [DIGIA] [WARN]: [canvas_new_nudge] Dropped β Campaigns are still loading; trigger dropped
π΅ [DIGIA-ME] [INFO]: [canvas_new_nudge] Received (cepId=6aabbf01362b7cb5)
βͺ [DIGIA] [DEBUG]: [summer_sale] Dropped β frequency capped (policy=1/day)
The campaign slot is what makes same-campaign lines group vertically
like a thread, and [<key>] an unambiguous filter β grepping the bare key
also hits lines that merely mention it (by=summer_sale). It is a
parameter, never hand-written brackets, so the format cannot rot; it is
omitted entirely when there is no campaign (init, fetch, session, queue),
never rendered empty; and it is always campaignKey, the human-meaningful
name the author typed into the dashboard. cepCampaignId and
presentationId stay in the trailing data.
There are exactly six tags, and the set is closed on purpose β nine were tried first and read as noise, because the SDK is one thing to the reader and sub-module detail belongs in the message when it matters:
| Tag | Written as | Covers |
|---|---|---|
DIGIA |
DigiaLogger() |
everything in core that is not one of the below |
DIGIA-ANALYTICS |
DigiaLogger('analytics') |
the first-party analytics pipeline |
DIGIA-LIVETEST |
DigiaLogger('liveTest') |
live campaign testing |
DIGIA-CT / -WE / -ME |
in the plugin packages | the CEP boundary β the #1 support question |
Message style, so a reader can scan the left edge: outcome first, sentence
case (Campaign received, not received campaign); never repeat the tag's
module in the message; data trails in one parenthesised key=value group.
One emit, many sinks. Every call builds exactly one TimelineRecord
and walks the sink registry; ConsoleSink renders the line above, and
ScreenSink records the on-device campaign timeline. Adding a destination
never touches a call site.
The two gates are independent, and that is the point:
| Sink | Accepts when | Who owns the knob |
|---|---|---|
ConsoleSink |
severity is at or above the configured DigiaLogLevel |
the host developer |
ScreenSink |
the record carries a TimelineStage |
us, per call site |
HealthSink |
the record's DiagnosticReason is on a central allowlist | us, in one list |
Each gate reads a different field with a different owner, which is what
makes escalation fail closed: forgetting one can only narrow the audience,
never widen it. There is deliberately no sendTo: parameter β per-call-site
routing drifts, and one mistyped flag would leak internals to a campaign
creator or to a backend.
So a debug gating drop that a release console suppresses still reaches
the campaign creator's screen. Promoting a call is a deliberate act:
pass a TimelineStage and a DiagnosticReason from a closed enum, and
free-text developer logging can never leak onto a non-developer's screen.
The promoted arguments do not change the console line β what a developer
reads is message and nothing else.
Three rules the SDK's release chain makes non-negotiable, since a bad line ships inside a customer app for months:
- A log call never throws. It runs on render paths. Every sink call is caught here, so a sink cannot break the app that hosts us.
- A disabled level costs nothing. Gate an expensive unstaged message with isEnabled rather than building it and discarding it inside.
- A staged call is never wrapped in isEnabled. That guard is for hot unstaged chatter only; around a staged call it silently blinds the timeline in exactly the release build someone opened it to debug.
Constructors
- DigiaLogger([String tag = ''])
-
Creates a logger for one module.
const
Properties
Methods
-
d(
String message, {String? campaign, TimelineStage? stage, DiagnosticReason? reason, String? presentationId, Map< String, String> ? extras}) β void - Per-node, per-frame, per-request detail.
-
e(
String message, {String? campaign, Object? error, StackTrace? stackTrace, TimelineStage? stage, DiagnosticReason? reason, String? presentationId, Map< String, String> ? extras}) β void - The SDK could not do the thing. Visible at every level but DigiaLogLevel.none.
-
i(
String message, {String? campaign, TimelineStage? stage, DiagnosticReason? reason, String? presentationId, Map< String, String> ? extras}) β void - A lifecycle milestone.
-
isEnabled(
DigiaLogSeverity severity) β bool -
Whether a
severityline would be emitted right now. -
noSuchMethod(
Invocation invocation) β dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toString(
) β String -
A string representation of this object.
inherited
-
w(
String message, {String? campaign, Object? error, TimelineStage? stage, DiagnosticReason? reason, String? presentationId, Map< String, String> ? extras}) β void - Degraded, but recovered.
Operators
-
operator ==(
Object other) β bool -
The equality operator.
inherited
Static Properties
- level β DigiaLogLevel
-
The threshold currently in force.
no setter
- screenNameSource β String? Function()?
-
Supplies the screen the app is currently on, so staged records can be
stamped with it without every call site passing one.
getter/setter pair
Static Methods
-
configure(
DigiaLogLevel level) β void -
Applies the host app's configured verbosity. Called once from
Digia.initialize(); until then DigiaLogLevel.auto is in force, so logs emitted during startup are not silently lost. -
isSeverityEnabled(
DigiaLogSeverity severity) β bool -
Whether the configured level admits
severity. The console's gate, and nothing else's. -
registerSink(
DiagnosticSink sink) β void - Adds a sink to the registry. Idempotent, so a repeated init cannot end up emitting a record twice into the same destination.
-
unregisterSink(
DiagnosticSink sink) β void - Removes a sink. A no-op if it was never registered.
-
withCampaign<
T> (String? campaign, T body()) β T -
Runs
bodywithcampaignstamped on each record it logs that names none. A parse runs deep below the campaign that owns it.