@@ -25,6 +25,14 @@ use opentelemetry::{
2525 Context ,
2626 trace:: { SpanKind , TraceContextExt } ,
2727} ;
28+ use opentelemetry_semantic_conventions:: {
29+ attribute:: { OTEL_STATUS_CODE , OTEL_STATUS_DESCRIPTION } ,
30+ trace:: {
31+ CLIENT_ADDRESS , CLIENT_PORT , HTTP_REQUEST_HEADER , HTTP_REQUEST_METHOD ,
32+ HTTP_RESPONSE_STATUS_CODE , HTTP_ROUTE , SERVER_ADDRESS , SERVER_PORT , URL_PATH , URL_QUERY ,
33+ URL_SCHEME , USER_AGENT_ORIGINAL ,
34+ } ,
35+ } ;
2836use pin_project:: pin_project;
2937use snafu:: { ResultExt , Snafu } ;
3038use tower:: { Layer , Service } ;
@@ -41,6 +49,14 @@ const X_FORWARDED_HOST_HEADER_KEY: &str = "X-Forwarded-Host";
4149const DEFAULT_HTTPS_PORT : u16 = 443 ;
4250const DEFAULT_HTTP_PORT : u16 = 80 ;
4351
52+ // NOTE (@Techassi): These constants are defined here because they are private in
53+ // the tracing-opentelemetry crate.
54+ const OTEL_NAME : & str = "otel.name" ;
55+ const OTEL_KIND : & str = "otel.kind" ;
56+
57+ const OTEL_TRACE_ID_FROM : & str = "opentelemetry.trace_id.from" ;
58+ const OTEL_TRACE_ID_TO : & str = "opentelemetry.trace_id.to" ;
59+
4460/// A Tower [`Layer`][1] which decorates [`TraceService`].
4561///
4662/// ### Example with Axum
@@ -414,21 +430,23 @@ impl SpanExt for Span {
414430
415431 let span = tracing:: trace_span!(
416432 "HTTP request" ,
417- "otel.name" = span_name,
418- "otel.kind" = ?SpanKind :: Server ,
419- "otel.status_code" = Empty ,
420- "otel.status_message" = Empty ,
421- "http.request.method" = http_method,
422- "http.response.status_code" = Empty ,
423- "http.route" = Empty ,
424- "url.path" = url. path( ) ,
425- "url.query" = url. query( ) ,
426- "url.scheme" = url. scheme_str( ) . unwrap_or_default( ) ,
427- "user_agent.original" = Empty ,
428- "server.address" = Empty ,
429- "server.port" = Empty ,
430- "client.address" = Empty ,
431- "client.port" = Empty ,
433+ { OTEL_NAME } = span_name,
434+ { OTEL_KIND } = ?SpanKind :: Server ,
435+ { OTEL_STATUS_CODE } = Empty ,
436+ // The current tracing-opentelemetry version still uses the old semantic convention
437+ // See https://github.com/tokio-rs/tracing-opentelemetry/pull/209
438+ { OTEL_STATUS_DESCRIPTION } = Empty ,
439+ { HTTP_REQUEST_METHOD } = http_method,
440+ { HTTP_RESPONSE_STATUS_CODE } = Empty ,
441+ { HTTP_ROUTE } = Empty ,
442+ { URL_PATH } = url. path( ) ,
443+ { URL_QUERY } = url. query( ) ,
444+ { URL_SCHEME } = url. scheme_str( ) . unwrap_or_default( ) ,
445+ { USER_AGENT_ORIGINAL } = Empty ,
446+ { SERVER_ADDRESS } = Empty ,
447+ { SERVER_PORT } = Empty ,
448+ { CLIENT_ADDRESS } = Empty ,
449+ { CLIENT_PORT } = Empty ,
432450 // TODO (@Techassi): Add network.protocol.version
433451 ) ;
434452
@@ -462,8 +480,8 @@ impl SpanExt for Span {
462480
463481 if new_span_context != current_span_context {
464482 tracing:: trace!(
465- opentelemetry . trace_id . from = ?current_span_context. trace_id( ) ,
466- opentelemetry . trace_id . to = ?new_span_context. trace_id( ) ,
483+ { OTEL_TRACE_ID_FROM } = ?current_span_context. trace_id( ) ,
484+ { OTEL_TRACE_ID_TO } = ?new_span_context. trace_id( ) ,
467485 "set parent span context based on context extracted from request headers"
468486 ) ;
469487
@@ -473,7 +491,7 @@ impl SpanExt for Span {
473491 }
474492
475493 if let Some ( user_agent) = req. user_agent ( ) {
476- span. record ( "user_agent.original" , user_agent) ;
494+ span. record ( USER_AGENT_ORIGINAL , user_agent) ;
477495 }
478496
479497 // Setting server.address and server.port
@@ -483,21 +501,21 @@ impl SpanExt for Span {
483501 // NOTE (@Techassi): We cast to i64, because otherwise the field
484502 // will NOT be recorded as a number but as a string. This is likely
485503 // an issue in the tracing-opentelemetry crate.
486- span. record ( "server.address" , host)
487- . record ( "server.port" , port as i64 ) ;
504+ span. record ( SERVER_ADDRESS , host)
505+ . record ( SERVER_PORT , port as i64 ) ;
488506 }
489507
490508 // Setting fields according to the HTTP server semantic conventions
491509 // See https://opentelemetry.io/docs/specs/semconv/http/http-spans/#http-server-semantic-conventions
492510
493511 if let Some ( client_socket_address) = req. client_socket_address ( ) {
494- span. record ( "client.address" , client_socket_address. ip ( ) . to_string ( ) ) ;
512+ span. record ( CLIENT_ADDRESS , client_socket_address. ip ( ) . to_string ( ) ) ;
495513
496514 if opt_in {
497515 // NOTE (@Techassi): We cast to i64, because otherwise the field
498516 // will NOT be recorded as a number but as a string. This is
499517 // likely an issue in the tracing-opentelemetry crate.
500- span. record ( "client.port" , client_socket_address. port ( ) as i64 ) ;
518+ span. record ( CLIENT_PORT , client_socket_address. port ( ) as i64 ) ;
501519 }
502520 }
503521
@@ -511,7 +529,7 @@ impl SpanExt for Span {
511529 // See: https://github.com/tokio-rs/tracing/issues/1343
512530
513531 if let Some ( http_route) = req. matched_path ( ) {
514- span. record ( "http.route" , http_route. as_str ( ) ) ;
532+ span. record ( HTTP_ROUTE , http_route. as_str ( ) ) ;
515533 }
516534
517535 span
@@ -525,7 +543,7 @@ impl SpanExt for Span {
525543 // header_name.as_str() always returns lowercase strings and thus we
526544 // don't need to call to_lowercase on it.
527545 let header_name = header_name. as_str ( ) ;
528- let field_name = format ! ( "http.request.header .{header_name}" ) ;
546+ let field_name = format ! ( "{HTTP_REQUEST_HEADER} .{header_name}" ) ;
529547
530548 self . record (
531549 field_name. as_str ( ) ,
@@ -540,15 +558,15 @@ impl SpanExt for Span {
540558 // NOTE (@Techassi): We cast to i64, because otherwise the field will
541559 // NOT be recorded as a number but as a string. This is likely an issue
542560 // in the tracing-opentelemetry crate.
543- self . record ( "http.response.status_code" , status_code. as_u16 ( ) as i64 ) ;
561+ self . record ( HTTP_RESPONSE_STATUS_CODE , status_code. as_u16 ( ) as i64 ) ;
544562
545563 // Only set the span status to "Error" when we encountered an server
546564 // error. See:
547565 //
548566 // - https://opentelemetry.io/docs/specs/semconv/http/http-spans/#status
549567 // - https://github.com/open-telemetry/opentelemetry-specification/blob/v1.26.0/specification/trace/api.md#set-status
550568 if status_code. is_server_error ( ) {
551- self . record ( "otel.status_code" , "Error" ) ;
569+ self . record ( OTEL_STATUS_CODE , "Error" ) ;
552570 // NOTE (@Techassi): Can we add a status_description here as well?
553571 }
554572
@@ -561,8 +579,9 @@ impl SpanExt for Span {
561579 E : std:: error:: Error ,
562580 {
563581 // NOTE (@Techassi): This field might get renamed: https://github.com/tokio-rs/tracing-opentelemetry/issues/115
564- self . record ( "otel.status_code" , "Error" )
565- . record ( "otel.status_message" , error. to_string ( ) ) ;
582+ // NOTE (@Techassi): It got renamed, a fixed version of tracing-opentelemetry is not available yet
583+ self . record ( OTEL_STATUS_CODE , "Error" )
584+ . record ( OTEL_STATUS_DESCRIPTION , error. to_string ( ) ) ;
566585 }
567586}
568587
0 commit comments