Class LogbackAlertAppender
- All Implemented Interfaces:
ch.qos.logback.core.Appender<ch.qos.logback.classic.spi.ILoggingEvent>,ch.qos.logback.core.spi.ContextAware,ch.qos.logback.core.spi.FilterAttachable<ch.qos.logback.classic.spi.ILoggingEvent>,ch.qos.logback.core.spi.LifeCycle
UnsynchronizedAppenderBase<ILoggingEvent> shell over the framework-neutral
AlertEngine. Configuration arrives either through JavaBean setters (Joran/XML config) or
through a pre-built NtfyConfig injected via setConfig(NtfyConfig) by the
auto-installing NtfyLogbackConfigurator. Every decision that matters — logger exclusion
(including this library's own package), the NO_ALERT marker gate, storm rate-limiting,
digesting, payload assembly, and HTTP publishing — lives in the engine; this class only maps a
Logback event onto an AlertEvent and calls AlertEngine.submit(io.github.pimak.ntfy.core.AlertEvent).
Self-diagnoses exclusively through the inherited StatusManager methods (via LogbackDiagnostics), so no SLF4J feedback loop is possible and no credential ever appears in
diagnostic output.
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringMarker name a caller attaches to a single log call to opt it out of alerting entirely.Fields inherited from class ch.qos.logback.core.UnsynchronizedAppenderBase
name, startedFields inherited from class ch.qos.logback.core.spi.ContextAwareBase
context -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected voidappend(ch.qos.logback.classic.spi.ILoggingEvent event) Gates on level, then maps the event and hands it to the engine, which owns all further gating and publishing.Read-only pipeline observability counters (published / suppressed / failed) for this appender.voidsetActions(String actions) Action buttons as a raw ntfyActionsheader value (short format, e.g.voidsetAppName(String appName) voidsetAsync(boolean async) Asynchronous (offloaded) delivery: individual error alerts are handed to the engine's bounded work queue and published by a daemon worker, so a slow/unreachable ntfy server never blocks the logging thread.voidsetAsyncQueueCapacity(int asyncQueueCapacity) Bounded async delivery queue capacity; only consulted whenasyncistrue.voidfalseasks the server not to store the message (Cache: no).voidsetClickUrl(String clickUrl) URL opened when a notification is tapped (ntfyClickheader).voidsetConnectTimeout(String connectTimeout) Accepts a duration string (bare int = ms,Nms/Ns/Nm/Nh/Nd, or ISO-8601).voidsetDigestPriority(String digestPriority) voidsetDigestTags(String digestTags) voidsetEnabled(boolean enabled) voidsetErrorPriority(String errorPriority) voidsetErrorTags(String errorTags) voidsetExcludedExceptionTypes(String excludedExceptionTypes) Comma-separated fully qualified exception class names.voidsetExcludedLoggers(String excludedLoggers) A single comma-separated value of logger-name prefixes to exclude from alerting.voidsetFirebase(String firebase) falseasks the server not to forward the message to Firebase (Firebase: no).voidURL of the icon shown beside the notification (ntfyIconheader).voidsetIconsByLogger(String iconsByLogger) Per-logger icon overrides asprefix=urlpairs separated by commas.voidsetIncludeMdcKeys(String includeMdcKeys) A comma-separated allow-list of MDC keys rendered into alert bodies, onekey: valueline each, in the order given here.voidLanguage of notification bodies and diagnostics as a BCP 47 tag (e.g.voidsetMaxAlertsPerWindow(int maxAlertsPerWindow) voidsetMaxStackFrames(int maxStackFrames) voidsetPassword(String password) voidsetRequestTimeout(String requestTimeout) Accepts a duration string (bare int = ms,Nms/Ns/Nm/Nh/Nd, or ISO-8601).voidsetRequireHttpsForCredentials(boolean requireHttpsForCredentials) Strict mode: refuse engine activation (rather than only warn) when credentials would be sent over a cleartexthttp://endpoint.voidsetStartupPing(String startupPing) Opt-in startup self-test:off(default),probe(read-only reachability check, publishes nothing) orpublish(a real low-priority test notification).voidsetStartupPingFailFast(boolean startupPingFailFast) Whentrue, a failed startup self-test aborts application startup instead of only warning.voidsetStartupPingNotifyFailures(boolean startupPingNotifyFailures) Whether a failed self-test is announced as a notification on a route that PASSED.voidsetStartupPingWarn(String startupPingWarn) Startup self-test for the optional WARN route:off(default),probeorpublish.voidsetSuppressionWindow(String suppressionWindow) Accepts a duration string (bare int = ms,Nms/Ns/Nm/Nh/Nd, or ISO-8601).voidvoidvoidvoidvoidsetUsername(String username) voidsetWarnPriority(String warnPriority) ntfyPriorityheader for WARN alerts and the WARN digest; defaultdefault.voidsetWarnTags(String warnTags) ntfyTagsheader for WARN alerts and the WARN digest; defaultwarning.voidsetWarnTopic(String warnTopic) The topic WARN-level events are published to.voidstart()Builds anAlertEnginefrom the injected config (if present) or from the JavaBean setters, starts it, and marks this appender started ONLY if the engine actually activated.voidstop()Tears the engine down (flushing any pending digest) and marks this appender stopped.Methods inherited from class ch.qos.logback.core.UnsynchronizedAppenderBase
addFilter, buildReentryGuard, clearAllFilters, doAppend, getCopyOfAttachedFiltersList, getFilterChainDecision, getName, isStarted, setName, toStringMethods inherited from class ch.qos.logback.core.spi.ContextAwareBase
addError, addError, addInfo, addInfo, addStatus, addWarn, addWarn, getContext, getDeclaredOrigin, getStatusManager, setContextMethods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, waitMethods inherited from interface ch.qos.logback.core.spi.ContextAware
addError, addError, addInfo, addInfo, addStatus, addWarn, addWarn, getContext, setContext
-
Field Details
-
NO_ALERT_MARKER_NAME
Marker name a caller attaches to a single log call to opt it out of alerting entirely. Re-exposed fromAlertEngine.NO_ALERT_MARKER_NAMEso existing callers keep a stable handle instead of a magic string.- See Also:
-
-
Constructor Details
-
LogbackAlertAppender
public LogbackAlertAppender()
-
-
Method Details
-
setUrl
-
setTopic
-
setToken
-
setUsername
-
setPassword
-
setTitle
-
setAppName
-
setMaxStackFrames
public void setMaxStackFrames(int maxStackFrames) -
setConnectTimeout
Accepts a duration string (bare int = ms,Nms/Ns/Nm/Nh/Nd, or ISO-8601). -
setRequestTimeout
Accepts a duration string (bare int = ms,Nms/Ns/Nm/Nh/Nd, or ISO-8601). -
setMaxAlertsPerWindow
public void setMaxAlertsPerWindow(int maxAlertsPerWindow) -
setSuppressionWindow
Accepts a duration string (bare int = ms,Nms/Ns/Nm/Nh/Nd, or ISO-8601). -
setErrorPriority
-
setDigestPriority
-
setErrorTags
-
setDigestTags
-
setWarnTopic
The topic WARN-level events are published to. Setting it to a non-blank value is the entire opt-in for WARN alerting: unset (the default), this appender alerts on ERROR and above only. Set it to the same value as<topic>to alert on warnings through the main topic at a different priority. XML:<warnTopic>my-app-warnings</warnTopic>. -
setWarnPriority
ntfyPriorityheader for WARN alerts and the WARN digest; defaultdefault. -
setWarnTags
ntfyTagsheader for WARN alerts and the WARN digest; defaultwarning. -
setClickUrl
URL opened when a notification is tapped (ntfyClickheader). -
setActions
Action buttons as a raw ntfyActionsheader value (short format, e.g."view, View logs, https://grafana.example.com/d/abc"). -
setExcludedLoggers
A single comma-separated value of logger-name prefixes to exclude from alerting. -
setExcludedExceptionTypes
Comma-separated fully qualified exception class names. An event whose cause chain contains any of them never alerts — matched anywhere in the chain, not just on the surface throwable. -
setCache
falseasks the server not to store the message (Cache: no). Subscribers who are offline at that moment never receive it. Defaulttrue.Declared as a String rather than a boolean on purpose. Joran converts an XML value with
Boolean.valueOf, which maps everything that is not"true"to false — so<cache>yes</cache>would turn caching OFF and cost every offline subscriber their alerts, silently, on the one surface where the value is typed by hand.NtfyConfig.Builderreads the common spellings and reports anything else atstart(). -
setFirebase
falseasks the server not to forward the message to Firebase (Firebase: no). Defaulttrue. A String for the same reason assetCache(String). -
setIcon
URL of the icon shown beside the notification (ntfyIconheader). Must be anhttp/httpsURL; a value that is not one is dropped with a diagnostic. ntfy renders JPEG and PNG only, but that is a property of the bytes served, not of the path, so a URL whose extension names another format is warned about and still sent. -
setIconsByLogger
Per-logger icon overrides asprefix=urlpairs separated by commas. The longest prefix matching an alert's logger wins; anything unmatched keeps the default icon. Alerts only — a notification has no logger to match on. -
setIncludeMdcKeys
A comma-separated allow-list of MDC keys rendered into alert bodies, onekey: valueline each, in the order given here. Unset by default, and there is deliberately no wildcard form: an MDC value reaches a notification only when an operator named its key, because a production MDC routinely holds tokens and user identifiers that must never leave the process. -
setLocale
Language of notification bodies and diagnostics as a BCP 47 tag (e.g.fr,de-DE). Defaults to English; an unknown/unshipped locale silently uses English. XML:<locale>fr</locale>. -
setEnabled
public void setEnabled(boolean enabled) -
setAsync
public void setAsync(boolean async) Asynchronous (offloaded) delivery: individual error alerts are handed to the engine's bounded work queue and published by a daemon worker, so a slow/unreachable ntfy server never blocks the logging thread. On by default; setfalsefor pre-2.0 synchronous delivery. -
setAsyncQueueCapacity
public void setAsyncQueueCapacity(int asyncQueueCapacity) Bounded async delivery queue capacity; only consulted whenasyncistrue. -
setRequireHttpsForCredentials
public void setRequireHttpsForCredentials(boolean requireHttpsForCredentials) Strict mode: refuse engine activation (rather than only warn) when credentials would be sent over a cleartexthttp://endpoint. On by default; setfalsefor the pre-2.0 warn-and-activate behavior. -
setStartupPing
Opt-in startup self-test:off(default),probe(read-only reachability check, publishes nothing) orpublish(a real low-priority test notification). Verifies at boot that the configured endpoint, credentials and topic actually work, instead of finding out when the first real error alert fails to deliver. An unrecognized value keeps the default and is warned about on the Logback status manager. -
setStartupPingFailFast
public void setStartupPingFailFast(boolean startupPingFailFast) Whentrue, a failed startup self-test aborts application startup instead of only warning. Off by default, and it also makes the self-test run inline (adding at most connect+request timeout to boot) since a start that already returned cannot be aborted. Aimed at CI/staging rather than production. -
setStartupPingWarn
Startup self-test for the optional WARN route:off(default),probeorpublish. Independent ofsetStartupPing(String)— ntfy permissions are granted per topic, so a healthy ERROR route proves nothing about the WARN one. Only consulted when awarnTopicis configured and its route survived. -
setStartupPingNotifyFailures
public void setStartupPingNotifyFailures(boolean startupPingNotifyFailures) Whether a failed self-test is announced as a notification on a route that PASSED. On by default; it can never fire unless some route passed, so it cannot publish to a topic the self-test has not just verified. Setfalseto keepprobeabsolutely publish-free. -
start
public void start()Builds anAlertEnginefrom the injected config (if present) or from the JavaBean setters, starts it, and marks this appender started ONLY if the engine actually activated. A silently/partially unconfigured engine leaves the appenderisStarted()==false(the engine already reported why via the StatusManager), exactly as the original appender did. A secondstart()without an interveningstop()is a guarded no-op, so the engine and its threads can never be orphaned.- Specified by:
startin interfacech.qos.logback.core.spi.LifeCycle- Overrides:
startin classch.qos.logback.core.UnsynchronizedAppenderBase<ch.qos.logback.classic.spi.ILoggingEvent>
-
append
protected void append(ch.qos.logback.classic.spi.ILoggingEvent event) Gates on level, then maps the event and hands it to the engine, which owns all further gating and publishing. The gate lives here (mirroring the Quarkus adapter's SEVERE gate) so the documented level contract holds on every install path — without it, a root-logger auto-install would push every INFO/DEBUG line verbatim to the ntfy topic.ERROR and above always alert. WARN alerts only when the engine activated a warn route; below WARN nothing ever does, on any configuration. Sub-ERROR events therefore cost a level comparison and nothing else in the default setup.
- Specified by:
appendin classch.qos.logback.core.UnsynchronizedAppenderBase<ch.qos.logback.classic.spi.ILoggingEvent>
-
stop
public void stop()Tears the engine down (flushing any pending digest) and marks this appender stopped. Null-safe when never started and safe to call twice —AlertEngine.stop()is itself idempotent.- Specified by:
stopin interfacech.qos.logback.core.spi.LifeCycle- Overrides:
stopin classch.qos.logback.core.UnsynchronizedAppenderBase<ch.qos.logback.classic.spi.ILoggingEvent>
-
getCounters
Read-only pipeline observability counters (published / suppressed / failed) for this appender. The returned holder is stable for the appender's whole lifetime — the same instance before and afterstart()/stop()cycles — so the tallies are monotonic and never reset by a stop or a Logback context reset/reattach. Counters are pulled here, never logged, preserving the loop-safe design.
-