/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.facebook.infrastructure.analytics; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; /** * This class sets up the analytics package to report metrics into * Ganglia for the various DB operations such as: reads per second, * average read latency, writes per second, average write latency. * * Author : Avinash Lakshman ( alakshman@facebook.com) & Prashant Malik ( pmalik@facebook.com ) & Karthik Ranganathan ( kranganathan@facebook.com ) */ public class DBAnalyticsSource implements IAnalyticsSource { private static final String METRIC_READ_OPS = "Read Operations"; private static final String RECORD_READ_OPS = "ReadOperationsRecord"; private static final String TAG_READOPS = "ReadOperationsTag"; private static final String TAG_READ_OPS = "ReadOperationsTagValue"; private static final String METRIC_READ_AVG = "Average Read Latency"; private static final String RECORD_READ_AVG = "ReadLatencyRecord"; private static final String TAG_READAVG = "AverageReadLatencyTag"; private static final String TAG_READ_AVG = "ReadLatencyTagValue"; private static final String METRIC_WRITE_OPS = "Write Operations"; private static final String RECORD_WRITE_OPS = "WriteOperationsRecord"; private static final String TAG_WRITEOPS = "WriteOperationsTag"; private static final String TAG_WRITE_OPS = "WriteOperationsTagValue"; private static final String METRIC_WRITE_AVG = "Average Write Latency"; private static final String RECORD_WRITE_AVG = "WriteLatencyRecord"; private static final String TAG_WRITEAVG = "AverageWriteLatencyTag"; private static final String TAG_WRITE_AVG = "WriteLatencyTagValue"; /* keep track of the number of read operations */ private AtomicInteger readOperations_ = new AtomicInteger(0); /* keep track of the number of read latencies */ private AtomicLong readLatencies_ = new AtomicLong(0); /* keep track of the number of write operations */ private AtomicInteger writeOperations_ = new AtomicInteger(0); /* keep track of the number of write latencies */ private AtomicLong writeLatencies_ = new AtomicLong(0); /** * Create all the required records we intend to display, and * register with the AnalyticsContext. */ public DBAnalyticsSource() { /* register with the AnalyticsContext */ AnalyticsContext.instance().registerUpdater(this); /* set the units for the metric type */ AnalyticsContext.instance().setAttribute("units." + METRIC_READ_OPS, "r/s"); /* create the record */ AnalyticsContext.instance().createRecord(RECORD_READ_OPS); /* set the units for the metric type */ AnalyticsContext.instance().setAttribute("units." + METRIC_READ_AVG, "ms"); /* create the record */ AnalyticsContext.instance().createRecord(RECORD_READ_AVG); /* set the units for the metric type */ AnalyticsContext.instance().setAttribute("units." + METRIC_WRITE_OPS, "w/s"); /* create the record */ AnalyticsContext.instance().createRecord(RECORD_WRITE_OPS); /* set the units for the metric type */ AnalyticsContext.instance().setAttribute("units." + METRIC_WRITE_AVG, "ms"); /* create the record */ AnalyticsContext.instance().createRecord(RECORD_WRITE_AVG); } /** * Update each of the records with the relevant data * * @param context the reference to the context which has called this callback */ public void doUpdates(AnalyticsContext context) { // update the read operations record MetricsRecord readUsageRecord = context.getMetricsRecord(RECORD_READ_OPS); int period = context.getPeriod(); if(readUsageRecord != null) { if ( readOperations_.get() > 0 ) { readUsageRecord.setTag(TAG_READOPS, TAG_READ_OPS); readUsageRecord.setMetric(METRIC_READ_OPS, readOperations_.get() / period); readUsageRecord.update(); } } // update the read latency record MetricsRecord readLatencyRecord = context.getMetricsRecord(RECORD_READ_AVG); if(readLatencyRecord != null) { if ( readOperations_.get() > 0 ) { readLatencyRecord.setTag(TAG_READAVG, TAG_READ_AVG); readLatencyRecord.setMetric(METRIC_READ_AVG, readLatencies_.get() / readOperations_.get() ); readLatencyRecord.update(); } } // update the write operations record MetricsRecord writeUsageRecord = context.getMetricsRecord(RECORD_WRITE_OPS); if(writeUsageRecord != null) { if ( writeOperations_.get() > 0 ) { writeUsageRecord.setTag(TAG_WRITEOPS, TAG_WRITE_OPS); writeUsageRecord.setMetric(METRIC_WRITE_OPS, writeOperations_.get() / period); writeUsageRecord.update(); } } // update the write latency record MetricsRecord writeLatencyRecord = context.getMetricsRecord(RECORD_WRITE_AVG); if(writeLatencyRecord != null) { if ( writeOperations_.get() > 0 ) { writeLatencyRecord.setTag(TAG_WRITEAVG, TAG_WRITE_AVG); writeLatencyRecord.setMetric(METRIC_WRITE_AVG, writeLatencies_.get() / writeOperations_.get() ); writeLatencyRecord.update(); } } clear(); } /** * Reset all the metric records */ private void clear() { readOperations_.set(0); readLatencies_.set(0); writeOperations_.set(0); writeLatencies_.set(0); } /** * Update the read statistics. */ public void updateReadStatistics(long latency) { readOperations_.incrementAndGet(); readLatencies_.addAndGet(latency); } /** * Update the write statistics. */ public void updateWriteStatistics(long latency) { writeOperations_.incrementAndGet(); writeLatencies_.addAndGet(latency); } }