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

org.zeromq.jms.protocol.ZmqSocketMetrics Maven / Gradle / Ivy

package org.zeromq.jms.protocol;

/*
 * Copyright (c) 2015 Jeremy Miller
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
import java.io.Serializable;

/**
 * Metric functionality for Zero MQ Sockets. The metric contains a total count for send and review messages,
 * but also a bucket of counters to enable temporal counting.
 */
public class ZmqSocketMetrics implements Serializable {

    private static final long serialVersionUID = 3377715287843053265L;
    private final String addr;

    private ZmqSocketStatus status;

    private long sendCount = 0;
    private long receiveCount = 0;

    private long sendTime;
    private long receiveTime;

    private final int bucketCount;
    private final int bucketInterval;

    private int sendBucketIndex = 0;
    private int receiveBucketIndex = 0;

    private final long[] sendBucketCounts;
    private final long[] receiveBucketCounts;

    /**
     * Construct the metric based on what is going to be logged.
     * @param addr            the address
     * @param bucketCount     the number of counter buckets
     * @param bucketInterval  the bucket interval in milliseconds
     * @param logSend         the log send indicator
     * @param logReceive      the log receive indicator
     */
    public ZmqSocketMetrics(final String addr, final int bucketCount, final int bucketInterval, final boolean logSend, final boolean logReceive) {
        this.addr = addr;

        this.bucketCount = bucketCount;
        this.bucketInterval = bucketInterval;
        this.sendBucketCounts = (logSend) ? new long[bucketCount] : null;
        this.receiveBucketCounts = (logReceive) ? new long[bucketCount] : null;
    }

    /**
     * Reset the buckets between now and last increment.
     * @param index         the current index based on current time
     * @param bucketIndex   the last bucket index ever incremented
     * @param bucketCounts  the bucket counts
     */
    private void resetBuckets(final int index, final int bucketIndex, final long[] bucketCounts) {
        // NOTE: this routine is not thread safe.
        int skipCount = index - bucketIndex;

        if (skipCount < 0) {
            skipCount = bucketCount - bucketIndex + index;
        }

        for (int i = 0; i < skipCount; i++) {
            final int skipIndex = (((bucketIndex + skipCount) % bucketCount) + bucketCount) % bucketCount;
            bucketCounts[skipIndex] = 0;
        }
    }

    /**
     * Increment the bucker counter based on time, and previous index.
     * @param currentTime   the current time
     * @param bucketIndex   the previous bucket index
     * @param bucketCounts  the bucket counts
     * @return              return the new bucket index (can be the same and previous depending on interval size).
     */
    protected int increment(final long currentTime, final int bucketIndex, final long[] bucketCounts) {
        final int index = (int) ((currentTime / bucketInterval) % bucketCount);

        // New index so reset bucket counter(s)
        if (bucketIndex != index) {
            resetBuckets(index, bucketIndex, bucketCounts);
        }

        bucketCounts[index]++;

        return index;
    }

    /**
     * @return  return the address of the socket
     */
    public String getAddr() {
        return addr;
    }

    /**
     * @return  return the audience
     */
    public boolean isActive() {
        return status == ZmqSocketStatus.ERROR;
    }

    /**
     * @return  return the current status for the socket, i.e. RUNNING ,STOPPED, etc...
     */
    public ZmqSocketStatus getStatus() {
        return status;
    }

    /**
     * Set the current status for the socket, i.e. RUNNING ,STOPPED, etc...
     * @param status  the new status
     */
    public void setStatus(final ZmqSocketStatus status) {
        this.status = status;
    }

    /**
     * @return  return the message sent count
     */
    public long getSendCount() {
        return sendCount;
    }

    /**
     * @return  return the last time a message was sent
     */
    public long getLastSendTime() {
        return sendTime;
    }

    /**
     * Increment the message sent count.
     */
    public void incrementSend() {
        if (sendBucketCounts == null) {
            throw new IllegalStateException("Socket statistics no setup to count sends.");
        }

        sendTime = System.currentTimeMillis();
        sendCount++;

        synchronized (sendBucketCounts) {
            sendBucketIndex = increment(sendTime, sendBucketIndex, sendBucketCounts);
        }
    }

    /**
     * @return  return the message received count
     */
    public long getReceiveCount() {
        return receiveCount;
    }

    /**
     * @return  return the last time a message was received
     */
    public long getLastReceiveTime() {
        return receiveTime;
    }

    /**
     * Increment the message received count.
     */
    public synchronized void incrementReceive() {
        if (receiveBucketCounts == null) {
            throw new IllegalStateException("Socket statistics no setup to count receives.");
        }

        receiveTime = System.currentTimeMillis();
        receiveCount++;

        synchronized (receiveBucketCounts) {
            receiveBucketIndex = increment(receiveTime, receiveBucketIndex, receiveBucketCounts);
        }
    }

    /**
     * @return  return the bucket interval (milliseconds)
     */
    public int getBucketInternval() {
        return bucketInterval;
    }

    /**
     * Return the temporal ascending order of historic bucket counts were the first is the current bucket count, and the last is the
     * last bucket count, and the index is the starting millisecond start point, i.e. 0, 5000, 10000, etc...
     * for a bucket interval of 5000 milliseconds.
     * @param bucketIndex   the current bucket index being fill (first bucket in the map)
     * @param bucketCounts  the bucket counts
     * @return              return a temporal map of bucket counts, 1, 30000, 60000, etc...
     */
    private long[] getBucketCounts(final int bucketIndex, final long[] bucketCounts) {
        // NOTE: this routine is not thread safe.

        // Reset any buckets that have not been increment recently
        final long currentTime = System.currentTimeMillis();
        final int currentIndex = (int) ((currentTime / bucketInterval) % bucketCount);
        if (bucketIndex != currentIndex) {
            resetBuckets(currentIndex, bucketIndex, bucketCounts);
        }

        final long[] tempotalBucketCounts = new long[bucketCounts.length];

        for (int i = 0; i < bucketCount; i++) {
            final int index = (((bucketIndex - i) % bucketCount) + bucketCount) % bucketCount;
            tempotalBucketCounts[i] = bucketCounts[index];
        }

        return tempotalBucketCounts;
    }

    /**
     * @return  return a temporal ascending order of send buckets counts (starting from the current time bucket)
     */
    public long[] getSendBucketCounts() {
        if (sendBucketCounts == null) {
            return null;
        }

        synchronized (sendBucketCounts) {
            return getBucketCounts(sendBucketIndex, sendBucketCounts);
        }
    }

    /**
     * @return  return a temporal ascending order of receive buckets counts (starting from the current time bucket)
     */
    public long[] getReceiveBucketCounts() {
        if (receiveBucketCounts == null) {
            return null;
        }

        synchronized (receiveBucketCounts) {
            return getBucketCounts(receiveBucketIndex, receiveBucketCounts);
        }
    }

    @Override
    public String toString() {
        return "ZmqSocketMetrics [addr=" + addr + ", status=" + status + ", sendCount=" + sendCount + ", receiveCount="
                + receiveCount + ", sendTime=" + sendTime + ", receiveTime=" + receiveTime + "]";
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy