com.cyngn.vertx.opentsdb.service.MetricsProcessor.java Source code

Java tutorial

Introduction

Here is the source code for com.cyngn.vertx.opentsdb.service.MetricsProcessor.java

Source

/*
 * Copyright 2015 Cyanogen Inc.
 * 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.cyngn.vertx.opentsdb.service;

import com.cyngn.vertx.opentsdb.client.EventBusMessage;
import com.cyngn.vertx.opentsdb.service.client.MetricsSender;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.json.JsonObject;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * Handles chunking metric data into optimal sizes to OpenTsdb
 *
 * @author truelove@cyngn.com (Jeremy Truelove) 11/10/14
 */
public class MetricsProcessor {
    private final List<MetricsSender> metricsSenders;
    private final int maxBufferSizeInBytes;
    private final EventBus bus;

    public MetricsProcessor(List<MetricsSender> metricsSenders, int maxBufferSizeInBytes, EventBus bus) {
        this.metricsSenders = metricsSenders;
        this.maxBufferSizeInBytes = maxBufferSizeInBytes;
        this.bus = bus;
    }

    /**
     * Given a queue of metrics to send, process the metrics into the right format and send them over a socket
     *
     * @param metrics the metrics queue to work off
     */
    public void processMetrics(LinkedBlockingQueue<String> metrics) {
        int metricCount = metrics.size();
        if (metricCount == 0) {
            return;
        }
        List<String> drainedMetrics = new ArrayList<>();

        metrics.drainTo(drainedMetrics);
        Buffer outputBuffer = Buffer.buffer();

        int senderPos = 0;
        MetricsSender currentSender = metricsSenders.get(senderPos);

        int nextRotateIndex = drainedMetrics.size() / metricsSenders.size();
        int switchInterval = nextRotateIndex + 1;

        // loop through and serialize the metrics and send them as we fill the buffer up to max buffer
        for (int i = 0; i < drainedMetrics.size(); i++) {
            // TODO ponder if one of the host is disconnected and stays that way
            if (i == nextRotateIndex) {
                // flush the current remaining data queued before moving to the next sender
                outputBuffer = write(currentSender, outputBuffer);

                senderPos++;
                currentSender = metricsSenders.get(senderPos);
                nextRotateIndex += switchInterval;
            }

            String metric = drainedMetrics.get(i);
            byte[] bytes = metric.getBytes();

            // if this would exceed the max buffer to send go ahead and pass to the sender
            if (bytes.length + outputBuffer.length() > maxBufferSizeInBytes) {
                outputBuffer = write(currentSender, outputBuffer);
            }

            outputBuffer.appendBytes(bytes);
        }

        // send whatever is left in the buffer
        if (outputBuffer.length() > 0) {
            write(currentSender, outputBuffer);
        }
    }

    private Buffer write(MetricsSender sender, Buffer data) {
        boolean success = sender.write(data);
        if (!success) {
            bus.send(OpenTsDbService.ERROR_MESSAGE_ADDRESS,
                    new JsonObject().put("error", EventBusMessage.WRITE_FAILURE.toString()));
        }

        return Buffer.buffer();
    }
}