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

com.netflix.dyno.jedis.DynoJedisPipelineMonitor Maven / Gradle / Ivy

/**
 * Copyright 2016 Netflix, 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.netflix.dyno.jedis; import java.util.Map; import java.util.concurrent.*; import com.netflix.dyno.connectionpool.impl.utils.EstimatedHistogram; import com.netflix.dyno.contrib.EstimatedHistogramBasedCounter.EstimatedHistogramMean; import com.netflix.dyno.contrib.EstimatedHistogramBasedCounter.EstimatedHistogramPercentile; import com.netflix.servo.DefaultMonitorRegistry; import com.netflix.servo.monitor.BasicCounter; import com.netflix.servo.monitor.MonitorConfig; import com.netflix.servo.tag.BasicTag; import org.slf4j.LoggerFactory; public class DynoJedisPipelineMonitor { private static final org.slf4j.Logger Logger = LoggerFactory.getLogger(DynoJedisPipelineMonitor.class); private final ConcurrentHashMap counterMap = new ConcurrentHashMap(); private final String appName; private final BasicCounter pipelineSync; private final BasicCounter pipelineDiscard; private final PipelineTimer timer; private final PipelineSendTimer sendTimer; private final int resetTimingsFrequencyInSeconds; private final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(1, new ThreadFactory() { @Override public Thread newThread(Runnable r) { return new Thread(r, "DynoJedisPipelineMonitor"); } }); public DynoJedisPipelineMonitor(String applicationName, int resetTimingsFrequencyInSeconds) { appName = applicationName; pipelineSync = getNewPipelineCounter("SYNC"); pipelineDiscard = getNewPipelineCounter("DISCARD"); timer = new PipelineTimer(appName); sendTimer = new PipelineSendTimer(appName); this.resetTimingsFrequencyInSeconds = resetTimingsFrequencyInSeconds; } public DynoJedisPipelineMonitor(String applicationName) { this(applicationName, 0); } public void init() { // register the counters DefaultMonitorRegistry.getInstance().register(pipelineSync); DefaultMonitorRegistry.getInstance().register(pipelineDiscard); // register the pipeline timer DefaultMonitorRegistry.getInstance().register(timer.latMean); DefaultMonitorRegistry.getInstance().register(timer.lat99); DefaultMonitorRegistry.getInstance().register(timer.lat995); DefaultMonitorRegistry.getInstance().register(timer.lat999); // NOTE -- pipeline 'send' timers are created on demand and are registered // in PipelineSendTimer.getOrCreateHistogram() Logger.debug(String.format("Initializing DynoJedisPipelineMonitor with timing counter reset frequency %d", resetTimingsFrequencyInSeconds)); if (resetTimingsFrequencyInSeconds > 0) { threadPool.scheduleAtFixedRate(new Runnable() { @Override public void run() { timer.reset(); sendTimer.reset(); } }, 1, resetTimingsFrequencyInSeconds, TimeUnit.SECONDS); } } public void recordOperation(String opName) { getOrCreateCounter(opName).increment(); } public void recordPipelineSync() { pipelineSync.increment(); } public void recordPipelineDiscard() { pipelineDiscard.increment(); } public void recordLatency(long duration, TimeUnit unit) { timer.recordLatency(duration, unit); } public void recordSendLatency(String opName, long duration, TimeUnit unit) { sendTimer.recordLatency(opName, duration, unit); } public void stop() { threadPool.shutdownNow(); } private BasicCounter getOrCreateCounter(String opName) { BasicCounter counter = counterMap.get(opName); if (counter != null) { return counter; } counter = getNewPipelineCounter(opName); BasicCounter prevCounter = counterMap.putIfAbsent(opName, counter); if (prevCounter != null) { return prevCounter; } DefaultMonitorRegistry.getInstance().register(counter); return counter; } private BasicCounter getNewPipelineCounter(String opName) { String metricName = "Dyno__" + appName + "__PL__" + opName; MonitorConfig config = MonitorConfig.builder(metricName) .withTag(new BasicTag("dyno_pl_op", opName)) .build(); return new BasicCounter(config); } /** * This class measures the latency of a sync() or syncAndReturnAll() operation, which is the time * it takes the client to receive the response of all operations in the pipeline. */ private class PipelineTimer { private final EstimatedHistogramMean latMean; private final EstimatedHistogramPercentile lat99; private final EstimatedHistogramPercentile lat995; private final EstimatedHistogramPercentile lat999; private final EstimatedHistogram estHistogram; private PipelineTimer(String appName) { estHistogram = new EstimatedHistogram(); latMean = new EstimatedHistogramMean("Dyno__" + appName + "__PL__latMean", "PL", "dyno_pl_op", estHistogram); lat99 = new EstimatedHistogramPercentile("Dyno__" + appName + "__PL__lat990", "PL", "dyno_pl_op", estHistogram, 0.99); lat995 = new EstimatedHistogramPercentile("Dyno__" + appName + "__PL__lat995", "PL", "dyno_pl_op", estHistogram, 0.995); lat999 = new EstimatedHistogramPercentile("Dyno__" + appName + "__PL__lat999", "PL", "dyno_pl_op", estHistogram, 0.999); } public void recordLatency(long duration, TimeUnit unit) { long durationMicros = TimeUnit.MICROSECONDS.convert(duration, unit); estHistogram.add(durationMicros); } public void reset() { Logger.info("resetting histogram"); estHistogram.getBuckets(true); } } /** * This class measures the time it takes to send a request from the client to the server via the pipeline. The * 'send' is not asynchronous within the Jedis client */ private class PipelineSendTimer { private final Map histograms = new ConcurrentHashMap(); private final String appName; private PipelineSendTimer(String appName) { this.appName = appName; } public void recordLatency(String opName, long duration, TimeUnit unit) { long durationMicros = TimeUnit.MICROSECONDS.convert(duration, unit); getOrCreateHistogram(opName).add(durationMicros); } private EstimatedHistogramMean getOrCreateHistogram(String opName) { if (histograms.containsKey(opName)) { return histograms.get(opName); } else { EstimatedHistogram histogram = new EstimatedHistogram(); EstimatedHistogramMean histogramMean = new EstimatedHistogramMean("Dyno__" + appName + "__PL__latMean", "PL_SEND", opName, histogram); histograms.put(opName, histogramMean); DefaultMonitorRegistry.getInstance().register(histogramMean); return histogramMean; } } public void reset() { Logger.info("resetting all SEND histograms"); for (EstimatedHistogramMean hm : histograms.values()) { hm.reset(); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy