1 package io.getunleash.metric;
2
3 import io.getunleash.util.Throttler;
4 import io.getunleash.util.UnleashConfig;
5 import io.getunleash.util.UnleashScheduledExecutor;
6 import java.time.LocalDateTime;
7 import java.time.ZoneId;
8 import java.util.Set;
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11
12 public class UnleashMetricServiceImpl implements UnleashMetricService {
13     private static final Logger LOGGER = LoggerFactory.getLogger(UnleashMetricServiceImpl.class);
14     private final LocalDateTime started;
15     private final UnleashConfig unleashConfig;
16     private final MetricSender metricSender;
17
18     // mutable
19     private volatile MetricsBucket currentMetricsBucket;
20
21     private final Throttler throttler;
22
23     public UnleashMetricServiceImpl(
24             UnleashConfig unleashConfig, UnleashScheduledExecutor executor) {
25         this(unleashConfig, unleashConfig.getMetricSenderFactory().apply(unleashConfig), executor);
26     }
27
28     public UnleashMetricServiceImpl(
29             UnleashConfig unleashConfig,
30             MetricSender metricSender,
31             UnleashScheduledExecutor executor) {
32         this.currentMetricsBucket = new MetricsBucket();
33         this.started = LocalDateTime.now(ZoneId.of("UTC"));
34         this.unleashConfig = unleashConfig;
35         this.metricSender = metricSender;
36         this.throttler =
37                 new Throttler(
38                         (int) unleashConfig.getSendMetricsInterval(),
39                         300,
40                         unleashConfig.getUnleashURLs().getClientMetricsURL());
41         long metricsInterval = unleashConfig.getSendMetricsInterval();
42
43         executor.setInterval(sendMetrics(), metricsInterval, metricsInterval);
44     }
45
46     @Override
47     public void register(Set<String> strategies) {
48         ClientRegistration registration =
49                 new ClientRegistration(unleashConfig, started, strategies);
50         metricSender.registerClient(registration);
51     }
52
53     @Override
54     public void count(String toggleName, boolean active) {
55         currentMetricsBucket.registerCount(toggleName, active);
56     }
57
58     @Override
59     public void countVariant(String toggleName, String variantName) {
60         currentMetricsBucket.registerCount(toggleName, variantName);
61     }
62
63     private Runnable sendMetrics() {
64         return () -> {
65             if (throttler.performAction()) {
66                 MetricsBucket metricsBucket = this.currentMetricsBucket;
67                 this.currentMetricsBucket = new MetricsBucket();
68                 metricsBucket.end();
69                 ClientMetrics metrics = new ClientMetrics(unleashConfig, metricsBucket);
70                 int statusCode = metricSender.sendMetrics(metrics);
71                 if (statusCode >= 200 && statusCode < 400) {
72                     throttler.decrementFailureCountAndResetSkips();
73                 }
74                 if (statusCode >= 400) {
75                     throttler.handleHttpErrorCodes(statusCode);
76                 }
77             } else {
78                 throttler.skipped();
79             }
80         };
81     }
82
83     protected int getSkips() {
84         return this.throttler.getSkips();
85     }
86
87     protected int getFailures() {
88         return this.throttler.getFailures();
89     }
90 }
91