You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ch...@apache.org on 2015/12/24 06:24:48 UTC

svn commit: r1721595 - in /jackrabbit/oak/trunk: oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/stats/BlobStoreStatsMBean.java oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/BlobStoreStats.java

Author: chetanm
Date: Thu Dec 24 05:24:48 2015
New Revision: 1721595

URL: http://svn.apache.org/viewvc?rev=1721595&view=rev
Log:
OAK-3806 - Collect and expose statistics related to BlobStore operations

Support for calculating upload and download rates in bytes/sec based on TimeSeries data

Modified:
    jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/stats/BlobStoreStatsMBean.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/BlobStoreStats.java

Modified: jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/stats/BlobStoreStatsMBean.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/stats/BlobStoreStatsMBean.java?rev=1721595&r1=1721594&r2=1721595&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/stats/BlobStoreStatsMBean.java (original)
+++ jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/stats/BlobStoreStatsMBean.java Thu Dec 24 05:24:48 2015
@@ -44,4 +44,12 @@ public interface BlobStoreStatsMBean {
     CompositeData getUploadSizeHistory();
 
     CompositeData getDownloadSizeHistory();
+
+    CompositeData getUploadRateHistory();
+
+    CompositeData getDownloadRateHistory();
+
+    CompositeData getUploadCountHistory();
+
+    CompositeData getDownloadCountHistory();
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/BlobStoreStats.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/BlobStoreStats.java?rev=1721595&r1=1721594&r2=1721595&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/BlobStoreStats.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/blob/BlobStoreStats.java Thu Dec 24 05:24:48 2015
@@ -21,44 +21,61 @@ package org.apache.jackrabbit.oak.plugin
 
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.Nonnull;
 import javax.management.openmbean.CompositeData;
 
+import org.apache.jackrabbit.api.stats.TimeSeries;
+import org.apache.jackrabbit.oak.commons.jmx.AnnotatedStandardMBean;
 import org.apache.jackrabbit.oak.spi.blob.stats.BlobStoreStatsMBean;
 import org.apache.jackrabbit.oak.spi.blob.stats.BlobStatsCollector;
 import org.apache.jackrabbit.oak.stats.HistogramStats;
 import org.apache.jackrabbit.oak.stats.MeterStats;
 import org.apache.jackrabbit.oak.stats.StatisticsProvider;
 import org.apache.jackrabbit.oak.stats.StatsOptions;
+import org.apache.jackrabbit.stats.TimeSeriesAverage;
 import org.apache.jackrabbit.stats.TimeSeriesStatsUtil;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static org.apache.jackrabbit.oak.commons.IOUtils.humanReadableByteCount;
 
-public class BlobStoreStats implements BlobStoreStatsMBean, BlobStatsCollector {
+@SuppressWarnings("Duplicates")
+public class BlobStoreStats extends AnnotatedStandardMBean implements BlobStoreStatsMBean, BlobStatsCollector {
+    private static final String BLOB_DOWNLOAD_COUNT = "BLOB_DOWNLOAD_COUNT";
     private static final String BLOB_UPLOADS = "BLOB_UPLOADS";
     private static final String BLOB_DOWNLOADS = "BLOB_DOWNLOADS";
+    private static final String BLOB_UPLOAD_COUNT = "BLOB_UPLOAD_COUNT";
 
     private final StatisticsProvider statisticsProvider;
 
     private final HistogramStats uploadHisto;
-    private final MeterStats uploadSizeMeter;
-    private final MeterStats uploadTimeMeter;
+    private final MeterStats uploadCount;
+    private final MeterStats uploadSizeSeries;
+    private final MeterStats uploadTimeSeries;
+    private final TimeSeries uploadRateSeries;
 
     private final HistogramStats downloadHisto;
-    private final MeterStats downloadSizeMeter;
-    private final MeterStats downloadTimeMeter;
-
-    public BlobStoreStats(StatisticsProvider sp) {
-        this.statisticsProvider = sp;
+    private final MeterStats downloadCount;
+    private final MeterStats downloadSizeSeries;
+    private final MeterStats downloadTimeSeries;
+    private final TimeSeries downloadRateSeries;
+
+    private final TimeUnit recordedTimeUnit = TimeUnit.NANOSECONDS;
+
+    public BlobStoreStats(@Nonnull  StatisticsProvider sp) {
+        super(BlobStoreStatsMBean.class);
+        this.statisticsProvider = checkNotNull(sp);
 
         this.uploadHisto = sp.getHistogram(BLOB_UPLOADS, StatsOptions.DEFAULT);
-        //TODO Need to expose an API in StatisticsProvider to register for avg
-        //That would give us upload and download *rate*
-        this.uploadSizeMeter = sp.getMeter("BLOB_UPLOAD_SIZE", StatsOptions.DEFAULT);
-        this.uploadTimeMeter = sp.getMeter("BLOB_UPLOAD_TIME", StatsOptions.DEFAULT);
+        this.uploadCount = sp.getMeter(BLOB_UPLOAD_COUNT, StatsOptions.DEFAULT);
+        this.uploadSizeSeries = sp.getMeter("BLOB_UPLOAD_SIZE", StatsOptions.TIME_SERIES_ONLY);
+        this.uploadTimeSeries = sp.getMeter("BLOB_UPLOAD_TIME", StatsOptions.TIME_SERIES_ONLY);
+        this.uploadRateSeries = getAvgTimeSeries("BLOB_UPLOAD_SIZE", "BLOB_UPLOAD_TIME");
 
         this.downloadHisto = sp.getHistogram(BLOB_DOWNLOADS, StatsOptions.DEFAULT);
-        this.downloadSizeMeter = sp.getMeter("BLOB_DOWNLOAD_SIZE", StatsOptions.DEFAULT);
-        this.downloadTimeMeter = sp.getMeter("BLOB_DOWNLOAD_TIME", StatsOptions.DEFAULT);
+        this.downloadCount = sp.getMeter(BLOB_DOWNLOAD_COUNT, StatsOptions.DEFAULT);
+        this.downloadSizeSeries = sp.getMeter("BLOB_DOWNLOAD_SIZE", StatsOptions.TIME_SERIES_ONLY);
+        this.downloadTimeSeries = sp.getMeter("BLOB_DOWNLOAD_TIME", StatsOptions.TIME_SERIES_ONLY);
+        this.downloadRateSeries = getAvgTimeSeries("BLOB_DOWNLOAD_SIZE", "BLOB_DOWNLOAD_TIME");
     }
 
     @Override
@@ -70,22 +87,25 @@ public class BlobStoreStats implements B
         //That would however add quite a bit of overhead
         //Approach below would record an upload/download at moment when
         //it got completed. So acts like a rough approximation
-        uploadSizeMeter.mark(size);
-        uploadTimeMeter.mark(TimeUnit.NANOSECONDS.convert(timeTaken, unit));
+        uploadSizeSeries.mark(size);
+        uploadTimeSeries.mark(recordedTimeUnit.convert(timeTaken, unit));
+        uploadCount.mark();
     }
 
     @Override
     public void downloaded(String blobId, long timeTaken, TimeUnit unit, long size) {
         downloadHisto.update(size);
-        downloadSizeMeter.mark(size);
-        downloadTimeMeter.mark(TimeUnit.NANOSECONDS.convert(timeTaken, unit));
+
+        downloadSizeSeries.mark(size);
+        downloadTimeSeries.mark(recordedTimeUnit.convert(timeTaken, unit));
+        downloadCount.mark();
     }
 
     //~--------------------------------------< BlobStoreMBean >
 
     @Override
     public long getUploadTotalSize() {
-        return uploadSizeMeter.getCount();
+        return uploadSizeSeries.getCount();
     }
 
     @Override
@@ -95,12 +115,12 @@ public class BlobStoreStats implements B
 
     @Override
     public long getUploadTotalSeconds() {
-        return TimeUnit.NANOSECONDS.toSeconds(uploadTimeMeter.getCount());
+        return recordedTimeUnit.toSeconds(uploadTimeSeries.getCount());
     }
 
     @Override
     public long getDownloadTotalSize() {
-        return downloadSizeMeter.getCount();
+        return downloadSizeSeries.getCount();
     }
 
     @Override
@@ -110,7 +130,7 @@ public class BlobStoreStats implements B
 
     @Override
     public long getDownloadTotalSeconds() {
-        return TimeUnit.NANOSECONDS.toSeconds(downloadTimeMeter.getCount());
+        return recordedTimeUnit.toSeconds(downloadTimeSeries.getCount());
     }
 
     @Override
@@ -125,16 +145,92 @@ public class BlobStoreStats implements B
 
     @Override
     public CompositeData getUploadSizeHistory() {
-        return getTimeSeries(BLOB_UPLOADS);
+        return getTimeSeriesData(BLOB_UPLOADS, "Blob Uploads (bytes)");
     }
 
     @Override
     public CompositeData getDownloadSizeHistory() {
-        return getTimeSeries(BLOB_DOWNLOADS);
+        return getTimeSeriesData(BLOB_DOWNLOADS, "Blob Downloads (bytes)");
+    }
+
+    @Override
+    public CompositeData getUploadRateHistory() {
+        return TimeSeriesStatsUtil.asCompositeData(uploadRateSeries, "Blob uploads bytes/secs");
+    }
+
+    @Override
+    public CompositeData getDownloadRateHistory() {
+        return TimeSeriesStatsUtil.asCompositeData(downloadRateSeries, "Blob downloads bytes/secs");
+    }
+
+    @Override
+    public CompositeData getUploadCountHistory() {
+        return getTimeSeriesData(BLOB_UPLOAD_COUNT, "Blob Upload Counts");
+    }
+
+    @Override
+    public CompositeData getDownloadCountHistory() {
+        return getTimeSeriesData(BLOB_DOWNLOAD_COUNT, "Blob Download Counts");
     }
 
-    private CompositeData getTimeSeries(String name){
-        return TimeSeriesStatsUtil.asCompositeData(statisticsProvider.getStats().getTimeSeries(name, true),
-                name);
+    private CompositeData getTimeSeriesData(String name, String desc){
+        return TimeSeriesStatsUtil.asCompositeData(getTimeSeries(name), desc);
+    }
+
+    private TimeSeries getTimeSeries(String name) {
+        return statisticsProvider.getStats().getTimeSeries(name, true);
+    }
+
+    private TimeSeries getAvgTimeSeries(String nameValue, String nameCounter){
+        return new TimeSeriesAverage(getTimeSeries(nameValue),
+                new UnitConvertingTimeSeries(getTimeSeries(nameCounter), recordedTimeUnit, TimeUnit.SECONDS));
+    }
+
+    /**
+     * TimeSeries which converts a Nanonsecond based time to Seconds for
+     * calculating bytes/sec rate for upload and download
+     */
+    private static class UnitConvertingTimeSeries implements TimeSeries {
+        private final TimeSeries series;
+        private final TimeUnit source;
+        private final TimeUnit dest;
+
+        public UnitConvertingTimeSeries(TimeSeries series, TimeUnit source, TimeUnit dest) {
+            this.series = series;
+            this.source = source;
+            this.dest = dest;
+        }
+
+        @Override
+        public long[] getValuePerSecond() {
+            return convert(series.getValuePerSecond());
+        }
+
+        @Override
+        public long[] getValuePerMinute() {
+            return convert(series.getValuePerMinute());
+        }
+
+        @Override
+        public long[] getValuePerHour() {
+            return convert(series.getValuePerHour());
+        }
+
+        @Override
+        public long[] getValuePerWeek() {
+            return convert(series.getValuePerWeek());
+        }
+
+        @Override
+        public long getMissingValue() {
+            return 0;
+        }
+
+        private long[] convert(long[] timings){
+            for (int i = 0; i < timings.length; i++) {
+                timings[i] = dest.convert(timings[i], source);
+            }
+            return timings;
+        }
     }
 }