Interface Telemetry


public interface Telemetry
Where AceMQ reports what it is doing.

Implemented by the Micrometer and OpenTelemetry bindings, and by a no-op used when neither is present. The interface is deliberately small and free of any vendor type, so the core never imports a metrics library and an application that wants neither pays nothing.

Implementations must not throw. Instrumentation that can break the thing it observes is worse than no instrumentation, so the core does not defend against it and expects implementations to swallow their own failures.

  • Field Details

    • NONE

      static final Telemetry NONE
      A telemetry sink that records nothing.
  • Method Details

    • publishStarted

      Telemetry.Scope publishStarted(String exchange, String routingKey, Envelope envelope)
      Called immediately before a message is published.
      Parameters:
      exchange - target exchange
      routingKey - routing key
      envelope - the envelope being sent
      Returns:
      a scope that must be closed with the outcome
    • consumeStarted

      Telemetry.Scope consumeStarted(String queue, Envelope envelope)
      Called immediately before a handler runs.
      Parameters:
      queue - queue the delivery came from
      envelope - the delivery's envelope
      Returns:
      a scope that must be closed with the outcome
    • messageRetried

      void messageRetried(String queue, Envelope envelope, Duration delay)
      Records that a message was sent for another attempt.
      Parameters:
      queue - source queue
      envelope - envelope of the message being retried
      delay - how long it will wait
    • messageDeadLettered

      void messageDeadLettered(String queue, Envelope envelope, String reason)
      Records that a message was given up on.
      Parameters:
      queue - source queue
      envelope - envelope of the message
      reason - why it was given up on
    • propagationHeaders

      Map<String,String> propagationHeaders()
      Headers to add to an outgoing message so a trace continues across the broker.

      Returns W3C trace context when tracing is active, and nothing otherwise. Called while the publish scope is open, so the context reflects the span being created.

      Returns:
      headers to merge into the message, never null
    • requestStarted

      default Telemetry.Scope requestStarted(String destination, Envelope envelope)
      Called once per request/reply round trip, around the wait for the answer.

      The publish and the reply's delivery are each already traced, and the trace context in the message headers chains them. What none of that produces is a single span whose duration is what the caller actually experienced — the question "how long did asking take" has no answer in a picture made of two unrelated hops. This is that span, and the two hops become its children.

      Parameters:
      destination - where the request was sent
      envelope - the request's envelope
      Returns:
      a scope closed with answered or timed_out
    • messageParked

      default void messageParked(String queue, Envelope envelope, String reason)
      Records that a message was put in the parking lot because nothing could read it.

      Separate from messageDeadLettered(java.lang.String, org.acemq.amqp.api.Envelope, java.lang.String) because the two are different operational events, however similar the mechanics look. Dead-lettered says a handler failed as many times as the policy allows, which is usually a dependency that will come back. Parked says the payload could not be decoded at all, which no number of retries will change and which is somebody's deploy. Reported as MetricNames.OUTCOME_PARKED.

      Parameters:
      queue - source queue
      envelope - envelope of the message, as far as it could be read
      reason - why nothing could read it
    • setAsideFailed

      default void setAsideFailed(String queue, String target, String reason)
      Records that a message could not be moved to a dead-letter or parking queue.

      Almost always a queue that was never declared. The message is settled to the broker instead, which is the last thing between it and nothing, and nothing else in the estate distinguishes this from an ordinary dead-lettering: both show one queue draining.

      Parameters:
      queue - source queue
      target - the queue it could not be moved to
      reason - why the republish failed
    • retryRungMissing

      default void retryRungMissing(String queue, String rung, Duration delay)
      Records that a retry had to wait in the consumer because its rung queue is not there.

      Degraded rather than broken: the message is still retried, and the wait still happens. What is lost is the reason a rung exists, which is that a consumer restarted mid-wait would otherwise turn a long backoff into no backoff at all.

      Java raises this when its own topology has no rung for the wait. Go, Python and Ruby raise it for that and for a rung the topology knows about that is not actually on the broker, which they find out by asking. Java derives its rungs from the policy and does not ask, so it does not see the second case; the counter means the same thing where both can see it.

      Parameters:
      queue - source queue
      rung - the rung queue that should have held the wait, which is the name to declare
      delay - how long the message was meant to wait in the broker
    • outboxPublished

      default void outboxPublished(String exchange, String routingKey, Duration lag)
      Called by the outbox relay when a record reaches the broker.

      The lag is the number that matters and the one nothing else can see: a row committed and not yet published is a message that exists, is owed to somebody, and appears in no queue depth anywhere. A relay that has stopped looks exactly like a system with nothing to send until this is measured.

      Parameters:
      exchange - where the record was published
      routingKey - the record's routing key
      lag - how long the record sat between being committed and being published
    • outboxFailed

      default void outboxFailed(String exchange, String routingKey, String reason)
      Called by the outbox relay when a record could not be published.
      Parameters:
      exchange - where the record was bound for
      routingKey - the record's routing key
      reason - why it failed
    • pipelineRunFinished

      default void pipelineRunFinished(String pipeline, String step, String outcome, Duration age)
      Called when a message leaves a pipeline, whether it finished or stopped early.

      A pipeline's steps are each traced as ordinary hops, so the stages are visible. What is not visible from them is the run: how long the whole thing took, and how often it ends before the last step. Both are properties of the run rather than of any step in it.

      Parameters:
      pipeline - the pipeline's name
      step - the step it left at, which is the last one when it completed
      outcome - completed or ended_early
      age - how long the message had existed when it left