From db1250d8c91237e3c20e77933e3aa8bdd1a4556b Mon Sep 17 00:00:00 2001 From: Mateusz Rzeszutek Date: Fri, 15 Jul 2022 23:48:52 +0200 Subject: [PATCH] Add a dropwizard-metrics -> OTel metrics bridge (#6259) * Add a dropwizard-metrics -> OTel metrics bridge * disable by default * enable metrics for test --- docs/supported-libraries.md | 209 +++++++++--------- .../javaagent/build.gradle.kts | 20 ++ .../CounterInstrumentation.java | 51 +++++ .../DropwizardMetricsAdapter.java | 174 +++++++++++++++ ...ropwizardMetricsInstrumentationModule.java | 48 ++++ .../DropwizardSingletons.java | 20 ++ .../HistogramInstrumentation.java | 41 ++++ .../MeterInstrumentation.java | 40 ++++ .../MetricRegistryInstrumentation.java | 40 ++++ .../TimerInstrumentation.java | 41 ++++ .../DropwizardMetricsTest.java | 199 +++++++++++++++++ ...ditionalLibraryIgnoredTypesConfigurer.java | 5 - settings.gradle.kts | 1 + 13 files changed, 781 insertions(+), 108 deletions(-) create mode 100644 instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/build.gradle.kts create mode 100644 instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/CounterInstrumentation.java create mode 100644 instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardMetricsAdapter.java create mode 100644 instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardMetricsInstrumentationModule.java create mode 100644 instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardSingletons.java create mode 100644 instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/HistogramInstrumentation.java create mode 100644 instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/MeterInstrumentation.java create mode 100644 instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/MetricRegistryInstrumentation.java create mode 100644 instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/TimerInstrumentation.java create mode 100644 instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardMetricsTest.java diff --git a/docs/supported-libraries.md b/docs/supported-libraries.md index 633aebf0b534..ea6b1dab472f 100644 --- a/docs/supported-libraries.md +++ b/docs/supported-libraries.md @@ -17,109 +17,110 @@ or [contributing](../CONTRIBUTING.md). These are the supported libraries and frameworks: -| Library/Framework | Versions | -|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------| -| [Akka Actors](https://doc.akka.io/docs/akka/current/typed/index.html) | 2.5+ | -| [Akka HTTP](https://doc.akka.io/docs/akka-http/current/index.html) | 10.0+ | -| [Apache Axis2](https://axis.apache.org/axis2/java/core/) | 1.6+ | -| [Apache Camel](https://camel.apache.org/) | 2.20+ (not including 3.x yet) | -| [Apache CXF JAX-RS](https://cxf.apache.org/) | 3.2+ | -| [Apache CXF JAX-RS Client](https://cxf.apache.org/) | 3.0+ | -| [Apache CXF JAX-WS](https://cxf.apache.org/) | 3.0+ | -| [Apache Dubbo](https://github.com/apache/dubbo/) | 2.7+ | -| [Apache HttpAsyncClient](https://hc.apache.org/index.html) | 4.1+ | -| [Apache HttpClient](https://hc.apache.org/index.html) | 2.0+ | -| [Apache Kafka Producer/Consumer API](https://kafka.apache.org/documentation/#producerapi) | 0.11+ | -| [Apache Kafka Streams API](https://kafka.apache.org/documentation/streams/) | 0.11+ | -| [Apache MyFaces](https://myfaces.apache.org/) | 1.2+ (not including 3.x yet) | -| [Apache RocketMQ](https://rocketmq.apache.org/) | 4.8+ | -| [Apache Struts 2](https://github.com/apache/struts) | 2.3+ | -| [Apache Tapestry](https://tapestry.apache.org/) | 5.4+ | -| [Apache Wicket](https://wicket.apache.org/) | 8.0+ | -| [Armeria](https://armeria.dev) | 1.3+ | -| [AsyncHttpClient](https://github.com/AsyncHttpClient/async-http-client) | 1.9+ | -| [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/java-handler.html) | 1.0+ | -| [AWS SDK](https://aws.amazon.com/sdk-for-java/) | 1.11.x and 2.2.0+ | -| [Azure Core](https://docs.microsoft.com/en-us/java/api/overview/azure/core-readme) | 1.14+ | -| [Cassandra Driver](https://github.com/datastax/java-driver) | 3.0+ | -| [Couchbase Client](https://github.com/couchbase/couchbase-java-client) | 2.0+ and 3.1+ | -| [Dropwizard Views](https://www.dropwizard.io/en/latest/manual/views.html) | 0.7+ | -| [Eclipse Grizzly](https://javaee.github.io/grizzly/httpserverframework.html) | 2.0+ (disabled by default) | -| [Eclipse Jersey](https://eclipse-ee4j.github.io/jersey/) | 2.0+ (not including 3.x yet) | -| [Eclipse Jetty HTTP Client](https://www.eclipse.org/jetty/javadoc/jetty-9/org/eclipse/jetty/client/HttpClient.html) | 9.2+ (not including 10+ yet) | -| [Eclipse Metro](https://projects.eclipse.org/projects/ee4j.metro) | 2.2+ (not including 3.x yet) | -| [Eclipse Mojarra](https://projects.eclipse.org/projects/ee4j.mojarra) | 1.2+ (not including 3.x yet) | -| [Elasticsearch API](https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/index.html) | 5.0+ | -| [Elasticsearch REST Client](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html) | 5.0+ | -| [Finatra](https://github.com/twitter/finatra) | 2.9+ | -| [Geode Client](https://geode.apache.org/) | 1.4+ | -| [Google HTTP Client](https://github.com/googleapis/google-http-java-client) | 1.19+ | -| [Grails](https://grails.org/) | 3.0+ | -| [GraphQL Java](https://www.graphql-java.com/) | 12.0+ | -| [gRPC](https://github.com/grpc/grpc-java) | 1.6+ | -| [Guava ListenableFuture](https://guava.dev/releases/snapshot/api/docs/com/google/common/util/concurrent/ListenableFuture.html) | 10.0+ | -| [GWT](http://www.gwtproject.org/) | 2.0+ | -| [Hibernate](https://github.com/hibernate/hibernate-orm) | 3.3+ | -| [HikariCP](https://github.com/brettwooldridge/HikariCP) | 3.0+ | -| [HttpURLConnection](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/HttpURLConnection.html) | Java 8+ | -| [Hystrix](https://github.com/Netflix/Hystrix) | 1.4+ | -| [Java Executors](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html) | Java 8+ | -| [Java Http Client](https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/package-summary.html) | Java 11+ | -| [java.util.logging](https://docs.oracle.com/javase/8/docs/api/java/util/logging/package-summary.html) | Java 8+ | -| [JAX-RS](https://javaee.github.io/javaee-spec/javadocs/javax/ws/rs/package-summary.html) | 0.5+ | -| [JAX-RS Client](https://javaee.github.io/javaee-spec/javadocs/javax/ws/rs/client/package-summary.html) | 1.1+ | -| [JAX-WS](https://jakarta.ee/specifications/xml-web-services/2.3/apidocs/javax/xml/ws/package-summary.html) | 2.0+ (not including 3.x yet) | -| [JDBC](https://docs.oracle.com/javase/8/docs/api/java/sql/package-summary.html) | Java 8+ | -| [Jedis](https://github.com/xetorthio/jedis) | 1.4+ | -| [JMS](https://javaee.github.io/javaee-spec/javadocs/javax/jms/package-summary.html) | 1.1+ | -| [JSP](https://javaee.github.io/javaee-spec/javadocs/javax/servlet/jsp/package-summary.html) | 2.3+ | -| [Kotlin Coroutines](https://kotlinlang.org/docs/coroutines-overview.html) | 1.0+ | -| [Kubernetes Client](https://github.com/kubernetes-client/java) | 7.0+ | -| [Lettuce](https://github.com/lettuce-io/lettuce-core) | 4.0+ | -| [Log4j 1](https://logging.apache.org/log4j/1.2/) | 1.2+ | -| [Log4j 2](https://logging.apache.org/log4j/2.x/) | 2.11+ | -| [Logback](http://logback.qos.ch/) | 1.0+ | -| [Micrometer](https://micrometer.io/) | 1.5+ | -| [MongoDB Driver](https://mongodb.github.io/mongo-java-driver/) | 3.1+ | -| [Netty](https://github.com/netty/netty) | 3.8+ | -| [OkHttp](https://github.com/square/okhttp/) | 2.2+ | -| [Oracle UCP](https://docs.oracle.com/database/121/JJUCP/) | 11.2+ | -| [OSHI](https://github.com/oshi/oshi/) | 5.3.1+ | -| [Play](https://github.com/playframework/playframework) | 2.4+ | -| [Play WS](https://github.com/playframework/play-ws) | 1.0+ | -| [Quartz](https://www.quartz-scheduler.org/) | 2.0+ | -| [RabbitMQ Client](https://github.com/rabbitmq/rabbitmq-java-client) | 2.7+ | -| [Ratpack](https://github.com/ratpack/ratpack) | 1.4+ | -| [Reactor](https://github.com/reactor/reactor-core) | 3.1+ | -| [Reactor Netty](https://github.com/reactor/reactor-netty) | 0.9+ | -| [Rediscala](https://github.com/etaty/rediscala) | 1.8+ | -| [Redisson](https://github.com/redisson/redisson) | 3.0+ | -| [RESTEasy](https://resteasy.github.io/) | 3.0+ | -| [Restlet](https://restlet.talend.com/) | 1.0+ | -| [RMI](https://docs.oracle.com/en/java/javase/11/docs/api/java.rmi/java/rmi/package-summary.html) | Java 8+ | -| [RxJava](https://github.com/ReactiveX/RxJava) | 1.0+ | -| [Scala ForkJoinPool](https://www.scala-lang.org/api/2.12.0/scala/concurrent/forkjoin/package$$ForkJoinPool$.html) | 2.8+ | -| [Servlet](https://javaee.github.io/javaee-spec/javadocs/javax/servlet/package-summary.html) | 2.2+ | -| [Spark Web Framework](https://github.com/perwendel/spark) | 2.3+ | -| [Spring Batch](https://spring.io/projects/spring-batch) | 3.0+ | -| [Spring Data](https://spring.io/projects/spring-data) | 1.8+ | -| [Spring Integration](https://spring.io/projects/spring-integration) | 4.1+ | -| [Spring Kafka](https://spring.io/projects/spring-kafka) | 2.7+ | -| [Spring RabbitMQ](https://spring.io/projects/spring-amqp) | 1.0+ | -| [Spring Scheduling](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/package-summary.html) | 3.1+ | -| [Spring Web MVC](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/package-summary.html) | 3.1+ | -| [Spring Web Services](https://spring.io/projects/spring-ws) | 2.0+ | -| [Spring WebFlux](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/package-summary.html) | 5.0+ | -| [Spymemcached](https://github.com/couchbase/spymemcached) | 2.12+ | -| [Tomcat JDBC Pool](https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html) | 8.5.0+ | -| [Twilio](https://github.com/twilio/twilio-java) | 6.6+ (not including 8.x yet) | -| [Undertow](https://undertow.io/) | 1.4+ | -| [Vaadin](https://vaadin.com/) | 14.2+ | -| [Vert.x Web](https://vertx.io/docs/vertx-web/java/) | 3.0+ | -| [Vert.x HttpClient](https://vertx.io/docs/apidocs/io/vertx/core/http/HttpClient.html) | 3.0+ | -| [Vert.x Kafka Client](https://vertx.io/docs/vertx-kafka-client/java/) | 3.6+ | -| [Vert.x RxJava2](https://vertx.io/docs/vertx-rx/java2/) | 3.5+ | -| [Vibur DBCP](https://www.vibur.org/) | 11.0+ | +| Library/Framework | Versions | +|-----------------------------------------------------------------------------------------------------------------------------------|-------------------------------| +| [Akka Actors](https://doc.akka.io/docs/akka/current/typed/index.html) | 2.5+ | +| [Akka HTTP](https://doc.akka.io/docs/akka-http/current/index.html) | 10.0+ | +| [Apache Axis2](https://axis.apache.org/axis2/java/core/) | 1.6+ | +| [Apache Camel](https://camel.apache.org/) | 2.20+ (not including 3.x yet) | +| [Apache CXF JAX-RS](https://cxf.apache.org/) | 3.2+ | +| [Apache CXF JAX-RS Client](https://cxf.apache.org/) | 3.0+ | +| [Apache CXF JAX-WS](https://cxf.apache.org/) | 3.0+ | +| [Apache Dubbo](https://github.com/apache/dubbo/) | 2.7+ | +| [Apache HttpAsyncClient](https://hc.apache.org/index.html) | 4.1+ | +| [Apache HttpClient](https://hc.apache.org/index.html) | 2.0+ | +| [Apache Kafka Producer/Consumer API](https://kafka.apache.org/documentation/#producerapi) | 0.11+ | +| [Apache Kafka Streams API](https://kafka.apache.org/documentation/streams/) | 0.11+ | +| [Apache MyFaces](https://myfaces.apache.org/) | 1.2+ (not including 3.x yet) | +| [Apache RocketMQ](https://rocketmq.apache.org/) | 4.8+ | +| [Apache Struts 2](https://github.com/apache/struts) | 2.3+ | +| [Apache Tapestry](https://tapestry.apache.org/) | 5.4+ | +| [Apache Wicket](https://wicket.apache.org/) | 8.0+ | +| [Armeria](https://armeria.dev) | 1.3+ | +| [AsyncHttpClient](https://github.com/AsyncHttpClient/async-http-client) | 1.9+ | +| [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/java-handler.html) | 1.0+ | +| [AWS SDK](https://aws.amazon.com/sdk-for-java/) | 1.11.x and 2.2.0+ | +| [Azure Core](https://docs.microsoft.com/en-us/java/api/overview/azure/core-readme) | 1.14+ | +| [Cassandra Driver](https://github.com/datastax/java-driver) | 3.0+ | +| [Couchbase Client](https://github.com/couchbase/couchbase-java-client) | 2.0+ and 3.1+ | +| [Dropwizard Metrics](https://metrics.dropwizard.io/) | 4.0+ (disabled by default) | +| [Dropwizard Views](https://www.dropwizard.io/en/latest/manual/views.html) | 0.7+ | +| [Eclipse Grizzly](https://javaee.github.io/grizzly/httpserverframework.html) | 2.0+ (disabled by default) | +| [Eclipse Jersey](https://eclipse-ee4j.github.io/jersey/) | 2.0+ (not including 3.x yet) | +| [Eclipse Jetty HTTP Client](https://www.eclipse.org/jetty/javadoc/jetty-9/org/eclipse/jetty/client/HttpClient.html) | 9.2+ (not including 10+ yet) | +| [Eclipse Metro](https://projects.eclipse.org/projects/ee4j.metro) | 2.2+ (not including 3.x yet) | +| [Eclipse Mojarra](https://projects.eclipse.org/projects/ee4j.mojarra) | 1.2+ (not including 3.x yet) | +| [Elasticsearch API](https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/index.html) | 5.0+ | +| [Elasticsearch REST Client](https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html) | 5.0+ | +| [Finatra](https://github.com/twitter/finatra) | 2.9+ | +| [Geode Client](https://geode.apache.org/) | 1.4+ | +| [Google HTTP Client](https://github.com/googleapis/google-http-java-client) | 1.19+ | +| [Grails](https://grails.org/) | 3.0+ | +| [GraphQL Java](https://www.graphql-java.com/) | 12.0+ | +| [gRPC](https://github.com/grpc/grpc-java) | 1.6+ | +| [Guava ListenableFuture](https://guava.dev/releases/snapshot/api/docs/com/google/common/util/concurrent/ListenableFuture.html) | 10.0+ | +| [GWT](http://www.gwtproject.org/) | 2.0+ | +| [Hibernate](https://github.com/hibernate/hibernate-orm) | 3.3+ | +| [HikariCP](https://github.com/brettwooldridge/HikariCP) | 3.0+ | +| [HttpURLConnection](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/net/HttpURLConnection.html) | Java 8+ | +| [Hystrix](https://github.com/Netflix/Hystrix) | 1.4+ | +| [Java Executors](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html) | Java 8+ | +| [Java Http Client](https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/package-summary.html) | Java 11+ | +| [java.util.logging](https://docs.oracle.com/javase/8/docs/api/java/util/logging/package-summary.html) | Java 8+ | +| [JAX-RS](https://javaee.github.io/javaee-spec/javadocs/javax/ws/rs/package-summary.html) | 0.5+ | +| [JAX-RS Client](https://javaee.github.io/javaee-spec/javadocs/javax/ws/rs/client/package-summary.html) | 1.1+ | +| [JAX-WS](https://jakarta.ee/specifications/xml-web-services/2.3/apidocs/javax/xml/ws/package-summary.html) | 2.0+ (not including 3.x yet) | +| [JDBC](https://docs.oracle.com/javase/8/docs/api/java/sql/package-summary.html) | Java 8+ | +| [Jedis](https://github.com/xetorthio/jedis) | 1.4+ | +| [JMS](https://javaee.github.io/javaee-spec/javadocs/javax/jms/package-summary.html) | 1.1+ | +| [JSP](https://javaee.github.io/javaee-spec/javadocs/javax/servlet/jsp/package-summary.html) | 2.3+ | +| [Kotlin Coroutines](https://kotlinlang.org/docs/coroutines-overview.html) | 1.0+ | +| [Kubernetes Client](https://github.com/kubernetes-client/java) | 7.0+ | +| [Lettuce](https://github.com/lettuce-io/lettuce-core) | 4.0+ | +| [Log4j 1](https://logging.apache.org/log4j/1.2/) | 1.2+ | +| [Log4j 2](https://logging.apache.org/log4j/2.x/) | 2.11+ | +| [Logback](http://logback.qos.ch/) | 1.0+ | +| [Micrometer](https://micrometer.io/) | 1.5+ | +| [MongoDB Driver](https://mongodb.github.io/mongo-java-driver/) | 3.1+ | +| [Netty](https://github.com/netty/netty) | 3.8+ | +| [OkHttp](https://github.com/square/okhttp/) | 2.2+ | +| [Oracle UCP](https://docs.oracle.com/database/121/JJUCP/) | 11.2+ | +| [OSHI](https://github.com/oshi/oshi/) | 5.3.1+ | +| [Play](https://github.com/playframework/playframework) | 2.4+ | +| [Play WS](https://github.com/playframework/play-ws) | 1.0+ | +| [Quartz](https://www.quartz-scheduler.org/) | 2.0+ | +| [RabbitMQ Client](https://github.com/rabbitmq/rabbitmq-java-client) | 2.7+ | +| [Ratpack](https://github.com/ratpack/ratpack) | 1.4+ | +| [Reactor](https://github.com/reactor/reactor-core) | 3.1+ | +| [Reactor Netty](https://github.com/reactor/reactor-netty) | 0.9+ | +| [Rediscala](https://github.com/etaty/rediscala) | 1.8+ | +| [Redisson](https://github.com/redisson/redisson) | 3.0+ | +| [RESTEasy](https://resteasy.github.io/) | 3.0+ | +| [Restlet](https://restlet.talend.com/) | 1.0+ | +| [RMI](https://docs.oracle.com/en/java/javase/11/docs/api/java.rmi/java/rmi/package-summary.html) | Java 8+ | +| [RxJava](https://github.com/ReactiveX/RxJava) | 1.0+ | +| [Scala ForkJoinPool](https://www.scala-lang.org/api/2.12.0/scala/concurrent/forkjoin/package$$ForkJoinPool$.html) | 2.8+ | +| [Servlet](https://javaee.github.io/javaee-spec/javadocs/javax/servlet/package-summary.html) | 2.2+ | +| [Spark Web Framework](https://github.com/perwendel/spark) | 2.3+ | +| [Spring Batch](https://spring.io/projects/spring-batch) | 3.0+ | +| [Spring Data](https://spring.io/projects/spring-data) | 1.8+ | +| [Spring Integration](https://spring.io/projects/spring-integration) | 4.1+ | +| [Spring Kafka](https://spring.io/projects/spring-kafka) | 2.7+ | +| [Spring RabbitMQ](https://spring.io/projects/spring-amqp) | 1.0+ | +| [Spring Scheduling](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/package-summary.html) | 3.1+ | +| [Spring Web MVC](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/package-summary.html) | 3.1+ | +| [Spring Web Services](https://spring.io/projects/spring-ws) | 2.0+ | +| [Spring WebFlux](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/package-summary.html) | 5.0+ | +| [Spymemcached](https://github.com/couchbase/spymemcached) | 2.12+ | +| [Tomcat JDBC Pool](https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html) | 8.5.0+ | +| [Twilio](https://github.com/twilio/twilio-java) | 6.6+ (not including 8.x yet) | +| [Undertow](https://undertow.io/) | 1.4+ | +| [Vaadin](https://vaadin.com/) | 14.2+ | +| [Vert.x Web](https://vertx.io/docs/vertx-web/java/) | 3.0+ | +| [Vert.x HttpClient](https://vertx.io/docs/apidocs/io/vertx/core/http/HttpClient.html) | 3.0+ | +| [Vert.x Kafka Client](https://vertx.io/docs/vertx-kafka-client/java/) | 3.6+ | +| [Vert.x RxJava2](https://vertx.io/docs/vertx-rx/java2/) | 3.5+ | +| [Vibur DBCP](https://www.vibur.org/) | 11.0+ | ## Application Servers @@ -152,6 +153,8 @@ Some instrumentations can produce too many spans and make traces very noisy. For this reason, the following instrumentations are disabled by default: - `jdbc-datasource` which creates spans whenever the `java.sql.DataSource#getConnection` method is called. +- `dropwizard-metrics` which might create a very low quality metrics data, because of lack of label/attribute support + in the Dropwizard metrics API. To enable them, add the `otel.instrumentation..enabled` system property: `-Dotel.instrumentation.jdbc-datasource.enabled=true` diff --git a/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/build.gradle.kts b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/build.gradle.kts new file mode 100644 index 000000000000..261d7550154c --- /dev/null +++ b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/build.gradle.kts @@ -0,0 +1,20 @@ +plugins { + id("otel.javaagent-instrumentation") +} + +muzzle { + pass { + group.set("io.dropwizard.metrics") + module.set("metrics-core") + versions.set("[4.0.0,)") + assertInverse.set(true) + } +} + +dependencies { + library("io.dropwizard.metrics:metrics-core:4.0.0") +} + +tasks.withType().configureEach { + jvmArgs("-Dotel.instrumentation.dropwizard-metrics.enabled=true") +} diff --git a/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/CounterInstrumentation.java b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/CounterInstrumentation.java new file mode 100644 index 000000000000..3db26d07e420 --- /dev/null +++ b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/CounterInstrumentation.java @@ -0,0 +1,51 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.dropwizardmetrics; + +import static io.opentelemetry.javaagent.instrumentation.dropwizardmetrics.DropwizardSingletons.metrics; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +import com.codahale.metrics.Counter; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class CounterInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return named("com.codahale.metrics.Counter"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + named("inc").and(takesArguments(long.class)), this.getClass().getName() + "$IncAdvice"); + transformer.applyAdviceToMethod( + named("dec").and(takesArguments(long.class)), this.getClass().getName() + "$DecAdvice"); + } + + @SuppressWarnings("unused") + public static class IncAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter(@Advice.This Counter counter, @Advice.Argument(0) long increment) { + metrics().counterAdd(counter, increment); + } + } + + @SuppressWarnings("unused") + public static class DecAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter(@Advice.This Counter counter, @Advice.Argument(0) long decrement) { + metrics().counterAdd(counter, -decrement); + } + } +} diff --git a/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardMetricsAdapter.java b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardMetricsAdapter.java new file mode 100644 index 000000000000..61c01ef1c38f --- /dev/null +++ b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardMetricsAdapter.java @@ -0,0 +1,174 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.dropwizardmetrics; + +import com.codahale.metrics.Counter; +import com.codahale.metrics.Gauge; +import com.codahale.metrics.Histogram; +import com.codahale.metrics.Meter; +import com.codahale.metrics.MetricRegistryListener; +import com.codahale.metrics.Timer; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.metrics.DoubleHistogram; +import io.opentelemetry.api.metrics.LongCounter; +import io.opentelemetry.api.metrics.LongHistogram; +import io.opentelemetry.api.metrics.LongUpDownCounter; +import io.opentelemetry.api.metrics.ObservableDoubleGauge; +import io.opentelemetry.instrumentation.api.util.VirtualField; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +public final class DropwizardMetricsAdapter implements MetricRegistryListener { + + private static final double NANOS_PER_MS = TimeUnit.MILLISECONDS.toNanos(1); + + private static final VirtualField otelUpDownCounterField = + VirtualField.find(Counter.class, LongUpDownCounter.class); + private static final VirtualField otelHistogramField = + VirtualField.find(Histogram.class, LongHistogram.class); + private static final VirtualField otelCounterField = + VirtualField.find(Meter.class, LongCounter.class); + private static final VirtualField otelDoubleHistogramField = + VirtualField.find(Timer.class, DoubleHistogram.class); + + private final io.opentelemetry.api.metrics.Meter otelMeter; + + private final Map otelDoubleHistograms = new ConcurrentHashMap<>(); + private final Map otelCounters = new ConcurrentHashMap<>(); + private final Map otelHistograms = new ConcurrentHashMap<>(); + private final Map otelUpDownCounters = new ConcurrentHashMap<>(); + private final Map otelGauges = new ConcurrentHashMap<>(); + + private final Map dropwizardCounters = new ConcurrentHashMap<>(); + private final Map dropwizardHistograms = new ConcurrentHashMap<>(); + private final Map dropwizardMeters = new ConcurrentHashMap<>(); + private final Map dropwizardTimers = new ConcurrentHashMap<>(); + + public DropwizardMetricsAdapter(OpenTelemetry openTelemetry) { + this.otelMeter = openTelemetry.getMeter("io.opentelemetry.dropwizard-metrics-4.0"); + } + + @Override + public void onGaugeAdded(String name, Gauge gauge) { + ObservableDoubleGauge otelGauge = + otelMeter + .gaugeBuilder(name) + .buildWithCallback( + measurement -> { + Object val = gauge.getValue(); + if (val instanceof Number) { + measurement.record(((Number) val).doubleValue()); + } + }); + otelGauges.put(name, otelGauge); + } + + @Override + public void onGaugeRemoved(String name) { + ObservableDoubleGauge otelGauge = otelGauges.remove(name); + if (otelGauge != null) { + otelGauge.close(); + } + } + + @Override + public void onCounterAdded(String name, Counter dropwizardCounter) { + dropwizardCounters.put(name, dropwizardCounter); + LongUpDownCounter otelCounter = + otelUpDownCounters.computeIfAbsent(name, n -> otelMeter.upDownCounterBuilder(n).build()); + otelUpDownCounterField.set(dropwizardCounter, otelCounter); + } + + @Override + public void onCounterRemoved(String name) { + Counter dropwizardCounter = dropwizardCounters.remove(name); + otelUpDownCounters.remove(name); + if (dropwizardCounter != null) { + otelUpDownCounterField.set(dropwizardCounter, null); + } + } + + public void counterAdd(Counter dropwizardCounter, long increment) { + LongUpDownCounter otelCounter = otelUpDownCounterField.get(dropwizardCounter); + if (otelCounter != null) { + otelCounter.add(increment); + } + } + + @Override + public void onHistogramAdded(String name, Histogram dropwizardHistogram) { + dropwizardHistograms.put(name, dropwizardHistogram); + LongHistogram otelHistogram = + otelHistograms.computeIfAbsent(name, n -> otelMeter.histogramBuilder(n).ofLongs().build()); + otelHistogramField.set(dropwizardHistogram, otelHistogram); + } + + @Override + public void onHistogramRemoved(String name) { + Histogram dropwizardHistogram = dropwizardHistograms.remove(name); + otelHistograms.remove(name); + if (dropwizardHistogram != null) { + otelHistogramField.set(dropwizardHistogram, null); + } + } + + public void histogramUpdate(Histogram dropwizardHistogram, long value) { + LongHistogram otelHistogram = otelHistogramField.get(dropwizardHistogram); + if (otelHistogram != null) { + otelHistogram.record(value); + } + } + + @Override + public void onMeterAdded(String name, Meter dropwizardMeter) { + dropwizardMeters.put(name, dropwizardMeter); + LongCounter otelCounter = + otelCounters.computeIfAbsent(name, n -> otelMeter.counterBuilder(n).build()); + otelCounterField.set(dropwizardMeter, otelCounter); + } + + @Override + public void onMeterRemoved(String name) { + Meter dropwizardMeter = dropwizardMeters.remove(name); + otelCounters.remove(name); + if (dropwizardMeter != null) { + otelCounterField.set(dropwizardMeter, null); + } + } + + public void meterMark(Meter dropwizardMeter, long increment) { + LongCounter otelCounter = otelCounterField.get(dropwizardMeter); + if (otelCounter != null) { + otelCounter.add(increment); + } + } + + @Override + public void onTimerAdded(String name, Timer dropwizardTimer) { + dropwizardTimers.put(name, dropwizardTimer); + DoubleHistogram otelHistogram = + otelDoubleHistograms.computeIfAbsent( + name, n -> otelMeter.histogramBuilder(n).setUnit("ms").build()); + otelDoubleHistogramField.set(dropwizardTimer, otelHistogram); + } + + @Override + public void onTimerRemoved(String name) { + Timer dropwizardTimer = dropwizardTimers.remove(name); + otelDoubleHistograms.remove(name); + if (dropwizardTimer != null) { + otelDoubleHistogramField.set(dropwizardTimer, null); + } + } + + public void timerUpdate(Timer dropwizardTimer, long nanos) { + DoubleHistogram otelHistogram = otelDoubleHistogramField.get(dropwizardTimer); + if (otelHistogram != null) { + otelHistogram.record(nanos / NANOS_PER_MS); + } + } +} diff --git a/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardMetricsInstrumentationModule.java b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardMetricsInstrumentationModule.java new file mode 100644 index 000000000000..72df1c263d7f --- /dev/null +++ b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardMetricsInstrumentationModule.java @@ -0,0 +1,48 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.dropwizardmetrics; + +import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; +import static java.util.Arrays.asList; +import static net.bytebuddy.matcher.ElementMatchers.not; + +import com.google.auto.service.AutoService; +import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import java.util.List; +import net.bytebuddy.matcher.ElementMatcher; + +@AutoService(InstrumentationModule.class) +public class DropwizardMetricsInstrumentationModule extends InstrumentationModule { + + public DropwizardMetricsInstrumentationModule() { + super("dropwizard-metrics", "dropwizard-metrics-4.0"); + } + + @Override + public ElementMatcher.Junction classLoaderMatcher() { + // removed in 4.0 + return not(hasClassesNamed("com.codahale.metrics.LongAdder")); + } + + @Override + public boolean defaultEnabled() { + // the Dropwizard metrics API does not have a concept of metric labels/tags/attributes, thus the + // data produced by this integration might be of very low quality, depending on how the API is + // used in the instrumented application + return false; + } + + @Override + public List typeInstrumentations() { + return asList( + new MetricRegistryInstrumentation(), + new CounterInstrumentation(), + new HistogramInstrumentation(), + new MeterInstrumentation(), + new TimerInstrumentation()); + } +} diff --git a/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardSingletons.java b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardSingletons.java new file mode 100644 index 000000000000..e8ea2ce5dd32 --- /dev/null +++ b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardSingletons.java @@ -0,0 +1,20 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.dropwizardmetrics; + +import io.opentelemetry.api.GlobalOpenTelemetry; + +public final class DropwizardSingletons { + + private static final DropwizardMetricsAdapter METRICS = + new DropwizardMetricsAdapter(GlobalOpenTelemetry.get()); + + public static DropwizardMetricsAdapter metrics() { + return METRICS; + } + + private DropwizardSingletons() {} +} diff --git a/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/HistogramInstrumentation.java b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/HistogramInstrumentation.java new file mode 100644 index 000000000000..6786a5cf41bd --- /dev/null +++ b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/HistogramInstrumentation.java @@ -0,0 +1,41 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.dropwizardmetrics; + +import static io.opentelemetry.javaagent.instrumentation.dropwizardmetrics.DropwizardSingletons.metrics; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +import com.codahale.metrics.Histogram; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class HistogramInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return named("com.codahale.metrics.Histogram"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + named("update").and(takesArguments(long.class)), + this.getClass().getName() + "$UpdateAdvice"); + } + + @SuppressWarnings("unused") + public static class UpdateAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter(@Advice.This Histogram histogram, @Advice.Argument(0) long value) { + metrics().histogramUpdate(histogram, value); + } + } +} diff --git a/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/MeterInstrumentation.java b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/MeterInstrumentation.java new file mode 100644 index 000000000000..2fbd48948644 --- /dev/null +++ b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/MeterInstrumentation.java @@ -0,0 +1,40 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.dropwizardmetrics; + +import static io.opentelemetry.javaagent.instrumentation.dropwizardmetrics.DropwizardSingletons.metrics; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +import com.codahale.metrics.Meter; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class MeterInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return named("com.codahale.metrics.Meter"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + named("mark").and(takesArguments(long.class)), this.getClass().getName() + "$MarkAdvice"); + } + + @SuppressWarnings("unused") + public static class MarkAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter(@Advice.This Meter meter, @Advice.Argument(0) long increment) { + metrics().meterMark(meter, increment); + } + } +} diff --git a/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/MetricRegistryInstrumentation.java b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/MetricRegistryInstrumentation.java new file mode 100644 index 000000000000..40decdfa1cb9 --- /dev/null +++ b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/MetricRegistryInstrumentation.java @@ -0,0 +1,40 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.dropwizardmetrics; + +import static io.opentelemetry.javaagent.instrumentation.dropwizardmetrics.DropwizardSingletons.metrics; +import static net.bytebuddy.matcher.ElementMatchers.isDefaultConstructor; +import static net.bytebuddy.matcher.ElementMatchers.named; + +import com.codahale.metrics.MetricRegistry; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class MetricRegistryInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return named("com.codahale.metrics.MetricRegistry"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + isDefaultConstructor(), this.getClass().getName() + "$ConstructorAdvice"); + } + + @SuppressWarnings("unused") + public static class ConstructorAdvice { + + @Advice.OnMethodExit(suppress = Throwable.class) + public static void onExit(@Advice.This MetricRegistry metricRegistry) { + metricRegistry.addListener(metrics()); + } + } +} diff --git a/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/TimerInstrumentation.java b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/TimerInstrumentation.java new file mode 100644 index 000000000000..e7762069874c --- /dev/null +++ b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/TimerInstrumentation.java @@ -0,0 +1,41 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.dropwizardmetrics; + +import static io.opentelemetry.javaagent.instrumentation.dropwizardmetrics.DropwizardSingletons.metrics; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; + +import com.codahale.metrics.Timer; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +public class TimerInstrumentation implements TypeInstrumentation { + + @Override + public ElementMatcher typeMatcher() { + return named("com.codahale.metrics.Timer"); + } + + @Override + public void transform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + named("update").and(takesArguments(long.class)), + this.getClass().getName() + "$UpdateAdvice"); + } + + @SuppressWarnings("unused") + public static class UpdateAdvice { + + @Advice.OnMethodEnter(suppress = Throwable.class) + public static void onEnter(@Advice.This Timer timer, @Advice.Argument(0) long nanos) { + metrics().timerUpdate(timer, nanos); + } + } +} diff --git a/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardMetricsTest.java b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardMetricsTest.java new file mode 100644 index 000000000000..193a9baf7848 --- /dev/null +++ b/instrumentation/dropwizard/dropwizard-metrics-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/dropwizardmetrics/DropwizardMetricsTest.java @@ -0,0 +1,199 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.dropwizardmetrics; + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; + +import com.codahale.metrics.Counter; +import com.codahale.metrics.Histogram; +import com.codahale.metrics.Meter; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.Timer; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; +import org.assertj.core.api.AbstractIterableAssert; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +public class DropwizardMetricsTest { + + static final String INSTRUMENTATION_NAME = "io.opentelemetry.dropwizard-metrics-4.0"; + + @RegisterExtension + static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + @Test + void gauge() throws InterruptedException { + // given + MetricRegistry metricRegistry = new MetricRegistry(); + + AtomicLong value = new AtomicLong(42); + + // when + metricRegistry.gauge("test.gauge", () -> value::get); + + // then + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "test.gauge", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasDoubleGaugeSatisfying( + g -> g.hasPointsSatisfying(point -> point.hasValue(42))))); + + // when + metricRegistry.remove("test.gauge"); + Thread.sleep(100); // give time for any inflight metric export to be received + testing.clearData(); + + // then + Thread.sleep(100); // interval of the test metrics exporter + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, "test.gauge", AbstractIterableAssert::isEmpty); + } + + @Test + void counter() throws InterruptedException { + // given + MetricRegistry metricRegistry = new MetricRegistry(); + + // when + Counter counter = metricRegistry.counter("test.counter"); + counter.inc(); + counter.inc(11); + counter.dec(5); + + // then + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "test.counter", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasLongSumSatisfying( + sum -> + sum.isNotMonotonic() + .hasPointsSatisfying(point -> point.hasValue(7))))); + testing.clearData(); + + // when + metricRegistry.remove("test.counter"); + counter.inc(123); + + // then + Thread.sleep(100); // interval of the test metrics exporter + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, "test.counter", AbstractIterableAssert::isEmpty); + } + + @Test + void histogram() throws InterruptedException { + // given + MetricRegistry metricRegistry = new MetricRegistry(); + + // when + Histogram histogram = metricRegistry.histogram("test.histogram"); + histogram.update(12); + histogram.update(30); + + // then + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "test.histogram", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasHistogramSatisfying( + histogramMetric -> + histogramMetric.hasPointsSatisfying( + point -> point.hasSum(42).hasCount(2))))); + testing.clearData(); + + // when + metricRegistry.remove("test.histogram"); + histogram.update(100); + + // then + Thread.sleep(100); // interval of the test metrics exporter + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, "test.histogram", AbstractIterableAssert::isEmpty); + } + + @Test + void meter() throws InterruptedException { + // given + MetricRegistry metricRegistry = new MetricRegistry(); + + // when + Meter meter = metricRegistry.meter("test.meter"); + meter.mark(); + meter.mark(11); + + // then + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "test.meter", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasLongSumSatisfying( + sum -> + sum.isMonotonic() + .hasPointsSatisfying(point -> point.hasValue(12))))); + testing.clearData(); + + // when + metricRegistry.remove("test.meter"); + meter.mark(); + + // then + Thread.sleep(100); // interval of the test metrics exporter + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, "test.meter", AbstractIterableAssert::isEmpty); + } + + @Test + void timer() throws InterruptedException { + // given + MetricRegistry metricRegistry = new MetricRegistry(); + + // when + Timer timer = metricRegistry.timer("test.timer"); + timer.update(1, TimeUnit.MILLISECONDS); + timer.update(234_000, TimeUnit.NANOSECONDS); + + // then + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, + "test.timer", + metrics -> + metrics.anySatisfy( + metric -> + assertThat(metric) + .hasUnit("ms") + .hasHistogramSatisfying( + histogram -> + histogram.hasPointsSatisfying( + point -> point.hasSum(1.234).hasCount(2))))); + testing.clearData(); + + // when + metricRegistry.remove("test.timer"); + timer.update(12, TimeUnit.SECONDS); + + // then + Thread.sleep(100); // interval of the test metrics exporter + testing.waitAndAssertMetrics( + INSTRUMENTATION_NAME, "test.timer", AbstractIterableAssert::isEmpty); + } +} diff --git a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/ignore/AdditionalLibraryIgnoredTypesConfigurer.java b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/ignore/AdditionalLibraryIgnoredTypesConfigurer.java index 451ae41cc2fe..0e5f662b873b 100644 --- a/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/ignore/AdditionalLibraryIgnoredTypesConfigurer.java +++ b/javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/ignore/AdditionalLibraryIgnoredTypesConfigurer.java @@ -213,11 +213,6 @@ public void configure(IgnoredTypesBuilder builder) { .allowClass("ch.qos.logback.classic.spi.LoggingEvent") .allowClass("ch.qos.logback.classic.spi.LoggingEventVO"); - builder - .ignoreClass("com.codahale.metrics.") - // We instrument servlets - .allowClass("com.codahale.metrics.servlets."); - builder .ignoreClass("com.couchbase.client.deps.") // Couchbase library includes some packaged dependencies, unfortunately some of them are diff --git a/settings.gradle.kts b/settings.gradle.kts index b859cc787dc3..830b458b4c1e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -204,6 +204,7 @@ include(":instrumentation:couchbase:couchbase-3.1.6:tracing-opentelemetry-shaded include(":instrumentation:couchbase:couchbase-3.2:javaagent") include(":instrumentation:couchbase:couchbase-3.2:tracing-opentelemetry-shaded") include(":instrumentation:couchbase:couchbase-common:testing") +include(":instrumentation:dropwizard:dropwizard-metrics-4.0:javaagent") include(":instrumentation:dropwizard:dropwizard-views-0.7:javaagent") include(":instrumentation:dropwizard:dropwizard-testing") include(":instrumentation:elasticsearch:elasticsearch-rest-common:javaagent")