Skip to content

Commit

Permalink
Split ArmeriaTelemetry into client and server
Browse files Browse the repository at this point in the history
  • Loading branch information
trask committed Dec 9, 2024
1 parent 4af0dd5 commit 4c95169
Show file tree
Hide file tree
Showing 11 changed files with 588 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import com.linecorp.armeria.server.HttpService;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.incubator.config.internal.CommonConfig;
import io.opentelemetry.instrumentation.armeria.v1_3.ArmeriaTelemetry;
import io.opentelemetry.instrumentation.armeria.v1_3.ArmeriaTelemetryBuilder;
import io.opentelemetry.instrumentation.armeria.v1_3.ArmeriaClientTelemetry;
import io.opentelemetry.instrumentation.armeria.v1_3.ArmeriaClientTelemetryBuilder;
import io.opentelemetry.instrumentation.armeria.v1_3.ArmeriaServerTelemetry;
import io.opentelemetry.instrumentation.armeria.v1_3.ArmeriaServerTelemetryBuilder;
import io.opentelemetry.instrumentation.armeria.v1_3.internal.ArmeriaInstrumenterBuilderUtil;
import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig;
import java.util.function.Function;
Expand All @@ -23,15 +25,25 @@ public final class ArmeriaSingletons {
public static final Function<? super HttpService, ? extends HttpService> SERVER_DECORATOR;

static {
ArmeriaTelemetryBuilder builder = ArmeriaTelemetry.builder(GlobalOpenTelemetry.get());
CommonConfig config = AgentCommonConfig.get();
ArmeriaInstrumenterBuilderUtil.getClientBuilderExtractor().apply(builder).configure(config);
ArmeriaInstrumenterBuilderUtil.getServerBuilderExtractor().apply(builder).configure(config);
ArmeriaTelemetry telemetry = builder.build();

CLIENT_DECORATOR = telemetry.newClientDecorator();
ArmeriaClientTelemetryBuilder clientBuilder =
ArmeriaClientTelemetry.builder(GlobalOpenTelemetry.get());
ArmeriaInstrumenterBuilderUtil.getClientBuilderExtractor()
.apply(clientBuilder)
.configure(config);
ArmeriaClientTelemetry clientTelemetry = clientBuilder.build();

ArmeriaServerTelemetryBuilder serverBuilder =
ArmeriaServerTelemetry.builder(GlobalOpenTelemetry.get());
ArmeriaInstrumenterBuilderUtil.getServerBuilderExtractor()
.apply(serverBuilder)
.configure(config);
ArmeriaServerTelemetry serverTelemetry = serverBuilder.build();

CLIENT_DECORATOR = clientTelemetry.newDecorator();
Function<? super HttpService, ? extends HttpService> libraryDecorator =
telemetry.newServiceDecorator().compose(ResponseCustomizingDecorator::new);
serverTelemetry.newDecorator().compose(ResponseCustomizingDecorator::new);
SERVER_DECORATOR = service -> new ServerDecorator(service, libraryDecorator.apply(service));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.armeria.v1_3;

import com.linecorp.armeria.client.ClientRequestContext;
import com.linecorp.armeria.client.HttpClient;
import com.linecorp.armeria.common.logging.RequestLog;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import java.util.function.Function;

/** Entrypoint for instrumenting Armeria clients. */
public final class ArmeriaClientTelemetry {

/**
* Returns a new {@link ArmeriaClientTelemetry} configured with the given {@link OpenTelemetry}.
*/
public static ArmeriaClientTelemetry create(OpenTelemetry openTelemetry) {
return builder(openTelemetry).build();
}

public static ArmeriaClientTelemetryBuilder builder(OpenTelemetry openTelemetry) {
return new ArmeriaClientTelemetryBuilder(openTelemetry);
}

private final Instrumenter<ClientRequestContext, RequestLog> instrumenter;

ArmeriaClientTelemetry(Instrumenter<ClientRequestContext, RequestLog> instrumenter) {
this.instrumenter = instrumenter;
}

/**
* Returns a new {@link HttpClient} decorator for use with methods like {@link
* com.linecorp.armeria.client.ClientBuilder#decorator(Function)}.
*/
public Function<? super HttpClient, ? extends HttpClient> newDecorator() {
return client -> new OpenTelemetryClient(client, instrumenter);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.armeria.v1_3;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.linecorp.armeria.client.ClientRequestContext;
import com.linecorp.armeria.common.logging.RequestLog;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpClientInstrumenterBuilder;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor;
import io.opentelemetry.instrumentation.api.semconv.http.HttpClientAttributesExtractorBuilder;
import io.opentelemetry.instrumentation.armeria.v1_3.internal.ArmeriaInstrumenterBuilderFactory;
import io.opentelemetry.instrumentation.armeria.v1_3.internal.ArmeriaInstrumenterBuilderUtil;
import io.opentelemetry.instrumentation.armeria.v1_3.internal.Experimental;
import java.util.List;
import java.util.Set;
import java.util.function.Function;

public final class ArmeriaClientTelemetryBuilder {

private final DefaultHttpClientInstrumenterBuilder<ClientRequestContext, RequestLog> builder;

static {
ArmeriaInstrumenterBuilderUtil.setClientBuilderExtractor(
ArmeriaClientTelemetryBuilder::getBuilder);
}

ArmeriaClientTelemetryBuilder(OpenTelemetry openTelemetry) {
builder = ArmeriaInstrumenterBuilderFactory.getClientBuilder(openTelemetry);
}

/** Sets the status extractor for client spans. */
@CanIgnoreReturnValue
public ArmeriaClientTelemetryBuilder setStatusExtractor(
Function<
SpanStatusExtractor<? super ClientRequestContext, ? super RequestLog>,
? extends SpanStatusExtractor<? super ClientRequestContext, ? super RequestLog>>
statusExtractor) {
builder.setStatusExtractor(statusExtractor);
return this;
}

/**
* Adds an extra client-only {@link AttributesExtractor} to invoke to set attributes to
* instrumented items. The {@link AttributesExtractor} will be executed after all default
* extractors.
*/
@CanIgnoreReturnValue
public ArmeriaClientTelemetryBuilder addAttributeExtractor(
AttributesExtractor<? super ClientRequestContext, ? super RequestLog> attributesExtractor) {
builder.addAttributeExtractor(attributesExtractor);
return this;
}

/**
* Sets the {@code peer.service} attribute for http client spans.
*
* @deprecated Use {@link Experimental#setClientPeerService(ArmeriaClientTelemetryBuilder,
* String)} instead.
*/
@Deprecated
@CanIgnoreReturnValue
public ArmeriaClientTelemetryBuilder setPeerService(String peerService) {
builder.setPeerService(peerService);
return this;
}

/**
* Configures the HTTP client request headers that will be captured as span attributes.
*
* @param requestHeaders A list of HTTP header names.
*/
@CanIgnoreReturnValue
public ArmeriaClientTelemetryBuilder setCapturedRequestHeaders(List<String> requestHeaders) {
builder.setCapturedRequestHeaders(requestHeaders);
return this;
}

/**
* Configures the HTTP client response headers that will be captured as span attributes.
*
* @param responseHeaders A list of HTTP header names.
*/
@CanIgnoreReturnValue
public ArmeriaClientTelemetryBuilder setCapturedResponseHeaders(List<String> responseHeaders) {
builder.setCapturedResponseHeaders(responseHeaders);
return this;
}

/**
* Configures the instrumentation to recognize an alternative set of HTTP request methods.
*
* <p>By default, this instrumentation defines "known" methods as the ones listed in <a
* href="https://www.rfc-editor.org/rfc/rfc9110.html#name-methods">RFC9110</a> and the PATCH
* method defined in <a href="https://www.rfc-editor.org/rfc/rfc5789.html">RFC5789</a>.
*
* <p>Note: calling this method <b>overrides</b> the default known method sets completely; it does
* not supplement it.
*
* @param knownMethods A set of recognized HTTP request methods.
* @see HttpClientAttributesExtractorBuilder#setKnownMethods(Set)
*/
@CanIgnoreReturnValue
public ArmeriaClientTelemetryBuilder setKnownMethods(Set<String> knownMethods) {
builder.setKnownMethods(knownMethods);
return this;
}

/**
* Configures the instrumentation to emit experimental HTTP client metrics.
*
* @param emitExperimentalHttpClientMetrics {@code true} if the experimental HTTP client metrics
* are to be emitted.
* @deprecated Use {@link
* Experimental#setEmitExperimentalHttpClientMetrics(ArmeriaClientTelemetryBuilder, boolean)}
* instead.
*/
@Deprecated
@CanIgnoreReturnValue
public ArmeriaClientTelemetryBuilder setEmitExperimentalHttpClientMetrics(
boolean emitExperimentalHttpClientMetrics) {
builder.setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientMetrics);
return this;
}

/** Sets custom client {@link SpanNameExtractor} via transform function. */
@CanIgnoreReturnValue
public ArmeriaClientTelemetryBuilder setSpanNameExtractor(
Function<
SpanNameExtractor<? super ClientRequestContext>,
? extends SpanNameExtractor<? super ClientRequestContext>>
clientSpanNameExtractor) {
builder.setSpanNameExtractor(clientSpanNameExtractor);
return this;
}

public ArmeriaClientTelemetry build() {
return new ArmeriaClientTelemetry(builder.build());
}

private DefaultHttpClientInstrumenterBuilder<ClientRequestContext, RequestLog> getBuilder() {
return builder;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.armeria.v1_3;

import com.linecorp.armeria.common.logging.RequestLog;
import com.linecorp.armeria.server.HttpService;
import com.linecorp.armeria.server.ServiceRequestContext;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import java.util.function.Function;

/** Entrypoint for instrumenting Armeria services. */
public final class ArmeriaServerTelemetry {

/**
* Returns a new {@link ArmeriaServerTelemetry} configured with the given {@link OpenTelemetry}.
*/
public static ArmeriaServerTelemetry create(OpenTelemetry openTelemetry) {
return builder(openTelemetry).build();
}

public static ArmeriaServerTelemetryBuilder builder(OpenTelemetry openTelemetry) {
return new ArmeriaServerTelemetryBuilder(openTelemetry);
}

private final Instrumenter<ServiceRequestContext, RequestLog> instrumenter;

ArmeriaServerTelemetry(Instrumenter<ServiceRequestContext, RequestLog> instrumenter) {
this.instrumenter = instrumenter;
}

/**
* Returns a new {@link HttpService} decorator for use with methods like {@link
* HttpService#decorate(Function)}.
*/
public Function<? super HttpService, ? extends HttpService> newDecorator() {
return service -> new OpenTelemetryService(service, instrumenter);
}
}
Loading

0 comments on commit 4c95169

Please sign in to comment.