forked from micrometer-metrics/micrometer
/
AbstractTimerBuilder.java
257 lines (231 loc) · 9.93 KB
/
AbstractTimerBuilder.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
/*
* Copyright 2020 VMware, 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
*
* https://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 io.micrometer.core.instrument;
import io.micrometer.common.lang.Nullable;
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
import io.micrometer.core.instrument.distribution.pause.PauseDetector;
import java.time.Duration;
import java.util.Arrays;
/**
* Base builder for {@link Timer}.
*
* @param <B> builder type
* @author Jon Schneider
* @since 1.6.0
*/
@SuppressWarnings("unchecked")
public abstract class AbstractTimerBuilder<B extends AbstractTimerBuilder<B>> {
protected final String name;
protected Tags tags = Tags.empty();
protected final DistributionStatisticConfig.Builder distributionConfigBuilder;
@Nullable
protected String description;
@Nullable
protected PauseDetector pauseDetector;
protected AbstractTimerBuilder(String name) {
this.name = name;
this.distributionConfigBuilder = new DistributionStatisticConfig.Builder();
minimumExpectedValue(Duration.ofMillis(1));
maximumExpectedValue(Duration.ofSeconds(30));
}
protected AbstractTimerBuilder(B builder) {
this.name = builder.name;
tags(builder.tags);
this.distributionConfigBuilder = new DistributionStatisticConfig.Builder(builder.distributionConfigBuilder);
description(builder.description);
pauseDetector(builder.pauseDetector);
}
/**
* @param tags Must be an even number of arguments representing key/value pairs of
* tags.
* @return This builder.
*/
public B tags(String... tags) {
return tags(Tags.of(tags));
}
/**
* @param tags Tags to add to the eventual timer.
* @return The timer builder with added tags.
*/
public B tags(Iterable<Tag> tags) {
this.tags = this.tags.and(tags);
return (B) this;
}
/**
* @param key The tag key.
* @param value The tag value.
* @return The timer builder with a single added tag.
*/
public B tag(String key, String value) {
this.tags = tags.and(key, value);
return (B) this;
}
/**
* Produces an additional time series for each requested percentile. This percentile
* is computed locally, and so can't be aggregated with percentiles computed across
* other dimensions (e.g. in a different instance). Use
* {@link #publishPercentileHistogram()} to publish a histogram that can be used to
* generate aggregable percentile approximations.
* @param percentiles Percentiles to compute and publish. The 95th percentile should
* be expressed as {@code 0.95}.
* @return This builder.
*/
public B publishPercentiles(@Nullable double... percentiles) {
this.distributionConfigBuilder.percentiles(percentiles);
return (B) this;
}
/**
* Determines the number of digits of precision to maintain on the dynamic range
* histogram used to compute percentile approximations. The higher the degrees of
* precision, the more accurate the approximation is at the cost of more memory.
* @param digitsOfPrecision The digits of precision to maintain for percentile
* approximations.
* @return This builder.
*/
public B percentilePrecision(@Nullable Integer digitsOfPrecision) {
this.distributionConfigBuilder.percentilePrecision(digitsOfPrecision);
return (B) this;
}
/**
* Adds histogram buckets used to generate aggregable percentile approximations in
* monitoring systems that have query facilities to do so (e.g. Prometheus'
* {@code histogram_quantile}, Atlas' {@code :percentiles}).
* @return This builder.
*/
public B publishPercentileHistogram() {
return publishPercentileHistogram(true);
}
/**
* Adds histogram buckets used to generate aggregable percentile approximations in
* monitoring systems that have query facilities to do so (e.g. Prometheus'
* {@code histogram_quantile}, Atlas' {@code :percentiles}).
* @param enabled Determines whether percentile histograms should be published.
* @return This builder.
*/
public B publishPercentileHistogram(@Nullable Boolean enabled) {
this.distributionConfigBuilder.percentilesHistogram(enabled);
return (B) this;
}
/**
* Publish at a minimum a histogram containing your defined service level objective
* (SLO) boundaries. When used in conjunction with
* {@link AbstractTimerBuilder#publishPercentileHistogram()}, the boundaries defined
* here are included alongside other buckets used to generate aggregable percentile
* approximations.
* @param sla Publish SLO boundaries in the set of histogram buckets shipped to the
* monitoring system.
* @return This builder.
* @deprecated Use {{@link #serviceLevelObjectives(Duration...)}} instead. "Service
* Level Agreement" is more formally the agreement between an engineering organization
* and the business. Service Level Objectives are set more conservatively than the SLA
* to provide some wiggle room while still satisfying the business requirement. SLOs
* are the threshold we intend to measure against, then.
*/
@Deprecated
public B sla(@Nullable Duration... sla) {
return serviceLevelObjectives(sla);
}
/**
* Publish at a minimum a histogram containing your defined service level objective
* (SLO) boundaries. When used in conjunction with
* {@link AbstractTimerBuilder#publishPercentileHistogram()}, the boundaries defined
* here are included alongside other buckets used to generate aggregable percentile
* approximations.
* @param slos Publish SLO boundaries in the set of histogram buckets shipped to the
* monitoring system.
* @return This builder.
* @since 1.5.0
*/
public B serviceLevelObjectives(@Nullable Duration... slos) {
if (slos != null) {
this.distributionConfigBuilder
.serviceLevelObjectives(Arrays.stream(slos).mapToDouble(Duration::toNanos).toArray());
}
return (B) this;
}
/**
* Sets the minimum value that this timer is expected to observe. Sets a lower bound
* on histogram buckets that are shipped to monitoring systems that support aggregable
* percentile approximations.
* @param min The minimum value that this timer is expected to observe.
* @return This builder.
*/
public B minimumExpectedValue(@Nullable Duration min) {
if (min != null)
this.distributionConfigBuilder.minimumExpectedValue((double) min.toNanos());
return (B) this;
}
/**
* Sets the maximum value that this timer is expected to observe. Sets an upper bound
* on histogram buckets that are shipped to monitoring systems that support aggregable
* percentile approximations.
* @param max The maximum value that this timer is expected to observe.
* @return This builder.
*/
public B maximumExpectedValue(@Nullable Duration max) {
if (max != null)
this.distributionConfigBuilder.maximumExpectedValue((double) max.toNanos());
return (B) this;
}
/**
* Statistics emanating from a timer like max, percentiles, and histogram counts decay
* over time to give greater weight to recent samples (exception: histogram counts are
* cumulative for those systems that expect cumulative histogram buckets). Samples are
* accumulated to such statistics in ring buffers which rotate after this expiry, with
* a buffer length of {@link #distributionStatisticBufferLength(Integer)}.
* @param expiry The amount of time samples are accumulated to a histogram before it
* is reset and rotated.
* @return This builder.
*/
public B distributionStatisticExpiry(@Nullable Duration expiry) {
this.distributionConfigBuilder.expiry(expiry);
return (B) this;
}
/**
* Statistics emanating from a timer like max, percentiles, and histogram counts decay
* over time to give greater weight to recent samples (exception: histogram counts are
* cumulative for those systems that expect cumulative histogram buckets). Samples are
* accumulated to such statistics in ring buffers which rotate after
* {@link #distributionStatisticExpiry(Duration)}, with this buffer length.
* @param bufferLength The number of histograms to keep in the ring buffer.
* @return This builder.
*/
public B distributionStatisticBufferLength(@Nullable Integer bufferLength) {
this.distributionConfigBuilder.bufferLength(bufferLength);
return (B) this;
}
/**
* Sets the pause detector implementation to use for this timer. Can also be
* configured on a registry-level with
* {@link MeterRegistry.Config#pauseDetector(PauseDetector)}.
* @param pauseDetector The pause detector implementation to use.
* @return This builder.
* @see io.micrometer.core.instrument.distribution.pause.NoPauseDetector
* @see io.micrometer.core.instrument.distribution.pause.ClockDriftPauseDetector
*/
public B pauseDetector(@Nullable PauseDetector pauseDetector) {
this.pauseDetector = pauseDetector;
return (B) this;
}
/**
* @param description Description text of the eventual timer.
* @return This builder.
*/
public B description(@Nullable String description) {
this.description = description;
return (B) this;
}
}