Skip to content

Commit

Permalink
Add ads served counter metric with request and response types
Browse files Browse the repository at this point in the history
Update documentation
Configure collector's prometheus exporter to convert resource attributes to prometheus labels
  • Loading branch information
jlawrienyt committed Jan 13, 2023
1 parent 06dc9f5 commit c606777
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 21 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,5 @@ significant modifications will be credited to OpenTelemetry Authors.
([#674](https://github.com/open-telemetry/opentelemetry-demo/pull/674))
* Add resource detectors to accounting service
([#676](https://github.com/open-telemetry/opentelemetry-demo/pull/676))
* Add custom metrics to ads service
([#678](https://github.com/open-telemetry/opentelemetry-demo/pull/678))
2 changes: 2 additions & 0 deletions docs/manual_span_attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ This document contains the list of manual Span Attributes used throughout the de
| `app.ads.contextKeys` | string | Context keys used to find related ads |
| `app.ads.contextKeys.count` | number | Count of unique context keys used |
| `app.ads.count` | number | Count of ads returned to user |
| `app.ads.ad_request_type` | string | Either `targeted` or `not_targeted` |
| `app.ads.ad_response_type` | string | Either `targeted` or `random` |

## CartService

Expand Down
33 changes: 16 additions & 17 deletions docs/metric_service_features.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,19 @@ Emoji Legend
- Not Applicable: :no_bell:
- Not Present (Yet): :construction:

| Service | Language | Instrumentation Libraries | Manual Span Creation | Span Data Enrichment | RPC Context Propagation | Span Links | Baggage | Resource Detection |
|--------------------|-----------------|---------------------------|----------------------|----------------------|-------------------------|----------------|----------------|--------------------|
| Accounting Service | Go | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | :100: |
| Ad | Java | :100: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Cart | .NET | :100: | :construction: | :construction: | :construction: | :construction: | :construction: | :100: |
| Checkout | Go | :100: | :construction: | :construction: | :construction: | :construction: | :construction: | :100: |
| Currency | C++ | :no_bell: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Email | Ruby | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Feature Flag | Erlang / Elixir | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Fraud Detection | Kotlin | :100: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Frontend | JavaScript | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Payment | JavaScript | :construction: | :100: | :construction: | :construction: | :construction: | :construction: | :100: |
| Product Catalog | Go | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Recommendation | Python | :100: | :100: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Shipping | Rust | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Recommendation | Python | :100: | :100: | :100: | :no_bell: | :no_bell: | :no_bell: | :construction: |
| Shipping | Rust | :no_bell: | :100: | :100: | :100: | :no_bell: | :no_bell: | :construction: |
| Service | Language | Instrumentation Libraries | Manual Metric Creation | Multiple Manual Metric Instruments | Metric Attributes | Resource Attributes | Exemplars | Views |
|--------------------|-----------------|---------------------------|------------------------|------------------------------------|-------------------|---------------------|----------------|----------------|
| Accounting Service | Go | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Ad | Java | :100: | :100: | :construction: | :100: | :100: | :construction: | :construction: |
| Cart | .NET | :100: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Checkout | Go | :100: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Currency | C++ | :no_bell: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Email | Ruby | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Feature Flag | Erlang / Elixir | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Fraud Detection | Kotlin | :100: | :construction: | :construction: | :construction: | :100: | :construction: | :construction: |
| Frontend | JavaScript | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Payment | JavaScript | :construction: | :100: | :construction: | :construction: | :100: | :construction: | :construction: |
| Product Catalog | Go | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Quote Service | PHP | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Recommendation | Python | :100: | :100: | :construction: | :construction: | :construction: | :construction: | :construction: |
| Shipping | Rust | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: | :construction: |
36 changes: 34 additions & 2 deletions docs/services/adservice.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ is caught.

### Setting span status

If the result of the operation is an error, the span status is should be set
If the result of the operation is an error, the span status should be set
accordingly using `setStatus` on the span object. In the `getAds` function the
span status is set when an exception is caught.

Expand Down Expand Up @@ -85,7 +85,39 @@ the span.

## Metrics

TBD
### Initializing Metrics

Similar to creating spans, the first step in creating metrics is initializing a
`Meter` instance, e.g. `GlobalOpenTelemetry.getMeter("adservice")`. From
there, use the various builder methods available on the `Meter` instance to
create the desired metric instrument, e.g.:

```java
meter
.counterBuilder("app.ads.ad_requests")
.setDescription("Counts ad requests by request and response type")
.build();
```

### Current Metrics Produced

Note that all the metric names below appear in Prometheus/Grafana with `.`
characters transformed to `_`.

#### Custom metrics

The following custom metrics are currently available:

* `app.ads.ad_requests`: A counter of ad requests with dimensions describing
whether the request was targeted with context keys or not, and whether the
response was targeted or random ads.

#### Auto-instrumented metrics

The following auto-instrumented metrics are available for the application:

* [Runtime metrics for the JVM](https://opentelemetry.io/docs/reference/specification/metrics/semantic_conventions/runtime-environment-metrics/#jvm-metrics).
* [Latency metrics for RPCs](https://opentelemetry.io/docs/reference/specification/metrics/semantic_conventions/rpc-metrics/#rpc-server)

## Logs

Expand Down
33 changes: 32 additions & 1 deletion src/adservice/src/main/java/hipstershop/AdService.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.api.trace.Tracer;
Expand Down Expand Up @@ -57,6 +59,16 @@ public final class AdService {
private HealthStatusManager healthMgr;

private static final AdService service = new AdService();
private static final Tracer tracer = GlobalOpenTelemetry.getTracer("adservice");
private static final Meter meter = GlobalOpenTelemetry.getMeter("adservice");

private static final LongCounter adRequestsCounter = meter
.counterBuilder("app.ads.ad_requests")
.setDescription("Counts ad requests by request and response type")
.build();

private static final AttributeKey<String> adRequestTypeKey = AttributeKey.stringKey("app.ads.ad_request_type");
private static final AttributeKey<String> adResponseTypeKey = AttributeKey.stringKey("app.ads.ad_response_type");

private void start() throws IOException {
int port = Integer.parseInt(Optional.ofNullable(System.getenv("AD_SERVICE_PORT")).orElseThrow(
Expand Down Expand Up @@ -92,6 +104,14 @@ private void stop() {
}
}

private enum AdRequestType {
TARGETED, NOT_TARGETED
}

private enum AdResponseType {
TARGETED, RANDOM
}

private static class AdServiceImpl extends hipstershop.AdServiceGrpc.AdServiceImplBase {

/**
Expand All @@ -109,6 +129,8 @@ public void getAds(AdRequest req, StreamObserver<AdResponse> responseObserver) {
Span span = Span.current();
try {
List<Ad> allAds = new ArrayList<>();
AdRequestType adRequestType;
AdResponseType adResponseType;

span.setAttribute("app.ads.contextKeys", req.getContextKeysList().toString());
span.setAttribute("app.ads.contextKeys.count", req.getContextKeysCount());
Expand All @@ -118,14 +140,24 @@ public void getAds(AdRequest req, StreamObserver<AdResponse> responseObserver) {
Collection<Ad> ads = service.getAdsByCategory(req.getContextKeys(i));
allAds.addAll(ads);
}
adRequestType = AdRequestType.TARGETED;
adResponseType = AdResponseType.TARGETED;
} else {
allAds = service.getRandomAds();
adRequestType = AdRequestType.NOT_TARGETED;
adResponseType = AdResponseType.RANDOM;
}
if (allAds.isEmpty()) {
// Serve random ads.
allAds = service.getRandomAds();
adResponseType = AdResponseType.RANDOM;
}
span.setAttribute("app.ads.count", allAds.size());
span.setAttribute("app.ads.ad_request_type", adRequestType.name());
span.setAttribute("app.ads.ad_response_type", adResponseType.name());

adRequestsCounter.add(1, Attributes.of(adRequestTypeKey, adRequestType.name(), adResponseTypeKey, adResponseType.name()));

AdResponse reply = AdResponse.newBuilder().addAllAds(allAds).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
Expand Down Expand Up @@ -155,7 +187,6 @@ private List<Ad> getRandomAds() {
List<Ad> ads = new ArrayList<>(MAX_ADS_TO_SERVE);

// create and start a new span manually
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
Expand Down
3 changes: 2 additions & 1 deletion src/otelcollector/otelcol-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ exporters:
logging:
prometheus:
endpoint: "otelcol:9464"

resource_to_telemetry_conversion:
enabled: true
processors:
batch:
spanmetrics:
Expand Down

0 comments on commit c606777

Please sign in to comment.