diff --git a/examples/example-exporter-opentelemetry/oats-tests/agent/Dockerfile b/examples/example-exporter-opentelemetry/oats-tests/agent/Dockerfile
new file mode 100644
index 000000000..23f980005
--- /dev/null
+++ b/examples/example-exporter-opentelemetry/oats-tests/agent/Dockerfile
@@ -0,0 +1,9 @@
+FROM eclipse-temurin:21-jre
+
+COPY target/example-exporter-opentelemetry.jar ./app.jar
+# check that the resource attributs from the agent are used, epsecially the service.instance.id should be the same
+ADD --chmod=644 https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v2.8.0/opentelemetry-javaagent.jar /usr/src/app/opentelemetry-javaagent.jar
+ENV JAVA_TOOL_OPTIONS=-javaagent:/usr/src/app/opentelemetry-javaagent.jar
+
+#ENTRYPOINT [ "java", "-Dotel.javaagent.debug=true","-jar", "./app.jar" ] # for debugging
+ENTRYPOINT [ "java", "-jar", "./app.jar" ]
diff --git a/examples/example-exporter-opentelemetry/oats-tests/agent/docker-compose.yml b/examples/example-exporter-opentelemetry/oats-tests/agent/docker-compose.yml
new file mode 100644
index 000000000..9c0fc66fb
--- /dev/null
+++ b/examples/example-exporter-opentelemetry/oats-tests/agent/docker-compose.yml
@@ -0,0 +1,13 @@
+# OATS is an acceptance testing framework for OpenTelemetry - https://github.com/grafana/oats/tree/main/yaml
+version: '3.4'
+
+services:
+ java:
+ build:
+ context: ../..
+ dockerfile: oats-tests/agent/Dockerfile
+ environment:
+ OTEL_SERVICE_NAME: "rolldice"
+ OTEL_EXPORTER_OTLP_ENDPOINT: http://lgtm:4317
+ OTEL_EXPORTER_OTLP_PROTOCOL: grpc
+ OTEL_METRIC_EXPORT_INTERVAL: "5000" # so we don't have to wait 60s for metrics
diff --git a/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml b/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml
new file mode 100644
index 000000000..08e4d8d3f
--- /dev/null
+++ b/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml
@@ -0,0 +1,12 @@
+# OATS is an acceptance testing framework for OpenTelemetry - https://github.com/grafana/oats/tree/main/yaml
+docker-compose:
+ generator: docker-lgtm
+ files:
+ - ./docker-compose.yml
+expected:
+ custom-checks:
+ - script: ./service-instance-id-check.py
+ metrics:
+ - promql: 'uptime_seconds_total{}'
+ value: '>= 0'
+
diff --git a/examples/example-exporter-opentelemetry/oats-tests/agent/service-instance-id-check.py b/examples/example-exporter-opentelemetry/oats-tests/agent/service-instance-id-check.py
new file mode 100755
index 000000000..196c629c9
--- /dev/null
+++ b/examples/example-exporter-opentelemetry/oats-tests/agent/service-instance-id-check.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python3
+
+# This script is used to check if the service instance id is present in the exported data
+# The script will return 0 if the service instance id is present in the exported data
+
+from urllib.request import urlopen
+import urllib.parse
+import json
+
+url = ' http://localhost:9090/api/v1/label/instance/values'
+res = json.loads(urlopen(url).read().decode('utf-8'))
+
+values = list(res['data'])
+print(values)
+
+if "localhost:8888" in values:
+ values.remove("localhost:8888")
+
+# both the agent and the exporter should report the same instance id
+assert len(values) == 1
+
+path = 'target_info{instance="%s"}' % values[0]
+path = urllib.parse.quote_plus(path)
+url = 'http://localhost:9090/api/v1/query?query=%s' % path
+res = json.loads(urlopen(url).read().decode('utf-8'))
+
+infos = res['data']['result']
+print(infos)
+
+# they should not have the same target info
+# e.g. only the agent has telemetry_distro_name
+assert len(infos) == 2
+
diff --git a/examples/example-exporter-opentelemetry/oats-tests/http/Dockerfile b/examples/example-exporter-opentelemetry/oats-tests/http/Dockerfile
new file mode 100644
index 000000000..22191f07e
--- /dev/null
+++ b/examples/example-exporter-opentelemetry/oats-tests/http/Dockerfile
@@ -0,0 +1,5 @@
+FROM eclipse-temurin:21-jre
+
+COPY target/example-exporter-opentelemetry.jar ./app.jar
+
+ENTRYPOINT [ "java", "-jar", "./app.jar" ]
diff --git a/examples/example-exporter-opentelemetry/oats-tests/http/docker-compose.yml b/examples/example-exporter-opentelemetry/oats-tests/http/docker-compose.yml
new file mode 100644
index 000000000..cec15bf19
--- /dev/null
+++ b/examples/example-exporter-opentelemetry/oats-tests/http/docker-compose.yml
@@ -0,0 +1,13 @@
+# OATS is an acceptance testing framework for OpenTelemetry - https://github.com/grafana/oats/tree/main/yaml
+version: '3.4'
+
+services:
+ java:
+ build:
+ context: ../..
+ dockerfile: oats-tests/http/Dockerfile
+ environment:
+ OTEL_SERVICE_NAME: "rolldice"
+ OTEL_EXPORTER_OTLP_ENDPOINT: http://lgtm:4318
+ OTEL_EXPORTER_OTLP_PROTOCOL: http/protobuf
+ OTEL_METRIC_EXPORT_INTERVAL: "5000" # so we don't have to wait 60s for metrics
diff --git a/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml b/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml
new file mode 100644
index 000000000..a3af9ffc2
--- /dev/null
+++ b/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml
@@ -0,0 +1,10 @@
+# OATS is an acceptance testing framework for OpenTelemetry - https://github.com/grafana/oats/tree/main/yaml
+docker-compose:
+ generator: docker-lgtm
+ files:
+ - ./docker-compose.yml
+expected:
+ metrics:
+ - promql: 'uptime_seconds_total{}'
+ value: '>= 0'
+
diff --git a/examples/example-exporter-opentelemetry/src/main/java/io/prometheus/metrics/examples/opentelemetry/Main.java b/examples/example-exporter-opentelemetry/src/main/java/io/prometheus/metrics/examples/opentelemetry/Main.java
index defe85074..b1aa440b1 100644
--- a/examples/example-exporter-opentelemetry/src/main/java/io/prometheus/metrics/examples/opentelemetry/Main.java
+++ b/examples/example-exporter-opentelemetry/src/main/java/io/prometheus/metrics/examples/opentelemetry/Main.java
@@ -9,6 +9,7 @@
public class Main {
public static void main(String[] args) throws Exception {
+ System.out.println("Starting example application");
// Note: Some JVM metrics are also defined as OpenTelemetry's semantic conventions.
// We have plans to implement a configuration option for JvmMetrics to use OpenTelemetry
@@ -34,6 +35,7 @@ public static void main(String[] args) throws Exception {
while (true) {
Thread.sleep(1000);
+ System.out.println("Incrementing counter");
counter.inc();
}
}
diff --git a/otel-agent-resources/pom.xml b/otel-agent-resources/pom.xml
new file mode 100644
index 000000000..176c2c6eb
--- /dev/null
+++ b/otel-agent-resources/pom.xml
@@ -0,0 +1,67 @@
+
+
+ 4.0.0
+
+
+ io.prometheus
+ client_java
+ 0.0.1-releasetest1
+
+
+ otel-agent-resources
+ bundle
+
+ OpenTelemetry Agent Resource Extractor
+
+ Reads the OpenTelemetry Agent resources the GlobalOpenTelemetry instance
+
+
+
+ io.prometheus.otel.resource.attributes
+
+ 1.29.0
+
+
+
+
+
+
+
+
+ src/main/resources
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy
+ validate
+
+ copy
+
+
+
+
+
+
+ io.opentelemetry
+ opentelemetry-api
+ ${otel-dynamic-load.version}
+ ${project.basedir}/src/main/resources/lib/
+
+
+ io.opentelemetry
+ opentelemetry-context
+ ${otel-dynamic-load.version}
+ ${project.basedir}/src/main/resources/lib/
+
+
+
+
+
+
+
diff --git a/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/ResourceAttributesFromOtelAgent.java b/otel-agent-resources/src/main/java/io/prometheus/otelagent/ResourceAttributesFromOtelAgent.java
similarity index 88%
rename from prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/ResourceAttributesFromOtelAgent.java
rename to otel-agent-resources/src/main/java/io/prometheus/otelagent/ResourceAttributesFromOtelAgent.java
index ce6baafe2..215b79de5 100644
--- a/prometheus-metrics-exporter-opentelemetry/src/main/java/io/prometheus/metrics/exporter/opentelemetry/ResourceAttributesFromOtelAgent.java
+++ b/otel-agent-resources/src/main/java/io/prometheus/otelagent/ResourceAttributesFromOtelAgent.java
@@ -1,4 +1,4 @@
-package io.prometheus.metrics.exporter.opentelemetry;
+package io.prometheus.otelagent;
import static java.nio.file.Files.createTempDirectory;
@@ -11,6 +11,8 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
public class ResourceAttributesFromOtelAgent {
@@ -31,8 +33,11 @@ public class ResourceAttributesFromOtelAgent {
*
* After that we discard the class loader so that all OTel specific classes are unloaded. No
* runtime dependency on any OTel version remains.
+ *
+ *
The test for this class is in
+ * examples/example-exporter-opentelemetry/oats-tests/agent/service-instance-id-check.py
*/
- public static void addIfAbsent(Map result, String instrumentationScopeName) {
+ public static Map getResourceAttributes(String instrumentationScopeName) {
try {
Path tmpDir = createTempDirectory(instrumentationScopeName + "-");
try {
@@ -43,7 +48,7 @@ public static void addIfAbsent(Map result, String instrumentatio
classLoader.loadClass("io.opentelemetry.api.GlobalOpenTelemetry");
Object globalOpenTelemetry = globalOpenTelemetryClass.getMethod("get").invoke(null);
if (globalOpenTelemetry.getClass().getSimpleName().contains("ApplicationOpenTelemetry")) {
- // GlobalOpenTelemetry is injected by the OTel Java aqent
+ // GlobalOpenTelemetry is injected by the OTel Java agent
Object applicationMeterProvider = callMethod("getMeterProvider", globalOpenTelemetry);
Object agentMeterProvider = getField("agentMeterProvider", applicationMeterProvider);
Object sdkMeterProvider = getField("delegate", agentMeterProvider);
@@ -52,11 +57,13 @@ public static void addIfAbsent(Map result, String instrumentatio
Object attributes = callMethod("getAttributes", resource);
Map, ?> attributeMap = (Map, ?>) callMethod("asMap", attributes);
+ Map result = new HashMap<>();
for (Map.Entry, ?> entry : attributeMap.entrySet()) {
if (entry.getKey() != null && entry.getValue() != null) {
- result.putIfAbsent(entry.getKey().toString(), entry.getValue().toString());
+ result.put(entry.getKey().toString(), entry.getValue().toString());
}
}
+ return Collections.unmodifiableMap(result);
}
}
} finally {
@@ -65,6 +72,7 @@ public static void addIfAbsent(Map result, String instrumentatio
} catch (Exception ignored) {
// ignore
}
+ return Collections.emptyMap();
}
private static Object getField(String name, Object obj) throws Exception {
diff --git a/prometheus-metrics-exporter-opentelemetry/src/main/resources/lib/.gitignore b/otel-agent-resources/src/main/resources/lib/.gitignore
similarity index 100%
rename from prometheus-metrics-exporter-opentelemetry/src/main/resources/lib/.gitignore
rename to otel-agent-resources/src/main/resources/lib/.gitignore
diff --git a/pom.xml b/pom.xml
index 4b62d968f..273f97881 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,7 +18,7 @@
UTF-8
--module-name-need-to-be-overriden--
5.11.2
- 1.42.1
+ 2.8.0-alpha
8
@@ -73,6 +73,7 @@
prometheus-metrics-instrumentation-dropwizard5
prometheus-metrics-instrumentation-guava
prometheus-metrics-simpleclient-bridge
+ otel-agent-resources
@@ -100,6 +101,12 @@
3.26.3
test
+
+ org.slf4j
+ slf4j-simple
+ 1.7.36
+ test
+
@@ -236,7 +243,7 @@
${java.version}
true
- -Xlint:all
+ -Xlint:all,-serial,-processing
-Werror
-XDcompilePolicy=simple
diff --git a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterOpenTelemetryProperties.java b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterOpenTelemetryProperties.java
index b8498d6c5..d009d2603 100644
--- a/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterOpenTelemetryProperties.java
+++ b/prometheus-metrics-config/src/main/java/io/prometheus/metrics/config/ExporterOpenTelemetryProperties.java
@@ -8,22 +8,23 @@ public class ExporterOpenTelemetryProperties {
// See
// https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/autoconfigure/README.md
- private static String PROTOCOL = "protocol"; // otel.exporter.otlp.protocol
- private static String ENDPOINT = "endpoint"; // otel.exporter.otlp.endpoint
- private static String HEADERS = "headers"; // otel.exporter.otlp.headers
- private static String INTERVAL_SECONDS = "intervalSeconds"; // otel.metric.export.interval
- private static String TIMEOUT_SECONDS = "timeoutSeconds"; // otel.exporter.otlp.timeout
- private static String SERVICE_NAME = "serviceName"; // otel.service.name
- private static String SERVICE_NAMESPACE = "serviceNamespace";
- private static String SERVICE_INSTANCE_ID = "serviceInstanceId";
- private static String SERVICE_VERSION = "serviceVersion";
- private static String RESOURCE_ATTRIBUTES = "resourceAttributes"; // otel.resource.attributes
+ private static final String PROTOCOL = "protocol"; // otel.exporter.otlp.protocol
+ private static final String ENDPOINT = "endpoint"; // otel.exporter.otlp.endpoint
+ private static final String HEADERS = "headers"; // otel.exporter.otlp.headers
+ private static final String INTERVAL_SECONDS = "intervalSeconds"; // otel.metric.export.interval
+ private static final String TIMEOUT_SECONDS = "timeoutSeconds"; // otel.exporter.otlp.timeout
+ private static final String SERVICE_NAME = "serviceName"; // otel.service.name
+ private static final String SERVICE_NAMESPACE = "serviceNamespace";
+ private static final String SERVICE_INSTANCE_ID = "serviceInstanceId";
+ private static final String SERVICE_VERSION = "serviceVersion";
+ private static final String RESOURCE_ATTRIBUTES =
+ "resourceAttributes"; // otel.resource.attributes
private final String protocol;
private final String endpoint;
private final Map headers;
- private final Integer intervalSeconds;
- private final Integer timeoutSeconds;
+ private final String interval;
+ private final String timeout;
private final String serviceName;
private final String serviceNamespace;
private final String serviceInstanceId;
@@ -34,8 +35,8 @@ private ExporterOpenTelemetryProperties(
String protocol,
String endpoint,
Map headers,
- Integer intervalSeconds,
- Integer timeoutSeconds,
+ String interval,
+ String timeout,
String serviceName,
String serviceNamespace,
String serviceInstanceId,
@@ -44,8 +45,8 @@ private ExporterOpenTelemetryProperties(
this.protocol = protocol;
this.endpoint = endpoint;
this.headers = headers;
- this.intervalSeconds = intervalSeconds;
- this.timeoutSeconds = timeoutSeconds;
+ this.interval = interval;
+ this.timeout = timeout;
this.serviceName = serviceName;
this.serviceNamespace = serviceNamespace;
this.serviceInstanceId = serviceInstanceId;
@@ -65,12 +66,12 @@ public Map getHeaders() {
return headers;
}
- public Integer getIntervalSeconds() {
- return intervalSeconds;
+ public String getInterval() {
+ return interval;
}
- public Integer getTimeoutSeconds() {
- return timeoutSeconds;
+ public String getTimeout() {
+ return timeout;
}
public String getServiceName() {
@@ -102,27 +103,20 @@ static ExporterOpenTelemetryProperties load(String prefix, Map