Skip to content

Commit

Permalink
Split ratpack into client and server (#12853)
Browse files Browse the repository at this point in the history
  • Loading branch information
trask authored Dec 16, 2024
1 parent cb35311 commit b178439
Show file tree
Hide file tree
Showing 17 changed files with 680 additions and 119 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.ratpack.v1_7;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.ratpack.v1_7.internal.OpenTelemetryHttpClient;
import ratpack.http.client.HttpClient;
import ratpack.http.client.HttpResponse;
import ratpack.http.client.RequestSpec;

/**
* Entrypoint for instrumenting Ratpack http client.
*
* <p>To apply OpenTelemetry instrumentation to a http client, wrap the {@link HttpClient} using
* {@link #instrument(HttpClient)}.
*
* <pre>{@code
* RatpackClientTelemetry telemetry = RatpackClientTelemetry.create(OpenTelemetrySdk.builder()
* ...
* .build());
* HttpClient instrumentedHttpClient = telemetry.instrument(httpClient);
* }</pre>
*/
public final class RatpackClientTelemetry {

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

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

private final OpenTelemetryHttpClient httpClientInstrumenter;

RatpackClientTelemetry(Instrumenter<RequestSpec, HttpResponse> clientInstrumenter) {
httpClientInstrumenter = new OpenTelemetryHttpClient(clientInstrumenter);
}

/** Returns instrumented instance of {@link HttpClient} with OpenTelemetry. */
public HttpClient instrument(HttpClient httpClient) throws Exception {
return httpClientInstrumenter.instrument(httpClient);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.ratpack.v1_7;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
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.semconv.http.HttpClientAttributesExtractorBuilder;
import io.opentelemetry.instrumentation.ratpack.v1_7.internal.Experimental;
import io.opentelemetry.instrumentation.ratpack.v1_7.internal.RatpackClientInstrumenterBuilderFactory;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import ratpack.http.client.HttpResponse;
import ratpack.http.client.RequestSpec;

/** A builder for {@link RatpackClientTelemetry}. */
public final class RatpackClientTelemetryBuilder {

private static final String INSTRUMENTATION_NAME = "io.opentelemetry.ratpack-1.7";

private final DefaultHttpClientInstrumenterBuilder<RequestSpec, HttpResponse> builder;

static {
Experimental.setSetEmitExperimentalClientTelemetry(
(builder, emit) -> builder.builder.setEmitExperimentalHttpClientMetrics(emit));
}

RatpackClientTelemetryBuilder(OpenTelemetry openTelemetry) {
builder = RatpackClientInstrumenterBuilderFactory.create(INSTRUMENTATION_NAME, openTelemetry);
}

@CanIgnoreReturnValue
public RatpackClientTelemetryBuilder addAttributesExtractor(
AttributesExtractor<? super RequestSpec, ? super HttpResponse> attributesExtractor) {
builder.addAttributesExtractor(attributesExtractor);
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 RatpackClientTelemetryBuilder 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 RatpackClientTelemetryBuilder 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 RatpackClientTelemetryBuilder setKnownMethods(Set<String> knownMethods) {
builder.setKnownMethods(knownMethods);
return this;
}

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

/** Returns a new {@link RatpackClientTelemetry} with the configuration of this builder. */
public RatpackClientTelemetry build() {
return new RatpackClientTelemetry(builder.build());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.ratpack.v1_7;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.ratpack.v1_7.internal.OpenTelemetryExecInitializer;
import io.opentelemetry.instrumentation.ratpack.v1_7.internal.OpenTelemetryExecInterceptor;
import io.opentelemetry.instrumentation.ratpack.v1_7.internal.OpenTelemetryServerHandler;
import ratpack.exec.ExecInitializer;
import ratpack.exec.ExecInterceptor;
import ratpack.handling.Handler;
import ratpack.handling.HandlerDecorator;
import ratpack.http.Request;
import ratpack.http.Response;
import ratpack.registry.RegistrySpec;

/**
* Entrypoint for instrumenting Ratpack server.
*
* <p>To apply OpenTelemetry instrumentation to a server, configure the {@link RegistrySpec} using
* {@link #configureRegistry(RegistrySpec)}.
*
* <pre>{@code
* RatpackServerTelemetry telemetry = RatpackServerTelemetry.create(OpenTelemetrySdk.builder()
* ...
* .build());
* RatpackServer.start(server -> {
* server.registryOf(telemetry::configureRegistry);
* server.handlers(chain -> ...);
* });
* }</pre>
*/
public final class RatpackServerTelemetry {

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

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

private final OpenTelemetryServerHandler serverHandler;

RatpackServerTelemetry(Instrumenter<Request, Response> serverInstrumenter) {
serverHandler = new OpenTelemetryServerHandler(serverInstrumenter);
}

/** Returns a {@link Handler} to support Ratpack Registry binding. */
public Handler getHandler() {
return serverHandler;
}

/** Returns instance of {@link ExecInterceptor} to support Ratpack Registry binding. */
public ExecInterceptor getExecInterceptor() {
return OpenTelemetryExecInterceptor.INSTANCE;
}

/** Returns instance of {@link ExecInitializer} to support Ratpack Registry binding. */
public ExecInitializer getExecInitializer() {
return OpenTelemetryExecInitializer.INSTANCE;
}

/** Configures the {@link RegistrySpec} with OpenTelemetry. */
public void configureRegistry(RegistrySpec registry) {
registry.add(HandlerDecorator.prepend(serverHandler));
registry.add(OpenTelemetryExecInterceptor.INSTANCE);
registry.add(OpenTelemetryExecInitializer.INSTANCE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.instrumentation.ratpack.v1_7;

import com.google.errorprone.annotations.CanIgnoreReturnValue;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.api.incubator.builder.internal.DefaultHttpServerInstrumenterBuilder;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
import io.opentelemetry.instrumentation.api.semconv.http.HttpServerAttributesExtractorBuilder;
import io.opentelemetry.instrumentation.ratpack.v1_7.internal.Experimental;
import io.opentelemetry.instrumentation.ratpack.v1_7.internal.RatpackServerInstrumenterBuilderFactory;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import ratpack.http.Request;
import ratpack.http.Response;

/** A builder for {@link RatpackServerTelemetry}. */
public final class RatpackServerTelemetryBuilder {

private static final String INSTRUMENTATION_NAME = "io.opentelemetry.ratpack-1.7";

private final DefaultHttpServerInstrumenterBuilder<Request, Response> builder;

static {
Experimental.setSetEmitExperimentalServerTelemetry(
(builder, emit) -> builder.builder.setEmitExperimentalHttpServerMetrics(emit));
}

RatpackServerTelemetryBuilder(OpenTelemetry openTelemetry) {
builder = RatpackServerInstrumenterBuilderFactory.create(INSTRUMENTATION_NAME, openTelemetry);
}

/**
* Adds an additional {@link AttributesExtractor} to invoke to set attributes to instrumented
* items. The {@link AttributesExtractor} will be executed after all default extractors.
*/
@CanIgnoreReturnValue
public RatpackServerTelemetryBuilder addAttributesExtractor(
AttributesExtractor<? super Request, ? super Response> attributesExtractor) {
builder.addAttributesExtractor(attributesExtractor);
return this;
}

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

/**
* Configures the HTTP server response headers that will be captured as span attributes.
*
* @param responseHeaders A list of HTTP header names.
*/
@CanIgnoreReturnValue
public RatpackServerTelemetryBuilder 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 HttpServerAttributesExtractorBuilder#setKnownMethods(Set)
*/
@CanIgnoreReturnValue
public RatpackServerTelemetryBuilder setKnownMethods(Set<String> knownMethods) {
builder.setKnownMethods(knownMethods);
return this;
}

/** Sets custom server {@link SpanNameExtractor} via transform function. */
@CanIgnoreReturnValue
public RatpackServerTelemetryBuilder setSpanNameExtractor(
Function<SpanNameExtractor<? super Request>, ? extends SpanNameExtractor<? super Request>>
serverSpanNameExtractor) {
builder.setSpanNameExtractor(serverSpanNameExtractor);
return this;
}

/** Returns a new {@link RatpackServerTelemetry} with the configuration of this builder. */
public RatpackServerTelemetry build() {
return new RatpackServerTelemetry(builder.build());
}
}
Loading

0 comments on commit b178439

Please sign in to comment.