Update tag keys to comply with Micrometer recommendations

Closes gh-30536
pull/30641/head
Andy Wilkinson 3 years ago
parent 6f62e1c743
commit b8b903527a

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -72,7 +72,7 @@ class CacheMetricsRegistrarConfiguration {
} }
private void bindCacheToRegistry(String beanName, Cache cache) { private void bindCacheToRegistry(String beanName, Cache cache) {
Tag cacheManagerTag = Tag.of("cacheManager", getCacheManagerName(beanName)); Tag cacheManagerTag = Tag.of("cache.manager", getCacheManagerName(beanName));
this.cacheMetricsRegistrar.bindCacheToRegistry(cache, cacheManagerTag); this.cacheMetricsRegistrar.bindCacheToRegistry(cache, cacheManagerTag);
} }

@ -44,8 +44,8 @@ class CacheMetricsAutoConfigurationTests {
this.contextRunner.withPropertyValues("spring.cache.type=cache2k", "spring.cache.cache-names=cache1,cache2") this.contextRunner.withPropertyValues("spring.cache.type=cache2k", "spring.cache.cache-names=cache1,cache2")
.run((context) -> { .run((context) -> {
MeterRegistry registry = context.getBean(MeterRegistry.class); MeterRegistry registry = context.getBean(MeterRegistry.class);
registry.get("cache.gets").tags("name", "cache1").tags("cacheManager", "cacheManager").meter(); registry.get("cache.gets").tags("name", "cache1").tags("cache.manager", "cacheManager").meter();
registry.get("cache.gets").tags("name", "cache2").tags("cacheManager", "cacheManager").meter(); registry.get("cache.gets").tags("name", "cache2").tags("cache.manager", "cacheManager").meter();
}); });
} }
@ -54,8 +54,8 @@ class CacheMetricsAutoConfigurationTests {
this.contextRunner.withPropertyValues("spring.cache.type=caffeine", "spring.cache.cache-names=cache1,cache2") this.contextRunner.withPropertyValues("spring.cache.type=caffeine", "spring.cache.cache-names=cache1,cache2")
.run((context) -> { .run((context) -> {
MeterRegistry registry = context.getBean(MeterRegistry.class); MeterRegistry registry = context.getBean(MeterRegistry.class);
registry.get("cache.gets").tags("name", "cache1").tags("cacheManager", "cacheManager").meter(); registry.get("cache.gets").tags("name", "cache1").tags("cache.manager", "cacheManager").meter();
registry.get("cache.gets").tags("name", "cache2").tags("cacheManager", "cacheManager").meter(); registry.get("cache.gets").tags("name", "cache2").tags("cache.manager", "cacheManager").meter();
}); });
} }
@ -64,9 +64,9 @@ class CacheMetricsAutoConfigurationTests {
this.contextRunner.withPropertyValues("spring.cache.type=simple", "spring.cache.cache-names=cache1,cache2") this.contextRunner.withPropertyValues("spring.cache.type=simple", "spring.cache.cache-names=cache1,cache2")
.run((context) -> { .run((context) -> {
MeterRegistry registry = context.getBean(MeterRegistry.class); MeterRegistry registry = context.getBean(MeterRegistry.class);
assertThat(registry.find("cache.gets").tags("name", "cache1").tags("cacheManager", "cacheManager") assertThat(registry.find("cache.gets").tags("name", "cache1").tags("cache.manager", "cacheManager")
.meter()).isNull(); .meter()).isNull();
assertThat(registry.find("cache.gets").tags("name", "cache2").tags("cacheManager", "cacheManager") assertThat(registry.find("cache.gets").tags("name", "cache2").tags("cache.manager", "cacheManager")
.meter()).isNull(); .meter()).isNull();
}); });
} }
@ -77,7 +77,7 @@ class CacheMetricsAutoConfigurationTests {
"spring.cache.cache-names=cache1").run((context) -> { "spring.cache.cache-names=cache1").run((context) -> {
MeterRegistry registry = context.getBean(MeterRegistry.class); MeterRegistry registry = context.getBean(MeterRegistry.class);
assertThat(registry.find("cache.requests").tags("name", "cache1") assertThat(registry.find("cache.requests").tags("name", "cache1")
.tags("cacheManager", "cacheManager").meter()).isNull(); .tags("cache.manager", "cacheManager").meter()).isNull();
}); });
} }

@ -41,7 +41,7 @@ public final class GraphQlTags {
private static final Tag OUTCOME_ERROR = Tag.of("outcome", "ERROR"); private static final Tag OUTCOME_ERROR = Tag.of("outcome", "ERROR");
private static final Tag UNKNOWN_ERRORTYPE = Tag.of("errorType", "UNKNOWN"); private static final Tag UNKNOWN_ERROR_TYPE = Tag.of("error.type", "UNKNOWN");
private GraphQlTags() { private GraphQlTags() {
@ -59,9 +59,9 @@ public final class GraphQlTags {
public static Tag errorType(GraphQLError error) { public static Tag errorType(GraphQLError error) {
ErrorClassification errorType = error.getErrorType(); ErrorClassification errorType = error.getErrorType();
if (errorType instanceof ErrorType) { if (errorType instanceof ErrorType) {
return Tag.of("errorType", ((ErrorType) errorType).name()); return Tag.of("error.type", ((ErrorType) errorType).name());
} }
return UNKNOWN_ERRORTYPE; return UNKNOWN_ERROR_TYPE;
} }
public static Tag errorPath(GraphQLError error) { public static Tag errorPath(GraphQLError error) {
@ -80,7 +80,7 @@ public final class GraphQlTags {
} }
} }
} }
return Tag.of("errorPath", builder.toString()); return Tag.of("error.path", builder.toString());
} }
public static Tag dataFetchingOutcome(Throwable exception) { public static Tag dataFetchingOutcome(Throwable exception) {

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2021 the original author or authors. * Copyright 2012-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -123,7 +123,7 @@ public class StartupTimeMetricsListener implements SmartApplicationListener {
private Iterable<Tag> createTagsFrom(SpringApplication springApplication) { private Iterable<Tag> createTagsFrom(SpringApplication springApplication) {
Class<?> mainClass = springApplication.getMainApplicationClass(); Class<?> mainClass = springApplication.getMainApplicationClass();
return (mainClass != null) ? this.tags.and("main-application-class", mainClass.getName()) : this.tags; return (mainClass != null) ? this.tags.and("main.application.class", mainClass.getName()) : this.tags;
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -105,17 +105,17 @@ public final class RestTemplateExchangeTags {
} }
/** /**
* Create a {@code clientName} {@code Tag} derived from the {@link URI#getHost host} * Create a {@code client.name} {@code Tag} derived from the {@link URI#getHost host}
* of the {@link HttpRequest#getURI() URI} of the given {@code request}. * of the {@link HttpRequest#getURI() URI} of the given {@code request}.
* @param request the request * @param request the request
* @return the clientName tag * @return the client.name tag
*/ */
public static Tag clientName(HttpRequest request) { public static Tag clientName(HttpRequest request) {
String host = request.getURI().getHost(); String host = request.getURI().getHost();
if (host == null) { if (host == null) {
host = "none"; host = "none";
} }
return Tag.of("clientName", host); return Tag.of("client.name", host);
} }
/** /**

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2021 the original author or authors. * Copyright 2012-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -45,7 +45,7 @@ public final class WebClientExchangeTags {
private static final Pattern PATTERN_BEFORE_PATH = Pattern.compile("^https?://[^/]+/"); private static final Pattern PATTERN_BEFORE_PATH = Pattern.compile("^https?://[^/]+/");
private static final Tag CLIENT_NAME_NONE = Tag.of("clientName", "none"); private static final Tag CLIENT_NAME_NONE = Tag.of("client.name", "none");
private WebClientExchangeTags() { private WebClientExchangeTags() {
} }
@ -95,18 +95,18 @@ public final class WebClientExchangeTags {
} }
/** /**
* Create a {@code clientName} {@code Tag} derived from the * Create a {@code client.name} {@code Tag} derived from the
* {@link java.net.URI#getHost host} of the {@link ClientRequest#url() URL} of the * {@link java.net.URI#getHost host} of the {@link ClientRequest#url() URL} of the
* given {@code request}. * given {@code request}.
* @param request the request * @param request the request
* @return the clientName tag * @return the client.name tag
*/ */
public static Tag clientName(ClientRequest request) { public static Tag clientName(ClientRequest request) {
String host = request.url().getHost(); String host = request.url().getHost();
if (host == null) { if (host == null) {
return CLIENT_NAME_NONE; return CLIENT_NAME_NONE;
} }
return Tag.of("clientName", host); return Tag.of("client.name", host);
} }
/** /**

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2021 the original author or authors. * Copyright 2012-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -39,21 +39,21 @@ class GraphQlTagsTests {
void executionOutcomeShouldSucceed() { void executionOutcomeShouldSucceed() {
ExecutionResult result = ExecutionResultImpl.newExecutionResult().build(); ExecutionResult result = ExecutionResultImpl.newExecutionResult().build();
Tag outcomeTag = GraphQlTags.executionOutcome(result, null); Tag outcomeTag = GraphQlTags.executionOutcome(result, null);
assertThat(outcomeTag.getValue()).isEqualTo("SUCCESS"); assertThat(outcomeTag).isEqualTo(Tag.of("outcome", "SUCCESS"));
} }
@Test @Test
void executionOutcomeShouldErrorWhenExceptionThrown() { void executionOutcomeShouldErrorWhenExceptionThrown() {
ExecutionResult result = ExecutionResultImpl.newExecutionResult().build(); ExecutionResult result = ExecutionResultImpl.newExecutionResult().build();
Tag tag = GraphQlTags.executionOutcome(result, new IllegalArgumentException("test error")); Tag tag = GraphQlTags.executionOutcome(result, new IllegalArgumentException("test error"));
assertThat(tag.getValue()).isEqualTo("ERROR"); assertThat(tag).isEqualTo(Tag.of("outcome", "ERROR"));
} }
@Test @Test
void executionOutcomeShouldErrorWhenResponseErrors() { void executionOutcomeShouldErrorWhenResponseErrors() {
GraphQLError error = GraphqlErrorBuilder.newError().message("Invalid query").build(); GraphQLError error = GraphqlErrorBuilder.newError().message("Invalid query").build();
Tag tag = GraphQlTags.executionOutcome(ExecutionResultImpl.newExecutionResult().addError(error).build(), null); Tag tag = GraphQlTags.executionOutcome(ExecutionResultImpl.newExecutionResult().addError(error).build(), null);
assertThat(tag.getValue()).isEqualTo("ERROR"); assertThat(tag).isEqualTo(Tag.of("outcome", "ERROR"));
} }
@Test @Test
@ -61,7 +61,7 @@ class GraphQlTagsTests {
GraphQLError error = GraphqlErrorBuilder.newError().errorType(ErrorType.DataFetchingException) GraphQLError error = GraphqlErrorBuilder.newError().errorType(ErrorType.DataFetchingException)
.message("test error").build(); .message("test error").build();
Tag errorTypeTag = GraphQlTags.errorType(error); Tag errorTypeTag = GraphQlTags.errorType(error);
assertThat(errorTypeTag.getValue()).isEqualTo("DataFetchingException"); assertThat(errorTypeTag).isEqualTo(Tag.of("error.type", "DataFetchingException"));
} }
@Test @Test
@ -69,7 +69,7 @@ class GraphQlTagsTests {
GraphQLError error = GraphqlErrorBuilder.newError().path(Arrays.asList("project", "name")).message("test error") GraphQLError error = GraphqlErrorBuilder.newError().path(Arrays.asList("project", "name")).message("test error")
.build(); .build();
Tag errorPathTag = GraphQlTags.errorPath(error); Tag errorPathTag = GraphQlTags.errorPath(error);
assertThat(errorPathTag.getValue()).isEqualTo("$.project.name"); assertThat(errorPathTag).isEqualTo(Tag.of("error.path", "$.project.name"));
} }
@Test @Test
@ -77,19 +77,19 @@ class GraphQlTagsTests {
GraphQLError error = GraphqlErrorBuilder.newError().path(Arrays.asList("issues", "42", "title")) GraphQLError error = GraphqlErrorBuilder.newError().path(Arrays.asList("issues", "42", "title"))
.message("test error").build(); .message("test error").build();
Tag errorPathTag = GraphQlTags.errorPath(error); Tag errorPathTag = GraphQlTags.errorPath(error);
assertThat(errorPathTag.getValue()).isEqualTo("$.issues[*].title"); assertThat(errorPathTag).isEqualTo(Tag.of("error.path", "$.issues[*].title"));
} }
@Test @Test
void dataFetchingOutcomeShouldBeSuccessfulIfNoException() { void dataFetchingOutcomeShouldBeSuccessfulIfNoException() {
Tag fetchingOutcomeTag = GraphQlTags.dataFetchingOutcome(null); Tag fetchingOutcomeTag = GraphQlTags.dataFetchingOutcome(null);
assertThat(fetchingOutcomeTag.getValue()).isEqualTo("SUCCESS"); assertThat(fetchingOutcomeTag).isEqualTo(Tag.of("outcome", "SUCCESS"));
} }
@Test @Test
void dataFetchingOutcomeShouldBeErrorIfException() { void dataFetchingOutcomeShouldBeErrorIfException() {
Tag fetchingOutcomeTag = GraphQlTags.dataFetchingOutcome(new IllegalStateException("error state")); Tag fetchingOutcomeTag = GraphQlTags.dataFetchingOutcome(new IllegalStateException("error state"));
assertThat(fetchingOutcomeTag.getValue()).isEqualTo("ERROR"); assertThat(fetchingOutcomeTag).isEqualTo(Tag.of("outcome", "ERROR"));
} }
} }

@ -118,7 +118,7 @@ class StartupTimeMetricsListenerTests {
private void assertMetricExistsWithCustomTagsAndValue(String metricName, Tags expectedCustomTags, private void assertMetricExistsWithCustomTagsAndValue(String metricName, Tags expectedCustomTags,
Long expectedValueInMillis) { Long expectedValueInMillis) {
assertThat(this.registry.find(metricName) assertThat(this.registry.find(metricName)
.tags(Tags.concat(expectedCustomTags, "main-application-class", TestMainApplication.class.getName())) .tags(Tags.concat(expectedCustomTags, "main.application.class", TestMainApplication.class.getName()))
.timeGauge()).isNotNull().extracting((m) -> m.value(TimeUnit.MILLISECONDS)) .timeGauge()).isNotNull().extracting((m) -> m.value(TimeUnit.MILLISECONDS))
.isEqualTo(expectedValueInMillis.doubleValue()); .isEqualTo(expectedValueInMillis.doubleValue());
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,11 +17,13 @@
package org.springframework.boot.actuate.metrics.web.client; package org.springframework.boot.actuate.metrics.web.client;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import io.micrometer.core.instrument.Tag; import io.micrometer.core.instrument.Tag;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.ClientHttpResponse;
import org.springframework.mock.http.client.MockClientHttpResponse; import org.springframework.mock.http.client.MockClientHttpResponse;
@ -102,4 +104,12 @@ class RestTemplateExchangeTagsTests {
assertThat(tag.getValue()).isEqualTo("UNKNOWN"); assertThat(tag.getValue()).isEqualTo("UNKNOWN");
} }
@Test
void clientNameTagIsHostOfRequestUri() throws IOException {
ClientHttpRequest request = mock(ClientHttpRequest.class);
given(request.getURI()).willReturn(URI.create("https://example.org"));
Tag tag = RestTemplateExchangeTags.clientName(request);
assertThat(tag).isEqualTo(Tag.of("client.name", "example.org"));
}
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -61,7 +61,7 @@ class DefaultWebClientExchangeTagsProviderTests {
void tagsShouldBePopulated() { void tagsShouldBePopulated() {
Iterable<Tag> tags = this.tagsProvider.tags(this.request, this.response, null); Iterable<Tag> tags = this.tagsProvider.tags(this.request, this.response, null);
assertThat(tags).containsExactlyInAnyOrder(Tag.of("method", "GET"), Tag.of("uri", "/projects/{project}"), assertThat(tags).containsExactlyInAnyOrder(Tag.of("method", "GET"), Tag.of("uri", "/projects/{project}"),
Tag.of("clientName", "example.org"), Tag.of("status", "200"), Tag.of("outcome", "SUCCESS")); Tag.of("client.name", "example.org"), Tag.of("status", "200"), Tag.of("outcome", "SUCCESS"));
} }
@Test @Test
@ -70,28 +70,28 @@ class DefaultWebClientExchangeTagsProviderTests {
.create(HttpMethod.GET, URI.create("https://example.org/projects/spring-boot")).build(); .create(HttpMethod.GET, URI.create("https://example.org/projects/spring-boot")).build();
Iterable<Tag> tags = this.tagsProvider.tags(request, this.response, null); Iterable<Tag> tags = this.tagsProvider.tags(request, this.response, null);
assertThat(tags).containsExactlyInAnyOrder(Tag.of("method", "GET"), Tag.of("uri", "/projects/spring-boot"), assertThat(tags).containsExactlyInAnyOrder(Tag.of("method", "GET"), Tag.of("uri", "/projects/spring-boot"),
Tag.of("clientName", "example.org"), Tag.of("status", "200"), Tag.of("outcome", "SUCCESS")); Tag.of("client.name", "example.org"), Tag.of("status", "200"), Tag.of("outcome", "SUCCESS"));
} }
@Test @Test
void tagsWhenIoExceptionShouldReturnIoErrorStatus() { void tagsWhenIoExceptionShouldReturnIoErrorStatus() {
Iterable<Tag> tags = this.tagsProvider.tags(this.request, null, new IOException()); Iterable<Tag> tags = this.tagsProvider.tags(this.request, null, new IOException());
assertThat(tags).containsExactlyInAnyOrder(Tag.of("method", "GET"), Tag.of("uri", "/projects/{project}"), assertThat(tags).containsExactlyInAnyOrder(Tag.of("method", "GET"), Tag.of("uri", "/projects/{project}"),
Tag.of("clientName", "example.org"), Tag.of("status", "IO_ERROR"), Tag.of("outcome", "UNKNOWN")); Tag.of("client.name", "example.org"), Tag.of("status", "IO_ERROR"), Tag.of("outcome", "UNKNOWN"));
} }
@Test @Test
void tagsWhenExceptionShouldReturnClientErrorStatus() { void tagsWhenExceptionShouldReturnClientErrorStatus() {
Iterable<Tag> tags = this.tagsProvider.tags(this.request, null, new IllegalArgumentException()); Iterable<Tag> tags = this.tagsProvider.tags(this.request, null, new IllegalArgumentException());
assertThat(tags).containsExactlyInAnyOrder(Tag.of("method", "GET"), Tag.of("uri", "/projects/{project}"), assertThat(tags).containsExactlyInAnyOrder(Tag.of("method", "GET"), Tag.of("uri", "/projects/{project}"),
Tag.of("clientName", "example.org"), Tag.of("status", "CLIENT_ERROR"), Tag.of("outcome", "UNKNOWN")); Tag.of("client.name", "example.org"), Tag.of("status", "CLIENT_ERROR"), Tag.of("outcome", "UNKNOWN"));
} }
@Test @Test
void tagsWhenCancelledRequestShouldReturnClientErrorStatus() { void tagsWhenCancelledRequestShouldReturnClientErrorStatus() {
Iterable<Tag> tags = this.tagsProvider.tags(this.request, null, null); Iterable<Tag> tags = this.tagsProvider.tags(this.request, null, null);
assertThat(tags).containsExactlyInAnyOrder(Tag.of("method", "GET"), Tag.of("uri", "/projects/{project}"), assertThat(tags).containsExactlyInAnyOrder(Tag.of("method", "GET"), Tag.of("uri", "/projects/{project}"),
Tag.of("clientName", "example.org"), Tag.of("status", "CLIENT_ERROR"), Tag.of("outcome", "UNKNOWN")); Tag.of("client.name", "example.org"), Tag.of("status", "CLIENT_ERROR"), Tag.of("outcome", "UNKNOWN"));
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2020 the original author or authors. * Copyright 2012-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -88,7 +88,7 @@ class WebClientExchangeTagsTests {
@Test @Test
void clientName() { void clientName() {
assertThat(WebClientExchangeTags.clientName(this.request)).isEqualTo(Tag.of("clientName", "example.org")); assertThat(WebClientExchangeTags.clientName(this.request)).isEqualTo(Tag.of("client.name", "example.org"));
} }
@Test @Test

Loading…
Cancel
Save