Skip to content

Commit

Permalink
Split ratpack 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 e03e83c
Show file tree
Hide file tree
Showing 15 changed files with 611 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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.OpenTelemetryHttpClient;
import ratpack.http.client.HttpClient;
import ratpack.http.client.HttpResponse;
import ratpack.http.client.RequestSpec;
import ratpack.registry.RegistrySpec;

/**
* 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);
}

/** Configures the {@link RegistrySpec} with OpenTelemetry. */
public void configureRegistry(RegistrySpec registry) {
registry.add(OpenTelemetryExecInitializer.INSTANCE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* 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> clientBuilder;

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

@CanIgnoreReturnValue
public RatpackClientTelemetryBuilder addAttributeExtractor(
AttributesExtractor<? super RequestSpec, ? super HttpResponse> attributesExtractor) {
clientBuilder.addAttributeExtractor(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) {
clientBuilder.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) {
clientBuilder.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) {
clientBuilder.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) {
clientBuilder.setSpanNameExtractor(clientSpanNameExtractor);
return this;
}

/**
* Can be used via the unstable method {@link
* Experimental#setEmitExperimentalHttpClientMetrics(RatpackClientTelemetryBuilder, boolean)}.
*/
void setEmitExperimentalHttpClientMetrics(boolean emitExperimentalHttpClientMetrics) {
clientBuilder.setEmitExperimentalHttpClientMetrics(emitExperimentalHttpClientMetrics);
}

/** Returns a new {@link RatpackClientTelemetry} with the configuration of this builder. */
public RatpackClientTelemetry build() {
return new RatpackClientTelemetry(clientBuilder.build());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* 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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* 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> serverBuilder;

RatpackServerTelemetryBuilder(OpenTelemetry openTelemetry) {
serverBuilder =
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 addAttributeExtractor(
AttributesExtractor<? super Request, ? super Response> attributesExtractor) {
serverBuilder.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) {
serverBuilder.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) {
serverBuilder.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) {
serverBuilder.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) {
serverBuilder.setSpanNameExtractor(serverSpanNameExtractor);
return this;
}

/**
* Can be used via the unstable method {@link
* Experimental#setEmitExperimentalHttpServerMetrics(RatpackServerTelemetryBuilder, boolean)}.
*/
void setEmitExperimentalHttpServerMetrics(boolean emitExperimentalHttpServerMetrics) {
serverBuilder.setEmitExperimentalHttpServerMetrics(emitExperimentalHttpServerMetrics);
}

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

0 comments on commit e03e83c

Please sign in to comment.