2121import java .util .concurrent .ScheduledExecutorService ;
2222import java .util .concurrent .TimeUnit ;
2323import java .util .concurrent .atomic .AtomicInteger ;
24+ import java .util .function .Consumer ;
2425
2526import org .jspecify .annotations .NonNull ;
2627
@@ -75,6 +76,7 @@ public class MicrometerMetrics implements Metrics {
7576 private final MeterRegistry registry ;
7677 private final Map <String , AtomicInteger > gauges = new ConcurrentHashMap <>();
7778 private final Cleaner cleaner ;
79+ private final Consumer <Timer .Builder > timerConfig ;
7880
7981 /**
8082 * Creates a MicrometerMetrics instance configured to not collect per-resource metrics, just
@@ -84,7 +86,7 @@ public class MicrometerMetrics implements Metrics {
8486 * @return a MicrometerMetrics instance configured to not collect per-resource metrics
8587 */
8688 public static MicrometerMetrics withoutPerResourceMetrics (MeterRegistry registry ) {
87- return new MicrometerMetrics (registry , Cleaner .NOOP , false );
89+ return new MicrometerMetrics (registry , Cleaner .NOOP , false , null );
8890 }
8991
9092 /**
@@ -108,7 +110,7 @@ public static MicrometerMetricsBuilder newMicrometerMetricsBuilder(MeterRegistry
108110 */
109111 public static PerResourceCollectingMicrometerMetricsBuilder
110112 newPerResourceCollectingMicrometerMetricsBuilder (MeterRegistry registry ) {
111- return new PerResourceCollectingMicrometerMetricsBuilder (registry );
113+ return new PerResourceCollectingMicrometerMetricsBuilder (registry , null );
112114 }
113115
114116 /**
@@ -119,12 +121,21 @@ public static MicrometerMetricsBuilder newMicrometerMetricsBuilder(MeterRegistry
119121 * @param registry the {@link MeterRegistry} instance to use for metrics recording
120122 * @param cleaner the {@link Cleaner} to use
121123 * @param collectingPerResourceMetrics whether to collect per resource metrics
124+ * @param timerConfig optional configuration for timers, defaults to publishing percentiles 0.5,
125+ * 0.95, 0.99 and histogram
122126 */
123127 private MicrometerMetrics (
124- MeterRegistry registry , Cleaner cleaner , boolean collectingPerResourceMetrics ) {
128+ MeterRegistry registry ,
129+ Cleaner cleaner ,
130+ boolean collectingPerResourceMetrics ,
131+ Consumer <Timer .Builder > timerConfig ) {
125132 this .registry = registry ;
126133 this .cleaner = cleaner ;
127134 this .collectPerResourceMetrics = collectingPerResourceMetrics ;
135+ this .timerConfig =
136+ timerConfig != null
137+ ? timerConfig
138+ : builder -> builder .publishPercentiles (0.5 , 0.95 , 0.99 ).publishPercentileHistogram ();
128139 }
129140
130141 @ Override
@@ -163,12 +174,9 @@ public <T> T timeControllerExecution(ControllerExecution<T> execution) {
163174 final var tags = new ArrayList <Tag >(16 );
164175 tags .add (Tag .of (CONTROLLER , name ));
165176 addMetadataTags (resourceID , metadata , tags , true );
166- final var timer =
167- Timer .builder (execName )
168- .tags (tags )
169- .publishPercentiles (0.3 , 0.5 , 0.95 )
170- .publishPercentileHistogram ()
171- .register (registry );
177+ final var timerBuilder = Timer .builder (execName ).tags (tags );
178+ timerConfig .accept (timerBuilder );
179+ final var timer = timerBuilder .register (registry );
172180 try {
173181 final var result =
174182 timer .record (
@@ -379,8 +387,27 @@ public static class PerResourceCollectingMicrometerMetricsBuilder
379387 private int cleaningThreadsNumber ;
380388 private int cleanUpDelayInSeconds ;
381389
382- private PerResourceCollectingMicrometerMetricsBuilder (MeterRegistry registry ) {
390+ private PerResourceCollectingMicrometerMetricsBuilder (
391+ MeterRegistry registry , Consumer <Timer .Builder > timerConfig ) {
383392 super (registry );
393+ this .executionTimerConfig = timerConfig ;
394+ }
395+
396+ /**
397+ * Configures the Timer used for timing controller executions. By default, timers are configured
398+ * to publish percentiles 0.5, 0.95, 0.99 and a percentile histogram. You can set: {@code
399+ * .minimumExpectedValue(Duration.ofMillis(...)).maximumExpectedValue(Duration.ofSeconds(...)) }
400+ * so micrometer can create the buckets for you.
401+ *
402+ * @param executionTimerConfig a consumer that will configure the Timer.Builder. The builder
403+ * will already have the metric name and tags set.
404+ * @return this builder for method chaining
405+ */
406+ @ Override
407+ public PerResourceCollectingMicrometerMetricsBuilder withExecutionTimerConfig (
408+ Consumer <Timer .Builder > executionTimerConfig ) {
409+ this .executionTimerConfig = executionTimerConfig ;
410+ return this ;
384411 }
385412
386413 /**
@@ -412,23 +439,38 @@ public PerResourceCollectingMicrometerMetricsBuilder withCleanUpDelayInSeconds(
412439 public MicrometerMetrics build () {
413440 final var cleaner =
414441 new DelayedCleaner (registry , cleanUpDelayInSeconds , cleaningThreadsNumber );
415- return new MicrometerMetrics (registry , cleaner , true );
442+ return new MicrometerMetrics (registry , cleaner , true , executionTimerConfig );
416443 }
417444 }
418445
419446 public static class MicrometerMetricsBuilder {
420447 protected final MeterRegistry registry ;
421448 private boolean collectingPerResourceMetrics = true ;
449+ protected Consumer <Timer .Builder > executionTimerConfig = null ;
422450
423451 private MicrometerMetricsBuilder (MeterRegistry registry ) {
424452 this .registry = registry ;
425453 }
426454
455+ /**
456+ * Configures the Timer used for timing controller executions. By default, timers are configured
457+ * to publish percentiles 0.5, 0.95, 0.99 and a percentile histogram.
458+ *
459+ * @param executionTimerConfig a consumer that will configure the Timer.Builder. The builder
460+ * will already have the metric name and tags set.
461+ * @return this builder for method chaining
462+ */
463+ public MicrometerMetricsBuilder withExecutionTimerConfig (
464+ Consumer <Timer .Builder > executionTimerConfig ) {
465+ this .executionTimerConfig = executionTimerConfig ;
466+ return this ;
467+ }
468+
427469 /** Configures the instance to collect metrics on a per-resource basis. */
428470 @ SuppressWarnings ("unused" )
429471 public PerResourceCollectingMicrometerMetricsBuilder collectingMetricsPerResource () {
430472 collectingPerResourceMetrics = true ;
431- return new PerResourceCollectingMicrometerMetricsBuilder (registry );
473+ return new PerResourceCollectingMicrometerMetricsBuilder (registry , executionTimerConfig );
432474 }
433475
434476 /**
@@ -442,7 +484,8 @@ public MicrometerMetricsBuilder notCollectingMetricsPerResource() {
442484 }
443485
444486 public MicrometerMetrics build () {
445- return new MicrometerMetrics (registry , Cleaner .NOOP , collectingPerResourceMetrics );
487+ return new MicrometerMetrics (
488+ registry , Cleaner .NOOP , collectingPerResourceMetrics , executionTimerConfig );
446489 }
447490 }
448491
0 commit comments