All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.mats3.matsbrokermonitor.activemq.ActiveMqBrokerStatsQuerier Maven / Gradle / Ivy

package io.mats3.matsbrokermonitor.activemq;

import java.io.Closeable;
import java.time.Instant;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.function.Consumer;

/**
 * @author Endre Stølsvik 2021-12-28 02:31 - http://stolsvik.com/, [email protected]
 */
public interface ActiveMqBrokerStatsQuerier extends Closeable {

    /**
     * @param nodeId
     *            the internal nodeId to decide whether an update came from "this node" or not, used for
     *            {@link ActiveMqBrokerStatsEvent#isStatsEventOriginatedOnThisNode()}. Must be different for each
     *            instance connected to the same ActiveMQ instance. Not really needed, since it works just nice with a
     *            random id (which it uses default), but it can be valuable for debugging.
     */
    void setNodeId(String nodeId);

    void start();

    void close();

    void setMatsDestinationPrefix(String matsDestinationPrefix);

    void registerListener(Consumer listener);

    interface ActiveMqBrokerStatsEvent {
        /**
         * @return the correlationId if this is an event in response to an invocation of
         *         {@link #forceUpdate(String, boolean)}
         */
        Optional getCorrelationId();

        /**
         * @return true if this is an event in response to an invocation of
         *         {@link #forceUpdate(String, boolean)}, and the 'fullUpdate' parameter was true.
         */
        boolean isFullUpdate();

        /**
         * @return true if this event was the result from a request sent from this node.
         */
        boolean isStatsEventOriginatedOnThisNode();

        /**
         * @return the nodeId which performed the request which resulted in this update event - the nodeId is a random
         *         string unless set using {@link ActiveMqBrokerStatsQuerier#setNodeId(String)}.
         */
        Optional getOriginatingNodeId();

        /**
         * @return the number of milliseconds between the statistics request(s) were started, to the (last) response was
         *         received.
         */
        OptionalDouble getStatsRequestReplyLatencyMillis();
    }

    /**
     * Requests ASAP update.
     *
     * @param correlationId
     *            this is only used to propagate through to the update event.
     * @param fullUpdate
     *            this is only used to propagate through to the update event.
     */
    void forceUpdate(String correlationId, boolean fullUpdate);

    Optional getCurrentBrokerStatsDto();

    ConcurrentNavigableMap getCurrentDestinationStatsDtos();

    /**
     * NOTE: Explanations from
     * [email protected]
     * mail-archive: "Re: Topic counts explanation", or
     * Stackoverflow: What do some of the fields returned from
     * ActiveMQ.Agent query mean?, or
     * ActiveMQ Docs: How do I find the Size of
     * a Queue
     */
    class CommonStatsDto {
        Instant statsReceived;

        String brokerId;
        String brokerName;
        Instant brokerTime;

        /**
         * The number of messages that currently reside in the queue.
         * 

* (Endre: Seems to be {@link #enqueueCount} - {@link #dequeueCount}). */ long size; /** * The number of messages that have been written to the queue over the lifetime of the queue (since last * restart). */ long enqueueCount; /** * The number of messages that have been successfully (i.e., they’ve been acknowledged from the consumer) read * off the queue over the lifetime of the queue (since last restart). */ long dequeueCount; /** * The number of messages that were not delivered because they were expired (since last restart). */ long expiredCount; /** * The number of messages that have been dispatched (sent) to the consumer over the lifetime of the queue. Note * that dispatched messages may not have all been acknowledged (since last restart). *

* (Endre: This number can evidently be higher than {@link #enqueueCount}, which I assume means that * redeliveries are included.) */ long dispatchCount; /** * The number of messages that have been dispatched and are currently awaiting acknowledgment from the consumer. * So as this number decreases, the DequeueCount increases. *

* (Endre: This number is included in the {@link #size} number, as inflight messages are not yet dequeued). */ long inflightCount; long producerCount; long consumerCount; /** * The minimum amount of time that messages remained enqueued. */ double minEnqueueTime; /** * On average, the amount of time (ms) that messages remained enqueued. Or average time it is taking the * consumers to successfully process messages. */ double averageEnqueueTime; /** * The maximum amount of time that messages remained enqueued. */ double maxEnqueueTime; long averageMessageSize; long messagesCached; long memoryUsage; long memoryLimit; int memoryPercentUsage; String getCommonToString() { return "statsReceivedTimeMillis=" + statsReceived + ", brokerId='" + brokerId + '\'' + ", brokerName='" + brokerName + '\'' + ", brokerTime='" + brokerTime + '\'' + ", size=" + size + ", enqueueCount=" + enqueueCount + ", dequeueCount=" + dequeueCount + ", expiredCount=" + expiredCount + ", dispatchCount=" + dispatchCount + ", inflightCount=" + inflightCount + ", producerCount=" + producerCount + ", consumerCount=" + consumerCount + ", minEnqueueTime=" + minEnqueueTime + ", averageEnqueueTime=" + averageEnqueueTime + ", maxEnqueueTime=" + maxEnqueueTime + ", averageMessageSize=" + averageMessageSize + ", messagesCached=" + messagesCached + ", memoryUsage=" + memoryUsage + ", memoryLimit=" + memoryLimit + ", memoryPercentUsage=" + memoryPercentUsage; } String getCommonJson() { return " \"statsReceivedTimeMillis\"=" + statsReceived + "\n" + " \"brokerId\"=\"" + brokerId + '"' + "\n" + " \"brokerName\"=\"" + brokerName + '"' + "\n" + " \"brokerTime\"=\"" + brokerTime + '"' + "\n" + " \"size\"=" + size + "\n" + " \"enqueueCount\"=" + enqueueCount + "\n" + " \"dequeueCount\"=" + dequeueCount + "\n" + " \"expiredCount\"=" + expiredCount + "\n" + " \"dispatchCount\"=" + dispatchCount + "\n" + " \"inflightCount\"=" + inflightCount + "\n" + " \"producerCount\"=" + producerCount + "\n" + " \"consumerCount\"=" + consumerCount + "\n" + " \"minEnqueueTime\"=" + minEnqueueTime + "\n" + " \"averageEnqueueTime\"=" + averageEnqueueTime + "\n" + " \"maxEnqueueTime\"=" + maxEnqueueTime + "\n" + " \"averageMessageSize\"=" + averageMessageSize + "\n" + " \"messagesCached\"=" + messagesCached + "\n" + " \"memoryUsage\"=" + memoryUsage + "\n" + " \"memoryLimit\"=" + memoryLimit + "\n" + " \"memoryPercentUsage\"=" + memoryPercentUsage + "\n"; } } class BrokerStatsDto extends CommonStatsDto { long storeUsage; long storeLimit; int storePercentUsage; long tempUsage; long tempLimit; int tempPercentUsage; String stompSsl; String ssl; String stomp; String openwire; String vm; String dataDirectory; @Override public String toString() { return "BrokerStatsDto{" + getCommonToString() + ", storeUsage=" + storeUsage + ", storeLimit=" + storeLimit + ", storePercentUsage=" + storePercentUsage + ", tempUsage=" + tempUsage + ", tempLimit=" + tempLimit + ", tempPercentUsage=" + tempPercentUsage + ", stompSsl='" + stompSsl + '\'' + ", ssl='" + ssl + '\'' + ", stomp='" + stomp + '\'' + ", openwire='" + openwire + '\'' + ", vm='" + vm + '\'' + ", dataDirectory='" + dataDirectory + '\'' + '}'; } public String toJson() { return "{\n" + getCommonJson() + " \"storeUsage\"=" + storeUsage + "\n" + " \"storeLimit\"=" + storeLimit + "\n" + " \"storePercentUsage\"=" + storePercentUsage + "\n" + " \"tempUsage\"=" + tempUsage + "\n" + " \"tempLimit\"=" + tempLimit + "\n" + " \"tempPercentUsage\"=" + tempPercentUsage + "\n" + " \"stompSsl\"=\"" + stompSsl + '"' + "\n" + " \"ssl\"=\"" + ssl + '"' + "\n" + " \"stomp\"=\"" + stomp + '"' + "\n" + " \"openwire\"=\"" + openwire + '"' + "\n" + " \"vm\"=\"" + vm + '"' + "\n" + " \"dataDirectory\"=\"" + dataDirectory + '"' + "\n" + '}'; } } class DestinationStatsDto extends CommonStatsDto { String destinationName; // Only present if there is a head message present (I created this feature in ActiveMQ!) Optional firstMessageTimestamp; @Override public String toString() { return "DestinationStatsDto{" + ", destinationName='" + destinationName + '\'' + ", firstMessageTimestamp='" + firstMessageTimestamp + '\'' + ", " + getCommonToString() + '}'; } public String toJson() { return "{\n" + " \"destinationName\"=\"" + destinationName + "\"\n" + " \"firstMessageTimestamp\"=" + (firstMessageTimestamp.map(instant -> "\"" + instant + "\"").orElse("null")) + "\n" + getCommonJson() + '}'; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy