/* * Copyright 2014 Avanza Bank AB * * 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.avanza.astrix.metrics; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Supplier; import com.avanza.astrix.context.metrics.MetricsSpi; import com.avanza.astrix.context.metrics.TimerSnaphot; import com.avanza.astrix.context.metrics.TimerSpi; import com.avanza.astrix.core.function.CheckedCommand; import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Snapshot; import com.codahale.metrics.Timer; import com.codahale.metrics.Timer.Context; import rx.Observable; final class DropwizardMetrics implements MetricsSpi { private final AtomicInteger nextTimerId = new AtomicInteger(0); private final MetricRegistry metrics = new MetricRegistry(); @Override public TimerSpi createTimer() { return new TimerAdapter(metrics.timer("timer-" + nextTimerId.incrementAndGet())); } static class TimerAdapter implements TimerSpi { private Timer timer; public TimerAdapter(Timer timer) { this.timer = timer; } @Override public <T> CheckedCommand<T> timeExecution(final CheckedCommand<T> execution) { return () -> { Context context = timer.time(); try { return execution.call(); } finally { context.stop(); } }; } @Override public <T> Supplier<Observable<T>> timeObservable(final Supplier<Observable<T>> observableFactory) { return () -> { final Context context = timer.time(); return observableFactory.get().doOnTerminate(() -> context.stop()); }; } @Override public TimerSnaphot getSnapshot() { // Rates are are in seconds by default // Duration are in NANO_SECONDS TimeUnit rateUnit = TimeUnit.SECONDS; TimeUnit durationUnit = TimeUnit.MILLISECONDS; double durationFactor = 1.0 / durationUnit.toNanos(1); // double rateFactor = 1.0 / rateUnit.toSeconds(1); Snapshot snapshot = timer.getSnapshot(); return TimerSnaphot.builder() .count(timer.getCount()) .meanRate(timer.getMeanRate()) // No need to convert rate since its already in SECONDS .oneMinuteRate(timer.getOneMinuteRate()) // No need to convert rate since its already in SECONDS .maxLatency(snapshot.getMax() * durationFactor) .minLatency(snapshot.getMin() * durationFactor) .set50thPercentileLatency(snapshot.getMedian() * durationFactor) .set90thPercentileLatency(snapshot.getValue(0.9) * durationFactor) .set99thPercentileLatency(snapshot.get99thPercentile() * durationFactor) .rateUnit(rateUnit) .durationUnit(durationUnit) .build(); } } // For testing MetricRegistry getMetrics() { return metrics; } }