-
Notifications
You must be signed in to change notification settings - Fork 995
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
JettyClientMetrics compatibility with Jetty 12
Add JettyClientMetrics and related classes to a micrometer-jetty12 module and migrate Jetty API accordingly.
- Loading branch information
Showing
16 changed files
with
1,179 additions
and
2 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
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
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,28 @@ | ||
description 'Micrometer instrumentation for Jetty 12' | ||
|
||
// skip this module when building with jdk <17 | ||
if (!javaLanguageVersion.canCompileOrRun(17)) { | ||
project.tasks.configureEach { task -> task.enabled = false } | ||
} | ||
|
||
dependencies { | ||
api project(":micrometer-core") | ||
|
||
optionalApi libs.jetty12Client | ||
|
||
testImplementation project(":micrometer-observation-test") | ||
testImplementation project(":micrometer-test") | ||
testImplementation libs.junitJupiter | ||
testImplementation libs.assertj | ||
testImplementation libs.wiremock | ||
} | ||
|
||
java { | ||
targetCompatibility = 17 | ||
} | ||
|
||
compileJava { | ||
sourceCompatibility = JavaVersion.VERSION_17 | ||
targetCompatibility = JavaVersion.VERSION_17 | ||
options.release = 17 | ||
} |
46 changes: 46 additions & 0 deletions
46
...2/src/main/java/io/micrometer/jetty12/client/DefaultJettyClientObservationConvention.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,46 @@ | ||
/* | ||
* Copyright 2024 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.jetty12.client; | ||
|
||
import io.micrometer.common.KeyValues; | ||
import org.eclipse.jetty.client.Request; | ||
import org.eclipse.jetty.client.Result; | ||
|
||
/** | ||
* Default implementation of {@link JettyClientObservationConvention}. | ||
* | ||
* @since 1.13.0 | ||
*/ | ||
public class DefaultJettyClientObservationConvention implements JettyClientObservationConvention { | ||
|
||
public static DefaultJettyClientObservationConvention INSTANCE = new DefaultJettyClientObservationConvention(); | ||
|
||
@Override | ||
public KeyValues getLowCardinalityKeyValues(JettyClientContext context) { | ||
Request request = context.getCarrier(); | ||
Result result = context.getResponse(); | ||
return KeyValues.of(JettyClientKeyValues.method(request), JettyClientKeyValues.host(request), | ||
JettyClientKeyValues.uri(request, result, context.getUriPatternFunction()), | ||
JettyClientKeyValues.exception(result), JettyClientKeyValues.status(result), | ||
JettyClientKeyValues.outcome(result)); | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return JettyClientMetrics.DEFAULT_JETTY_CLIENT_REQUESTS_TIMER_NAME; | ||
} | ||
|
||
} |
46 changes: 46 additions & 0 deletions
46
micrometer-jetty12/src/main/java/io/micrometer/jetty12/client/JettyClientContext.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,46 @@ | ||
/* | ||
* Copyright 2024 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.jetty12.client; | ||
|
||
import io.micrometer.observation.transport.RequestReplySenderContext; | ||
import org.eclipse.jetty.client.Request; | ||
import org.eclipse.jetty.client.Result; | ||
|
||
import java.util.Objects; | ||
import java.util.function.BiFunction; | ||
|
||
/** | ||
* Context to use when instrumenting Jetty client metrics with the Observation API. | ||
* | ||
* @since 1.13.0 | ||
* @see JettyClientMetrics | ||
*/ | ||
public class JettyClientContext extends RequestReplySenderContext<Request, Result> { | ||
|
||
private final BiFunction<Request, Result, String> uriPatternFunction; | ||
|
||
public JettyClientContext(Request request, BiFunction<Request, Result, String> uriPatternFunction) { | ||
super((carrier, key, value) -> Objects.requireNonNull(carrier) | ||
.headers(httpFields -> httpFields.add(key, value))); | ||
this.uriPatternFunction = uriPatternFunction; | ||
setCarrier(request); | ||
} | ||
|
||
public BiFunction<Request, Result, String> getUriPatternFunction() { | ||
return uriPatternFunction; | ||
} | ||
|
||
} |
163 changes: 163 additions & 0 deletions
163
micrometer-jetty12/src/main/java/io/micrometer/jetty12/client/JettyClientKeyValues.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,163 @@ | ||
/* | ||
* Copyright 2024 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.jetty12.client; | ||
|
||
import io.micrometer.common.KeyValue; | ||
import io.micrometer.common.lang.Nullable; | ||
import io.micrometer.common.util.StringUtils; | ||
import io.micrometer.core.instrument.binder.http.Outcome; | ||
import org.eclipse.jetty.client.Request; | ||
import org.eclipse.jetty.client.Result; | ||
import org.eclipse.jetty.http.HttpStatus; | ||
|
||
import java.util.function.BiFunction; | ||
import java.util.regex.Pattern; | ||
|
||
/** | ||
* Factory methods for {@link KeyValue} associated with a request-response exchange that | ||
* is handled by Jetty {@link org.eclipse.jetty.client.HttpClient}. | ||
* | ||
* @author Jon Schneider | ||
* @since 1.13.0 | ||
*/ | ||
public final class JettyClientKeyValues { | ||
|
||
private static final KeyValue URI_NOT_FOUND = KeyValue.of("uri", "NOT_FOUND"); | ||
|
||
private static final KeyValue URI_REDIRECTION = KeyValue.of("uri", "REDIRECTION"); | ||
|
||
private static final KeyValue URI_ROOT = KeyValue.of("uri", "root"); | ||
|
||
private static final KeyValue EXCEPTION_NONE = KeyValue.of("exception", "None"); | ||
|
||
private static final KeyValue EXCEPTION_UNKNOWN = KeyValue.of("exception", "UNKNOWN"); | ||
|
||
private static final KeyValue METHOD_UNKNOWN = KeyValue.of("method", "UNKNOWN"); | ||
|
||
private static final KeyValue HOST_UNKNOWN = KeyValue.of("host", "UNKNOWN"); | ||
|
||
private static final KeyValue STATUS_UNKNOWN = KeyValue.of("status", "UNKNOWN"); | ||
|
||
private static final Pattern TRAILING_SLASH_PATTERN = Pattern.compile("/$"); | ||
|
||
private static final Pattern MULTIPLE_SLASH_PATTERN = Pattern.compile("//+"); | ||
|
||
private static final KeyValue OUTCOME_UNKNOWN = KeyValue.of("outcome", "UNKNOWN"); | ||
|
||
private JettyClientKeyValues() { | ||
} | ||
|
||
/** | ||
* Creates a {@code method} KeyValue based on the {@link Request#getMethod() method} | ||
* of the given {@code request}. | ||
* @param request the request | ||
* @return the method KeyValue whose value is a capitalized method (e.g. GET). | ||
*/ | ||
public static KeyValue method(Request request) { | ||
return (request != null) ? KeyValue.of("method", request.getMethod()) : METHOD_UNKNOWN; | ||
} | ||
|
||
/** | ||
* Creates a {@code host} KeyValue based on the {@link Request#getHost()} of the given | ||
* {@code request}. | ||
* @param request the request | ||
* @return the host KeyValue derived from request | ||
*/ | ||
public static KeyValue host(Request request) { | ||
return (request != null) ? KeyValue.of("host", request.getHost()) : HOST_UNKNOWN; | ||
} | ||
|
||
/** | ||
* Creates a {@code status} KeyValue based on the status of the given {@code result}. | ||
* @param result the request result | ||
* @return the status KeyValue derived from the status of the response | ||
*/ | ||
public static KeyValue status(@Nullable Result result) { | ||
return result != null ? KeyValue.of("status", Integer.toString(result.getResponse().getStatus())) | ||
: STATUS_UNKNOWN; | ||
} | ||
|
||
/** | ||
* Creates a {@code uri} KeyValue based on the URI of the given {@code result}. | ||
* {@code REDIRECTION} for 3xx responses, {@code NOT_FOUND} for 404 responses. | ||
* @param request the request | ||
* @param result the request result | ||
* @param successfulUriPattern successful URI pattern | ||
* @return the uri KeyValue derived from the request and its result | ||
*/ | ||
public static KeyValue uri(Request request, @Nullable Result result, | ||
BiFunction<Request, Result, String> successfulUriPattern) { | ||
if (result != null && result.getResponse() != null) { | ||
int status = result.getResponse().getStatus(); | ||
if (HttpStatus.isRedirection(status)) { | ||
return URI_REDIRECTION; | ||
} | ||
if (status == 404) { | ||
return URI_NOT_FOUND; | ||
} | ||
} | ||
|
||
String matchingPattern = successfulUriPattern.apply(request, result); | ||
matchingPattern = MULTIPLE_SLASH_PATTERN.matcher(matchingPattern).replaceAll("/"); | ||
if (matchingPattern.equals("/")) { | ||
return URI_ROOT; | ||
} | ||
matchingPattern = TRAILING_SLASH_PATTERN.matcher(matchingPattern).replaceAll(""); | ||
return KeyValue.of("uri", matchingPattern); | ||
} | ||
|
||
/** | ||
* Creates an {@code exception} KeyValue based on the {@link Class#getSimpleName() | ||
* simple name} of the class of the given {@code exception}. | ||
* @param result the request result | ||
* @return the exception KeyValue derived from the exception | ||
*/ | ||
public static KeyValue exception(@Nullable Result result) { | ||
if (result == null) { | ||
return EXCEPTION_UNKNOWN; | ||
} | ||
Throwable exception = result.getFailure(); | ||
if (exception == null) { | ||
return EXCEPTION_NONE; | ||
} | ||
if (result.getResponse() != null) { | ||
int status = result.getResponse().getStatus(); | ||
if (status == 404 || HttpStatus.isRedirection(status)) { | ||
return EXCEPTION_NONE; | ||
} | ||
} | ||
if (exception.getCause() != null) { | ||
exception = exception.getCause(); | ||
} | ||
String simpleName = exception.getClass().getSimpleName(); | ||
return KeyValue.of("exception", | ||
StringUtils.isNotEmpty(simpleName) ? simpleName : exception.getClass().getName()); | ||
} | ||
|
||
/** | ||
* Creates an {@code outcome} KeyValue based on the status of the given | ||
* {@code result}. | ||
* @param result the request result | ||
* @return the outcome KeyValue derived from the status of the response | ||
*/ | ||
public static KeyValue outcome(@Nullable Result result) { | ||
if (result == null) { | ||
return OUTCOME_UNKNOWN; | ||
} | ||
return Outcome.forStatus(result.getResponse().getStatus()).asKeyValue(); | ||
} | ||
|
||
} |
Oops, something went wrong.