-
Notifications
You must be signed in to change notification settings - Fork 786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Separate HTTP client/server AttributesExtractors #4195
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.api.instrumenter.http; | ||
|
||
import io.opentelemetry.api.common.AttributesBuilder; | ||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; | ||
import org.checkerframework.checker.nullness.qual.Nullable; | ||
|
||
/** | ||
* Extractor of <a | ||
* href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-client">HTTP | ||
* client attributes</a>. Instrumentation of HTTP client frameworks should extend this class, | ||
* defining {@link REQUEST} and {@link RESPONSE} with the actual request / response types of the | ||
* instrumented library. If an attribute is not available in this library, it is appropriate to | ||
* return {@code null} from the protected attribute methods, but implement as many as possible for | ||
* best compliance with the OpenTelemetry specification. | ||
*/ | ||
public abstract class HttpClientAttributesExtractor<REQUEST, RESPONSE> | ||
extends HttpCommonAttributesExtractor<REQUEST, RESPONSE> { | ||
|
||
@Override | ||
protected final void onStart(AttributesBuilder attributes, REQUEST request) { | ||
super.onStart(attributes, request); | ||
set(attributes, SemanticAttributes.HTTP_URL, url(request)); | ||
|
||
// TODO: these are specific to servers, should we remove those? | ||
set(attributes, SemanticAttributes.HTTP_TARGET, target(request)); | ||
set(attributes, SemanticAttributes.HTTP_HOST, host(request)); | ||
set(attributes, SemanticAttributes.HTTP_SCHEME, scheme(request)); | ||
Comment on lines
+28
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 for removing these. We can always add them later if there's really a compelling reason. cc: @lmolkova |
||
} | ||
|
||
@Override | ||
protected final void onEnd( | ||
AttributesBuilder attributes, | ||
REQUEST request, | ||
@Nullable RESPONSE response, | ||
@Nullable Throwable error) { | ||
super.onEnd(attributes, request, response, error); | ||
} | ||
|
||
// Attributes that always exist in a request | ||
|
||
@Nullable | ||
protected abstract String url(REQUEST request); | ||
|
||
// TODO: this is specific to servers, should we remove this? | ||
@Nullable | ||
protected abstract String target(REQUEST request); | ||
|
||
// TODO: this is specific to servers, should we remove this? | ||
@Nullable | ||
protected abstract String host(REQUEST request); | ||
|
||
// TODO: this is specific to servers, should we remove this? | ||
@Nullable | ||
protected abstract String scheme(REQUEST request); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.api.instrumenter.http; | ||
|
||
import io.opentelemetry.api.common.AttributesBuilder; | ||
import io.opentelemetry.context.Context; | ||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; | ||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; | ||
import org.checkerframework.checker.nullness.qual.Nullable; | ||
|
||
/** | ||
* Extractor of <a | ||
* href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-server">HTTP | ||
* server attributes</a>. Instrumentation of HTTP server frameworks should extend this class, | ||
* defining {@link REQUEST} and {@link RESPONSE} with the actual request / response types of the | ||
* instrumented library. If an attribute is not available in this library, it is appropriate to | ||
* return {@code null} from the protected attribute methods, but implement as many as possible for | ||
* best compliance with the OpenTelemetry specification. | ||
*/ | ||
public abstract class HttpServerAttributesExtractor<REQUEST, RESPONSE> | ||
extends HttpCommonAttributesExtractor<REQUEST, RESPONSE> { | ||
|
||
@Override | ||
protected final void onStart(AttributesBuilder attributes, REQUEST request) { | ||
super.onStart(attributes, request); | ||
|
||
set(attributes, SemanticAttributes.HTTP_SCHEME, scheme(request)); | ||
set(attributes, SemanticAttributes.HTTP_HOST, host(request)); | ||
set(attributes, SemanticAttributes.HTTP_TARGET, target(request)); | ||
set(attributes, SemanticAttributes.HTTP_ROUTE, route(request)); | ||
|
||
// TODO: this is specific to clients, should we remove this? | ||
set(attributes, SemanticAttributes.HTTP_URL, url(request)); | ||
Comment on lines
+34
to
+36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same, +1 for removing this and we can always add it later if there's really a compelling reason. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure that we can remove this. I arbitrary took a couple of server instrumentation's extractor, and they all returned |
||
} | ||
|
||
@Override | ||
protected final void onEnd( | ||
AttributesBuilder attributes, | ||
REQUEST request, | ||
@Nullable RESPONSE response, | ||
@Nullable Throwable error) { | ||
|
||
super.onEnd(attributes, request, response, error); | ||
set(attributes, SemanticAttributes.HTTP_SERVER_NAME, serverName(request, response)); | ||
} | ||
|
||
// Attributes that always exist in a request | ||
|
||
// TODO: this is specific to clients, should we remove this? | ||
@Nullable | ||
protected abstract String url(REQUEST request); | ||
|
||
@Nullable | ||
protected abstract String target(REQUEST request); | ||
|
||
@Nullable | ||
protected abstract String host(REQUEST request); | ||
|
||
@Nullable | ||
protected abstract String route(REQUEST request); | ||
|
||
@Nullable | ||
protected abstract String scheme(REQUEST request); | ||
|
||
// Attributes which are not always available when the request is ready. | ||
|
||
/** | ||
* Extracts the {@code http.server_name} span attribute. | ||
* | ||
* <p>This is called from {@link Instrumenter#end(Context, Object, Object, Throwable)}, whether | ||
* {@code response} is {@code null} or not. | ||
*/ | ||
@Nullable | ||
protected abstract String serverName(REQUEST request, @Nullable RESPONSE response); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
package io.opentelemetry.instrumentation.api.instrumenter.http; | ||
|
||
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; | ||
import org.checkerframework.checker.nullness.qual.Nullable; | ||
|
||
/** | ||
* Extractor of the <a | ||
|
@@ -20,19 +21,19 @@ public final class HttpSpanNameExtractor<REQUEST> implements SpanNameExtractor<R | |
* will be examined to determine the name of the span. | ||
*/ | ||
public static <REQUEST> SpanNameExtractor<REQUEST> create( | ||
HttpAttributesExtractor<REQUEST, ?> attributesExtractor) { | ||
HttpCommonAttributesExtractor<REQUEST, ?> attributesExtractor) { | ||
return new HttpSpanNameExtractor<>(attributesExtractor); | ||
} | ||
|
||
private final HttpAttributesExtractor<REQUEST, ?> attributesExtractor; | ||
private final HttpCommonAttributesExtractor<REQUEST, ?> attributesExtractor; | ||
|
||
private HttpSpanNameExtractor(HttpAttributesExtractor<REQUEST, ?> attributesExtractor) { | ||
private HttpSpanNameExtractor(HttpCommonAttributesExtractor<REQUEST, ?> attributesExtractor) { | ||
this.attributesExtractor = attributesExtractor; | ||
} | ||
|
||
@Override | ||
public String extract(REQUEST request) { | ||
String route = attributesExtractor.route(request); | ||
String route = extractRoute(request); | ||
if (route != null) { | ||
return route; | ||
} | ||
|
@@ -42,4 +43,12 @@ public String extract(REQUEST request) { | |
} | ||
return "HTTP request"; | ||
} | ||
|
||
@Nullable | ||
private String extractRoute(REQUEST request) { | ||
if (attributesExtractor instanceof HttpServerAttributesExtractor) { | ||
return ((HttpServerAttributesExtractor<REQUEST, ?>) attributesExtractor).route(request); | ||
} | ||
return null; | ||
} | ||
Comment on lines
+48
to
+53
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is it worth There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, maybe we could have different factory methods in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.