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

com.github.autoscaler.workload.rabbit.RabbitStatsReporter Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2015-2024 Open Text.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.autoscaler.workload.rabbit;


import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.autoscaler.api.ScalerException;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import jakarta.ws.rs.core.Response;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * A RabbitStatsReporter is an object that actually makes HTTP calls to a RabbitMQ management server,
 * and interprets the results to return QueueStats objects which are used by the RabbitWorkloadAnalyser.
 */
public class RabbitStatsReporter
{
    private final RabbitManagementApi rabbitApi;
    private final ObjectMapper mapper = new ObjectMapper();
    private final String vhost;
    private static final String RMQ_MESSAGES_READY = "messages_ready";
    private static final String RMQ_MESSAGE_STATS = "message_stats";
    private static final String RMQ_DELIVER_DETAILS = "deliver_get_details";
    private static final String RMQ_PUBLISH_DETAILS = "publish_details";
    private static final String RMQ_RATE = "rate";
    private static final int PAGE_SIZE = 100;
    private static final Logger LOG = LoggerFactory.getLogger(RabbitStatsReporter.class);

    public RabbitStatsReporter(final String endpoint, final String user, final String pass, final String vhost)
    {
        this.vhost = Objects.requireNonNull(vhost);

        rabbitApi = RabbitManagementApiFactory.create(endpoint, user, pass);
    }


    /**
     * Get statistics for a particular RabbitMQ queue.
     * @param queueReference the named queue
     * @return statistics for the requested queue
     * @throws ScalerException if the statistics cannot be acquired
     */
    public QueueStats getQueueStats(final String queueReference)
            throws ScalerException
    {
        try {
            Response res = rabbitApi.getQueueStatus(vhost, queueReference);
            JsonNode root = mapper.readTree(res.readEntity(InputStream.class));
            int msgs = root.get(RMQ_MESSAGES_READY).asInt();
            JsonNode stats = root.get(RMQ_MESSAGE_STATS);
            double pubrate;
            double conrate;
            if ( stats != null ) {
                JsonNode ack = stats.get(RMQ_DELIVER_DETAILS);
                JsonNode pub = stats.get(RMQ_PUBLISH_DETAILS);
                pubrate = pub == null ? 0.0 : pub.get(RMQ_RATE).asDouble();
                conrate = ack == null ? 0.0 : ack.get(RMQ_RATE).asDouble();
            } else {
                // this queue hasn't had any messages yet
                pubrate = 0.0;
                conrate = 0.0;
            }
            return new QueueStats(msgs, pubrate, conrate);
        } catch (IOException e) {
            throw new ScalerException("Failed to get queue size", e);
        }
    }

    /**
     * Get statistics for all RabbitMQ staging queues whose names match the supplied stagingQueueNameRegex regular expression.
     * @param stagingQueueNameRegex A regular expression describing the pattern of staging queue names to match
     * @return a list of statistics for the requested staging queues
     * @throws ScalerException if the statistics cannot be acquired
     */
    public List getStagingQueueStats(final String stagingQueueNameRegex)
            throws ScalerException
    {
        if (stagingQueueNameRegex == null) {
            return Collections.emptyList();
        }

        final List stagingQueueStatsList = new ArrayList<>();

        int currentPage = 1;

        while (true) {

            LOG.debug("Getting page {} of queues matching regex {}", currentPage, stagingQueueNameRegex);

            // Get next page of queues
            final PagedQueues pagedQueues = rabbitApi.getPagedQueues(
                    vhost, stagingQueueNameRegex, currentPage, PAGE_SIZE, "name,messages_ready,message_stats");

            LOG.debug("Got page {} of queues matching regex {}: {}", currentPage, stagingQueueNameRegex, pagedQueues);

            // Read the queue stats for each queue in this page of queues
            for (final PagedQueues.Item item : pagedQueues.getItems()) {

                final double publishRate;
                final PagedQueues.MessageStats messageStats = item.getMessageStats();
                if (messageStats != null) {
                    final PagedQueues.Rate publishDetails = messageStats.getPublishDetails();
                    publishRate = publishDetails != null ? publishDetails.getRate() : 0.0;
                } else {
                    publishRate = 0.0;
                }

                // Add the stats for this queue to the list
                final StagingQueueStats stagingQueueStats = new StagingQueueStats(item.getName(), item.getMessagesReady(), publishRate);
                stagingQueueStatsList.add(stagingQueueStats);
            }

            // If we've reached the last page of queues, stop
            // Using >= rather than == because if there are no queues (items) in the response, page = 1 and page_count = 0
            if (pagedQueues.getPage() >= pagedQueues.getPageCount()) {
                break;
            } else {
                // Else get the next page of queues
                currentPage++;
            }
        }

        return stagingQueueStatsList;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy