Skip to content

Commit

Permalink
Calendar app: use instrumentation annotations (#127)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
krlv authored Aug 14, 2024
1 parent ec6280b commit 22de51b
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 66 deletions.
6 changes: 3 additions & 3 deletions apps/rest-services/java/calendar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

```
GET /calendar
Returns a random date in 2022.
Returns a random date within the current year.
```

```
Expand Down Expand Up @@ -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
```
4 changes: 1 addition & 3 deletions apps/rest-services/java/calendar/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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'
Expand Down
2 changes: 1 addition & 1 deletion apps/rest-services/java/calendar/deploys/Dockerfile.otel
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -27,62 +18,50 @@
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<String, String> getDate(@RequestHeader MultiValueMap<String, String> 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();
latency.record(endTime - startTime);
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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}

0 comments on commit 22de51b

Please sign in to comment.