Class NtfyMeterBinder

java.lang.Object
io.github.pimak.ntfy.quarkus.runtime.NtfyMeterBinder
All Implemented Interfaces:
io.micrometer.core.instrument.binder.MeterBinder

@Singleton public class NtfyMeterBinder extends Object implements io.micrometer.core.instrument.binder.MeterBinder
Binds the ntfy pipeline observability counters to Micrometer as three FunctionCounters: ntfy.pipeline.published, ntfy.pipeline.suppressed, and ntfy.pipeline.failed — the same three meters, with the same names and meanings, that the Spring Boot starter exports.

This is a plain CDI MeterBinder: the Quarkus Micrometer extension discovers every MeterBinder bean and applies it to the registry it creates, so nothing here has to know which registry implementation (Prometheus, OTLP, …) the application chose.

Registered conditionally. The bean is only added to the container when the application actually has the Quarkus Micrometer extension: NtfyProcessor gates its AdditionalBeanBuildItem on Capability.METRICS — io.quarkus.metrics, the capability quarkus-micrometer provides — together with a runtime-classpath check for MeterRegistry. It names this class by string, never by class literal, so on a build without Micrometer this class is never loaded and its io.micrometer references never have to resolve. micrometer-core is therefore an optional dependency of the extension: an application that does not want metrics pulls in nothing.

Counters are resolved lazily, at scrape time, through NtfyPipelineCountersHolder. That decouples the meters from the log handler's lifecycle: the handler is installed at RUNTIME_INIT, well before the CDI container (and hence this bean) exists, and when the config is inactive it is never installed at all. Reading through the holder on every scrape means there is no ordering dependency in either direction, and the meters simply report 0 when no handler is installed instead of failing or disappearing.

The counters are monotonic for a handler's lifetime, so within one application run the meters only ever climb. A dev-mode reload installs a new handler with fresh counters, and the meters — which resolve through the holder rather than capturing an instance — follow it down to zero and back up. That is an ordinary counter reset, indistinguishable to a monitoring system from the process itself restarting.

  • Constructor Details

    • NtfyMeterBinder

      public NtfyMeterBinder()
  • Method Details

    • bindTo

      public void bindTo(io.micrometer.core.instrument.MeterRegistry registry)
      Specified by:
      bindTo in interface io.micrometer.core.instrument.binder.MeterBinder