Add Jodd-Http instrumentation (#7868)
This PR resolves #7629 This adds javaagent instrumentation for the [jodd-http](https://http.jodd.org/) `HttpRequest`. It creates `Http Client Spans` and `Http Client Metrics`, the lowest supported version is `org.jodd:jodd-http:4.2.0` (most recent: `6.3.0`), since this is the first version of the library supporting java 8, having follow-redirect capability and `HttpRequest#overwriteHeader()` method. The instrumented method's signature and return type `HttpRequest#send()` has not been modified since, and therefore the instrumentation works for all `jodd-http` versions above `4.2.0`. Since this is my first contribution/instrumentation, I orientated myself on the `apache-httpclient-5.0` instrumentation, but obviously I would be glad to get some feedback on this --------- Co-authored-by: Mateusz Rzeszutek <mrzeszutek@splunk.com>
This commit is contained in:
parent
6cb00d3de0
commit
fad7b24253
|
@ -77,6 +77,7 @@ These are the supported libraries and frameworks:
|
|||
| [JDBC](https://docs.oracle.com/javase/8/docs/api/java/sql/package-summary.html) | Java 8+ | [opentelemetry-jdbc](../instrumentation/jdbc/library) | [Database Client Spans] |
|
||||
| [Jedis](https://github.com/xetorthio/jedis) | 1.4+ | N/A | [Database Client Spans] |
|
||||
| [JMS](https://javaee.github.io/javaee-spec/javadocs/javax/jms/package-summary.html) | 1.1+ | N/A | [Messaging Spans] |
|
||||
| [Jodd Http](https://javadoc.io/doc/org.jodd/jodd-http/latest/index.html) | 4.2+ | N/A | [HTTP Client Spans], [HTTP Client Metrics] |
|
||||
| [JSP](https://javaee.github.io/javaee-spec/javadocs/javax/servlet/jsp/package-summary.html) | 2.3+ | N/A | none |
|
||||
| [Kotlin Coroutines](https://kotlinlang.org/docs/coroutines-overview.html) | 1.0+ | N/A | Context propagation |
|
||||
| [Ktor](https://github.com/ktorio/ktor) | 1.0+ | [opentelemetry-ktor-1.0](../instrumentation/ktor/ktor-1.0/library),<br>[opentelemetry-ktor-2.0](../instrumentation/ktor/ktor-2.0/library) | [HTTP Server Spans], [HTTP Server Metrics] |
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
plugins {
|
||||
id("otel.javaagent-instrumentation")
|
||||
}
|
||||
|
||||
muzzle {
|
||||
pass {
|
||||
group.set("org.jodd")
|
||||
module.set("jodd-http")
|
||||
versions.set("[4.2.0,)")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// 4.2 is the first version with java 8, follow-redirects and HttpRequest#headerOverwrite method
|
||||
library("org.jodd:jodd-http:4.2.0")
|
||||
|
||||
testImplementation(project(":instrumentation:jodd-http-4.2:javaagent"))
|
||||
testImplementation(project(":instrumentation-api-semconv"))
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.joddhttp.v4_2;
|
||||
|
||||
import io.opentelemetry.context.propagation.TextMapSetter;
|
||||
import javax.annotation.Nullable;
|
||||
import jodd.http.HttpRequest;
|
||||
|
||||
enum HttpHeaderSetter implements TextMapSetter<HttpRequest> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public void set(@Nullable HttpRequest carrier, String key, String value) {
|
||||
if (carrier == null) {
|
||||
return;
|
||||
}
|
||||
carrier.headerOverwrite(key, value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.joddhttp.v4_2;
|
||||
|
||||
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HttpFlavorValues.HTTP_1_0;
|
||||
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HttpFlavorValues.HTTP_1_1;
|
||||
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HttpFlavorValues.HTTP_2_0;
|
||||
import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HttpFlavorValues.HTTP_3_0;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientAttributesGetter;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
import jodd.http.HttpRequest;
|
||||
import jodd.http.HttpResponse;
|
||||
|
||||
final class JoddHttpHttpAttributesGetter
|
||||
implements HttpClientAttributesGetter<HttpRequest, HttpResponse> {
|
||||
private static final Logger logger =
|
||||
Logger.getLogger(JoddHttpHttpAttributesGetter.class.getName());
|
||||
private static final Set<String> ALLOWED_HTTP_FLAVORS =
|
||||
new HashSet<>(Arrays.asList(HTTP_1_0, HTTP_1_1, HTTP_2_0, HTTP_3_0));
|
||||
|
||||
@Override
|
||||
public String getMethod(HttpRequest request) {
|
||||
return request.method();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUrl(HttpRequest request) {
|
||||
return request.url();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRequestHeader(HttpRequest request, String name) {
|
||||
return request.headers(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getStatusCode(
|
||||
HttpRequest request, HttpResponse response, @Nullable Throwable error) {
|
||||
return response.statusCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getFlavor(HttpRequest request, @Nullable HttpResponse response) {
|
||||
String httpVersion = request.httpVersion();
|
||||
if (httpVersion == null && response != null) {
|
||||
httpVersion = response.httpVersion();
|
||||
}
|
||||
if (httpVersion != null) {
|
||||
if (httpVersion.contains("/")) {
|
||||
httpVersion = httpVersion.substring(httpVersion.lastIndexOf("/") + 1);
|
||||
}
|
||||
|
||||
if (ALLOWED_HTTP_FLAVORS.contains(httpVersion)) {
|
||||
return httpVersion;
|
||||
}
|
||||
}
|
||||
logger.log(Level.FINE, "unexpected http protocol version: {0}", httpVersion);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getResponseHeader(HttpRequest request, HttpResponse response, String name) {
|
||||
return response.headers(name);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.joddhttp.v4_2;
|
||||
|
||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
|
||||
import static io.opentelemetry.javaagent.instrumentation.joddhttp.v4_2.JoddHttpSingletons.instrumenter;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||
|
||||
import io.opentelemetry.context.Context;
|
||||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||
import jodd.http.HttpRequest;
|
||||
import jodd.http.HttpResponse;
|
||||
import net.bytebuddy.asm.Advice;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
class JoddHttpInstrumentation implements TypeInstrumentation {
|
||||
|
||||
@Override
|
||||
public ElementMatcher<TypeDescription> typeMatcher() {
|
||||
return named("jodd.http.HttpRequest");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(TypeTransformer transformer) {
|
||||
transformer.applyAdviceToMethod(
|
||||
isMethod().and(named("send")).and(takesArguments(0)),
|
||||
this.getClass().getName() + "$RequestAdvice");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class RequestAdvice {
|
||||
|
||||
@Advice.OnMethodEnter(suppress = Throwable.class)
|
||||
public static void methodEnter(
|
||||
@Advice.This HttpRequest request,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
Context parentContext = currentContext();
|
||||
if (!instrumenter().shouldStart(parentContext, request)) {
|
||||
return;
|
||||
}
|
||||
context = instrumenter().start(parentContext, request);
|
||||
scope = context.makeCurrent();
|
||||
}
|
||||
|
||||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
|
||||
public static void methodExit(
|
||||
@Advice.This HttpRequest request,
|
||||
@Advice.Return HttpResponse response,
|
||||
@Advice.Thrown Throwable throwable,
|
||||
@Advice.Local("otelContext") Context context,
|
||||
@Advice.Local("otelScope") Scope scope) {
|
||||
if (scope == null) {
|
||||
return;
|
||||
}
|
||||
scope.close();
|
||||
instrumenter().end(context, request, response, throwable);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.joddhttp.v4_2;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
|
||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@AutoService(InstrumentationModule.class)
|
||||
public class JoddHttpInstrumentationModule extends InstrumentationModule {
|
||||
|
||||
public JoddHttpInstrumentationModule() {
|
||||
super("jodd-http", "jodd-http-4.2");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TypeInstrumentation> typeInstrumentations() {
|
||||
return Collections.singletonList(new JoddHttpInstrumentation());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.joddhttp.v4_2;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.net.NetClientAttributesGetter;
|
||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
|
||||
import javax.annotation.Nullable;
|
||||
import jodd.http.HttpRequest;
|
||||
import jodd.http.HttpResponse;
|
||||
|
||||
final class JoddHttpNetAttributesGetter
|
||||
implements NetClientAttributesGetter<HttpRequest, HttpResponse> {
|
||||
|
||||
@Override
|
||||
public String getTransport(HttpRequest request, @Nullable HttpResponse response) {
|
||||
return SemanticAttributes.NetTransportValues.IP_TCP;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String getPeerName(HttpRequest request) {
|
||||
return request.host();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPeerPort(HttpRequest request) {
|
||||
return request.port();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.joddhttp.v4_2;
|
||||
|
||||
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientAttributesExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpClientMetrics;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanNameExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpSpanStatusExtractor;
|
||||
import io.opentelemetry.instrumentation.api.instrumenter.net.PeerServiceAttributesExtractor;
|
||||
import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig;
|
||||
import jodd.http.HttpRequest;
|
||||
import jodd.http.HttpResponse;
|
||||
|
||||
public final class JoddHttpSingletons {
|
||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.jodd-http-4.2";
|
||||
|
||||
private static final Instrumenter<HttpRequest, HttpResponse> INSTRUMENTER;
|
||||
|
||||
static {
|
||||
JoddHttpHttpAttributesGetter httpAttributesGetter = new JoddHttpHttpAttributesGetter();
|
||||
JoddHttpNetAttributesGetter netAttributesGetter = new JoddHttpNetAttributesGetter();
|
||||
|
||||
INSTRUMENTER =
|
||||
Instrumenter.<HttpRequest, HttpResponse>builder(
|
||||
GlobalOpenTelemetry.get(),
|
||||
INSTRUMENTATION_NAME,
|
||||
HttpSpanNameExtractor.create(httpAttributesGetter))
|
||||
.setSpanStatusExtractor(HttpSpanStatusExtractor.create(httpAttributesGetter))
|
||||
.addAttributesExtractor(
|
||||
HttpClientAttributesExtractor.builder(httpAttributesGetter, netAttributesGetter)
|
||||
.setCapturedRequestHeaders(CommonConfig.get().getClientRequestHeaders())
|
||||
.setCapturedResponseHeaders(CommonConfig.get().getClientResponseHeaders())
|
||||
.build())
|
||||
.addAttributesExtractor(
|
||||
PeerServiceAttributesExtractor.create(
|
||||
netAttributesGetter, CommonConfig.get().getPeerServiceMapping()))
|
||||
.addOperationMetrics(HttpClientMetrics.get())
|
||||
.buildClientInstrumenter(HttpHeaderSetter.INSTANCE);
|
||||
}
|
||||
|
||||
public static Instrumenter<HttpRequest, HttpResponse> instrumenter() {
|
||||
return INSTRUMENTER;
|
||||
}
|
||||
|
||||
private JoddHttpSingletons() {}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.joddhttp.v4_2;
|
||||
|
||||
import static jodd.http.HttpStatus.HTTP_FORBIDDEN;
|
||||
import static jodd.http.HttpStatus.HTTP_INTERNAL_ERROR;
|
||||
import static jodd.http.HttpStatus.HTTP_NOT_FOUND;
|
||||
import static jodd.http.HttpStatus.HTTP_OK;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes.HttpFlavorValues;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import jodd.http.HttpBase;
|
||||
import jodd.http.HttpRequest;
|
||||
import jodd.http.HttpResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class JoddHttpHttpAttributesGetterTest {
|
||||
|
||||
private static final JoddHttpHttpAttributesGetter attributesGetter =
|
||||
new JoddHttpHttpAttributesGetter();
|
||||
|
||||
@Test
|
||||
void getMethod() {
|
||||
for (String method : Arrays.asList("GET", "PUT", "POST", "PATCH")) {
|
||||
assertEquals(method, attributesGetter.getMethod(new HttpRequest().method(method)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUrl() {
|
||||
HttpRequest request =
|
||||
HttpRequest.get("/test/subpath")
|
||||
.host("test.com")
|
||||
.query("param1", "val1")
|
||||
.query("param2", "val1")
|
||||
.query("param2", "val2");
|
||||
assertEquals(
|
||||
"http://test.com/test/subpath?param1=val1¶m2=val1¶m2=val2",
|
||||
attributesGetter.getUrl(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getRequestHeader() {
|
||||
HttpRequest request =
|
||||
HttpRequest.get("/test")
|
||||
.header("single", "val1")
|
||||
.header("multiple", "val1")
|
||||
.header("multiple", "val2");
|
||||
List<String> headerVals = attributesGetter.getRequestHeader(request, "single");
|
||||
assertEquals(1, headerVals.size());
|
||||
assertEquals("val1", headerVals.get(0));
|
||||
headerVals = attributesGetter.getRequestHeader(request, "multiple");
|
||||
assertEquals(2, headerVals.size());
|
||||
assertEquals("val1", headerVals.get(0));
|
||||
assertEquals("val2", headerVals.get(1));
|
||||
headerVals = attributesGetter.getRequestHeader(request, "not-existing");
|
||||
assertEquals(0, headerVals.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getStatusCode() {
|
||||
for (Integer code :
|
||||
Arrays.asList(HTTP_OK, HTTP_FORBIDDEN, HTTP_INTERNAL_ERROR, HTTP_NOT_FOUND)) {
|
||||
assertEquals(
|
||||
code, attributesGetter.getStatusCode(null, new HttpResponse().statusCode(code), null));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFlavor() {
|
||||
HttpRequest request = HttpRequest.get("/test").httpVersion(HttpBase.HTTP_1_1);
|
||||
assertEquals(HttpFlavorValues.HTTP_1_1, attributesGetter.getFlavor(request, null));
|
||||
request.httpVersion(null);
|
||||
assertNull(attributesGetter.getFlavor(request, null));
|
||||
request.httpVersion("INVALID-HTTP-Version");
|
||||
assertNull(attributesGetter.getFlavor(request, null));
|
||||
request.httpVersion(null);
|
||||
HttpResponse response = new HttpResponse().httpVersion(HttpBase.HTTP_1_0);
|
||||
assertEquals(HttpFlavorValues.HTTP_1_0, attributesGetter.getFlavor(request, response));
|
||||
response.httpVersion(null);
|
||||
assertNull(attributesGetter.getFlavor(request, response));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getResponseHeader() {
|
||||
HttpResponse response =
|
||||
new HttpResponse()
|
||||
.header("single", "val1")
|
||||
.header("multiple", "val1")
|
||||
.header("multiple", "val2");
|
||||
List<String> headerVals = attributesGetter.getResponseHeader(null, response, "single");
|
||||
assertEquals(1, headerVals.size());
|
||||
assertEquals("val1", headerVals.get(0));
|
||||
headerVals = attributesGetter.getResponseHeader(null, response, "multiple");
|
||||
assertEquals(2, headerVals.size());
|
||||
assertEquals("val1", headerVals.get(0));
|
||||
assertEquals("val2", headerVals.get(1));
|
||||
headerVals = attributesGetter.getResponseHeader(null, response, "not-existing");
|
||||
assertEquals(0, headerVals.size());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.javaagent.instrumentation.joddhttp.v4_2;
|
||||
|
||||
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
||||
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest;
|
||||
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension;
|
||||
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions;
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import jodd.http.HttpRequest;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
public class JoddHttpTest extends AbstractHttpClientTest<HttpRequest> {
|
||||
|
||||
@RegisterExtension
|
||||
static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected String userAgent() {
|
||||
return "Jodd HTTP";
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpRequest buildRequest(String method, URI uri, Map<String, String> headers) {
|
||||
HttpRequest request =
|
||||
new HttpRequest()
|
||||
.method(method)
|
||||
.set(uri.toString())
|
||||
.followRedirects(true)
|
||||
.connectionKeepAlive(true)
|
||||
.header("user-agent", userAgent());
|
||||
for (Map.Entry<String, String> header : headers.entrySet()) {
|
||||
request.headerOverwrite(header.getKey(), header.getValue());
|
||||
}
|
||||
if (uri.toString().contains("/read-timeout")) {
|
||||
request.timeout((int) READ_TIMEOUT.toMillis());
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sendRequest(HttpRequest request, String method, URI uri, Map<String, String> headers)
|
||||
throws Exception {
|
||||
request.method(method).set(uri.toString());
|
||||
for (Map.Entry<String, String> header : headers.entrySet()) {
|
||||
request.headerOverwrite(header.getKey(), header.getValue());
|
||||
}
|
||||
return request.send().statusCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpClientTestOptions.Builder optionsBuilder) {
|
||||
optionsBuilder.enableTestReadTimeout();
|
||||
optionsBuilder.disableTestCallback();
|
||||
// Circular Redirects are not explicitly handled by jodd-http
|
||||
optionsBuilder.disableTestCircularRedirects();
|
||||
}
|
||||
}
|
|
@ -300,6 +300,7 @@ hideFromDependabot(":instrumentation:jms:jms-common:javaagent")
|
|||
hideFromDependabot(":instrumentation:jms:jms-common:javaagent-unit-tests")
|
||||
hideFromDependabot(":instrumentation:jmx-metrics:javaagent")
|
||||
hideFromDependabot(":instrumentation:jmx-metrics:library")
|
||||
hideFromDependabot(":instrumentation:jodd-http-4.2:javaagent")
|
||||
hideFromDependabot(":instrumentation:jsf:jsf-javax-common:javaagent")
|
||||
hideFromDependabot(":instrumentation:jsf:jsf-javax-common:testing")
|
||||
hideFromDependabot(":instrumentation:jsf:jsf-jakarta-common:javaagent")
|
||||
|
|
Loading…
Reference in New Issue