From 40a7ca5323aee202e5813c5754e01df6badc21e6 Mon Sep 17 00:00:00 2001 From: Pierre Tessier Date: Thu, 16 Jun 2022 22:20:54 -0400 Subject: [PATCH 1/3] add manual instrumentation --- src/adservice/build.gradle | 5 +++ .../src/main/java/hipstershop/AdService.java | 45 ++++++++++++++++--- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/adservice/build.gradle b/src/adservice/build.gradle index a1acc6168c..916a4941df 100644 --- a/src/adservice/build.gradle +++ b/src/adservice/build.gradle @@ -14,6 +14,7 @@ description = 'Ad Service' group = "adservice" version = "0.1.0-SNAPSHOT" +def opentelemetryVersion = "1.12.0" def grpcVersion = "1.45.1" def jacksonVersion = "2.13.2" def protocVersion = "3.20.0" @@ -32,12 +33,16 @@ dependencies { if (speed) { implementation fileTree(dir: offlineCompile, include: '*.jar') } else { + implementation "com.google.api.grpc:proto-google-common-protos:2.8.0", "javax.annotation:javax.annotation-api:1.3.2", "io.grpc:grpc-protobuf:${grpcVersion}", "io.grpc:grpc-stub:${grpcVersion}", "io.grpc:grpc-netty:${grpcVersion}", "io.grpc:grpc-services:${grpcVersion}", + "io.opentelemetry:opentelemetry-api:${opentelemetryVersion}", + "io.opentelemetry:opentelemetry-sdk:${opentelemetryVersion}", + "io.opentelemetry:opentelemetry-extension-annotations:${opentelemetryVersion}", "org.apache.logging.log4j:log4j-core:2.17.2" runtimeOnly "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}", diff --git a/src/adservice/src/main/java/hipstershop/AdService.java b/src/adservice/src/main/java/hipstershop/AdService.java index 7d28dc4ad4..32bc4842d8 100644 --- a/src/adservice/src/main/java/hipstershop/AdService.java +++ b/src/adservice/src/main/java/hipstershop/AdService.java @@ -27,6 +27,13 @@ import io.grpc.health.v1.HealthCheckResponse.ServingStatus; import io.grpc.protobuf.services.*; import io.grpc.stub.StreamObserver; +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Scope; +import io.opentelemetry.extension.annotations.SpanAttribute; +import io.opentelemetry.extension.annotations.WithSpan; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -41,7 +48,7 @@ public final class AdService { private static final Logger logger = LogManager.getLogger(AdService.class); @SuppressWarnings("FieldCanBeLocal") - private static int MAX_ADS_TO_SERVE = 2; + private static final int MAX_ADS_TO_SERVE = 2; private Server server; private HealthStatusManager healthMgr; @@ -91,8 +98,14 @@ private static class AdServiceImpl extends hipstershop.AdServiceGrpc.AdServiceIm @Override public void getAds(AdRequest req, StreamObserver responseObserver) { AdService service = AdService.getInstance(); + + // get the current span in context + Span span = Span.current(); try { List allAds = new ArrayList<>(); + + span.setAttribute("app.ads.contextKeys", req.getContextKeysList().toString()); + span.setAttribute("app.ads.contextKeys.count", req.getContextKeysCount()); logger.info("received ad request (context_words=" + req.getContextKeysList() + ")"); if (req.getContextKeysCount() > 0) { for (int i = 0; i < req.getContextKeysCount(); i++) { @@ -106,10 +119,12 @@ public void getAds(AdRequest req, StreamObserver responseObserver) { // Serve random ads. allAds = service.getRandomAds(); } + span.setAttribute("app.ads.count", allAds.size()); AdResponse reply = AdResponse.newBuilder().addAllAds(allAds).build(); responseObserver.onNext(reply); responseObserver.onCompleted(); } catch (StatusRuntimeException e) { + span.setStatus(StatusCode.ERROR); logger.log(Level.WARN, "GetAds Failed with status {}", e.getStatus()); responseObserver.onError(e); } @@ -118,18 +133,36 @@ public void getAds(AdRequest req, StreamObserver responseObserver) { private static final ImmutableListMultimap adsMap = createAdsMap(); - private Collection getAdsByCategory(String category) { - return adsMap.get(category); + @WithSpan("getAdsByCategory") + private Collection getAdsByCategory(@SpanAttribute("app.ads.category") String category) { + Collection ads = adsMap.get(category); + Span.current().setAttribute("app.ads.count", ads.size()); + return ads; } private static final Random random = new Random(); private List getRandomAds() { + List ads = new ArrayList<>(MAX_ADS_TO_SERVE); - Collection allAds = adsMap.values(); - for (int i = 0; i < MAX_ADS_TO_SERVE; i++) { - ads.add(Iterables.get(allAds, random.nextInt(allAds.size()))); + + // create and start a new span manually + Tracer tracer = GlobalOpenTelemetry.getTracer(""); + Span span = tracer.spanBuilder("getRandomAds").startSpan(); + + // put the span into context, so if any child span is started the parent will be set properly + try (Scope ignored = span.makeCurrent()) { + + Collection allAds = adsMap.values(); + for (int i = 0; i < MAX_ADS_TO_SERVE; i++) { + ads.add(Iterables.get(allAds, random.nextInt(allAds.size()))); + } + span.setAttribute("app.ads.count", ads.size()); + + } finally { + span.end(); } + return ads; } From aa8013ab5926c86629d857a78fa36cfa7b991993 Mon Sep 17 00:00:00 2001 From: Pierre Tessier Date: Fri, 17 Jun 2022 20:29:03 -0400 Subject: [PATCH 2/3] add span event on error --- src/adservice/src/main/java/hipstershop/AdService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/adservice/src/main/java/hipstershop/AdService.java b/src/adservice/src/main/java/hipstershop/AdService.java index 32bc4842d8..fe853c79d0 100644 --- a/src/adservice/src/main/java/hipstershop/AdService.java +++ b/src/adservice/src/main/java/hipstershop/AdService.java @@ -28,6 +28,8 @@ import io.grpc.protobuf.services.*; import io.grpc.stub.StreamObserver; import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.StatusCode; import io.opentelemetry.api.trace.Tracer; @@ -124,6 +126,7 @@ public void getAds(AdRequest req, StreamObserver responseObserver) { responseObserver.onNext(reply); responseObserver.onCompleted(); } catch (StatusRuntimeException e) { + span.addEvent("Error", Attributes.of(AttributeKey.stringKey("exception.message"), e.getMessage())); span.setStatus(StatusCode.ERROR); logger.log(Level.WARN, "GetAds Failed with status {}", e.getStatus()); responseObserver.onError(e); From 9a85a5c6ce40cade868a9d0fe88ed1c4203cdc4a Mon Sep 17 00:00:00 2001 From: Pierre Tessier Date: Tue, 21 Jun 2022 23:47:28 -0400 Subject: [PATCH 3/3] use service name for tracer --- src/adservice/src/main/java/hipstershop/AdService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adservice/src/main/java/hipstershop/AdService.java b/src/adservice/src/main/java/hipstershop/AdService.java index fe853c79d0..b0b9fe0f96 100644 --- a/src/adservice/src/main/java/hipstershop/AdService.java +++ b/src/adservice/src/main/java/hipstershop/AdService.java @@ -150,7 +150,7 @@ private List getRandomAds() { List ads = new ArrayList<>(MAX_ADS_TO_SERVE); // create and start a new span manually - Tracer tracer = GlobalOpenTelemetry.getTracer(""); + Tracer tracer = GlobalOpenTelemetry.getTracer("adservice"); Span span = tracer.spanBuilder("getRandomAds").startSpan(); // put the span into context, so if any child span is started the parent will be set properly