diff --git a/pom.xml b/pom.xml
index 6ea3dd6e6..a1f7e80aa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,44 @@
+
+
+
+
+ io.opentelemetry
+ opentelemetry-bom
+ 1.12.0
+ pom
+ import
+
+
+
+
+
+
+ io.opentelemetry
+ opentelemetry-api
+
+
+ io.opentelemetry
+ opentelemetry-api
+
+
+ io.opentelemetry
+ opentelemetry-sdk
+
+
+ io.opentelemetry
+ opentelemetry-exporter-otlp-http-trace
+
+
+ io.opentelemetry
+ opentelemetry-semconv
+ 1.12.0-alpha
+
+
+
org.springframework.boot
diff --git a/run.sh b/run.sh
new file mode 100644
index 000000000..d62321bc5
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+
+OTEL_RESOURCE_ATTRIBUTES="service.name=spring-petclinic,service.version=1.0.0"
+
+
+java -jar target/spring-petclinic-3.0.0-SNAPSHOT.jar
\ No newline at end of file
diff --git a/src/main/java/org/springframework/samples/petclinic/OpenTelemetryInstrumentation.java b/src/main/java/org/springframework/samples/petclinic/OpenTelemetryInstrumentation.java
new file mode 100644
index 000000000..c38e60fa1
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/OpenTelemetryInstrumentation.java
@@ -0,0 +1,31 @@
+
+package org.springframework.samples.petclinic;
+import io.opentelemetry.api.GlobalOpenTelemetry;
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.api.trace.Tracer;
+import io.opentelemetry.context.Scope;
+
+
+public class OpenTelemetryInstrumentation {
+
+ public static void instrumentTracing() {
+ Tracer tracer = GlobalOpenTelemetry
+ .getTracerProvider()
+ .tracerBuilder("my-tracer") //TODO Replace with the name of your tracer
+ .build();
+
+ Span span = tracer
+ .spanBuilder("my-span") //TODO Replace with the name of your span
+ .setAttribute("my-key-1", "my-value-1") //TODO Add initial attributes
+ .startSpan();
+
+ try (Scope scope = span.makeCurrent()) {
+ span.setAttribute("key-2", "value-2"); //TODO Add extra attributes if necessary
+ //TODO your code goes here
+ } finally {
+ span.end();
+
+ }
+
+ }
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/OtelExporter.java b/src/main/java/org/springframework/samples/petclinic/OtelExporter.java
new file mode 100644
index 000000000..d02c64c98
--- /dev/null
+++ b/src/main/java/org/springframework/samples/petclinic/OtelExporter.java
@@ -0,0 +1,70 @@
+package org.springframework.samples.petclinic;
+import io.opentelemetry.api.common.AttributeKey;
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
+import io.opentelemetry.context.propagation.ContextPropagators;
+import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
+import io.opentelemetry.sdk.OpenTelemetrySdk;
+import io.opentelemetry.sdk.resources.Resource;
+import io.opentelemetry.sdk.trace.SdkTracerProvider;
+import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
+import io.opentelemetry.sdk.trace.export.SpanExporter;
+import io.opentelemetry.sdk.trace.samplers.Sampler;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.stream.Stream;
+
+
+
+public class OtelExporter {
+ public static void initOpenTelemetry() throws IOException {
+ Resource serviceName = Optional.ofNullable(System.getenv("petClinic"))
+ .map(n -> Attributes.of(AttributeKey.stringKey("springPetClinic"), n))
+ .map(Resource::create)
+ .orElseGet(Resource::empty);
+
+ Resource envResourceAttributes = Resource.create(Stream.of(Optional.ofNullable(System.getenv("OTEL_RESOURCE_ATTRIBUTES")).orElse("").split(","))
+ .filter(pair -> pair != null && pair.length() > 0 && pair.contains("="))
+ .map(pair -> pair.split("="))
+ .filter(pair -> pair.length == 2)
+ .collect(Attributes::builder, (b, p) -> b.put(p[0], p[1]), (b1, b2) -> b1.putAll(b2.build()))
+ .build()
+ );
+
+
+ Resource dtMetadata = Resource.empty();
+ for (String name : new String[] {"dt_metadata_e617c525669e072eebe3d0f08212e8f2.properties", "/var/lib/dynatrace/enrichment/dt_metadata.properties"}) {
+ try {
+ Properties props = new Properties();
+ props.load(name.startsWith("/var") ? new FileInputStream(name) : new FileInputStream(Files.readAllLines(Paths.get(name)).get(0)));
+ dtMetadata = dtMetadata.merge(Resource.create(props.entrySet().stream()
+ .collect(Attributes::builder, (b, e) -> b.put(e.getKey().toString(), e.getValue().toString()), (b1, b2) -> b1.putAll(b2.build()))
+ .build())
+ );
+ } catch (IOException e) {}
+ }
+
+
+ SpanExporter exporter = OtlpHttpSpanExporter.builder()
+ .setEndpoint("http://englab-tdbank.datadog.hq.com") //TODO Replace to your SaaS/Managed-URL as mentioned in the next step
+ .addHeader("Authorization", "93ffd05f8f2a91e0b8a22e476e1bb3c6a3de5dcd") //TODO Replace with your API Token as mentioned in the next step
+ .build();
+
+ SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
+ .setResource(Resource.getDefault().merge(envResourceAttributes).merge(serviceName).merge(dtMetadata))
+ .setSampler(Sampler.alwaysOn())
+ .addSpanProcessor(BatchSpanProcessor.builder(exporter).build())
+ .build();
+
+ OpenTelemetrySdk.builder()
+ .setTracerProvider(sdkTracerProvider)
+ .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
+ .buildAndRegisterGlobal();
+ Runtime.getRuntime().addShutdownHook(new Thread(sdkTracerProvider::close));
+ }
+}
diff --git a/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java b/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java
index ac6e15030..88b12e7b7 100644
--- a/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java
+++ b/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java
@@ -14,24 +14,31 @@
* limitations under the License.
*/
-package org.springframework.samples.petclinic;
+ package org.springframework.samples.petclinic;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.annotation.ImportRuntimeHints;
+ import org.aspectj.apache.bcel.classfile.Module;
+ import org.springframework.boot.SpringApplication;
+ import org.springframework.boot.autoconfigure.SpringBootApplication;
+ import org.springframework.context.annotation.ImportRuntimeHints;
+
+ import java.io.IOException;
/**
- * PetClinic Spring Boot Application.
- *
- * @author Dave Syer
- *
- */
-@SpringBootApplication
-@ImportRuntimeHints(PetClinicRuntimeHints.class)
-public class PetClinicApplication {
+ * PetClinic Spring Boot Application.
+ *
+ * @author Dave Syer
+ *
+ */
+ @SpringBootApplication
+ @ImportRuntimeHints(PetClinicRuntimeHints.class)
+ public class PetClinicApplication {
- public static void main(String[] args) {
- SpringApplication.run(PetClinicApplication.class, args);
- }
+ public static void main(String[] args) throws IOException {
+ OtelExporter.initOpenTelemetry();
+ OpenTelemetryInstrumentation.instrumentTracing();
+ SpringApplication.run(PetClinicApplication.class, args);
-}
+
+ }
+
+ }