Skip to content
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

Capture enduser.id in servlet instrumentation #6225

Merged
merged 4 commits into from
Jun 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ public final class GrizzlySingletons {
.addOperationMetrics(HttpServerMetrics.get())
.addContextCustomizer(
(context, request, attributes) ->
new AppServerBridge.Builder().recordException().init(context))
new AppServerBridge.Builder()
.captureServletAttributes()
.recordException()
.init(context))
.addContextCustomizer(
(context, httpRequestPacket, startAttributes) -> GrizzlyErrorHolder.init(context))
.addContextCustomizer(HttpRouteHolder.get())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import io.opentelemetry.javaagent.bootstrap.servlet.AppServerBridge;
import io.opentelemetry.javaagent.bootstrap.servlet.MappingResolver;
import io.opentelemetry.javaagent.bootstrap.servlet.ServletContextPath;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.security.Principal;
import java.util.function.Function;

public abstract class BaseServletHelper<REQUEST, RESPONSE> {
Expand Down Expand Up @@ -92,25 +94,56 @@ public Context updateContext(
}

/**
* Capture servlet request parameters as span attributes when SERVER span is not create by servlet
* Capture servlet specific span attributes when SERVER span is not create by servlet
* instrumentation.
*
* <p>When SERVER span is created by servlet instrumentation we register {@link
* ServletRequestParametersExtractor} as an attribute extractor. When SERVER span is not created
* by servlet instrumentation we call this method on exit from the last servlet or filter.
*/
public void captureServletAttributes(Context context, REQUEST request) {
if (parameterExtractor == null || !AppServerBridge.captureServletAttributes(context)) {
if (!AppServerBridge.captureServletAttributes(context)) {
return;
}
Span serverSpan = LocalRootSpan.fromContextOrNull(context);
if (serverSpan == null) {
return;
}

captureRequestParameters(serverSpan, request);
captureEnduserId(serverSpan, request);
}

/**
* Capture servlet request parameters as span attributes when SERVER span is not create by servlet
* instrumentation.
*
* <p>When SERVER span is created by servlet instrumentation we register {@link
* ServletRequestParametersExtractor} as an attribute extractor. When SERVER span is not created
* by servlet instrumentation we call this method on exit from the last servlet or filter.
*/
private void captureRequestParameters(Span serverSpan, REQUEST request) {
if (parameterExtractor == null) {
return;
}

parameterExtractor.setAttributes(request, (key, value) -> serverSpan.setAttribute(key, value));
}

/**
* Capture {@link SemanticAttributes#ENDUSER_ID} as span attributes when SERVER span is not create
* by servlet instrumentation.
*
* <p>When SERVER span is created by servlet instrumentation we register {@link
* ServletAdditionalAttributesExtractor} as an attribute extractor. When SERVER span is not
* created by servlet instrumentation we call this method on exit from the last servlet or filter.
*/
private void captureEnduserId(Span serverSpan, REQUEST request) {
Principal principal = accessor.getRequestUserPrincipal(request);
if (principal != null) {
String name = principal.getName();
if (name != null) {
serverSpan.setAttribute(SemanticAttributes.ENDUSER_ID, name);
}
}
}

/*
Given request already has a context associated with it.
As there should not be nested spans of kind SERVER, we should NOT create a new span here.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
public final class Tomcat10Singletons {
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.tomcat-10.0";
private static final Instrumenter<Request, Response> INSTRUMENTER =
TomcatInstrumenterFactory.create(
INSTRUMENTATION_NAME, Servlet5Accessor.INSTANCE, Tomcat10ServletEntityProvider.INSTANCE);
TomcatInstrumenterFactory.create(INSTRUMENTATION_NAME, Servlet5Accessor.INSTANCE);
private static final TomcatHelper<HttpServletRequest, HttpServletResponse> HELPER =
new TomcatHelper<>(
INSTRUMENTER, Tomcat10ServletEntityProvider.INSTANCE, Servlet5Singletons.helper());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
public final class Tomcat7Singletons {
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.tomcat-7.0";
private static final Instrumenter<Request, Response> INSTRUMENTER =
TomcatInstrumenterFactory.create(
INSTRUMENTATION_NAME, Servlet3Accessor.INSTANCE, Tomcat7ServletEntityProvider.INSTANCE);
TomcatInstrumenterFactory.create(INSTRUMENTATION_NAME, Servlet3Accessor.INSTANCE);
private static final TomcatHelper<HttpServletRequest, HttpServletResponse> HELPER =
new TomcatHelper<>(
INSTRUMENTER, Tomcat7ServletEntityProvider.INSTANCE, Servlet3Singletons.helper());
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
package io.opentelemetry.javaagent.instrumentation.tomcat.common;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpRouteHolder;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpServerAttributesExtractor;
Expand All @@ -25,13 +24,9 @@ public final class TomcatInstrumenterFactory {
private TomcatInstrumenterFactory() {}

public static <REQUEST, RESPONSE> Instrumenter<Request, Response> create(
String instrumentationName,
ServletAccessor<REQUEST, RESPONSE> accessor,
TomcatServletEntityProvider<REQUEST, RESPONSE> servletEntityProvider) {
String instrumentationName, ServletAccessor<REQUEST, RESPONSE> accessor) {
TomcatHttpAttributesGetter httpAttributesGetter = new TomcatHttpAttributesGetter();
TomcatNetAttributesGetter netAttributesGetter = new TomcatNetAttributesGetter();
AttributesExtractor<Request, Response> additionalAttributeExtractor =
new TomcatAdditionalAttributesExtractor<>(accessor, servletEntityProvider);

return Instrumenter.<Request, Response>builder(
GlobalOpenTelemetry.get(),
Expand All @@ -41,7 +36,6 @@ public static <REQUEST, RESPONSE> Instrumenter<Request, Response> create(
.setErrorCauseExtractor(new ServletErrorCauseExtractor<>(accessor))
.addAttributesExtractor(HttpServerAttributesExtractor.create(httpAttributesGetter))
.addAttributesExtractor(NetServerAttributesExtractor.create(netAttributesGetter))
.addAttributesExtractor(additionalAttributeExtractor)
.addContextCustomizer(HttpRouteHolder.get())
.addContextCustomizer(
(context, request, attributes) ->
Expand Down