|
17 | 17 | import io.opentelemetry.javaagent.bootstrap.servlet.AppServerBridge;
|
18 | 18 | import io.opentelemetry.javaagent.bootstrap.servlet.MappingResolver;
|
19 | 19 | import io.opentelemetry.javaagent.bootstrap.servlet.ServletContextPath;
|
| 20 | +import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; |
| 21 | +import java.security.Principal; |
20 | 22 | import java.util.function.Function;
|
21 | 23 |
|
22 | 24 | public abstract class BaseServletHelper<REQUEST, RESPONSE> {
|
@@ -92,25 +94,56 @@ public Context updateContext(
|
92 | 94 | }
|
93 | 95 |
|
94 | 96 | /**
|
95 |
| - * Capture servlet request parameters as span attributes when SERVER span is not create by servlet |
| 97 | + * Capture servlet specific span attributes when SERVER span is not create by servlet |
96 | 98 | * instrumentation.
|
97 |
| - * |
98 |
| - * <p>When SERVER span is created by servlet instrumentation we register {@link |
99 |
| - * ServletRequestParametersExtractor} as an attribute extractor. When SERVER span is not created |
100 |
| - * by servlet instrumentation we call this method on exit from the last servlet or filter. |
101 | 99 | */
|
102 | 100 | public void captureServletAttributes(Context context, REQUEST request) {
|
103 |
| - if (parameterExtractor == null || !AppServerBridge.captureServletAttributes(context)) { |
| 101 | + if (!AppServerBridge.captureServletAttributes(context)) { |
104 | 102 | return;
|
105 | 103 | }
|
106 | 104 | Span serverSpan = LocalRootSpan.fromContextOrNull(context);
|
107 | 105 | if (serverSpan == null) {
|
108 | 106 | return;
|
109 | 107 | }
|
110 | 108 |
|
| 109 | + captureRequestParameters(serverSpan, request); |
| 110 | + captureEnduserId(serverSpan, request); |
| 111 | + } |
| 112 | + |
| 113 | + /** |
| 114 | + * Capture servlet request parameters as span attributes when SERVER span is not create by servlet |
| 115 | + * instrumentation. |
| 116 | + * |
| 117 | + * <p>When SERVER span is created by servlet instrumentation we register {@link |
| 118 | + * ServletRequestParametersExtractor} as an attribute extractor. When SERVER span is not created |
| 119 | + * by servlet instrumentation we call this method on exit from the last servlet or filter. |
| 120 | + */ |
| 121 | + private void captureRequestParameters(Span serverSpan, REQUEST request) { |
| 122 | + if (parameterExtractor == null) { |
| 123 | + return; |
| 124 | + } |
| 125 | + |
111 | 126 | parameterExtractor.setAttributes(request, (key, value) -> serverSpan.setAttribute(key, value));
|
112 | 127 | }
|
113 | 128 |
|
| 129 | + /** |
| 130 | + * Capture {@link SemanticAttributes#ENDUSER_ID} as span attributes when SERVER span is not create |
| 131 | + * by servlet instrumentation. |
| 132 | + * |
| 133 | + * <p>When SERVER span is created by servlet instrumentation we register {@link |
| 134 | + * ServletAdditionalAttributesExtractor} as an attribute extractor. When SERVER span is not |
| 135 | + * created by servlet instrumentation we call this method on exit from the last servlet or filter. |
| 136 | + */ |
| 137 | + private void captureEnduserId(Span serverSpan, REQUEST request) { |
| 138 | + Principal principal = accessor.getRequestUserPrincipal(request); |
| 139 | + if (principal != null) { |
| 140 | + String name = principal.getName(); |
| 141 | + if (name != null) { |
| 142 | + serverSpan.setAttribute(SemanticAttributes.ENDUSER_ID, name); |
| 143 | + } |
| 144 | + } |
| 145 | + } |
| 146 | + |
114 | 147 | /*
|
115 | 148 | Given request already has a context associated with it.
|
116 | 149 | As there should not be nested spans of kind SERVER, we should NOT create a new span here.
|
|
0 commit comments