From 22de51b24bb272d8412a278d6e1cb3c8a2881871 Mon Sep 17 00:00:00 2001 From: eugene kirillov <3404064+krlv@users.noreply.github.com> Date: Wed, 14 Aug 2024 14:31:02 -0700 Subject: [PATCH] Calendar app: use instrumentation annotations (#127) * Add a dependency on the `opentelemetry-instrumentation-annotations` library to use `@WithSpan` annotation. * Move `getDate` method to the `CalendarService` class. * Update OTel Java Agent to the latest `2.6.0` version * Fix helm instructions in the README --- apps/rest-services/java/calendar/README.md | 6 +- apps/rest-services/java/calendar/build.gradle | 4 +- .../java/calendar/deploys/Dockerfile.otel | 2 +- .../otel/controller/CalendarController.java | 63 +++++++------------ .../main/java/com/otel/main/SpringApp.java | 35 ++++++----- .../com/otel/service/CalendarService.java | 49 +++++++++++++++ 6 files changed, 93 insertions(+), 66 deletions(-) create mode 100644 apps/rest-services/java/calendar/src/main/java/com/otel/service/CalendarService.java diff --git a/apps/rest-services/java/calendar/README.md b/apps/rest-services/java/calendar/README.md index cfa398a..aaecf58 100644 --- a/apps/rest-services/java/calendar/README.md +++ b/apps/rest-services/java/calendar/README.md @@ -2,7 +2,7 @@ ``` GET /calendar -Returns a random date in 2022. +Returns a random date within the current year. ``` ``` @@ -70,11 +70,11 @@ As of now, in order for trace/log correlation to work the `trace_id` key needs t Install calendar in K8s with OTel SDK ``` -helm install -n otel-ingest calendar-otel-java ./calendar/k8s/ --set image.repository=dineshgurumurthydd/calendar-java --set image.tag=otel-0.1,node_group=ng-1 +helm install -n otel-ingest calendar-otel-java ./deploys/calendar/ --set image.repository=dineshgurumurthydd/calendar-java --set image.tag=otel-0.1,node_group=ng-1 ``` Install calendar in K8s with DD SDK ``` -helm install -n otel-ingest calendar-dd-java ./calendar-dd/k8s/ --set image.repository=dineshgurumurthydd/calendar-java --set image.tag=otel-0.1,node_group=ng-1 +helm install -n otel-ingest calendar-dd-java ./deploys/calendar-dd/ --set image.repository=dineshgurumurthydd/calendar-java --set image.tag=otel-0.1,node_group=ng-1 ``` diff --git a/apps/rest-services/java/calendar/build.gradle b/apps/rest-services/java/calendar/build.gradle index 707039e..e79a565 100644 --- a/apps/rest-services/java/calendar/build.gradle +++ b/apps/rest-services/java/calendar/build.gradle @@ -9,7 +9,6 @@ plugins { id 'application' id 'org.springframework.boot' version '3.0.2' id 'io.spring.dependency-management' version '1.1.0' - } repositories { @@ -28,8 +27,7 @@ dependencies { implementation 'org.slf4j:slf4j-api:2.0.6' runtimeOnly 'io.opentelemetry.instrumentation:opentelemetry-logback-appender-1.0:1.28.0-alpha' implementation 'io.opentelemetry:opentelemetry-api:1.28.0' - - + implementation 'io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations:2.6.0' } group = 'com.datadog.example' diff --git a/apps/rest-services/java/calendar/deploys/Dockerfile.otel b/apps/rest-services/java/calendar/deploys/Dockerfile.otel index b04b654..d392100 100644 --- a/apps/rest-services/java/calendar/deploys/Dockerfile.otel +++ b/apps/rest-services/java/calendar/deploys/Dockerfile.otel @@ -6,7 +6,7 @@ FROM openjdk:17-buster RUN apt-get update -y; apt-get install curl -y WORKDIR /home/otel -RUN curl -Lo opentelemetry-javaagent.jar https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v2.4.0/opentelemetry-javaagent.jar +RUN curl -Lo opentelemetry-javaagent.jar https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v2.6.0/opentelemetry-javaagent.jar COPY . calendar/ WORKDIR /home/otel/calendar diff --git a/apps/rest-services/java/calendar/src/main/java/com/otel/controller/CalendarController.java b/apps/rest-services/java/calendar/src/main/java/com/otel/controller/CalendarController.java index 79f1e18..326dc67 100644 --- a/apps/rest-services/java/calendar/src/main/java/com/otel/controller/CalendarController.java +++ b/apps/rest-services/java/calendar/src/main/java/com/otel/controller/CalendarController.java @@ -1,24 +1,15 @@ /* Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2.0 License. + +This product includes software developed at Datadog (https://www.datadoghq.com/) +Copyright 2024 Datadog, Inc. */ package com.otel.controller; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.metrics.DoubleHistogram; -import io.opentelemetry.api.metrics.LongCounter; -import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.api.metrics.ObservableDoubleGauge; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.SpanKind; -import io.opentelemetry.api.trace.Tracer; -import io.opentelemetry.context.Scope; -import java.time.LocalDate; -import java.time.Month; -import java.time.format.DateTimeFormatter; import java.util.Map; -import java.util.Random; import java.util.concurrent.atomic.AtomicLong; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -27,38 +18,45 @@ import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RestController; +import com.otel.service.CalendarService; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.metrics.DoubleHistogram; +import io.opentelemetry.api.metrics.LongCounter; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.api.metrics.ObservableDoubleGauge; + @RestController public class CalendarController { private final Logger log = LoggerFactory.getLogger(CalendarController.class); - private final Tracer tracer; private final LongCounter hitsCounter; private final DoubleHistogram latency; private final ObservableDoubleGauge activeUsersGauge; private final AtomicLong activeUsersCounter; - private final Random random = new Random(); + private final CalendarService calendarService; @Autowired - CalendarController(OpenTelemetry openTelemetry, String serviceName) { + CalendarController(OpenTelemetry openTelemetry, String serviceName, CalendarService service) { log.info("Starting CalendarController for {}", serviceName); - tracer = openTelemetry.getTracer(CalendarController.class.getName()); + Meter meter = openTelemetry.getMeter(CalendarController.class.getName()); hitsCounter = meter.counterBuilder(serviceName + ".api.hits").build(); latency = meter.histogramBuilder(serviceName + ".task.duration").build(); + activeUsersCounter = new AtomicLong(); - activeUsersGauge = meter.gaugeBuilder(serviceName + ".active.users.guage").buildWithCallback(measurement -> measurement.record(activeUsersCounter.get())); - + activeUsersGauge = meter.gaugeBuilder(serviceName + ".active.users.gauge").buildWithCallback(measurement -> measurement.record(activeUsersCounter.get())); + + calendarService = service; } - @GetMapping("/calendar") public Map getDate(@RequestHeader MultiValueMap headers) { long startTime = System.currentTimeMillis(); activeUsersCounter.incrementAndGet(); + try { hitsCounter.add(1); - String output = getDate(); - // the correct JSON output should put this in quotes. Spring does not, so let's put quotes here - // by hand. + String output = calendarService.getDate(); return Map.of("date", output); } finally { long endTime = System.currentTimeMillis(); @@ -66,23 +64,4 @@ public Map getDate(@RequestHeader MultiValueMap activeUsersCounter.decrementAndGet(); } } - - private String getDate() { - Span span = tracer.spanBuilder("getDate").setAttribute("peer.service", "random-date-service").setSpanKind(SpanKind.CLIENT).startSpan(); - try (Scope scope = span.makeCurrent()) { - // get back a random date in the year 2022 - int val = new Random().nextInt(365); - LocalDate start = LocalDate.of(2022, Month.JANUARY, 1).plusDays(val); - String output = start.format(DateTimeFormatter.ISO_LOCAL_DATE); - span.setAttribute("date", output); - // Add random sleep - Thread.sleep(random.nextLong(1,950)); - log.info("generated date: {}", output); - return output; - } catch (InterruptedException e) { - throw new RuntimeException(e); - } finally { - span.end(); - } - } } diff --git a/apps/rest-services/java/calendar/src/main/java/com/otel/main/SpringApp.java b/apps/rest-services/java/calendar/src/main/java/com/otel/main/SpringApp.java index 1af65e3..6c226c4 100644 --- a/apps/rest-services/java/calendar/src/main/java/com/otel/main/SpringApp.java +++ b/apps/rest-services/java/calendar/src/main/java/com/otel/main/SpringApp.java @@ -3,30 +3,31 @@ under the Apache 2.0 License. This product includes software developed at Datadog (https://www.datadoghq.com/) -Copyright 2023 Datadog, Inc. - */ +Copyright 2024 Datadog, Inc. +*/ package com.otel.main; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.api.OpenTelemetry; -import org.springframework.beans.BeanUtils; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; + @SpringBootApplication(scanBasePackages = "com.otel") public class SpringApp { - public static void main(String[] args) { - SpringApplication.run(SpringApp.class, args); - } - @Bean - public OpenTelemetry openTelemetry() { - return GlobalOpenTelemetry.get(); - } + public static void main(String[] args) { + SpringApplication.run(SpringApp.class, args); + } + + @Bean + public OpenTelemetry openTelemetry() { + return GlobalOpenTelemetry.get(); + } - @Bean - public String serviceName() { - String serviceName = System.getProperty("otel.serviceName"); - return serviceName != null ? serviceName : "calendar"; - } + @Bean + public String serviceName() { + String serviceName = System.getProperty("otel.service.name"); + return serviceName != null ? serviceName : "calendar"; + } } diff --git a/apps/rest-services/java/calendar/src/main/java/com/otel/service/CalendarService.java b/apps/rest-services/java/calendar/src/main/java/com/otel/service/CalendarService.java new file mode 100644 index 0000000..c9056b2 --- /dev/null +++ b/apps/rest-services/java/calendar/src/main/java/com/otel/service/CalendarService.java @@ -0,0 +1,49 @@ +/* +Unless explicitly stated otherwise all files in this repository are licensed +under the Apache 2.0 License. + +This product includes software developed at Datadog (https://www.datadoghq.com/) +Copyright 2024 Datadog, Inc. +*/ +package com.otel.service; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Random; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.annotations.WithSpan; + +@Component +public class CalendarService { + private final Logger log = LoggerFactory.getLogger(CalendarService.class); + private final Random random = new Random(); + + @WithSpan(kind = SpanKind.CLIENT) + public String getDate() { + Span span = Span.current(); + span.setAttribute("peer.service", "random-date-service"); + + // generate a random day within current year + int day = new Random().nextInt(365); + LocalDate date = LocalDate.now().withDayOfYear(1 + day); + String output = date.format(DateTimeFormatter.ISO_LOCAL_DATE); + + span.setAttribute("date", output); + + try { + // add random sleep + Thread.sleep(random.nextLong(1, 950)); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + log.info("generated date: {}", output); + return output; + } +}