org.graylog2.metrics.MongoDbMetricsReporter.java Source code

Java tutorial

Introduction

Here is the source code for org.graylog2.metrics.MongoDbMetricsReporter.java

Source

/**
 * This file is part of Graylog.
 *
 * Graylog is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Graylog is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Graylog.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.graylog2.metrics;

import com.codahale.metrics.*;
import com.google.common.collect.Lists;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.WriteConcern;
import org.bson.types.ObjectId;
import org.graylog2.database.MongoConnection;
import org.graylog2.plugin.ServerStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.concurrent.TimeUnit;

public class MongoDbMetricsReporter extends ScheduledReporter {
    private static final Logger LOG = LoggerFactory.getLogger(MongoDbMetricsReporter.class);

    private final Clock clock;
    private final String nodeId;
    private final MongoConnection mongoConnection;

    private MongoDbMetricsReporter(MetricRegistry registry, MongoConnection mongoConnection,
            ServerStatus serverStatus, Clock clock, TimeUnit rateUnit, TimeUnit durationUnit, MetricFilter filter) {
        super(registry, "mongodb-reporter", filter, rateUnit, durationUnit);
        this.mongoConnection = mongoConnection;
        this.nodeId = serverStatus.getNodeId().toString();
        this.clock = clock;
    }

    public static Builder forRegistry(MetricRegistry registry, MongoConnection mongoConnection,
            ServerStatus serverStatus) {
        return new Builder(registry, mongoConnection, serverStatus);
    }

    public static class Builder {
        private final MetricRegistry registry;
        private final MongoConnection mongoConnection;
        private final ServerStatus serverStatus;
        private final Clock clock;
        private final TimeUnit rateUnit;
        private final TimeUnit durationUnit;
        private final MetricFilter filter;

        @Inject
        private Builder(MetricRegistry registry, MongoConnection mongoConnection, ServerStatus serverStatus) {
            this.registry = registry;
            this.mongoConnection = mongoConnection;
            this.serverStatus = serverStatus;
            this.clock = Clock.defaultClock();
            this.rateUnit = TimeUnit.SECONDS;
            this.durationUnit = TimeUnit.MILLISECONDS;
            this.filter = MetricFilter.ALL;
        }

        public MongoDbMetricsReporter build() {
            return new MongoDbMetricsReporter(registry, mongoConnection, serverStatus, clock, rateUnit,
                    durationUnit, filter);
        }
    }

    @Override
    public void report(SortedMap<String, Gauge> gauges, SortedMap<String, Counter> counters,
            SortedMap<String, Histogram> histograms, SortedMap<String, Meter> meters,
            SortedMap<String, Timer> timers) {
        final Date timestamp = new Date(clock.getTime());

        List<DBObject> docs = Lists.newArrayListWithExpectedSize(
                gauges.size() + counters.size() + histograms.size() + meters.size() + timers.size());

        collectGaugeReports(docs, gauges, timestamp);
        collectCounterReports(docs, counters, timestamp);
        collectHistogramReports(docs, histograms, timestamp);
        collectMeterReports(docs, meters, timestamp);
        collectTimerReports(docs, timers, timestamp);

        try {
            final DBCollection collection = mongoConnection.getDatabase().getCollection("graylog2_metrics");
            // don't hang on to the data for too long.
            final BasicDBObject indexField = new BasicDBObject("timestamp", 1);
            final BasicDBObject indexOptions = new BasicDBObject("expireAfterSeconds", 5 * 60);
            collection.createIndex(indexField, indexOptions);

            collection.insert(docs, WriteConcern.UNACKNOWLEDGED);
        } catch (Exception e) {
            LOG.warn("Unable to write graylog2 metrics to mongodb. Ignoring this error.", e);
        }
    }

    private void collectGaugeReports(List<DBObject> docs, SortedMap<String, Gauge> gauges, Date timestamp) {
        if (gauges.isEmpty())
            return;

        for (Map.Entry<String, Gauge> entry : gauges.entrySet()) {
            final BasicDBObject report = getBasicDBObject(timestamp, entry.getKey(), "gauge");
            report.put("value", entry.getValue().getValue());
            docs.add(report);
        }
    }

    private void collectCounterReports(List<DBObject> docs, SortedMap<String, Counter> counters, Date timestamp) {
        if (counters.isEmpty())
            return;

        for (Map.Entry<String, Counter> entry : counters.entrySet()) {
            final BasicDBObject report = getBasicDBObject(timestamp, entry.getKey(), "counter");
            report.put("count", entry.getValue().getCount());
            docs.add(report);
        }
    }

    private void collectHistogramReports(List<DBObject> docs, SortedMap<String, Histogram> histograms,
            Date timestamp) {
        if (histograms.isEmpty())
            return;

        for (Map.Entry<String, Histogram> entry : histograms.entrySet()) {
            final BasicDBObject report = getBasicDBObject(timestamp, entry.getKey(), "histogram");
            final Histogram histogram = entry.getValue();

            final Snapshot s = histogram.getSnapshot();
            report.put("count", s.size());
            report.put("75th_percentile", s.get75thPercentile());
            report.put("95th_percentile", s.get95thPercentile());
            report.put("98th_percentile", s.get98thPercentile());
            report.put("99th_percentile", s.get99thPercentile());
            report.put("999th_percentile", s.get999thPercentile());
            report.put("max", s.getMax());
            report.put("min", s.getMin());
            report.put("mean", s.getMean());
            report.put("median", s.getMedian());
            report.put("std_dev", s.getStdDev());
            docs.add(report);
        }
    }

    private void collectMeterReports(List<DBObject> docs, SortedMap<String, Meter> meters, Date timestamp) {
        if (meters.isEmpty())
            return;
        for (Map.Entry<String, Meter> entry : meters.entrySet()) {
            final BasicDBObject report = getBasicDBObject(timestamp, entry.getKey(), "meter");
            final Meter v = entry.getValue();
            report.put("count", v.getCount());
            report.put("1-minute-rate", v.getOneMinuteRate());
            report.put("5-minute-rate", v.getFiveMinuteRate());
            report.put("15-minute-rate", v.getFifteenMinuteRate());
            report.put("mean-rate", v.getMeanRate());
            docs.add(report);
        }

    }

    private void collectTimerReports(List<DBObject> docs, SortedMap<String, Timer> timers, Date timestamp) {
        if (timers.isEmpty())
            return;
        for (Map.Entry<String, Timer> entry : timers.entrySet()) {
            final BasicDBObject report = getBasicDBObject(timestamp, entry.getKey(), "timer");
            final Timer v = entry.getValue();
            final Snapshot s = v.getSnapshot();
            // meter part
            report.put("count", v.getCount());
            report.put("rate-unit", getRateUnit());
            report.put("1-minute-rate", convertRate(v.getOneMinuteRate()));
            report.put("5-minute-rate", convertRate(v.getFiveMinuteRate()));
            report.put("15-minute-rate", convertRate(v.getFifteenMinuteRate()));
            report.put("mean-rate", convertRate(v.getMeanRate()));

            // histogram part
            report.put("duration-unit", getDurationUnit());
            report.put("75-percentile", convertDuration(s.get75thPercentile()));
            report.put("95-percentile", convertDuration(s.get95thPercentile()));
            report.put("98-percentile", convertDuration(s.get98thPercentile()));
            report.put("99-percentile", convertDuration(s.get99thPercentile()));
            report.put("999-percentile", convertDuration(s.get999thPercentile()));
            report.put("max", convertDuration(s.getMax()));
            report.put("min", convertDuration(s.getMin()));
            report.put("mean", convertDuration(s.getMean()));
            report.put("median", convertDuration(s.getMedian()));
            report.put("stddev", convertDuration(s.getStdDev()));
            docs.add(report);
        }
    }

    private BasicDBObject getBasicDBObject(Date timestamp, String metricName, String metricType) {
        final BasicDBObject report = new BasicDBObject();

        report.put("_id", new ObjectId());
        report.put("type", metricType);
        report.put("timestamp", timestamp);
        report.put("name", metricName);
        report.put("node", nodeId);

        return report;
    }
}