diff --git a/examples/microprofile/README.md b/examples/microprofile/README.md index f678273b5c4..da6de0afa86 100644 --- a/examples/microprofile/README.md +++ b/examples/microprofile/README.md @@ -1,3 +1,64 @@ -# Helidon MP Examples +# Helidon MicroProfile Telemetry Example -This directory contains Helidon MP examples. +This example implements demonstrates usage of MP Telemetry Tracing. + +## Build and run + +With JDK17+ +```bash +mvn package +java -jar greeting/target/helidon-examples-microprofile-telemetry-greeting.jar +``` + +Run Jaeger tracer. If you prefer to use Docker, run in terminal: +```bash +docker run -d --name jaeger \ + -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \ + -e COLLECTOR_OTLP_ENABLED=true \ + -p 6831:6831/udp \ + -p 6832:6832/udp \ + -p 5778:5778 \ + -p 16686:16686 \ + -p 4317:4317 \ + -p 4318:4318 \ + -p 14250:14250 \ + -p 14268:14268 \ + -p 14269:14269 \ + -p 9411:9411 \ + jaegertracing/all-in-one:1.43 +``` + +If you have Jaeger all-in-one installed, use this command: + +```bash +jaeger-all-in-one --collector.zipkin.host-port=9411 --collector.otlp.enabled=true +``` + +Run the Secondary service: + +With JDK17+ +```bash +mvn package +java -jar secondary/target/helidon-examples-microprofile-telemetry-secondary.jar +``` + +## Exercise the application + +``` +curl -X GET http://localhost:8080/greet +"Hello World!" + +curl -X GET http://localhost:8080/greet/span +{"Span":"PropagatedSpan{ImmutableSpanContext{traceId=00000000000000000000000000000000, spanId=0000000000000000, traceFlags=00, traceState=ArrayBasedTraceState{entries=[]}, remote=false, valid=false}}"} + +curl -X GET http://localhost:8080/greet/custom +{ + "Custom Span": "SdkSpan{traceId=bea7da56d1fe82400af8ec0a8adb370d, spanId=57647ead5dc32ae7, parentSpanContext=ImmutableSpanContext{traceId=bea7da56d1fe82400af8ec0a8adb370d, spanId=0ca670f1e3330ea5, traceFlags=01, traceState=ArrayBasedTraceState{entries=[]}, remote=false, valid=true}, name=custom, kind=INTERNAL, attributes=AttributesMap{data={attribute=value}, capacity=128, totalAddedValues=1}, status=ImmutableStatusData{statusCode=UNSET, description=}, totalRecordedEvents=0, totalRecordedLinks=0, startEpochNanos=1683724682576003542, endEpochNanos=1683724682576006000}" +} + +curl -X GET http://localhost:8080/greet/outbound +Secondary + +``` + +Proceed Jaeger UI http://localhost:16686. In the top-down menu select "greeting-service" and click "Find traces". Tracing information should become available. \ No newline at end of file diff --git a/examples/microprofile/pom.xml b/examples/microprofile/pom.xml index 55dd9b7821c..959ad1a86f2 100644 --- a/examples/microprofile/pom.xml +++ b/examples/microprofile/pom.xml @@ -49,5 +49,6 @@ bean-validation http-status-count-mp lra + telemetry diff --git a/examples/microprofile/telemetry/README.md b/examples/microprofile/telemetry/README.md new file mode 100644 index 00000000000..d7d3baf46ed --- /dev/null +++ b/examples/microprofile/telemetry/README.md @@ -0,0 +1,64 @@ +# Helidon MicroProfile Telemetry Example + +This example implements demonstrates usage of MP Telemetry Tracing. + +## Build and run + +With JDK17+ +```bash +mvn package +java -jar greeting/target/helidon-examples-microprofile-telemetry-greeting.jar +``` + +Run Jaeger tracer. If you prefer to use Docker, run in terminal: +```bash +docker run -d --name jaeger \ + -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \ + -e COLLECTOR_OTLP_ENABLED=true \ + -p 6831:6831/udp \ + -p 6832:6832/udp \ + -p 5778:5778 \ + -p 16686:16686 \ + -p 4317:4317 \ + -p 4318:4318 \ + -p 14250:14250 \ + -p 14268:14268 \ + -p 14269:14269 \ + -p 9411:9411 \ + jaegertracing/all-in-one:1.43 +``` + +If you have Jaeger all-in-one installed, use this command: + +```bash +jaeger-all-in-one --collector.zipkin.host-port=9411 --collector.otlp.enabled=true +``` + +Run the Secondary service: + +With JDK17+ +```bash +mvn package +java -jar secondary/target/helidon-examples-microprofile-telemetry-secondary.jar +``` + +## Exercise the application + +``` +curl -X GET http://localhost:8080/greet +"Hello World!" + +curl -X GET http://localhost:8080/greet/span +{"Span":"PropagatedSpan{ImmutableSpanContext{traceId=00000000000000000000000000000000, spanId=0000000000000000, traceFlags=00, traceState=ArrayBasedTraceState{entries=[]}, remote=false, valid=false}}"} + +curl -X GET http://localhost:8080/greet/custom +{ + "Custom Span": "SdkSpan{traceId=bea7da56d1fe82400af8ec0a8adb370d, spanId=57647ead5dc32ae7, parentSpanContext=ImmutableSpanContext{traceId=bea7da56d1fe82400af8ec0a8adb370d, spanId=0ca670f1e3330ea5, traceFlags=01, traceState=ArrayBasedTraceState{entries=[]}, remote=false, valid=true}, name=custom, kind=INTERNAL, attributes=AttributesMap{data={attribute=value}, capacity=128, totalAddedValues=1}, status=ImmutableStatusData{statusCode=UNSET, description=}, totalRecordedEvents=0, totalRecordedLinks=0, startEpochNanos=1683724682576003542, endEpochNanos=1683724682576006000}" +} + +curl -X GET http://localhost:8080/greet/outbound +Secondary + +``` + +Proceed Jaeger UI http://localhost:16686. In the top-down menu select "greeting-service" and click "Find traces". Tracing information should become available. \ No newline at end of file diff --git a/examples/microprofile/telemetry/greeting/pom.xml b/examples/microprofile/telemetry/greeting/pom.xml new file mode 100644 index 00000000000..7f8a1996ff1 --- /dev/null +++ b/examples/microprofile/telemetry/greeting/pom.xml @@ -0,0 +1,77 @@ + + + + + 4.0.0 + + io.helidon.applications + helidon-mp + 4.0.0-SNAPSHOT + ../../../../applications/mp/pom.xml + + io.helidon.examples.microprofile + helidon-examples-microprofile-telemetry-greeting + Microprofile Telemetry Greeting Example + + + + io.helidon.microprofile.bundles + helidon-microprofile + + + io.opentelemetry + opentelemetry-exporter-jaeger + + + io.helidon.microprofile.telemetry + helidon-microprofile-telemetry + + + io.smallrye + jandex + runtime + true + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-libs + + + + + io.smallrye + jandex-maven-plugin + + + make-index + + + + + + diff --git a/examples/microprofile/telemetry/greeting/src/main/java/io/helidon/examples/microprofile/telemetry/GreetResource.java b/examples/microprofile/telemetry/greeting/src/main/java/io/helidon/examples/microprofile/telemetry/GreetResource.java new file mode 100644 index 00000000000..ffecee136b5 --- /dev/null +++ b/examples/microprofile/telemetry/greeting/src/main/java/io/helidon/examples/microprofile/telemetry/GreetResource.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.examples.microprofile.telemetry; + +import java.util.Collections; + +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.instrumentation.annotations.WithSpan; +import jakarta.inject.Inject; +import jakarta.json.Json; +import jakarta.json.JsonBuilderFactory; +import jakarta.json.JsonObject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.MediaType; +import org.glassfish.jersey.server.Uri; + + +/** + * A simple JAX-RS resource to greet you. Examples: + * + * Get default greeting message: + * curl -X GET http://localhost:8080/greet + * + * Get Span information: + * curl -X GET http://localhost:8080/greet/span + * + * Call secondary service: + * curl -X GET http://localhost:8080/greet/outbound + */ +@Path("/greet") +public class GreetResource { + + private static final JsonBuilderFactory JSON = Json.createBuilderFactory(Collections.emptyMap()); + + private Span span; + + private Tracer tracer; + + @Uri("http://localhost:8081/secondary") + private WebTarget target; + + @Inject + GreetResource(Span span, Tracer tracer) { + this.span = span; + this.tracer = tracer; + } + + /** + * Return a worldly greeting message. + * + * @return {@link String} + */ + @GET + @WithSpan("default") + public String getDefaultMessage() { + return "Hello World"; + } + + /** + * Create an internal custom span and return its description. + * @return {@link JsonObject} + */ + @GET + @Path("custom") + @Produces(MediaType.APPLICATION_JSON) + @WithSpan + public JsonObject useCustomSpan(){ + Span span = tracer.spanBuilder("custom") + .setSpanKind(SpanKind.INTERNAL) + .setAttribute("attribute", "value") + .startSpan(); + span.end(); + + return JSON.createObjectBuilder() + .add("Custom Span", span.toString()) + .build(); + } + /** + * Get Span info. + * + * @return {@link JsonObject} + */ + @GET + @Path("span") + @Produces(MediaType.APPLICATION_JSON) + @WithSpan + public JsonObject getSpanInfo(){ + return JSON.createObjectBuilder() + .add("Span", span.toString()) + .build(); + } + + /** + * Call the secondary service running on port 8081. + * + * @return String from the secondary service. + */ + @GET + @Path("/outbound") + @WithSpan("outbound") + public String outbound() { + return target.request().accept(MediaType.TEXT_PLAIN).get(String.class); + } + +} diff --git a/examples/microprofile/telemetry/greeting/src/main/java/io/helidon/examples/microprofile/telemetry/package-info.java b/examples/microprofile/telemetry/greeting/src/main/java/io/helidon/examples/microprofile/telemetry/package-info.java new file mode 100644 index 00000000000..23dff1e8930 --- /dev/null +++ b/examples/microprofile/telemetry/greeting/src/main/java/io/helidon/examples/microprofile/telemetry/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * MicroProfile Telemetry example. + */ +package io.helidon.examples.microprofile.telemetry; diff --git a/examples/microprofile/telemetry/greeting/src/main/resources/META-INF/beans.xml b/examples/microprofile/telemetry/greeting/src/main/resources/META-INF/beans.xml new file mode 100644 index 00000000000..cf179d28185 --- /dev/null +++ b/examples/microprofile/telemetry/greeting/src/main/resources/META-INF/beans.xml @@ -0,0 +1,25 @@ + + + + diff --git a/examples/microprofile/telemetry/greeting/src/main/resources/META-INF/microprofile-config.properties b/examples/microprofile/telemetry/greeting/src/main/resources/META-INF/microprofile-config.properties new file mode 100644 index 00000000000..a2579922b94 --- /dev/null +++ b/examples/microprofile/telemetry/greeting/src/main/resources/META-INF/microprofile-config.properties @@ -0,0 +1,27 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Microprofile server properties +server.port=8080 +server.host=0.0.0.0 + +# Enable the optional MicroProfile Metrics REST.request metrics +metrics.rest-request.enabled=true + +#OpenTelemtry +otel.sdk.disabled=false +otel.traces.exporter=jaeger +otel.service.name=greeting-service diff --git a/examples/microprofile/telemetry/greeting/src/main/resources/logging.properties b/examples/microprofile/telemetry/greeting/src/main/resources/logging.properties new file mode 100644 index 00000000000..b1d014b4237 --- /dev/null +++ b/examples/microprofile/telemetry/greeting/src/main/resources/logging.properties @@ -0,0 +1,40 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Example Logging Configuration File +# For more information see $JAVA_HOME/jre/lib/logging.properties + +# Send messages to the console +handlers=io.helidon.logging.jul.HelidonConsoleHandler + +# HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread +java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n + +# Global logging level. Can be overridden by specific loggers +.level=INFO + +# Quiet Weld +org.jboss.level=WARNING + +# Component specific log levels +#io.helidon.nima.webserver.level=INFO +#io.helidon.config.level=INFO +#io.helidon.security.level=INFO +#io.helidon.microprofile.level=INFO +#io.helidon.common.level=INFO +#io.netty.level=INFO +#org.glassfish.jersey.level=INFO +#org.jboss.weld=INFO diff --git a/examples/microprofile/telemetry/pom.xml b/examples/microprofile/telemetry/pom.xml new file mode 100644 index 00000000000..0fbbf8843a5 --- /dev/null +++ b/examples/microprofile/telemetry/pom.xml @@ -0,0 +1,37 @@ + + + + 4.0.0 + + io.helidon.examples.microprofile + helidon-examples-microprofile-project + 4.0.0-SNAPSHOT + + io.helidon.examples.telemetry + helidon-examples-microprofile-telemetry + Helidon MP Telemetry Examples + pom + + + greeting + secondary + + diff --git a/examples/microprofile/telemetry/secondary/pom.xml b/examples/microprofile/telemetry/secondary/pom.xml new file mode 100644 index 00000000000..cdd5571cf59 --- /dev/null +++ b/examples/microprofile/telemetry/secondary/pom.xml @@ -0,0 +1,92 @@ + + + + + 4.0.0 + + io.helidon.applications + helidon-mp + 4.0.0-SNAPSHOT + ../../../../applications/mp/pom.xml + + io.helidon.examples.microprofile + helidon-examples-microprofile-telemetry-secondary + Microprofile Telemetry Secondary service + + + + io.helidon.microprofile.bundles + helidon-microprofile + + + io.helidon.microprofile.telemetry + helidon-microprofile-telemetry + + + io.opentelemetry + opentelemetry-exporter-jaeger + + + io.smallrye + jandex + runtime + true + + + org.junit.jupiter + junit-jupiter-api + test + + + org.hamcrest + hamcrest-all + test + + + io.helidon.microprofile.tests + helidon-microprofile-tests-junit5 + test + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-libs + + + + + io.smallrye + jandex-maven-plugin + + + make-index + + + + + + diff --git a/examples/microprofile/telemetry/secondary/src/main/java/io/helidon/examples/microprofile/telemetry/SecondaryResource.java b/examples/microprofile/telemetry/secondary/src/main/java/io/helidon/examples/microprofile/telemetry/SecondaryResource.java new file mode 100644 index 00000000000..1ceef8330f4 --- /dev/null +++ b/examples/microprofile/telemetry/secondary/src/main/java/io/helidon/examples/microprofile/telemetry/SecondaryResource.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.helidon.examples.microprofile.telemetry; + +import java.util.Collections; + +import io.opentelemetry.instrumentation.annotations.WithSpan; +import jakarta.json.Json; +import jakarta.json.JsonBuilderFactory; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; + + + +/** + * A simple JAX-RS resource used by Telemetry Example. + */ +@Path("/secondary") +public class SecondaryResource { + + private static final JsonBuilderFactory JSON = Json.createBuilderFactory(Collections.emptyMap()); + + /** + * Return a secondary message. + * + * @return {@link String} + */ + @GET + @WithSpan + public String getSecondaryMessage() { + return "Secondary"; + } + +} diff --git a/examples/microprofile/telemetry/secondary/src/main/java/io/helidon/examples/microprofile/telemetry/package-info.java b/examples/microprofile/telemetry/secondary/src/main/java/io/helidon/examples/microprofile/telemetry/package-info.java new file mode 100644 index 00000000000..23dff1e8930 --- /dev/null +++ b/examples/microprofile/telemetry/secondary/src/main/java/io/helidon/examples/microprofile/telemetry/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * MicroProfile Telemetry example. + */ +package io.helidon.examples.microprofile.telemetry; diff --git a/examples/microprofile/telemetry/secondary/src/main/resources/META-INF/beans.xml b/examples/microprofile/telemetry/secondary/src/main/resources/META-INF/beans.xml new file mode 100644 index 00000000000..cf179d28185 --- /dev/null +++ b/examples/microprofile/telemetry/secondary/src/main/resources/META-INF/beans.xml @@ -0,0 +1,25 @@ + + + + diff --git a/examples/microprofile/telemetry/secondary/src/main/resources/META-INF/microprofile-config.properties b/examples/microprofile/telemetry/secondary/src/main/resources/META-INF/microprofile-config.properties new file mode 100644 index 00000000000..ec42ced3774 --- /dev/null +++ b/examples/microprofile/telemetry/secondary/src/main/resources/META-INF/microprofile-config.properties @@ -0,0 +1,28 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Microprofile server properties +server.port=8081 +server.host=0.0.0.0 + +# Enable the optional MicroProfile Metrics REST.request metrics +metrics.rest-request.enabled=true + +#OpenTelemtry +otel.sdk.disabled=false +otel.traces.exporter=jaeger +otel.service.name=secondary-service + diff --git a/examples/microprofile/telemetry/secondary/src/main/resources/logging.properties b/examples/microprofile/telemetry/secondary/src/main/resources/logging.properties new file mode 100644 index 00000000000..b1d014b4237 --- /dev/null +++ b/examples/microprofile/telemetry/secondary/src/main/resources/logging.properties @@ -0,0 +1,40 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Example Logging Configuration File +# For more information see $JAVA_HOME/jre/lib/logging.properties + +# Send messages to the console +handlers=io.helidon.logging.jul.HelidonConsoleHandler + +# HelidonConsoleHandler uses a SimpleFormatter subclass that replaces "!thread!" with the current thread +java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$s %3$s !thread!: %5$s%6$s%n + +# Global logging level. Can be overridden by specific loggers +.level=INFO + +# Quiet Weld +org.jboss.level=WARNING + +# Component specific log levels +#io.helidon.nima.webserver.level=INFO +#io.helidon.config.level=INFO +#io.helidon.security.level=INFO +#io.helidon.microprofile.level=INFO +#io.helidon.common.level=INFO +#io.netty.level=INFO +#org.glassfish.jersey.level=INFO +#org.jboss.weld=INFO