/*
* Copyright 2016 LINE Corporation
*
* LINE Corporation 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.linecorp.armeria.client.circuitbreaker.metrics;
import static java.util.Objects.requireNonNull;
import java.util.concurrent.atomic.AtomicReference;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.RatioGauge;
import com.linecorp.armeria.client.circuitbreaker.CircuitState;
import com.linecorp.armeria.client.circuitbreaker.EventCount;
/**
* Stores dropwirzard's metrics tracking circuit breaker events.
*/
final class DropwizardCircuitBreakerMetrics {
private final AtomicReference<EventCount> latestEventCount = new AtomicReference<>(EventCount.ZERO);
private final Meter closed;
private final Meter halfOpen;
private final Meter open;
private final Meter requestRejected;
DropwizardCircuitBreakerMetrics(String prefix, String name, MetricRegistry registry) {
requireNonNull(prefix, "prefix");
requireNonNull(name, "name");
requireNonNull(registry, "registry");
// {prefix}.{name}.counter.rate.success
registry.register(MetricRegistry.name(prefix, name, "counter", "rate", "success"), new RatioGauge() {
@Override
protected Ratio getRatio() {
final EventCount currentCount = latestEventCount.get();
return Ratio.of(currentCount.success(), currentCount.total());
}
});
// {prefix}.{name}.counter.rate.failure
registry.register(MetricRegistry.name(prefix, name, "counter", "rate", "failure"), new RatioGauge() {
@Override
protected Ratio getRatio() {
final EventCount currentCount = latestEventCount.get();
return Ratio.of(currentCount.failure(), currentCount.total());
}
});
// {prefix}.{name}.counter.count.success
final Gauge<Long> successCount = () -> latestEventCount.get().success();
registry.register(MetricRegistry.name(prefix, name, "counter", "count", "success"), successCount);
// {prefix}.{name}.counter.count.failure
final Gauge<Long> failureCount = () -> latestEventCount.get().failure();
registry.register(MetricRegistry.name(prefix, name, "counter", "count", "failure"), failureCount);
// {prefix}.{name}.transitions.closed
closed = registry.meter(MetricRegistry.name(prefix, name, "transitions", "closed"));
// {prefix}.{name}.transitions.halfopen
halfOpen = registry.meter(MetricRegistry.name(prefix, name, "transitions", "halfopen"));
// {prefix}.{name}.transitions.open
open = registry.meter(MetricRegistry.name(prefix, name, "transitions", "open"));
// {prefix}.{name}.requests.rejected
requestRejected = registry.meter(MetricRegistry.name(prefix, name, "requests", "rejected"));
}
void onStateChanged(CircuitState state) {
if (state == CircuitState.CLOSED) {
closed.mark();
} else if (state == CircuitState.HALF_OPEN) {
halfOpen.mark();
} else if (state == CircuitState.OPEN) {
open.mark();
}
}
void onCountUpdated(EventCount count) {
latestEventCount.set(count);
}
void onRequestRejected() {
requestRejected.mark();
}
}