27
27
import io .opentelemetry .context .Context ;
28
28
import io .opentelemetry .instrumentation .api .incubator .semconv .db .RedisCommandSanitizer ;
29
29
import io .opentelemetry .instrumentation .api .instrumenter .AttributesExtractor ;
30
+ import io .opentelemetry .instrumentation .api .instrumenter .OperationListener ;
30
31
import io .opentelemetry .instrumentation .api .internal .SemconvStability ;
31
32
import io .opentelemetry .instrumentation .api .semconv .network .NetworkAttributesExtractor ;
32
33
import io .opentelemetry .instrumentation .api .semconv .network .ServerAttributesExtractor ;
@@ -54,8 +55,11 @@ final class OpenTelemetryTracing implements Tracing {
54
55
NetworkAttributesExtractor .create (new LettuceServerAttributesGetter ());
55
56
private final TracerProvider tracerProvider ;
56
57
57
- OpenTelemetryTracing (io .opentelemetry .api .trace .Tracer tracer , RedisCommandSanitizer sanitizer ) {
58
- this .tracerProvider = new OpenTelemetryTracerProvider (tracer , sanitizer );
58
+ OpenTelemetryTracing (
59
+ io .opentelemetry .api .trace .Tracer tracer ,
60
+ RedisCommandSanitizer sanitizer ,
61
+ OperationListener metrics ) {
62
+ this .tracerProvider = new OpenTelemetryTracerProvider (tracer , sanitizer , metrics );
59
63
}
60
64
61
65
@ Override
@@ -93,8 +97,10 @@ private static class OpenTelemetryTracerProvider implements TracerProvider {
93
97
private final Tracer openTelemetryTracer ;
94
98
95
99
OpenTelemetryTracerProvider (
96
- io .opentelemetry .api .trace .Tracer tracer , RedisCommandSanitizer sanitizer ) {
97
- openTelemetryTracer = new OpenTelemetryTracer (tracer , sanitizer );
100
+ io .opentelemetry .api .trace .Tracer tracer ,
101
+ RedisCommandSanitizer sanitizer ,
102
+ OperationListener metrics ) {
103
+ openTelemetryTracer = new OpenTelemetryTracer (tracer , sanitizer , metrics );
98
104
}
99
105
100
106
@ Override
@@ -135,10 +141,15 @@ private static class OpenTelemetryTracer extends Tracer {
135
141
136
142
private final io .opentelemetry .api .trace .Tracer tracer ;
137
143
private final RedisCommandSanitizer sanitizer ;
144
+ private final OperationListener metrics ;
138
145
139
- OpenTelemetryTracer (io .opentelemetry .api .trace .Tracer tracer , RedisCommandSanitizer sanitizer ) {
146
+ OpenTelemetryTracer (
147
+ io .opentelemetry .api .trace .Tracer tracer ,
148
+ RedisCommandSanitizer sanitizer ,
149
+ OperationListener metrics ) {
140
150
this .tracer = tracer ;
141
151
this .sanitizer = sanitizer ;
152
+ this .metrics = metrics ;
142
153
}
143
154
144
155
@ Override
@@ -165,7 +176,7 @@ private OpenTelemetrySpan nextSpan(Context context) {
165
176
.setSpanKind (SpanKind .CLIENT )
166
177
.setParent (context )
167
178
.setAttribute (DB_SYSTEM , REDIS );
168
- return new OpenTelemetrySpan (context , spanBuilder , sanitizer );
179
+ return new OpenTelemetrySpan (context , spanBuilder , sanitizer , metrics );
169
180
}
170
181
}
171
182
@@ -178,18 +189,26 @@ private static class OpenTelemetrySpan extends Tracer.Span {
178
189
private final Context context ;
179
190
private final SpanBuilder spanBuilder ;
180
191
private final RedisCommandSanitizer sanitizer ;
192
+ private final OperationListener metrics ;
181
193
182
194
@ Nullable private String name ;
183
195
@ Nullable private List <Object > events ;
184
196
@ Nullable private Throwable error ;
185
197
@ Nullable private Span span ;
198
+ private long spanStartNanos ;
199
+ private final AttributesBuilder attributesBuilder = Attributes .builder ().put (DB_SYSTEM , REDIS );
186
200
@ Nullable private List <String > argsList ;
187
201
@ Nullable private String argsString ;
188
202
189
- OpenTelemetrySpan (Context context , SpanBuilder spanBuilder , RedisCommandSanitizer sanitizer ) {
203
+ OpenTelemetrySpan (
204
+ Context context ,
205
+ SpanBuilder spanBuilder ,
206
+ RedisCommandSanitizer sanitizer ,
207
+ OperationListener metrics ) {
190
208
this .context = context ;
191
209
this .spanBuilder = spanBuilder ;
192
210
this .sanitizer = sanitizer ;
211
+ this .metrics = metrics ;
193
212
}
194
213
195
214
@ Override
@@ -218,11 +237,13 @@ private void fillEndpoint(OpenTelemetryEndpoint endpoint) {
218
237
Context currentContext = span == null ? context : context .with (span );
219
238
serverAttributesExtractor .onStart (attributesBuilder , currentContext , endpoint );
220
239
networkAttributesExtractor .onEnd (attributesBuilder , currentContext , endpoint , null , null );
240
+ Attributes attributes = attributesBuilder .build ();
221
241
if (span != null ) {
222
- span .setAllAttributes (attributesBuilder . build () );
242
+ span .setAllAttributes (attributes );
223
243
} else {
224
- spanBuilder .setAllAttributes (attributesBuilder . build () );
244
+ spanBuilder .setAllAttributes (attributes );
225
245
}
246
+ this .attributesBuilder .putAll (attributes );
226
247
}
227
248
228
249
// Added and called in 6.0+
@@ -231,6 +252,7 @@ private void fillEndpoint(OpenTelemetryEndpoint endpoint) {
231
252
@ SuppressWarnings ("UnusedMethod" )
232
253
public synchronized Tracer .Span start (RedisCommand <?, ?, ?> command ) {
233
254
start ();
255
+ long startNanos = System .nanoTime ();
234
256
235
257
Span span = this .span ;
236
258
if (span == null ) {
@@ -258,7 +280,7 @@ public synchronized Tracer.Span start(RedisCommand<?, ?, ?> command) {
258
280
}
259
281
}
260
282
261
- finish (span );
283
+ finish (span , startNanos );
262
284
});
263
285
}
264
286
@@ -270,6 +292,7 @@ public synchronized Tracer.Span start(RedisCommand<?, ?, ?> command) {
270
292
@ CanIgnoreReturnValue
271
293
public synchronized Tracer .Span start () {
272
294
span = spanBuilder .startSpan ();
295
+ spanStartNanos = System .nanoTime ();
273
296
if (name != null ) {
274
297
span .updateName (name );
275
298
}
@@ -330,6 +353,7 @@ public synchronized Tracer.Span tag(String key, String value) {
330
353
} else {
331
354
spanBuilder .setAttribute (key , value );
332
355
}
356
+ attributesBuilder .put (key , value );
333
357
return this ;
334
358
}
335
359
@@ -347,16 +371,20 @@ public synchronized Tracer.Span error(Throwable throwable) {
347
371
@ Override
348
372
public synchronized void finish () {
349
373
if (span != null ) {
350
- finish (span );
374
+ finish (span , spanStartNanos );
351
375
}
352
376
}
353
377
354
- private void finish (Span span ) {
378
+ private void finish (Span span , long startTime ) {
355
379
if (name != null ) {
356
380
String statement =
357
381
sanitizer .sanitize (name , argsList != null ? argsList : splitArgs (argsString ));
358
382
if (SemconvStability .emitStableDatabaseSemconv ()) {
359
383
span .setAttribute (DB_QUERY_TEXT , statement );
384
+ metrics .onEnd (
385
+ metrics .onStart (Context .current (), Attributes .empty (), startTime ),
386
+ attributesBuilder .build (),
387
+ System .nanoTime ());
360
388
}
361
389
if (SemconvStability .emitOldDatabaseSemconv ()) {
362
390
span .setAttribute (DB_STATEMENT , statement );
0 commit comments