Class NtfyConfig
NtfyConfig.Builder (NtfyConfig.builder()...build()); every field is a
plain JDK type so adapters can populate it from Joran setters, Spring @Configuration
Properties, Quarkus @ConfigMapping, or ConfigLoader without core ever depending
on a framework.
Defaults are applied by the builder (not here) so a builder that is never touched still yields a fully-populated config. Every collection-valued field is stored unmodifiable — stated as a rule rather than a list of field names, which is what let this sentence go stale once already.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classFluent builder forNtfyConfig; every setter returnsthis. -
Method Summary
Modifier and TypeMethodDescriptionstatic NtfyConfig.Builderbuilder()Returns a freshNtfyConfig.Builderpre-loaded with every default.The pre-serialized ntfyActionsheader value (action buttons) sent with both individual error alerts and the storm digest, ornull/blank to send noActionsheader.intMaximum number of pending error alerts the asynchronous delivery queue holds before overflow kicks in (seeAlertEngine).The URL ntfy opens when a notification is tapped (sent as theClickheader), ornull/blank to send noClickheader.The unmodifiable list of fully qualified exception class names whose presence ANYWHERE in an event's cause chain gates the event out.The unmodifiable list of logger-name prefixes excluded from alerting.getIcon()URL of the icon shown beside the notification (ntfyIconheader), ornullwhen unset.The unmodifiable logger-prefix → icon-URL table that overridesgetIcon()for alerts, in configured order.The unmodifiable, EXPLICIT allow-list of MDC keys whose values are rendered into alert bodies (onekey: valueline each), in configured order — that order is the rendering order.Language of the notification bodies and self-diagnostic messages the engine produces.intintWhat the opt-in startup self-test does once the engine has finished activating — seeStartupPingMode.What the startup self-test does for the optional WARN route — seeStartupPingMode.getTitle()getToken()getTopic()getUrl()The ntfyPriorityheader for WARN alerts (defaultdefault).The ntfyTagsheader for WARN alerts and the WARN digest (defaultwarning).The ntfy topic WARN-level events are published to, ornull/blank when WARN alerting is off (the default).booleanisActive()True when this config should actually deliver alerts: it isenabled, and bothgetUrl()andgetTopic()are non-blank.booleanTrue when the operator has explicitly opted in to activating alert delivery from an endpoint URL supplied only by a classpathntfy.properties(seeisEndpointFromClasspathFile()).booleanTrue when delivery of individual error alerts should be offloaded to the engine's bounded asynchronous work queue instead of running inline on the calling (logging) thread.booleanisCache()Whether the ntfy server may cache published messages (trueby default, matching ntfy's own default of storing them for 12 hours).booleanTrue when acacheorfirebasevalue was supplied but could not be read as a boolean, so the default was kept.booleanbooleanTrue when the endpoint URL was supplied ONLY by a classpathntfy.properties(no system property or environment variable set it).booleanWhether the ntfy server may forward published messages to Firebase Cloud Messaging (trueby default).booleanTrue when anicons-by-loggerentry could not be read as aprefix=urlpair, so it was discarded.booleanTrue when the engine must REFUSE activation (rather than merely warn) if credentials — a configured token, a username/password pair, or userinfo embedded in the URL itself — would be sent over a cleartexthttp://endpoint.booleanTrue when a failed startup self-test must abort application startup (by throwingNtfyStartupSelfTestExceptionout ofAlertEngine.start()) rather than merely warn.booleanWhether a failed self-test should be announced as an ntfy notification on a route that PASSED.booleanTrue when astartup-pingvalue was supplied but matched no known mode, so the default was kept.booleanAsisStartupPingValueRejected(), forstartup-ping-warn.booleanTrue when a non-blankgetWarnTopic()is configured, i.e.booleanTrue whengetWarnTopic()was supplied ONLY by a classpathntfy.properties— nontfy.warn-topicsystem property and noNTFY_WARN_TOPICenvironment variable.
-
Method Details
-
builder
Returns a freshNtfyConfig.Builderpre-loaded with every default. -
getUrl
-
getTopic
-
getToken
-
getUsername
-
getPassword
-
getTitle
-
getAppName
-
getMaxStackFrames
public int getMaxStackFrames() -
getConnectTimeout
-
getRequestTimeout
-
getMaxAlertsPerWindow
public int getMaxAlertsPerWindow() -
getSuppressionWindow
-
getErrorPriority
-
getDigestPriority
-
getErrorTags
-
getDigestTags
-
getWarnTopic
The ntfy topic WARN-level events are published to, ornull/blank when WARN alerting is off (the default).This single value is the whole opt-in switch — see
isWarnRoutingEnabled(). Set it to the same value asgetTopic()to alert on warnings through the main topic at a different priority. -
getWarnPriority
The ntfyPriorityheader for WARN alerts (defaultdefault). Consulted only whenisWarnRoutingEnabled()is true, and used for the WARN storm digest as well as individual WARN alerts — the warn route is deliberately uniform, so routing warnings to a quiet channel is not undone by its own digest arriving aturgent. -
getWarnTags
The ntfyTagsheader for WARN alerts and the WARN digest (defaultwarning). -
isWarnRoutingEnabled
public boolean isWarnRoutingEnabled()True when a non-blankgetWarnTopic()is configured, i.e. WARN-level events should be alerted. False by default: alerting is ERROR-only unless an operator names a destination for warnings.Adapters gate on this before submitting a WARN event, and
AlertEnginerefuses WARN events again on its own when it is false — the same double-floor discipline the Log4j2 adapter already applies to its attach level. -
isWarnTopicFromClasspathFile
public boolean isWarnTopicFromClasspathFile()True whengetWarnTopic()was supplied ONLY by a classpathntfy.properties— nontfy.warn-topicsystem property and noNTFY_WARN_TOPICenvironment variable. Set byConfigLoaderonly.Mirrors
isEndpointFromClasspathFile()and exists for the same reason:warn-topicnames a destination and widens the volume of log content leaving the host, so on the zero-code auto-install paths it is subject to the sameallow-classpath-endpointopt-in. (Contrastinclude-mdc-keys, which is read from all three layers precisely because it cannot redirect where alerts go.)The refusal itself lives in
AlertEngine.start()rather than in the three per-adapter ambient guards that handle the endpoint case. Those guards must refuse INSTALLATION outright, which only they can do; dropping an optional extra route is a decision the engine can make once for every adapter. Configs built explicitly — a<Ntfy warnTopic="…">attribute, a<warnTopic>element,application.yml— never set this flag and are never affected. -
getClickUrl
The URL ntfy opens when a notification is tapped (sent as theClickheader), ornull/blank to send noClickheader. Applies to both individual error alerts and the storm digest. -
getActions
The pre-serialized ntfyActionsheader value (action buttons) sent with both individual error alerts and the storm digest, ornull/blank to send noActionsheader. Set either as a raw ntfy short-format string (NtfyConfig.Builder.actionsHeader(String)) or from typedNtfyActions (NtfyConfig.Builder.actions(List)). -
getExcludedLoggerPrefixes
The unmodifiable list of logger-name prefixes excluded from alerting. -
getExcludedExceptionTypes
The unmodifiable list of fully qualified exception class names whose presence ANYWHERE in an event's cause chain gates the event out. Empty by default.Matched as whole names, not prefixes — the opposite of
getExcludedLoggerPrefixes(), and deliberately so. A logger name is hierarchical, so a prefix names a subtree an operator can reason about; a class name is not, so a prefix there would silently catch unrelated types that merely share a spelling. -
isCache
public boolean isCache()Whether the ntfy server may cache published messages (trueby default, matching ntfy's own default of storing them for 12 hours).falsesendsCache: no. The message then reaches CONNECTED subscribers only: a subscriber with a momentary network problem never receives it, andsince=/poll=1stop returning it. That is a real trade — privacy against delivery to anyone who was not listening at the time. -
isFirebase
public boolean isFirebase()Whether the ntfy server may forward published messages to Firebase Cloud Messaging (trueby default).Worth knowing before leaving it on: ntfy.sh is configured to use FCM, so on the default endpoint every alert — stack traces and allow-listed MDC values included — also transits Google's infrastructure.
falsesendsFirebase: no. The cost is delivery latency on the Google Play Android client when instant delivery is off (up to 15 minutes); on a self-hosted server with no FCM configured the header is simply inert. -
isDeliveryPolicyValueRejected
public boolean isDeliveryPolicyValueRejected()True when acacheorfirebasevalue was supplied but could not be read as a boolean, so the default was kept. Exists for the same reason asisStartupPingValueRejected(): on these two keys a silent misparse costs delivered alerts, so an unreadable value has to be reported rather than guessed at. -
getIcon
URL of the icon shown beside the notification (ntfyIconheader), ornullwhen unset. Must be a fetchable http(s) URL; a value that is not one is dropped, because a bad one is otherwise undetectable — the subscriber's client fetches the icon, not the server, so nothing on the publish path ever reports it.Where that drop is REPORTED depends on who is publishing.
AlertEnginechecks the value atstart()and warns;NtfyClienthas no diagnostics channel and drops it in silence. Same rule, one of the two paths simply has nowhere to say so.The FORMAT is not checked either way: ntfy renders JPEG and PNG only, but a URL says little about the bytes behind it.
-
getIconsByLoggerPrefix
The unmodifiable logger-prefix → icon-URL table that overridesgetIcon()for alerts, in configured order. Empty by default.A table rather than placeholders in a single URL, and the difference is a security one. The subscriber's client downloads the icon automatically when it DISPLAYS a notification — no tap involved — so an interpolated URL would send whatever it interpolated, plus the subscriber's IP, to a third-party host on every notification. A table only ever selects among URLs the operator wrote out in full, so nothing derived from a running application ever leaves.
Applies to alerts only. A notification published through
NtfyClienthas no logger to match on and always carriesgetIcon(). -
isIconsByLoggerValueRejected
public boolean isIconsByLoggerValueRejected()True when anicons-by-loggerentry could not be read as aprefix=urlpair, so it was discarded. Exists for the same reason asisStartupPingValueRejected(): without it a pair mistyped with a space instead of an=would be indistinguishable from an unset key, and would produce no icon and no signal — the invisible failure the icon URL check exists to prevent, reintroduced one layer earlier. -
getIncludeMdcKeys
The unmodifiable, EXPLICIT allow-list of MDC keys whose values are rendered into alert bodies (onekey: valueline each), in configured order — that order is the rendering order. Empty by default, i.e. no MDC content is published at all unless an operator opts in.There is deliberately NO wildcard and no "include everything" mode: a production MDC routinely carries session tokens and user identifiers, so no MDC value may ever leave the process in a notification unless it was named here. Adapters project the live context through
MdcProjector.project(java.util.List<java.lang.String>, java.util.function.Function<java.lang.String, java.lang.String>), which also scrubs, truncates, and caps whatever the named keys hold. -
isEnabled
public boolean isEnabled() -
isAsyncEnabled
public boolean isAsyncEnabled()True when delivery of individual error alerts should be offloaded to the engine's bounded asynchronous work queue instead of running inline on the calling (logging) thread. On by default (since 2.0): a slow or unreachable ntfy server can never back-pressure application threads during an error storm — seeAlertEnginefor the queue/overflow semantics. Disable it to restore the pre-2.0 synchronous behavior, where each publish blocks the calling thread until the HTTP exchange completes — useful for short-lived processes (batch jobs, CLIs) that must know the alert left the process before the logging call returns. -
getAsyncQueueCapacity
public int getAsyncQueueCapacity()Maximum number of pending error alerts the asynchronous delivery queue holds before overflow kicks in (seeAlertEngine). Only consulted whenisAsyncEnabled()is true. A non-positive value is clamped to a safe minimum by the engine at start. -
isRequireHttpsForCredentials
public boolean isRequireHttpsForCredentials()True when the engine must REFUSE activation (rather than merely warn) if credentials — a configured token, a username/password pair, or userinfo embedded in the URL itself — would be sent over a cleartexthttp://endpoint. On by default (since 2.0): secrets never traverse the network unencrypted unless the operator explicitly opts out. Setting it tofalserestores the pre-2.0 warn-and-activate behavior for deliberate self-hosted plain-HTTP setups. -
isEndpointFromClasspathFile
public boolean isEndpointFromClasspathFile()True when the endpoint URL was supplied ONLY by a classpathntfy.properties(no system property or environment variable set it). Set byConfigLoader; auto-installing adapters use it to warn loudly, because any jar on the classpath can carry such a file and silently redirect log-derived alerts to a server the operator never chose. -
isAllowClasspathEndpoint
public boolean isAllowClasspathEndpoint()True when the operator has explicitly opted in to activating alert delivery from an endpoint URL supplied only by a classpathntfy.properties(seeisEndpointFromClasspathFile()). Defaultfalse: because any jar on the classpath can ship such a file and silently redirect log-derived alerts (messages and stack traces) to a server the operator never chose, auto-installing adapters refuse classpath-only activation unless this flag is set (kebab keyallow-classpath-endpoint, envNTFY_ALLOW_CLASSPATH_ENDPOINT, syspropntfy.allow-classpath-endpoint). -
getStartupPing
What the opt-in startup self-test does once the engine has finished activating — seeStartupPingMode. Defaults toStartupPingMode.OFF, which is a true no-op: no request is made and no diagnostic line is emitted, so the default path's diagnostic stream is unchanged. Nevernull. -
isStartupPingFailFast
public boolean isStartupPingFailFast()True when a failed startup self-test must abort application startup (by throwingNtfyStartupSelfTestExceptionout ofAlertEngine.start()) rather than merely warn. Defaultfalse: a logging backend must never be able to kill the application it instruments, so failing the deployment is strictly opt-in.Enabling this also makes the self-test run inline instead of on a background thread, because a start that has already returned can no longer be aborted. That is a bounded but real addition to startup time (at most
connect-timeout + request-timeout), and is the reason this is aimed at CI/staging rather than production.Inert when
getStartupPing()isStartupPingMode.OFF; the engine warns about that combination, since it is always a mistake. -
isStartupPingValueRejected
public boolean isStartupPingValueRejected()True when astartup-pingvalue was supplied but matched no known mode, so the default was kept. Exists purely so the engine can warn about the typo at start: without it, a misspelledstartup-ping=probwould be indistinguishable from an unset key and would silently behave asoff— the exact class of silent misconfiguration this whole feature was added to eliminate. -
getStartupPingWarn
What the startup self-test does for the optional WARN route — seeStartupPingMode. Independent ofgetStartupPing()and likewiseStartupPingMode.OFFby default, because the two routes are configured, permissioned and paid for separately: ntfy grants access per topic, so a healthy ERROR route is no evidence at all about the WARN one, and inpublishmode each route costs its own notification on every boot. Nevernull.Only consulted when the WARN route actually survived its own preconditions; testing a route the engine has withdrawn would report on something that is not going to be used.
-
isStartupPingWarnValueRejected
public boolean isStartupPingWarnValueRejected()AsisStartupPingValueRejected(), forstartup-ping-warn. -
isStartupPingNotifyFailures
public boolean isStartupPingNotifyFailures()Whether a failed self-test should be announced as an ntfy notification on a route that PASSED. On by default — the one opt-OUT in this feature.A diagnostic line lands on a status manager or stderr that nobody reads until they are already investigating; the point of alerting is that it reaches people. When one route is broken and another is proven healthy, the healthy one can carry that news to where operators actually look.
It cannot fire unless some route's self-test PASSED, which is what stops it from publishing to a topic the self-test has not just verified: with no WARN route tested, nothing fails, and the ERROR topic is never pinged. Note the one surprise it does introduce — with this on, a self-test configured purely as
probecan still publish exactly one notification, the failure report. Set itfalseto keepprobeabsolutely publish-free. -
getLocale
Language of the notification bodies and self-diagnostic messages the engine produces. Defaults toLocale.ENGLISHand, deliberately, never follows the host JVM's default locale, so the language of alerts is deterministic regardless of where the process runs. A locale with no shipped translation falls back wholesale to English; a partial translation degrades to English per missing key. Nevernull. -
isActive
public boolean isActive()True when this config should actually deliver alerts: it isenabled, and bothgetUrl()andgetTopic()are non-blank. A config that is disabled or missing either endpoint half is inactive (the engine reports why viaDiagnosticsat start).
-