Skip to content

Commit

Permalink
Fix parsing of day duration meter values
Browse files Browse the repository at this point in the history
Switch `MeterValue` parsing logic so that we try `Duration` before
`double`. Prior to this commit, the value `1d` would result in `1.0`
rather than "1 day".

Fixes gh-28302
  • Loading branch information
wilkinsona authored and philwebb committed Oct 14, 2021
1 parent fc2c460 commit 540468b
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ private Long getTimerValue() {
* @return a {@link MeterValue} instance
*/
public static MeterValue valueOf(String value) {
Double number = safeParseDouble(value);
if (number != null) {
return new MeterValue(number);
Duration duration = safeParseDuration(value);
if (duration != null) {
return new MeterValue(duration);
}
return new MeterValue(DurationStyle.detectAndParse(value));
return new MeterValue(Double.valueOf(value));
}

/**
Expand All @@ -114,11 +114,11 @@ public static MeterValue valueOf(double value) {
return new MeterValue(value);
}

private static Double safeParseDouble(String value) {
private static Duration safeParseDuration(String value) {
try {
return Double.valueOf(value);
return DurationStyle.detectAndParse(value);
}
catch (NumberFormatException ex) {
catch (IllegalArgumentException ex) {
return null;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -235,21 +235,21 @@ public static class Distribution {
/**
* Specific service-level objective boundaries for meter IDs starting with the
* specified name. The longest match wins. Counters will be published for each
* specified boundary. Values can be specified as a long or as a Duration value
* specified boundary. Values can be specified as a double or as a Duration value
* (for timer meters, defaulting to ms if no unit specified).
*/
private final Map<String, ServiceLevelObjectiveBoundary[]> slo = new LinkedHashMap<>();

/**
* Minimum value that meter IDs starting with the specified name are expected to
* observe. The longest match wins. Values can be specified as a long or as a
* observe. The longest match wins. Values can be specified as a double or as a
* Duration value (for timer meters, defaulting to ms if no unit specified).
*/
private final Map<String, String> minimumExpectedValue = new LinkedHashMap<>();

/**
* Maximum value that meter IDs starting with the specified name are expected to
* observe. The longest match wins. Values can be specified as a long or as a
* observe. The longest match wins. Values can be specified as a double or as a
* Duration value (for timer meters, defaulting to ms if no unit specified).
*/
private final Map<String, String> maximumExpectedValue = new LinkedHashMap<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,8 @@

package org.springframework.boot.actuate.autoconfigure.metrics;

import java.time.Duration;

import io.micrometer.core.instrument.Meter.Type;
import org.junit.jupiter.api.Test;

Expand All @@ -42,11 +44,17 @@ void getValueForTimerWhenFromNumberStringShouldMsToNanosValue() {
}

@Test
void getValueForTimerWhenFromDurationStringShouldReturnDurationNanos() {
void getValueForTimerWhenFromMillisecondDurationStringShouldReturnDurationNanos() {
ServiceLevelObjectiveBoundary slo = ServiceLevelObjectiveBoundary.valueOf("123ms");
assertThat(slo.getValue(Type.TIMER)).isEqualTo(123000000);
}

@Test
void getValueForTimerWhenFromDaysDurationStringShouldReturnDurationNanos() {
ServiceLevelObjectiveBoundary slo = ServiceLevelObjectiveBoundary.valueOf("1d");
assertThat(slo.getValue(Type.TIMER)).isEqualTo(Duration.ofDays(1).toNanos());
}

@Test
void getValueForDistributionSummaryWhenFromDoubleShouldReturnDoubleValue() {
ServiceLevelObjectiveBoundary slo = ServiceLevelObjectiveBoundary.valueOf(123.42);
Expand Down

0 comments on commit 540468b

Please sign in to comment.