-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
to have that working we've added additional convention and contexts around javax and jakarta classes
- Loading branch information
1 parent
8a129bc
commit a456e47
Showing
15 changed files
with
1,402 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
147 changes: 147 additions & 0 deletions
147
...er/core/instrument/binder/http/AbstractDefaultHttpClientRequestObservationConvention.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
/* | ||
* 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.binder.http; | ||
|
||
import io.micrometer.common.KeyValue; | ||
import io.micrometer.common.KeyValues; | ||
import io.micrometer.common.lang.Nullable; | ||
import io.micrometer.common.util.StringUtils; | ||
import io.micrometer.core.instrument.binder.http.HttpObservationDocumentation.ClientLowCardinalityKeys; | ||
import io.micrometer.core.instrument.binder.http.HttpObservationDocumentation.CommonHighCardinalityKeys; | ||
import io.micrometer.core.instrument.binder.http.HttpObservationDocumentation.CommonLowCardinalityKeys; | ||
|
||
import java.net.URI; | ||
import java.util.regex.Pattern; | ||
|
||
class AbstractDefaultHttpClientRequestObservationConvention { | ||
|
||
private static final Pattern PATTERN_BEFORE_PATH = Pattern.compile("^https?://[^/]+/"); | ||
|
||
private static final KeyValue URI_NONE = KeyValue.of(CommonLowCardinalityKeys.URI, KeyValue.NONE_VALUE); | ||
|
||
private static final KeyValue METHOD_NONE = KeyValue.of(CommonLowCardinalityKeys.METHOD, KeyValue.NONE_VALUE); | ||
|
||
private static final KeyValue STATUS_CLIENT_ERROR = KeyValue.of(CommonLowCardinalityKeys.STATUS, "CLIENT_ERROR"); | ||
|
||
private static final KeyValue HTTP_OUTCOME_SUCCESS = KeyValue.of(CommonLowCardinalityKeys.OUTCOME, "SUCCESS"); | ||
|
||
private static final KeyValue HTTP_OUTCOME_UNKNOWN = KeyValue.of(CommonLowCardinalityKeys.OUTCOME, "UNKNOWN"); | ||
|
||
private static final KeyValue CLIENT_NAME_NONE = KeyValue.of(ClientLowCardinalityKeys.CLIENT_NAME, | ||
KeyValue.NONE_VALUE); | ||
|
||
private static final KeyValue EXCEPTION_NONE = KeyValue.of(CommonLowCardinalityKeys.EXCEPTION, KeyValue.NONE_VALUE); | ||
|
||
private static final KeyValue HTTP_URL_NONE = KeyValue.of(CommonHighCardinalityKeys.HTTP_URL, KeyValue.NONE_VALUE); | ||
|
||
private static final KeyValue USER_AGENT_NONE = KeyValue.of(CommonHighCardinalityKeys.USER_AGENT_ORIGINAL, | ||
KeyValue.NONE_VALUE); | ||
|
||
protected String getContextualName(String lowercaseMethod) { | ||
return "http " + lowercaseMethod; | ||
} | ||
|
||
protected KeyValues getLowCardinalityKeyValues(@Nullable URI uri, @Nullable Throwable throwable, | ||
@Nullable String methodName, @Nullable Integer statusCode, @Nullable String uriPathPattern) { | ||
return KeyValues.of(clientName(uri), exception(throwable), method(methodName), outcome(statusCode), | ||
status(statusCode), uri(uriPathPattern)); | ||
} | ||
|
||
private KeyValue uri(@Nullable String uriTemplate) { | ||
if (uriTemplate != null) { | ||
return KeyValue.of(CommonLowCardinalityKeys.URI, extractPath(uriTemplate)); | ||
} | ||
return URI_NONE; | ||
} | ||
|
||
private static String extractPath(String uriTemplate) { | ||
String path = PATTERN_BEFORE_PATH.matcher(uriTemplate).replaceFirst(""); | ||
return (path.startsWith("/") ? path : "/" + path); | ||
} | ||
|
||
private KeyValue method(@Nullable String methodName) { | ||
if (methodName != null) { | ||
return KeyValue.of(CommonLowCardinalityKeys.METHOD, methodName); | ||
} | ||
else { | ||
return METHOD_NONE; | ||
} | ||
} | ||
|
||
private KeyValue status(@Nullable Integer statusCode) { | ||
if (statusCode == null) { | ||
return STATUS_CLIENT_ERROR; | ||
} | ||
return KeyValue.of(CommonLowCardinalityKeys.STATUS, String.valueOf(statusCode)); | ||
} | ||
|
||
private KeyValue clientName(@Nullable URI uri) { | ||
if (uri != null && uri.getHost() != null) { | ||
return KeyValue.of(ClientLowCardinalityKeys.CLIENT_NAME, uri.getHost()); | ||
} | ||
return CLIENT_NAME_NONE; | ||
} | ||
|
||
private KeyValue exception(@Nullable Throwable error) { | ||
if (error != null) { | ||
String simpleName = error.getClass().getSimpleName(); | ||
return KeyValue.of(CommonLowCardinalityKeys.EXCEPTION, | ||
StringUtils.isNotBlank(simpleName) ? simpleName : error.getClass().getName()); | ||
} | ||
return EXCEPTION_NONE; | ||
} | ||
|
||
private KeyValue outcome(@Nullable Integer statusCode) { | ||
if (statusCode != null) { | ||
return HttpOutcome.forStatus(statusCode); | ||
} | ||
return HTTP_OUTCOME_UNKNOWN; | ||
} | ||
|
||
protected KeyValues getHighCardinalityKeyValues(@Nullable URI uri, @Nullable String userAgent) { | ||
// Make sure that KeyValues entries are already sorted by name for better | ||
// performance | ||
return KeyValues.of(requestUri(uri), userAgent(userAgent)); | ||
} | ||
|
||
private KeyValue requestUri(@Nullable URI uri) { | ||
if (uri != null) { | ||
return KeyValue.of(CommonHighCardinalityKeys.HTTP_URL, uri.toASCIIString()); | ||
} | ||
return HTTP_URL_NONE; | ||
} | ||
|
||
private KeyValue userAgent(@Nullable String userAgent) { | ||
if (userAgent != null) { | ||
return KeyValue.of(CommonHighCardinalityKeys.USER_AGENT_ORIGINAL, userAgent); | ||
} | ||
return USER_AGENT_NONE; | ||
} | ||
|
||
static class HttpOutcome { | ||
|
||
static KeyValue forStatus(int statusCode) { | ||
if (statusCode >= 200 && statusCode < 300) { | ||
return HTTP_OUTCOME_SUCCESS; | ||
} | ||
else { | ||
return HTTP_OUTCOME_UNKNOWN; | ||
} | ||
} | ||
|
||
} | ||
|
||
} |
157 changes: 157 additions & 0 deletions
157
...er/core/instrument/binder/http/AbstractDefaultHttpServerRequestObservationConvention.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/* | ||
* 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.binder.http; | ||
|
||
import java.net.URI; | ||
|
||
import io.micrometer.common.KeyValue; | ||
import io.micrometer.common.KeyValues; | ||
import io.micrometer.common.lang.Nullable; | ||
import io.micrometer.common.util.StringUtils; | ||
import io.micrometer.core.instrument.binder.http.HttpObservationDocumentation.CommonHighCardinalityKeys; | ||
import io.micrometer.core.instrument.binder.http.HttpObservationDocumentation.CommonLowCardinalityKeys; | ||
|
||
class AbstractDefaultHttpServerRequestObservationConvention { | ||
|
||
protected static final String DEFAULT_NAME = "http.server.requests"; | ||
|
||
private static final KeyValue METHOD_UNKNOWN = KeyValue.of(CommonLowCardinalityKeys.METHOD, "UNKNOWN"); | ||
|
||
private static final KeyValue STATUS_UNKNOWN = KeyValue.of(CommonLowCardinalityKeys.STATUS, "UNKNOWN"); | ||
|
||
private static final KeyValue HTTP_OUTCOME_SUCCESS = KeyValue.of(CommonLowCardinalityKeys.OUTCOME, "SUCCESS"); | ||
|
||
private static final KeyValue HTTP_OUTCOME_UNKNOWN = KeyValue.of(CommonLowCardinalityKeys.OUTCOME, "UNKNOWN"); | ||
|
||
private static final KeyValue URI_UNKNOWN = KeyValue.of(CommonLowCardinalityKeys.URI, "UNKNOWN"); | ||
|
||
private static final KeyValue URI_ROOT = KeyValue.of(CommonLowCardinalityKeys.URI, "root"); | ||
|
||
private static final KeyValue URI_NOT_FOUND = KeyValue.of(CommonLowCardinalityKeys.URI, "NOT_FOUND"); | ||
|
||
private static final KeyValue URI_REDIRECTION = KeyValue.of(CommonLowCardinalityKeys.URI, "REDIRECTION"); | ||
|
||
private static final KeyValue EXCEPTION_NONE = KeyValue.of(CommonLowCardinalityKeys.EXCEPTION, KeyValue.NONE_VALUE); | ||
|
||
private static final KeyValue HTTP_URL_UNKNOWN = KeyValue.of(CommonHighCardinalityKeys.HTTP_URL, "UNKNOWN"); | ||
|
||
protected String getContextualName(String lowercaseHttpMethod, @Nullable String pathPattern) { | ||
if (pathPattern != null) { | ||
return "http " + lowercaseHttpMethod + " " + pathPattern; | ||
} | ||
return "http " + lowercaseHttpMethod; | ||
} | ||
|
||
protected KeyValues getLowCardinalityKeyValues(@Nullable Throwable error, @Nullable String method, | ||
@Nullable Integer status, @Nullable String pathPattern, @Nullable String requestUri) { | ||
// Make sure that KeyValues entries are already sorted by name for better | ||
// performance | ||
KeyValues micrometerKeyValues = KeyValues.of(exception(error), method(method), outcome(status), status(status), | ||
uri(pathPattern, status)); | ||
if (method == null) { | ||
return micrometerKeyValues; | ||
} | ||
return micrometerKeyValues.and(lowCardinalityKeyValues(method, requestUri, status)); | ||
} | ||
|
||
private KeyValues lowCardinalityKeyValues(String method, String requestUri, @Nullable Integer responseStatus) { | ||
try { | ||
URI uri = URI.create(requestUri); | ||
KeyValue requestMethod = CommonLowCardinalityKeys.HTTP_REQUEST_METHOD.withValue(method); | ||
KeyValue network = CommonLowCardinalityKeys.NETWORK_PROTOCOL_NAME.withValue("http"); | ||
KeyValue serverAddress = CommonLowCardinalityKeys.SERVER_ADDRESS.withValue(uri.getHost()); | ||
KeyValue serverPort = CommonLowCardinalityKeys.SERVER_PORT.withValue(String.valueOf(uri.getPort())); | ||
KeyValue urlScheme = CommonLowCardinalityKeys.URL_SCHEME.withValue(String.valueOf(uri.getScheme())); | ||
KeyValues keyValues = KeyValues.of(requestMethod, network, serverAddress, serverPort, urlScheme); | ||
if (responseStatus != null) { | ||
keyValues = keyValues | ||
.and(CommonLowCardinalityKeys.HTTP_RESPONSE_STATUS_CODE.withValue(String.valueOf(responseStatus))); | ||
} | ||
return keyValues; | ||
} | ||
catch (Exception ex) { | ||
return KeyValues.empty(); | ||
} | ||
} | ||
|
||
protected KeyValues getHighCardinalityKeyValues(String requestUri) { | ||
return KeyValues.of(httpUrl(requestUri)); | ||
} | ||
|
||
protected KeyValue method(@Nullable String method) { | ||
return (method != null) ? KeyValue.of(CommonLowCardinalityKeys.METHOD, method) : METHOD_UNKNOWN; | ||
} | ||
|
||
private KeyValue status(@Nullable Integer status) { | ||
return (status != null) ? KeyValue.of(CommonLowCardinalityKeys.STATUS, Integer.toString(status)) | ||
: STATUS_UNKNOWN; | ||
} | ||
|
||
private KeyValue uri(@Nullable String pattern, @Nullable Integer status) { | ||
if (pattern != null) { | ||
if (pattern.isEmpty()) { | ||
return URI_ROOT; | ||
} | ||
return KeyValue.of(CommonLowCardinalityKeys.URI, pattern); | ||
} | ||
if (status != null) { | ||
if (status >= 300 && status < 400) { | ||
return URI_REDIRECTION; | ||
} | ||
if (status == 404) { | ||
return URI_NOT_FOUND; | ||
} | ||
} | ||
return URI_UNKNOWN; | ||
} | ||
|
||
private KeyValue exception(@Nullable Throwable error) { | ||
if (error != null) { | ||
String simpleName = error.getClass().getSimpleName(); | ||
return KeyValue.of(CommonLowCardinalityKeys.EXCEPTION, | ||
StringUtils.isNotBlank(simpleName) ? simpleName : error.getClass().getName()); | ||
} | ||
return EXCEPTION_NONE; | ||
} | ||
|
||
private KeyValue outcome(@Nullable Integer status) { | ||
if (status != null) { | ||
return HttpOutcome.forStatus(status); | ||
} | ||
return HTTP_OUTCOME_UNKNOWN; | ||
} | ||
|
||
private KeyValue httpUrl(@Nullable String requestUri) { | ||
if (requestUri != null) { | ||
return KeyValue.of(CommonHighCardinalityKeys.HTTP_URL, requestUri); | ||
} | ||
return HTTP_URL_UNKNOWN; | ||
} | ||
|
||
static class HttpOutcome { | ||
|
||
static KeyValue forStatus(int statusCode) { | ||
if (statusCode >= 200 && statusCode < 300) { | ||
return HTTP_OUTCOME_SUCCESS; | ||
} | ||
else { | ||
return HTTP_OUTCOME_UNKNOWN; | ||
} | ||
} | ||
|
||
} | ||
|
||
} |
80 changes: 80 additions & 0 deletions
80
...ter/core/instrument/binder/http/DefaultHttpJakartaClientRequestObservationConvention.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* | ||
* 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.binder.http; | ||
|
||
import java.net.URI; | ||
|
||
import io.micrometer.common.KeyValues; | ||
|
||
/** | ||
* Default {@link HttpJakartaServerRequestObservationConvention}. | ||
* | ||
* @author Brian Clozel | ||
* @author Marcin Grzejszczak | ||
* @since 1.12.0 | ||
*/ | ||
public class DefaultHttpJakartaClientRequestObservationConvention extends | ||
AbstractDefaultHttpClientRequestObservationConvention implements HttpJakartaClientRequestObservationConvention { | ||
|
||
private static final String DEFAULT_NAME = "http.client.requests"; | ||
|
||
private final String name; | ||
|
||
/** | ||
* Create a convention with the default name {@code "http.client.requests"}. | ||
*/ | ||
public DefaultHttpJakartaClientRequestObservationConvention() { | ||
this(DEFAULT_NAME); | ||
} | ||
|
||
/** | ||
* Create a convention with a custom name. | ||
* @param name the observation name | ||
*/ | ||
public DefaultHttpJakartaClientRequestObservationConvention(String name) { | ||
this.name = name; | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return this.name; | ||
} | ||
|
||
@Override | ||
public String getContextualName(HttpJakartaClientRequestObservationContext context) { | ||
String method = context.getCarrier() != null | ||
? (context.getCarrier().getMethod() != null ? context.getCarrier().getMethod() : null) : null; | ||
return getContextualName(method); | ||
} | ||
|
||
@Override | ||
public KeyValues getLowCardinalityKeyValues(HttpJakartaClientRequestObservationContext context) { | ||
URI uri = context.getCarrier() != null ? context.getCarrier().getUriInfo().getRequestUri() : null; | ||
Throwable throwable = context.getError(); | ||
String methodName = context.getCarrier() != null ? context.getCarrier().getMethod() : null; | ||
Integer statusCode = context.getResponse() != null ? context.getResponse().getStatus() : null; | ||
String uriPathPattern = context.getUriTemplate(); | ||
return getLowCardinalityKeyValues(uri, throwable, methodName, statusCode, uriPathPattern); | ||
} | ||
|
||
@Override | ||
public KeyValues getHighCardinalityKeyValues(HttpJakartaClientRequestObservationContext context) { | ||
URI uri = context.getCarrier() != null ? context.getCarrier().getUriInfo().getRequestUri() : null; | ||
String userAgent = context.getCarrier() != null ? context.getCarrier().getHeaderString("User-Agent") : null; | ||
return getHighCardinalityKeyValues(uri, userAgent); | ||
} | ||
|
||
} |
Oops, something went wrong.