Class AceMqActuator

java.lang.Object
org.acemq.amqp.actuator.AceMqActuator
All Implemented Interfaces:
AutoCloseable

public final class AceMqActuator extends Object implements AutoCloseable
Serves AceMQ's metrics, health and version over HTTP.

 AceMq mq = AceMq.connect("amqp://localhost");
 try (AceMqActuator actuator = AceMqActuator.start(mq)) {
     // http://127.0.0.1:9464/acemq-metrics
 }
 

Why this exists

MicrometerTelemetry in the core is the right way to get these numbers, and a Spring Boot application needs nothing else: Actuator supplies both halves of a scrape surface -- a MeterRegistry to record into and an endpoint to serve from -- and the starter wires the library to it. A worker, a daemon or a command-line consumer has neither half, so on the JVM alone, and nowhere else in the family, a non-framework application could not expose its messaging metrics without writing an HTTP endpoint of its own. Go ships actuator, .NET ships AceMq.Amqp.Diagnostics, Python ships prometheus, Ruby ships telemetry; this is Java's.

It is an addition to MicrometerTelemetry, not a second implementation of it. The numbers are recorded by the core exactly as they always were; this owns a PrometheusMeterRegistry they land in and a small HTTP server that renders it.

When to use it, and when not to

  • Spring Boot: do not. Add spring-boot-starter-actuator and micrometer-registry-prometheus and scrape /actuator/prometheus. That endpoint is managed, secured and configured alongside every other endpoint the application has, and a second HTTP server on a second port is one more thing to firewall for no gain.
  • Quarkus, Micronaut, Helidon, a servlet application: also no, for the same reason -- each has a metrics endpoint already. If you want the library's registry served from it, take metrics() or registry() and hand it to whatever you already run, without starting this server at all.
  • A worker, a batch consumer, a daemon, a CLI: yes. This is the case nothing else covers.

The HTTP server

com.sun.net.httpserver.HttpServer, from the JDK's jdk.httpserver module. Despite the package name it is a supported API, present in every JDK since 6, and it costs this module no dependency at all. Embedding Jetty or Netty to serve three text endpoints would put a second HTTP stack inside applications that frequently already have one, and the version fights that follow are a poor trade for a scrape endpoint.

It is not an application server and is not meant to face the internet. What a real deployment wants is this bound to loopback or a pod-local address, scraped from the same network namespace by a sidecar or a node agent, with authentication supplied by the platform -- a network policy, a mesh, an ingress -- rather than by a messaging library. A deployment that wants more than that already has an HTTP server, and should serve metrics() from it instead.

These endpoints are unauthenticated

Health names the transport and the broker's state; metrics carry queue and exchange names and traffic rates. See ActuatorOptions.Builder.bindAddress(String).

  • Method Details

    • start

      public static AceMqActuator start(AceMq mq)
      Starts an actuator on the default port and paths, reporting on one connection.
      Parameters:
      mq - the connection health and info describe
      Returns:
      the running actuator
      Throws:
      AceMqException - if the port cannot be bound
    • start

      public static AceMqActuator start(ActuatorOptions options)
      Starts an actuator.
      Parameters:
      options - how to expose it
      Returns:
      the running actuator
      Throws:
      AceMqException - if the port cannot be bound
    • registry

      public io.micrometer.prometheusmetrics.PrometheusMeterRegistry registry()
      The registry the metrics are read from.

      Hand it to MicrometerSupport.telemetry(registry, transport) when connecting if you would rather wire the connection to it explicitly than rely on Micrometer's global registry -- or hand it to a framework's own Prometheus endpoint and never start this server at all.

      Returns:
      the registry
    • metrics

      public String metrics()
      Returns:
      the metrics body, byte for byte what a scrape receives
    • url

      public String url()
      Where it is listening.

      Worth logging at start-up, and the only way to learn the port when 0 was asked for.

      Returns:
      the base URL
    • port

      public int port()
      Returns:
      the port actually bound, which differs from the one requested when 0 was asked for
    • paths

      public List<String> paths()
      Returns:
      the three paths being served, for logging at start-up
    • close

      public void close()
      Stops the server and releases the port.

      A registry the actuator created is detached from Micrometer's global registry and closed; one that was supplied is left alone, because the caller owns it. Calling this twice is harmless.

      Specified by:
      close in interface AutoCloseable