diff --git a/docs/instrumentation-list.yaml b/docs/instrumentation-list.yaml index 21da6cbb6646..f711f11a6f5a 100644 --- a/docs/instrumentation-list.yaml +++ b/docs/instrumentation-list.yaml @@ -54,46 +54,88 @@ libraries: - com.alibaba:druid:(,) library: - com.alibaba:druid:1.0.0 - metrics: - - name: db.client.connections.usage - description: The number of connections that are currently in state described - by the state attribute. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: state - type: STRING - - name: db.client.connections.pending_requests - description: The number of pending requests for an open connection, cumulative - for the entire pool. - type: LONG_SUM - unit: requests - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.max - description: The maximum number of open connections allowed. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.idle.min - description: The minimum number of idle open connections allowed. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.idle.max - description: The maximum number of idle open connections allowed. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING + telemetry: + - when: default + metrics: + - name: db.client.connections.idle.max + description: The maximum number of idle open connections allowed. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.idle.min + description: The minimum number of idle open connections allowed. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.max + description: The maximum number of open connections allowed. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.pending_requests + description: The number of pending requests for an open connection, cumulative + for the entire pool. + type: LONG_SUM + unit: requests + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.usage + description: The number of connections that are currently in state described + by the state attribute. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: state + type: STRING + - when: otel.semconv-stability.opt-in=database + metrics: + - name: db.client.connection.count + description: The number of connections that are currently in state described + by the state attribute. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.state + type: STRING + - name: db.client.connection.idle.max + description: The maximum number of idle open connections allowed. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.idle.min + description: The minimum number of idle open connections allowed. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.max + description: The maximum number of open connections allowed. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.pending_requests + description: The number of current pending requests for an open connection. + type: LONG_SUM + unit: request + attributes: + - name: db.client.connection.pool.name + type: STRING apache: - name: apache-shenyu-2.4 source_path: instrumentation/apache-shenyu-2.4 @@ -167,22 +209,24 @@ libraries: target_versions: javaagent: - org.apache.httpcomponents.client5:httpclient5:[5.0,) - metrics: - - name: http.client.request.duration - description: Duration of HTTP client requests. - type: HISTOGRAM - unit: s - attributes: - - name: http.request.method - type: STRING - - name: http.response.status_code - type: LONG - - name: network.protocol.version - type: STRING - - name: server.address - type: STRING - - name: server.port - type: LONG + telemetry: + - when: default + metrics: + - name: http.client.request.duration + description: Duration of HTTP client requests. + type: HISTOGRAM + unit: s + attributes: + - name: http.request.method + type: STRING + - name: http.response.status_code + type: LONG + - name: network.protocol.version + type: STRING + - name: server.address + type: STRING + - name: server.port + type: LONG - name: apache-dbcp-2.0 source_path: instrumentation/apache-dbcp-2.0 scope: @@ -192,38 +236,73 @@ libraries: - org.apache.commons:commons-dbcp2:[2,) library: - org.apache.commons:commons-dbcp2:2.0 - metrics: - - name: db.client.connections.usage - description: The number of connections that are currently in state described - by the state attribute. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: state - type: STRING - - name: db.client.connections.max - description: The maximum number of open connections allowed. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.idle.min - description: The minimum number of idle open connections allowed. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.idle.max - description: The maximum number of idle open connections allowed. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING + telemetry: + - when: default + metrics: + - name: db.client.connections.idle.max + description: The maximum number of idle open connections allowed. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.idle.min + description: The minimum number of idle open connections allowed. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.max + description: The maximum number of open connections allowed. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.usage + description: The number of connections that are currently in state described + by the state attribute. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: state + type: STRING + - when: otel.semconv-stability.opt-in=database + metrics: + - name: db.client.connection.count + description: The number of connections that are currently in state described + by the state attribute. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.state + type: STRING + - name: db.client.connection.idle.max + description: The maximum number of idle open connections allowed. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.idle.min + description: The minimum number of idle open connections allowed. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.max + description: The maximum number of open connections allowed. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING armeria: - name: armeria-1.3 source_path: instrumentation/armeria/armeria-1.3 @@ -405,25 +484,46 @@ libraries: - com.mchange:c3p0:(,) library: - com.mchange:c3p0:0.9.2 - metrics: - - name: db.client.connections.usage - description: The number of connections that are currently in state described - by the state attribute. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: state - type: STRING - - name: db.client.connections.pending_requests - description: The number of pending requests for an open connection, cumulative - for the entire pool. - type: LONG_SUM - unit: requests - attributes: - - name: pool.name - type: STRING + telemetry: + - when: default + metrics: + - name: db.client.connections.pending_requests + description: The number of pending requests for an open connection, cumulative + for the entire pool. + type: LONG_SUM + unit: requests + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.usage + description: The number of connections that are currently in state described + by the state attribute. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: state + type: STRING + - when: otel.semconv-stability.opt-in=database + metrics: + - name: db.client.connection.count + description: The number of connections that are currently in state described + by the state attribute. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.state + type: STRING + - name: db.client.connection.pending_requests + description: The number of current pending requests for an open connection. + type: LONG_SUM + unit: request + attributes: + - name: db.client.connection.pool.name + type: STRING camel: - name: camel-2.20 description: | @@ -499,6 +599,24 @@ libraries: description: Enables statement sanitization for database queries. type: boolean default: true + telemetry: + - when: otel.semconv-stability.opt-in=database + metrics: + - name: db.client.operation.duration + description: Duration of database client operations. + type: HISTOGRAM + unit: s + attributes: + - name: db.namespace + type: STRING + - name: db.operation.name + type: STRING + - name: db.system.name + type: STRING + - name: server.address + type: STRING + - name: server.port + type: LONG couchbase: - name: couchbase-3.1.6 description: | @@ -808,69 +926,134 @@ libraries: - com.zaxxer:HikariCP:[3.0.0,) library: - com.zaxxer:HikariCP:3.0.0 - metrics: - - name: db.client.connections.wait_time - description: The time it took to obtain an open connection from the pool. - type: HISTOGRAM - unit: ms - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.usage - description: The number of connections that are currently in state described - by the state attribute. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: state - type: STRING - - name: db.client.connections.pending_requests - description: The number of pending requests for an open connection, cumulative - for the entire pool. - type: LONG_SUM - unit: requests - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.timeouts - description: The number of connection timeouts that have occurred trying to - obtain a connection from the pool. - type: LONG_SUM - unit: timeouts - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.max - description: The maximum number of open connections allowed. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.create_time - description: The time it took to create a new connection. - type: HISTOGRAM - unit: ms - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.idle.min - description: The minimum number of idle open connections allowed. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.use_time - description: The time between borrowing a connection and returning it to the - pool. - type: HISTOGRAM - unit: ms - attributes: - - name: pool.name - type: STRING + telemetry: + - when: default + metrics: + - name: db.client.connections.create_time + description: The time it took to create a new connection. + type: HISTOGRAM + unit: ms + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.idle.min + description: The minimum number of idle open connections allowed. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.max + description: The maximum number of open connections allowed. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.pending_requests + description: The number of pending requests for an open connection, cumulative + for the entire pool. + type: LONG_SUM + unit: requests + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.timeouts + description: The number of connection timeouts that have occurred trying to + obtain a connection from the pool. + type: LONG_SUM + unit: timeouts + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.usage + description: The number of connections that are currently in state described + by the state attribute. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: state + type: STRING + - name: db.client.connections.use_time + description: The time between borrowing a connection and returning it to the + pool. + type: HISTOGRAM + unit: ms + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.wait_time + description: The time it took to obtain an open connection from the pool. + type: HISTOGRAM + unit: ms + attributes: + - name: pool.name + type: STRING + - when: otel.semconv-stability.opt-in=database + metrics: + - name: db.client.connection.count + description: The number of connections that are currently in state described + by the state attribute. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.state + type: STRING + - name: db.client.connection.create_time + description: The time it took to create a new connection. + type: HISTOGRAM + unit: s + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.idle.min + description: The minimum number of idle open connections allowed. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.max + description: The maximum number of open connections allowed. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.pending_requests + description: The number of current pending requests for an open connection. + type: LONG_SUM + unit: request + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.timeouts + description: The number of connection timeouts that have occurred trying to + obtain a connection from the pool. + type: LONG_SUM + unit: timeout + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.use_time + description: The time between borrowing a connection and returning it to the + pool. + type: HISTOGRAM + unit: s + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.wait_time + description: The time it took to obtain an open connection from the pool. + type: HISTOGRAM + unit: s + attributes: + - name: db.client.connection.pool.name + type: STRING http: - name: http-url-connection source_path: instrumentation/http-url-connection @@ -1530,32 +1713,60 @@ libraries: library: - com.oracle.database.jdbc:ucp:11.2.0.4 - com.oracle.database.jdbc:ojdbc8:12.2.0.1 - metrics: - - name: db.client.connections.usage - description: The number of connections that are currently in state described - by the state attribute. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: state - type: STRING - - name: db.client.connections.pending_requests - description: The number of pending requests for an open connection, cumulative - for the entire pool. - type: LONG_SUM - unit: requests - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.max - description: The maximum number of open connections allowed. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING + telemetry: + - when: default + metrics: + - name: db.client.connections.max + description: The maximum number of open connections allowed. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.pending_requests + description: The number of pending requests for an open connection, cumulative + for the entire pool. + type: LONG_SUM + unit: requests + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.usage + description: The number of connections that are currently in state described + by the state attribute. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: state + type: STRING + - when: otel.semconv-stability.opt-in=database + metrics: + - name: db.client.connection.count + description: The number of connections that are currently in state described + by the state attribute. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.state + type: STRING + - name: db.client.connection.max + description: The maximum number of open connections allowed. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.pending_requests + description: The number of current pending requests for an open connection. + type: LONG_SUM + unit: request + attributes: + - name: db.client.connection.pool.name + type: STRING oshi: - name: oshi description: When the OSHI library is detected on the classpath, this instrumentation @@ -1571,83 +1782,146 @@ libraries: - com.github.oshi:oshi-core:5.3.1 configurations: - name: otel.instrumentation.oshi.experimental-metrics.enabled - description: Enable the OSHI process metrics. + description: Enable the OSHI process runtime metrics. type: boolean default: false - metrics: - - name: system.memory.utilization - description: System memory utilization - type: DOUBLE_GAUGE - unit: '1' - attributes: - - name: state - type: STRING - - name: system.network.packets - description: System network packets - type: LONG_SUM - unit: packets - attributes: - - name: device - type: STRING - - name: direction - type: STRING - - name: system.disk.operations - description: System disk operations - type: LONG_SUM - unit: operations - attributes: - - name: device - type: STRING - - name: direction - type: STRING - - name: runtime.java.cpu_time - description: Runtime Java CPU time - type: LONG_GAUGE - unit: ms - attributes: - - name: type - type: STRING - - name: runtime.java.memory - description: Runtime Java memory - type: LONG_SUM - unit: By - attributes: - - name: type - type: STRING - - name: system.disk.io - description: System disk IO - type: LONG_SUM - unit: By - attributes: - - name: device - type: STRING - - name: direction - type: STRING - - name: system.network.io - description: System network IO - type: LONG_SUM - unit: By - attributes: - - name: device - type: STRING - - name: direction - type: STRING - - name: system.memory.usage - description: System memory usage - type: LONG_SUM - unit: By - attributes: - - name: state - type: STRING - - name: system.network.errors - description: System network errors - type: LONG_SUM - unit: errors - attributes: - - name: device - type: STRING - - name: direction - type: STRING + telemetry: + - when: default + metrics: + - name: system.disk.io + description: System disk IO + type: LONG_SUM + unit: By + attributes: + - name: device + type: STRING + - name: direction + type: STRING + - name: system.disk.operations + description: System disk operations + type: LONG_SUM + unit: operations + attributes: + - name: device + type: STRING + - name: direction + type: STRING + - name: system.memory.usage + description: System memory usage + type: LONG_SUM + unit: By + attributes: + - name: state + type: STRING + - name: system.memory.utilization + description: System memory utilization + type: DOUBLE_GAUGE + unit: '1' + attributes: + - name: state + type: STRING + - name: system.network.errors + description: System network errors + type: LONG_SUM + unit: errors + attributes: + - name: device + type: STRING + - name: direction + type: STRING + - name: system.network.io + description: System network IO + type: LONG_SUM + unit: By + attributes: + - name: device + type: STRING + - name: direction + type: STRING + - name: system.network.packets + description: System network packets + type: LONG_SUM + unit: packets + attributes: + - name: device + type: STRING + - name: direction + type: STRING + - when: otel.instrumentation.oshi.experimental-metrics.enabled=true + metrics: + - name: runtime.java.cpu_time + description: Runtime Java CPU time + type: LONG_GAUGE + unit: ms + attributes: + - name: type + type: STRING + - name: runtime.java.memory + description: Runtime Java memory + type: LONG_SUM + unit: By + attributes: + - name: type + type: STRING + - name: system.disk.io + description: System disk IO + type: LONG_SUM + unit: By + attributes: + - name: device + type: STRING + - name: direction + type: STRING + - name: system.disk.operations + description: System disk operations + type: LONG_SUM + unit: operations + attributes: + - name: device + type: STRING + - name: direction + type: STRING + - name: system.memory.usage + description: System memory usage + type: LONG_SUM + unit: By + attributes: + - name: state + type: STRING + - name: system.memory.utilization + description: System memory utilization + type: DOUBLE_GAUGE + unit: '1' + attributes: + - name: state + type: STRING + - name: system.network.errors + description: System network errors + type: LONG_SUM + unit: errors + attributes: + - name: device + type: STRING + - name: direction + type: STRING + - name: system.network.io + description: System network IO + type: LONG_SUM + unit: By + attributes: + - name: device + type: STRING + - name: direction + type: STRING + - name: system.network.packets + description: System network packets + type: LONG_SUM + unit: packets + attributes: + - name: device + type: STRING + - name: direction + type: STRING payara: - name: payara source_path: instrumentation/payara @@ -2223,46 +2497,88 @@ libraries: target_versions: javaagent: - org.apache.tomcat:tomcat-jdbc:[8.5.0,) - metrics: - - name: db.client.connections.usage - description: The number of connections that are currently in state described - by the state attribute. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: state - type: STRING - - name: db.client.connections.pending_requests - description: The number of pending requests for an open connection, cumulative - for the entire pool. - type: LONG_SUM - unit: requests - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.max - description: The maximum number of open connections allowed. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.idle.min - description: The minimum number of idle open connections allowed. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: db.client.connections.idle.max - description: The maximum number of idle open connections allowed. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING + telemetry: + - when: default + metrics: + - name: db.client.connections.idle.max + description: The maximum number of idle open connections allowed. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.idle.min + description: The minimum number of idle open connections allowed. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.max + description: The maximum number of open connections allowed. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.pending_requests + description: The number of pending requests for an open connection, cumulative + for the entire pool. + type: LONG_SUM + unit: requests + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.usage + description: The number of connections that are currently in state described + by the state attribute. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: state + type: STRING + - when: otel.semconv-stability.opt-in=database + metrics: + - name: db.client.connection.count + description: The number of connections that are currently in state described + by the state attribute. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.state + type: STRING + - name: db.client.connection.idle.max + description: The maximum number of idle open connections allowed. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.idle.min + description: The minimum number of idle open connections allowed. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.max + description: The maximum number of open connections allowed. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.pending_requests + description: The number of current pending requests for an open connection. + type: LONG_SUM + unit: request + attributes: + - name: db.client.connection.pool.name + type: STRING twilio: - name: twilio-6.6 source_path: instrumentation/twilio-6.6 @@ -2366,24 +2682,45 @@ libraries: - org.vibur:vibur-dbcp:[11.0,) library: - org.vibur:vibur-dbcp:11.0 - metrics: - - name: db.client.connections.usage - description: The number of connections that are currently in state described - by the state attribute. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING - - name: state - type: STRING - - name: db.client.connections.max - description: The maximum number of open connections allowed. - type: LONG_SUM - unit: connections - attributes: - - name: pool.name - type: STRING + telemetry: + - when: default + metrics: + - name: db.client.connections.max + description: The maximum number of open connections allowed. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: db.client.connections.usage + description: The number of connections that are currently in state described + by the state attribute. + type: LONG_SUM + unit: connections + attributes: + - name: pool.name + type: STRING + - name: state + type: STRING + - when: otel.semconv-stability.opt-in=database + metrics: + - name: db.client.connection.count + description: The number of connections that are currently in state described + by the state attribute. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING + - name: db.client.connection.state + type: STRING + - name: db.client.connection.max + description: The maximum number of open connections allowed. + type: LONG_SUM + unit: connection + attributes: + - name: db.client.connection.pool.name + type: STRING wicket: - name: wicket-8.0 source_path: instrumentation/wicket-8.0 diff --git a/instrumentation-docs/collect.sh b/instrumentation-docs/collect.sh index 6d51b9fcee15..c967c09636dc 100755 --- a/instrumentation-docs/collect.sh +++ b/instrumentation-docs/collect.sh @@ -14,15 +14,25 @@ fi readonly INSTRUMENTATIONS=( # : : [ gradle-task-suffix ] + "alibaba-druid-1.0:javaagent:test" + "alibaba-druid-1.0:javaagent:testStableSemconv" "apache-dbcp-2.0:javaagent:test" + "apache-dbcp-2.0:javaagent:testStableSemconv" "apache-httpclient:apache-httpclient-5.0:javaagent:test" - "alibaba-druid-1.0:javaagent:test" "c3p0-0.9:javaagent:test" + "c3p0-0.9:javaagent:testStableSemconv" + "clickhouse-client-0.5:javaagent:test" + "clickhouse-client-0.5:javaagent:testStableSemconv" "hikaricp-3.0:javaagent:test" + "hikaricp-3.0:javaagent:testStableSemconv" "tomcat:tomcat-jdbc:javaagent:test" + "tomcat:tomcat-jdbc:javaagent:testStableSemconv" "oracle-ucp-11.2:javaagent:test" + "oracle-ucp-11.2:javaagent:testStableSemconv" "oshi:javaagent:test" + "oshi:javaagent:testExperimental" "vibur-dbcp-11.0:javaagent:test" + "vibur-dbcp-11.0:javaagent:testStableSemconv" ) readonly TELEMETRY_DIR_NAME=".telemetry" diff --git a/instrumentation-docs/readme.md b/instrumentation-docs/readme.md index 36a568ccdb5a..b7810c19492a 100644 --- a/instrumentation-docs/readme.md +++ b/instrumentation-docs/readme.md @@ -22,6 +22,35 @@ tasks { } ``` +Sometimes instrumentation will behave differently based on configuration options, and we can +differentiate between these configurations by using the `metaDataConfig` system property. When the +telemetry is written to a file, the value of this property will be included, or it will default to +a `default` attribution. + +For example, to collect and write metadata for the `otel.semconv-stability.opt-in=database` option +set for an instrumentation: + +```kotlin +val collectMetadata = findProperty("collectMetadata")?.toString() ?: "false" + +tasks { + val testStableSemconv by registering(Test::class) { + jvmArgs("-Dotel.semconv-stability.opt-in=database") + + systemProperty("collectMetadata", collectMetadata) + systemProperty("metaDataConfig", "otel.semconv-stability.opt-in=database") + } + + test { + systemProperty("collectMetadata", collectMetadata) + } + + check { + dependsOn(testStableSemconv) + } +} +``` + Then, prior to running the analyzer, run the following command to generate `.telemetry` files: `./gradlew test -PcollectMetadata=true` @@ -36,8 +65,6 @@ or use the helper script that will run only the currently supported tests (recom ./instrumentation-docs/collect.sh ``` -This script will also clean up all `.telemetry` files after the analysis is done. - ## Instrumentation Hierarchy An "InstrumentationModule" represents a module that that targets specific code in a @@ -101,7 +128,8 @@ public class SpringWebInstrumentationModule extends InstrumentationModule * List of settings that are available for the instrumentation module * Each setting has a name, description, type, and default value * metrics - * List of metrics that the instrumentation module collects, including the metric name, description, type, and attributes + * List of metrics that the instrumentation module collects, including the metric name, description, type, and attributes. + * Separate lists for the metrics emitted by default vs via configuration options. ## Methodology @@ -150,3 +178,6 @@ generate the metrics section of the instrumentation-list.yaml file. The data is written into a `.telemetry` directory in the root of each instrumentation module. This data will be excluded from git and just generated on demand. + +Each file has a `when` value along with the list of metrics that indicates whether the telemetry is emitted by default or via a +configuration option. diff --git a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/InstrumentationAnalyzer.java b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/InstrumentationAnalyzer.java index 771b905d2330..074d14b1a61c 100644 --- a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/InstrumentationAnalyzer.java +++ b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/InstrumentationAnalyzer.java @@ -92,10 +92,14 @@ List analyze() throws IOException { } } - EmittedMetrics metrics = + Map metrics = MetricParser.getMetricsFromFiles(fileManager.rootDir(), module.getSrcPath()); - if (!metrics.getMetrics().isEmpty()) { - module.setMetrics(metrics.getMetrics()); + + for (Map.Entry entry : metrics.entrySet()) { + if (entry.getValue() == null || entry.getValue().getMetrics() == null) { + continue; + } + module.getMetrics().put(entry.getKey(), entry.getValue().getMetrics()); } } return modules; diff --git a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/EmittedMetrics.java b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/EmittedMetrics.java index 997468a245f8..c13c11247410 100644 --- a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/EmittedMetrics.java +++ b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/EmittedMetrics.java @@ -9,20 +9,33 @@ import java.util.List; /** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. + * Representation of metrics emitted by an instrumentation. Includes context about whether emitted + * by default or via a configuration option. This class is internal and is hence not for public use. + * Its APIs are unstable and can change at any time. */ public class EmittedMetrics { + // Condition in which the metrics are emitted (ex: default, or configuration option names). + private String when; private List metrics; public EmittedMetrics() { + this.when = ""; this.metrics = new ArrayList<>(); } - public EmittedMetrics(List metrics) { + public EmittedMetrics(String when, List metrics) { + this.when = ""; this.metrics = metrics; } + public String getWhen() { + return when; + } + + public void setWhen(String when) { + this.when = when; + } + public List getMetrics() { return metrics; } diff --git a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationModule.java b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationModule.java index dba4d64c9b19..437cecc52380 100644 --- a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationModule.java +++ b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/internal/InstrumentationModule.java @@ -9,8 +9,10 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.sdk.common.InstrumentationScopeInfo; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import javax.annotation.Nullable; @@ -26,7 +28,7 @@ public class InstrumentationModule { private final String namespace; private final String group; private final InstrumentationScopeInfo scopeInfo; - @Nullable private List metrics; + private Map> metrics; @Nullable private Map> targetVersions; @@ -44,11 +46,11 @@ public InstrumentationModule(Builder builder) { requireNonNull(builder.namespace, "namespace required"); requireNonNull(builder.group, "group required"); + this.metrics = Objects.requireNonNullElseGet(builder.metrics, HashMap::new); this.srcPath = builder.srcPath; this.instrumentationName = builder.instrumentationName; this.namespace = builder.namespace; this.group = builder.group; - this.metrics = builder.metrics; this.metadata = builder.metadata; this.targetVersions = builder.targetVersions; this.minJavaVersion = builder.minJavaVersion; @@ -93,8 +95,7 @@ public Integer getMinJavaVersion() { return minJavaVersion; } - @Nullable - public List getMetrics() { + public Map> getMetrics() { return metrics; } @@ -110,7 +111,7 @@ public void setMinJavaVersion(Integer minJavaVersion) { this.minJavaVersion = minJavaVersion; } - public void setMetrics(List metrics) { + public void setMetrics(Map> metrics) { this.metrics = metrics; } @@ -126,7 +127,7 @@ public static class Builder { @Nullable private Integer minJavaVersion; @Nullable private InstrumentationMetaData metadata; @Nullable private Map> targetVersions; - @Nullable private List metrics; + @Nullable private Map> metrics; @CanIgnoreReturnValue public Builder srcPath(String srcPath) { @@ -171,7 +172,7 @@ public Builder targetVersions(Map> targetVersio } @CanIgnoreReturnValue - public Builder metrics(List metrics) { + public Builder metrics(Map> metrics) { this.metrics = metrics; return this; } diff --git a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/parsers/MetricParser.java b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/parsers/MetricParser.java index 32fc6cf3e09c..50ae9fd5b6c9 100644 --- a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/parsers/MetricParser.java +++ b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/parsers/MetricParser.java @@ -13,7 +13,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -30,9 +29,9 @@ public class MetricParser { * @param instrumentationDirectory the directory to traverse * @return contents of aggregated files */ - public static EmittedMetrics getMetricsFromFiles( + public static Map getMetricsFromFiles( String rootDir, String instrumentationDirectory) { - StringBuilder metricsContent = new StringBuilder("metrics:\n"); + Map metricsByWhen = new HashMap<>(); Path telemetryDir = Paths.get(rootDir + "/" + instrumentationDirectory, ".telemetry"); if (Files.exists(telemetryDir) && Files.isDirectory(telemetryDir)) { @@ -43,11 +42,17 @@ public static EmittedMetrics getMetricsFromFiles( path -> { String content = FileManager.readFileToString(path.toString()); if (content != null) { - // Skip the first line of yaml ("metrics:") so we can aggregate into one list - int firstNewline = content.indexOf('\n'); - if (firstNewline != -1) { - String contentWithoutFirstLine = content.substring(firstNewline + 1); - metricsContent.append(contentWithoutFirstLine); + String when = content.substring(0, content.indexOf('\n')); + String whenKey = when.replace("when: ", ""); + + metricsByWhen.putIfAbsent(whenKey, new StringBuilder("metrics:\n")); + + // Skip the metric label ("metrics:") so we can aggregate into one list + int metricsIndex = content.indexOf("metrics:\n"); + if (metricsIndex != -1) { + String contentAfterMetrics = + content.substring(metricsIndex + "metrics:\n".length()); + metricsByWhen.get(whenKey).append(contentAfterMetrics); } } }); @@ -56,31 +61,38 @@ public static EmittedMetrics getMetricsFromFiles( } } - return parseMetrics(metricsContent.toString()); + return parseMetrics(metricsByWhen); } /** - * Takes in a raw string representation of the aggregated EmittedMetrics yaml, deduplicates the - * metrics by name and then returns a new EmittedMetrics object. + * Takes in a raw string representation of the aggregated EmittedMetrics yaml map, separated by + * the `when`, indicating the conditions under which the metrics are emitted. deduplicates the + * metrics by name and then returns a new map EmittedMetrics objects. * * @param input raw string representation of EmittedMetrics yaml - * @return EmittedMetrics + * @return {@code Map} where the key is the `when` condition */ // visible for testing - public static EmittedMetrics parseMetrics(String input) { - EmittedMetrics metrics = YamlHelper.emittedMetricsParser(input); - if (metrics.getMetrics() == null) { - return new EmittedMetrics(Collections.emptyList()); - } + public static Map parseMetrics(Map input) { + Map metricsMap = new HashMap<>(); + for (Map.Entry entry : input.entrySet()) { + String when = entry.getKey(); + StringBuilder content = entry.getValue(); - // deduplicate metrics by name - Map deduplicatedMetrics = new HashMap<>(); - for (EmittedMetrics.Metric metric : metrics.getMetrics()) { - deduplicatedMetrics.put(metric.getName(), metric); - } + EmittedMetrics metrics = YamlHelper.emittedMetricsParser(content.toString()); + if (metrics.getMetrics() == null) { + continue; + } + + Map deduplicatedMetrics = new HashMap<>(); + for (EmittedMetrics.Metric metric : metrics.getMetrics()) { + deduplicatedMetrics.put(metric.getName(), metric); + } - List uniqueMetrics = new ArrayList<>(deduplicatedMetrics.values()); - return new EmittedMetrics(uniqueMetrics); + List uniqueMetrics = new ArrayList<>(deduplicatedMetrics.values()); + metricsMap.put(when, new EmittedMetrics(when, uniqueMetrics)); + } + return metricsMap; } private MetricParser() {} diff --git a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/utils/YamlHelper.java b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/utils/YamlHelper.java index 7832a40f2440..30743e2e2148 100644 --- a/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/utils/YamlHelper.java +++ b/instrumentation-docs/src/main/java/io/opentelemetry/instrumentation/docs/utils/YamlHelper.java @@ -16,9 +16,12 @@ import io.opentelemetry.instrumentation.docs.internal.InstrumentationModule; import java.io.BufferedWriter; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.TreeMap; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -128,11 +131,29 @@ private static Map baseProperties(InstrumentationModule module) addTargetVersions(module, moduleMap); addConfigurations(module, moduleMap); - if (module.getMetrics() != null) { - List> metricsList = getMetricsList(module); - moduleMap.put("metrics", metricsList); + // Get telemetry grouping list + Set telemetryGroups = module.getMetrics().keySet(); + + if (!telemetryGroups.isEmpty()) { + List> telemetryList = new ArrayList<>(); + for (String group : telemetryGroups) { + Map telemetryEntry = new LinkedHashMap<>(); + telemetryEntry.put("when", group); + List metrics = + new ArrayList<>(module.getMetrics().getOrDefault(group, Collections.emptyList())); + List> metricsList = new ArrayList<>(); + + // sort metrics by name for some determinism in the order + metrics.sort(Comparator.comparing(EmittedMetrics.Metric::getName)); + + for (EmittedMetrics.Metric metric : metrics) { + metricsList.add(getMetricsMap(metric)); + } + telemetryEntry.put("metrics", metricsList); + telemetryList.add(telemetryEntry); + } + moduleMap.put("telemetry", telemetryList); } - return moduleMap; } @@ -200,30 +221,22 @@ private static Map configurationToMap(ConfigurationOption config return conf; } - private static List> getMetricsList(InstrumentationModule module) { - List> metricsList = new ArrayList<>(); - if (module.getMetrics() == null) { - return metricsList; - } - - for (EmittedMetrics.Metric metric : module.getMetrics()) { - Map metricMap = new LinkedHashMap<>(); - metricMap.put("name", metric.getName()); - metricMap.put("description", metric.getDescription()); - metricMap.put("type", metric.getType()); - metricMap.put("unit", metric.getUnit()); - - List> attributes = new ArrayList<>(); - for (EmittedMetrics.Attribute attribute : metric.getAttributes()) { - Map attributeMap = new LinkedHashMap<>(); - attributeMap.put("name", attribute.getName()); - attributeMap.put("type", attribute.getType()); - attributes.add(attributeMap); - } - metricMap.put("attributes", attributes); - metricsList.add(metricMap); + private static Map getMetricsMap(EmittedMetrics.Metric metric) { + Map innerMetricMap = new LinkedHashMap<>(); + innerMetricMap.put("name", metric.getName()); + innerMetricMap.put("description", metric.getDescription()); + innerMetricMap.put("type", metric.getType()); + innerMetricMap.put("unit", metric.getUnit()); + + List> attributes = new ArrayList<>(); + for (EmittedMetrics.Attribute attribute : metric.getAttributes()) { + Map attributeMap = new LinkedHashMap<>(); + attributeMap.put("name", attribute.getName()); + attributeMap.put("type", attribute.getType()); + attributes.add(attributeMap); } - return metricsList; + innerMetricMap.put("attributes", attributes); + return innerMetricMap; } public static InstrumentationMetaData metaDataParser(String input) diff --git a/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/parsers/MetricParserTest.java b/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/parsers/MetricParserTest.java index 531d40e720fc..da068a8f5ca8 100644 --- a/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/parsers/MetricParserTest.java +++ b/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/parsers/MetricParserTest.java @@ -13,11 +13,14 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.mockito.MockedStatic; +@SuppressWarnings("NullAway") class MetricParserTest { @Test @@ -33,9 +36,15 @@ void parseMetricsDeduplicatesMetricsByName() { type: gauge """; - EmittedMetrics result = MetricParser.parseMetrics(input); + Map metricMap = new HashMap<>(); + metricMap.put("default", new StringBuilder(input)); + + Map result = MetricParser.parseMetrics(metricMap); List metricNames = - result.getMetrics().stream().map(EmittedMetrics.Metric::getName).sorted().toList(); + result.get("default").getMetrics().stream() + .map(EmittedMetrics.Metric::getName) + .sorted() + .toList(); assertThat(metricNames).hasSize(2); assertThat(metricNames).containsExactly("metric1", "metric2"); @@ -44,16 +53,19 @@ void parseMetricsDeduplicatesMetricsByName() { @Test void parseMetricsHandlesEmptyInput() { String input = "metrics:\n"; - EmittedMetrics result = MetricParser.parseMetrics(input); - assertThat(result.getMetrics()).isEmpty(); + Map metricMap = new HashMap<>(); + metricMap.put("default", new StringBuilder(input)); + + Map result = MetricParser.parseMetrics(metricMap); + assertThat(result).isEmpty(); } @Test void getMetricsFromFilesCombinesFilesCorrectly(@TempDir Path tempDir) throws IOException { Path telemetryDir = Files.createDirectories(tempDir.resolve(".telemetry")); - String file1Content = "metrics:\n - name: metric1\n type: counter\n"; - String file2Content = "metrics:\n - name: metric2\n type: gauge\n"; + String file1Content = "when: default\n metrics:\n - name: metric1\n type: counter\n"; + String file2Content = "when: default\n metrics:\n - name: metric2\n type: gauge\n"; Files.writeString(telemetryDir.resolve("metrics-1.yaml"), file1Content); Files.writeString(telemetryDir.resolve("metrics-2.yaml"), file2Content); @@ -71,18 +83,20 @@ void getMetricsFromFilesCombinesFilesCorrectly(@TempDir Path tempDir) throws IOE () -> FileManager.readFileToString(telemetryDir.resolve("metrics-2.yaml").toString())) .thenReturn(file2Content); - EmittedMetrics result = MetricParser.getMetricsFromFiles(tempDir.toString(), ""); + Map result = MetricParser.getMetricsFromFiles(tempDir.toString(), ""); + + EmittedMetrics metrics = result.get("default"); - assertThat(result.getMetrics()).hasSize(2); + assertThat(metrics.getMetrics()).hasSize(2); List metricNames = - result.getMetrics().stream().map(EmittedMetrics.Metric::getName).sorted().toList(); + metrics.getMetrics().stream().map(EmittedMetrics.Metric::getName).sorted().toList(); assertThat(metricNames).containsExactly("metric1", "metric2"); } } @Test void getMetricsFromFilesHandlesNonexistentDirectory() { - EmittedMetrics result = MetricParser.getMetricsFromFiles("/nonexistent", "path"); - assertThat(result.getMetrics()).isEmpty(); + Map result = MetricParser.getMetricsFromFiles("/nonexistent", "path"); + assertThat(result).isEmpty(); } } diff --git a/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/utils/YamlHelperTest.java b/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/utils/YamlHelperTest.java index 2127a0b0840a..b23467aa891e 100644 --- a/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/utils/YamlHelperTest.java +++ b/instrumentation-docs/src/test/java/io/opentelemetry/instrumentation/docs/utils/YamlHelperTest.java @@ -312,7 +312,7 @@ void testMetricsParsing() throws Exception { .namespace("mylib") .group("mylib") .targetVersions(targetVersions) - .metrics(List.of(metric)) + .metrics(Map.of("default", List.of(metric))) .build()); StringWriter stringWriter = new StringWriter(); @@ -332,22 +332,24 @@ void testMetricsParsing() throws Exception { target_versions: library: - org.apache.mylib:mylib-core:2.3.0 - metrics: - - name: db.client.operation.duration - description: Duration of database client operations. - type: HISTOGRAM - unit: s - attributes: - - name: db.namespace - type: STRING - - name: db.operation.name - type: STRING - - name: db.system.name - type: STRING - - name: server.address - type: STRING - - name: server.port - type: LONG + telemetry: + - when: default + metrics: + - name: db.client.operation.duration + description: Duration of database client operations. + type: HISTOGRAM + unit: s + attributes: + - name: db.namespace + type: STRING + - name: db.operation.name + type: STRING + - name: db.system.name + type: STRING + - name: server.address + type: STRING + - name: server.port + type: LONG """; assertThat(expectedYaml).isEqualTo(stringWriter.toString()); diff --git a/instrumentation/alibaba-druid-1.0/javaagent/build.gradle.kts b/instrumentation/alibaba-druid-1.0/javaagent/build.gradle.kts index f435d672c43e..5f3b242fb791 100644 --- a/instrumentation/alibaba-druid-1.0/javaagent/build.gradle.kts +++ b/instrumentation/alibaba-druid-1.0/javaagent/build.gradle.kts @@ -19,13 +19,18 @@ dependencies { testImplementation(project(":instrumentation:alibaba-druid-1.0:testing")) } +val collectMetadata = findProperty("collectMetadata")?.toString() ?: "false" + tasks { val testStableSemconv by registering(Test::class) { jvmArgs("-Dotel.semconv-stability.opt-in=database") + + systemProperty("collectMetadata", collectMetadata) + systemProperty("metaDataConfig", "otel.semconv-stability.opt-in=database") } test { - systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false") + systemProperty("collectMetadata", collectMetadata) } check { diff --git a/instrumentation/apache-dbcp-2.0/javaagent/build.gradle.kts b/instrumentation/apache-dbcp-2.0/javaagent/build.gradle.kts index 54020d8dfded..e7c30b98ced1 100644 --- a/instrumentation/apache-dbcp-2.0/javaagent/build.gradle.kts +++ b/instrumentation/apache-dbcp-2.0/javaagent/build.gradle.kts @@ -19,13 +19,18 @@ dependencies { testImplementation(project(":instrumentation:apache-dbcp-2.0:testing")) } +val collectMetadata = findProperty("collectMetadata")?.toString() ?: "false" + tasks { val testStableSemconv by registering(Test::class) { jvmArgs("-Dotel.semconv-stability.opt-in=database") + + systemProperty("collectMetadata", collectMetadata) + systemProperty("metaDataConfig", "otel.semconv-stability.opt-in=database") } test { - systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false") + systemProperty("collectMetadata", collectMetadata) } check { diff --git a/instrumentation/c3p0-0.9/javaagent/build.gradle.kts b/instrumentation/c3p0-0.9/javaagent/build.gradle.kts index 483910939081..c90aaa3e5cb2 100644 --- a/instrumentation/c3p0-0.9/javaagent/build.gradle.kts +++ b/instrumentation/c3p0-0.9/javaagent/build.gradle.kts @@ -21,13 +21,18 @@ dependencies { testImplementation(project(":instrumentation:c3p0-0.9:testing")) } +val collectMetadata = findProperty("collectMetadata")?.toString() ?: "false" + tasks { val testStableSemconv by registering(Test::class) { jvmArgs("-Dotel.semconv-stability.opt-in=database") + + systemProperty("collectMetadata", collectMetadata) + systemProperty("metaDataConfig", "otel.semconv-stability.opt-in=database") } test { - systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false") + systemProperty("collectMetadata", collectMetadata) } check { diff --git a/instrumentation/clickhouse-client-0.5/javaagent/build.gradle.kts b/instrumentation/clickhouse-client-0.5/javaagent/build.gradle.kts index 7628d2d0a4e7..fc5d940a534e 100644 --- a/instrumentation/clickhouse-client-0.5/javaagent/build.gradle.kts +++ b/instrumentation/clickhouse-client-0.5/javaagent/build.gradle.kts @@ -22,13 +22,18 @@ dependencies { testLibrary("org.apache.httpcomponents.client5:httpclient5:5.2.3") } +val collectMetadata = findProperty("collectMetadata")?.toString() ?: "false" + tasks { test { usesService(gradle.sharedServices.registrations["testcontainersBuildService"].service) + systemProperty("collectMetadata", collectMetadata) } val testStableSemconv by registering(Test::class) { jvmArgs("-Dotel.semconv-stability.opt-in=database") + systemProperty("collectMetadata", collectMetadata) + systemProperty("metaDataConfig", "otel.semconv-stability.opt-in=database") } check { diff --git a/instrumentation/clickhouse-client-0.5/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseClientTest.java b/instrumentation/clickhouse-client-0.5/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseClientTest.java index deb9fcda73c2..b63258b596f4 100644 --- a/instrumentation/clickhouse-client-0.5/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseClientTest.java +++ b/instrumentation/clickhouse-client-0.5/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseClientTest.java @@ -5,9 +5,13 @@ package io.opentelemetry.javaagent.instrumentation.clickhouse; +import static io.opentelemetry.instrumentation.testing.junit.db.DbClientMetricsTestUtil.assertDurationMetric; import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.semconv.DbAttributes.DB_NAMESPACE; +import static io.opentelemetry.semconv.DbAttributes.DB_OPERATION_NAME; import static io.opentelemetry.semconv.DbAttributes.DB_RESPONSE_STATUS_CODE; +import static io.opentelemetry.semconv.DbAttributes.DB_SYSTEM_NAME; import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE; import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS; import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT; @@ -115,6 +119,15 @@ void testConnectionStringWithoutDatabaseSpecifiedStillGeneratesSpans() .hasNoParent() .hasAttributesSatisfyingExactly( attributeAssertions("select * from " + tableName, "SELECT")))); + + assertDurationMetric( + testing, + "io.opentelemetry.clickhouse-client-0.5", + DB_SYSTEM_NAME, + DB_OPERATION_NAME, + DB_NAMESPACE, + SERVER_ADDRESS, + SERVER_PORT); } @Test diff --git a/instrumentation/hikaricp-3.0/javaagent/build.gradle.kts b/instrumentation/hikaricp-3.0/javaagent/build.gradle.kts index ad2f01808c53..d5262fe7f54d 100644 --- a/instrumentation/hikaricp-3.0/javaagent/build.gradle.kts +++ b/instrumentation/hikaricp-3.0/javaagent/build.gradle.kts @@ -22,13 +22,18 @@ dependencies { testImplementation(project(":instrumentation:hikaricp-3.0:testing")) } +val collectMetadata = findProperty("collectMetadata")?.toString() ?: "false" + tasks { val testStableSemconv by registering(Test::class) { jvmArgs("-Dotel.semconv-stability.opt-in=database") + + systemProperty("collectMetadata", collectMetadata) + systemProperty("metaDataConfig", "otel.semconv-stability.opt-in=database") } test { - systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false") + systemProperty("collectMetadata", collectMetadata) } check { diff --git a/instrumentation/oracle-ucp-11.2/javaagent/build.gradle.kts b/instrumentation/oracle-ucp-11.2/javaagent/build.gradle.kts index 3438caf2215b..65d60d416e68 100644 --- a/instrumentation/oracle-ucp-11.2/javaagent/build.gradle.kts +++ b/instrumentation/oracle-ucp-11.2/javaagent/build.gradle.kts @@ -20,17 +20,19 @@ dependencies { testImplementation(project(":instrumentation:oracle-ucp-11.2:testing")) } +val collectMetadata = findProperty("collectMetadata")?.toString() ?: "false" + tasks { test { usesService(gradle.sharedServices.registrations["testcontainersBuildService"].service) + systemProperty("collectMetadata", collectMetadata) } val testStableSemconv by registering(Test::class) { jvmArgs("-Dotel.semconv-stability.opt-in=database") - } - test { - systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false") + systemProperty("collectMetadata", collectMetadata) + systemProperty("metaDataConfig", "otel.semconv-stability.opt-in=database") } check { diff --git a/instrumentation/oshi/javaagent/build.gradle.kts b/instrumentation/oshi/javaagent/build.gradle.kts index 61bbb729f4c8..e8293171a9c7 100644 --- a/instrumentation/oshi/javaagent/build.gradle.kts +++ b/instrumentation/oshi/javaagent/build.gradle.kts @@ -24,10 +24,16 @@ dependencies { tasks { withType().configureEach { + systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false") + } + + val testExperimental by registering(Test::class) { jvmArgs("-Dotel.instrumentation.oshi.experimental-metrics.enabled=true") + systemProperty("testExperimental", "true") + systemProperty("metaDataConfig", "otel.instrumentation.oshi.experimental-metrics.enabled=true") } - test { - systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false") + check { + dependsOn(testExperimental) } } diff --git a/instrumentation/oshi/metadata.yaml b/instrumentation/oshi/metadata.yaml index 0afedf010d6a..7abda9582c21 100644 --- a/instrumentation/oshi/metadata.yaml +++ b/instrumentation/oshi/metadata.yaml @@ -1,6 +1,6 @@ description: When the OSHI library is detected on the classpath, this instrumentation will use the system class loader to load classes from the oshi-core jar that are then used to generate system metrics. configurations: - name: otel.instrumentation.oshi.experimental-metrics.enabled - description: Enable the OSHI process metrics. + description: Enable the OSHI process runtime metrics. type: boolean default: false diff --git a/instrumentation/oshi/testing/src/main/java/io/opentelemetry/instrumentation/oshi/AbstractProcessMetricsTest.java b/instrumentation/oshi/testing/src/main/java/io/opentelemetry/instrumentation/oshi/AbstractProcessMetricsTest.java index 7a4f043eb297..ff8b322a4310 100644 --- a/instrumentation/oshi/testing/src/main/java/io/opentelemetry/instrumentation/oshi/AbstractProcessMetricsTest.java +++ b/instrumentation/oshi/testing/src/main/java/io/opentelemetry/instrumentation/oshi/AbstractProcessMetricsTest.java @@ -9,6 +9,7 @@ import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIfSystemProperty; public abstract class AbstractProcessMetricsTest { @@ -17,6 +18,7 @@ public abstract class AbstractProcessMetricsTest { protected abstract InstrumentationExtension testing(); @Test + @EnabledIfSystemProperty(named = "testExperimental", matches = "true") void test() { // when registerMetrics(); diff --git a/instrumentation/tomcat/tomcat-jdbc/javaagent/build.gradle.kts b/instrumentation/tomcat/tomcat-jdbc/javaagent/build.gradle.kts index 47541bf80e47..e712e958f876 100644 --- a/instrumentation/tomcat/tomcat-jdbc/javaagent/build.gradle.kts +++ b/instrumentation/tomcat/tomcat-jdbc/javaagent/build.gradle.kts @@ -16,8 +16,21 @@ dependencies { testImplementation("org.apache.tomcat:tomcat-jdbc:8.5.0") } +val collectMetadata = findProperty("collectMetadata")?.toString() ?: "false" + tasks { + val testStableSemconv by registering(Test::class) { + jvmArgs("-Dotel.semconv-stability.opt-in=database") + + systemProperty("collectMetadata", collectMetadata) + systemProperty("metaDataConfig", "otel.semconv-stability.opt-in=database") + } + test { - systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false") + systemProperty("collectMetadata", collectMetadata) + } + + check { + dependsOn(testStableSemconv) } } diff --git a/instrumentation/vibur-dbcp-11.0/javaagent/build.gradle.kts b/instrumentation/vibur-dbcp-11.0/javaagent/build.gradle.kts index 601ffb6e066b..5fd9a33e6b37 100644 --- a/instrumentation/vibur-dbcp-11.0/javaagent/build.gradle.kts +++ b/instrumentation/vibur-dbcp-11.0/javaagent/build.gradle.kts @@ -19,13 +19,18 @@ dependencies { testImplementation(project(":instrumentation:vibur-dbcp-11.0:testing")) } +val collectMetadata = findProperty("collectMetadata")?.toString() ?: "false" + tasks { val testStableSemconv by registering(Test::class) { jvmArgs("-Dotel.semconv-stability.opt-in=database") + + systemProperty("collectMetadata", collectMetadata) + systemProperty("metaDataConfig", "otel.semconv-stability.opt-in=database") } test { - systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false") + systemProperty("collectMetadata", collectMetadata) } check { diff --git a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/internal/MetaDataCollector.java b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/internal/MetaDataCollector.java index 6a15c133539b..76ddac93b6d9 100644 --- a/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/internal/MetaDataCollector.java +++ b/testing-common/src/main/java/io/opentelemetry/instrumentation/testing/internal/MetaDataCollector.java @@ -69,30 +69,36 @@ private static void writeMetricData(String instrumentationPath, Map { - try { - writer.write(" - name: " + key.getKey() + "\n"); - writer.write(" type: " + key.getType().toString() + "\n"); - } catch (IOException e) { - throw new IllegalStateException(e); - } - }); - } + writer.write("when: " + when + "\n"); + + writer.write("metrics:\n"); + for (MetricData metric : metrics.values()) { + writer.write(" - name: " + metric.getName() + "\n"); + writer.write(" description: " + metric.getDescription() + "\n"); + writer.write(" type: " + metric.getType().toString() + "\n"); + writer.write(" unit: " + sanitizeUnit(metric.getUnit()) + "\n"); + writer.write(" attributes: \n"); + metric.getData().getPoints().stream() + .findFirst() + .get() + .getAttributes() + .forEach( + (key, value) -> { + try { + writer.write(" - name: " + key.getKey() + "\n"); + writer.write(" type: " + key.getType().toString() + "\n"); + } catch (IOException e) { + throw new IllegalStateException(e); + } + }); } } }