Skip to content

Commit 094a1cb

Browse files
committed
Disable logger exporter metrics if metrics disabled.
Clarify documentation of properties enabling OTel logs and metrics
1 parent b11cdaf commit 094a1cb

File tree

9 files changed

+293
-2
lines changed

9 files changed

+293
-2
lines changed

extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/OpenTelemetryProcessor.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.quarkus.opentelemetry.deployment;
22

3+
import static io.quarkus.bootstrap.classloading.QuarkusClassLoader.isClassPresentAtRuntime;
34
import static io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem.SPI_ROOT;
45
import static io.quarkus.opentelemetry.runtime.OpenTelemetryRecorder.OPEN_TELEMETRY_DRIVER;
56
import static java.util.stream.Collectors.toList;
@@ -8,6 +9,7 @@
89
import java.util.List;
910
import java.util.Set;
1011
import java.util.function.Predicate;
12+
import java.util.logging.Level;
1113

1214
import jakarta.enterprise.inject.Instance;
1315
import jakarta.inject.Singleton;
@@ -57,6 +59,7 @@
5759
import io.quarkus.deployment.annotations.Record;
5860
import io.quarkus.deployment.builditem.ApplicationInfoBuildItem;
5961
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
62+
import io.quarkus.deployment.builditem.LogCategoryBuildItem;
6063
import io.quarkus.deployment.builditem.RemovedResourceBuildItem;
6164
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
6265
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
@@ -65,6 +68,7 @@
6568
import io.quarkus.deployment.util.ServiceUtil;
6669
import io.quarkus.maven.dependency.ArtifactKey;
6770
import io.quarkus.opentelemetry.OpenTelemetryDestroyer;
71+
import io.quarkus.opentelemetry.deployment.metric.MetricProcessor;
6872
import io.quarkus.opentelemetry.runtime.AutoConfiguredOpenTelemetrySdkBuilderCustomizer;
6973
import io.quarkus.opentelemetry.runtime.DelayedAttributes;
7074
import io.quarkus.opentelemetry.runtime.OpenTelemetryRecorder;
@@ -94,6 +98,15 @@ public boolean test(AnnotationInstance annotationInstance) {
9498
private static final DotName ADD_SPAN_ATTRIBUTES_INTERCEPTOR = DotName
9599
.createSimple(AddingSpanAttributesInterceptor.class.getName());
96100

101+
@BuildStep(onlyIfNot = MetricProcessor.MetricEnabled.class)
102+
void disableMetricLogExporter(BuildProducer<LogCategoryBuildItem> log) {
103+
if (isClassPresentAtRuntime(
104+
"io.opentelemetry.exporter.logging.LoggingMetricExporter")) {
105+
log.produce(new LogCategoryBuildItem(
106+
"io.opentelemetry.exporter.logging.LoggingMetricExporter", Level.OFF));
107+
}
108+
}
109+
97110
@BuildStep
98111
AdditionalBeanBuildItem ensureProducerIsRetained() {
99112
return AdditionalBeanBuildItem.builder()

extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/config/build/LogsBuildConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public interface LogsBuildConfig {
1414
* This property is not available in the Open Telemetry SDK. It's Quarkus specific.
1515
* <p>
1616
* Support for logs will be enabled if OpenTelemetry support is enabled
17-
* and either this value is true, or this value is unset.
17+
* and either this value is true.
1818
*/
1919
@WithDefault("false")
2020
Optional<Boolean> enabled();

extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/config/build/MetricsBuildConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public interface MetricsBuildConfig {
1515
* This property is not available in the Open Telemetry SDK. It's Quarkus specific.
1616
* <p>
1717
* Support for metrics will be enabled if OpenTelemetry support is enabled
18-
* and either this value is true, or this value is unset.
18+
* and either this value is true.
1919
*/
2020
@WithDefault("false")
2121
Optional<Boolean> enabled();
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<groupId>io.quarkus</groupId>
9+
<artifactId>quarkus-integration-tests-parent</artifactId>
10+
<version>999-SNAPSHOT</version>
11+
</parent>
12+
13+
<artifactId>quarkus-integration-test-opentelemetry-exporter-logging</artifactId>
14+
<name>Quarkus - Integration Tests - OpenTelemetry exporter logging</name>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>io.quarkus</groupId>
19+
<artifactId>quarkus-rest-jackson</artifactId>
20+
</dependency>
21+
<dependency>
22+
<groupId>io.quarkus</groupId>
23+
<artifactId>quarkus-opentelemetry</artifactId>
24+
</dependency>
25+
<dependency>
26+
<groupId>io.opentelemetry</groupId>
27+
<artifactId>opentelemetry-exporter-logging</artifactId>
28+
</dependency>
29+
<dependency>
30+
<groupId>io.quarkus</groupId>
31+
<artifactId>quarkus-arc</artifactId>
32+
</dependency>
33+
<dependency>
34+
<groupId>io.quarkus</groupId>
35+
<artifactId>quarkus-junit5</artifactId>
36+
<scope>test</scope>
37+
</dependency>
38+
<dependency>
39+
<groupId>org.assertj</groupId>
40+
<artifactId>assertj-core</artifactId>
41+
<scope>test</scope>
42+
</dependency>
43+
<dependency>
44+
<groupId>org.awaitility</groupId>
45+
<artifactId>awaitility</artifactId>
46+
<scope>test</scope>
47+
</dependency>
48+
<dependency>
49+
<groupId>io.rest-assured</groupId>
50+
<artifactId>rest-assured</artifactId>
51+
<scope>test</scope>
52+
</dependency>
53+
<!-- Minimal test dependencies to *-deployment artifacts for consistent build order -->
54+
<dependency>
55+
<groupId>io.quarkus</groupId>
56+
<artifactId>quarkus-arc-deployment</artifactId>
57+
<version>${project.version}</version>
58+
<type>pom</type>
59+
<scope>test</scope>
60+
<exclusions>
61+
<exclusion>
62+
<groupId>*</groupId>
63+
<artifactId>*</artifactId>
64+
</exclusion>
65+
</exclusions>
66+
</dependency>
67+
<dependency>
68+
<groupId>io.quarkus</groupId>
69+
<artifactId>quarkus-opentelemetry-deployment</artifactId>
70+
<version>${project.version}</version>
71+
<type>pom</type>
72+
<scope>test</scope>
73+
<exclusions>
74+
<exclusion>
75+
<groupId>*</groupId>
76+
<artifactId>*</artifactId>
77+
</exclusion>
78+
</exclusions>
79+
</dependency>
80+
<dependency>
81+
<groupId>io.quarkus</groupId>
82+
<artifactId>quarkus-rest-jackson-deployment</artifactId>
83+
<version>${project.version}</version>
84+
<type>pom</type>
85+
<scope>test</scope>
86+
<exclusions>
87+
<exclusion>
88+
<groupId>*</groupId>
89+
<artifactId>*</artifactId>
90+
</exclusion>
91+
</exclusions>
92+
</dependency>
93+
94+
</dependencies>
95+
96+
<build>
97+
<plugins>
98+
<plugin>
99+
<groupId>io.quarkus</groupId>
100+
<artifactId>quarkus-maven-plugin</artifactId>
101+
<executions>
102+
<execution>
103+
<goals>
104+
<goal>build</goal>
105+
</goals>
106+
</execution>
107+
</executions>
108+
</plugin>
109+
<plugin>
110+
<groupId>org.apache.maven.plugins</groupId>
111+
<artifactId>maven-surefire-plugin</artifactId>
112+
<configuration>
113+
<systemPropertyVariables>
114+
<vertx.disableWebsockets>false</vertx.disableWebsockets>
115+
</systemPropertyVariables>
116+
</configuration>
117+
</plugin>
118+
</plugins>
119+
</build>
120+
121+
<profiles>
122+
<profile>
123+
<id>native-image</id>
124+
<activation>
125+
<property>
126+
<name>native</name>
127+
</property>
128+
</activation>
129+
130+
<properties>
131+
<quarkus.native.enabled>true</quarkus.native.enabled>
132+
</properties>
133+
134+
<build>
135+
<plugins>
136+
<plugin>
137+
<groupId>org.apache.maven.plugins</groupId>
138+
<artifactId>maven-surefire-plugin</artifactId>
139+
<configuration>
140+
<skipTests>${native.surefire.skip}</skipTests>
141+
<systemPropertyVariables>
142+
<vertx.disableWebsockets>false</vertx.disableWebsockets>
143+
</systemPropertyVariables>
144+
</configuration>
145+
</plugin>
146+
147+
<plugin>
148+
<artifactId>maven-failsafe-plugin</artifactId>
149+
<executions>
150+
<execution>
151+
<goals>
152+
<goal>integration-test</goal>
153+
<goal>verify</goal>
154+
</goals>
155+
<configuration>
156+
<systemPropertyVariables>
157+
<vertx.disableWebsockets>false</vertx.disableWebsockets>
158+
<native.image.path>
159+
${project.build.directory}/${project.build.finalName}-runner
160+
</native.image.path>
161+
</systemPropertyVariables>
162+
</configuration>
163+
</execution>
164+
</executions>
165+
</plugin>
166+
</plugins>
167+
</build>
168+
</profile>
169+
</profiles>
170+
</project>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.acme;
2+
3+
import io.quarkus.logging.Log;
4+
import jakarta.ws.rs.GET;
5+
import jakarta.ws.rs.Path;
6+
import jakarta.ws.rs.Produces;
7+
import jakarta.ws.rs.core.MediaType;
8+
9+
@Path("/hello")
10+
public class GreetingResource {
11+
12+
@GET
13+
@Produces(MediaType.TEXT_PLAIN)
14+
public String hello() {
15+
Log.info("request received");
16+
return "Hello from Quarkus REST";
17+
}
18+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
quarkus.application.name=myservice
2+
quarkus.otel.metrics.exporter=logging
3+
# Force quick output of metrics to increase test reliability.
4+
quarkus.otel.metric.export.interval=100ms
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package org.acme;
2+
3+
import io.quarkus.test.junit.QuarkusIntegrationTest;
4+
5+
@QuarkusIntegrationTest
6+
class LoggingMetricsNotPresentIT extends LoggingMetricsNotPresentTest {
7+
// Execute the same tests but in packaged mode.
8+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package org.acme;
2+
3+
import io.quarkus.test.junit.QuarkusTest;
4+
import org.junit.jupiter.api.Test;
5+
6+
import java.util.ArrayList;
7+
import java.util.logging.Handler;
8+
import java.util.logging.LogManager;
9+
import java.util.logging.LogRecord;
10+
import java.util.logging.Logger;
11+
12+
import static io.restassured.RestAssured.given;
13+
import static org.assertj.core.api.Assertions.assertThat;
14+
import static org.awaitility.Awaitility.await;
15+
import static org.hamcrest.Matchers.is;
16+
17+
@QuarkusTest
18+
class LoggingMetricsNotPresentTest {
19+
20+
@Test
21+
void testHelloEndpoint() throws InterruptedException {
22+
23+
final TestingJulHandler julHandler = new TestingJulHandler();
24+
final Logger rootLogger = LogManager.getLogManager().getLogger("");
25+
rootLogger.addHandler(julHandler);
26+
27+
Thread.sleep(100);// give time to export metrics records (but must not be there)
28+
29+
given()
30+
.when().get("/hello")
31+
.then()
32+
.statusCode(200)
33+
.body(is("Hello from Quarkus REST"));
34+
35+
await().untilAsserted(() -> {
36+
assertThat(julHandler.logRecords).hasSizeGreaterThanOrEqualTo(1);
37+
});
38+
39+
ArrayList<LogRecord> logRecords = julHandler.logRecords;
40+
rootLogger.removeHandler(julHandler);
41+
42+
assertThat(logRecords.stream()
43+
.anyMatch(logRecord -> logRecord.getLoggerName().startsWith(GreetingResource.class.getName())))
44+
.as( "Log line from the service must be logged")
45+
.isTrue();
46+
// Only present if opentelemetry-exporter-logging is used
47+
// But we are turning it off if metrics are disabled
48+
assertThat(logRecords.stream()
49+
.noneMatch(logRecord -> logRecord.getLoggerName().startsWith("io.opentelemetry.exporter.logging.LoggingMetricExporter")))
50+
.as("Log lines from the OTel logging metrics exporter must NOT be logged")
51+
.isTrue();
52+
}
53+
54+
private static class TestingJulHandler extends Handler {
55+
56+
private final ArrayList<LogRecord> logRecords = new ArrayList<>();
57+
58+
public ArrayList<LogRecord> getLogRecords() {
59+
return logRecords;
60+
}
61+
62+
@Override
63+
public void publish(LogRecord record) {
64+
logRecords.add(record);
65+
}
66+
67+
@Override
68+
public void flush() {
69+
// Do nothing
70+
}
71+
72+
@Override
73+
public void close() throws SecurityException {
74+
// Do nothing
75+
}
76+
}
77+
}

integration-tests/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@
384384
<module>opentelemetry-vertx-exporter</module>
385385
<module>opentelemetry-reactive-messaging</module>
386386
<module>opentelemetry-redis-instrumentation</module>
387+
<module>opentelemetry-exporter-logging</module>
387388
<module>logging-json</module>
388389
<module>jaxb</module>
389390
<module>jaxp</module>

0 commit comments

Comments
 (0)