@@ -193,6 +193,14 @@ def response_hook(span, req, resp):
193193
194194import opentelemetry .instrumentation .wsgi as otel_wsgi
195195from opentelemetry import context , trace
196+ from opentelemetry .instrumentation ._semconv import (
197+ _HTTPStabilityMode ,
198+ _OpenTelemetrySemanticConventionStability ,
199+ _OpenTelemetryStabilitySignalType ,
200+ _report_new ,
201+ _report_old ,
202+ _set_status ,
203+ )
196204from opentelemetry .instrumentation .falcon .package import _instruments
197205from opentelemetry .instrumentation .falcon .version import __version__
198206from opentelemetry .instrumentation .instrumentor import BaseInstrumentor
@@ -203,12 +211,12 @@ def response_hook(span, req, resp):
203211from opentelemetry .instrumentation .utils import (
204212 _start_internal_or_server_span ,
205213 extract_attributes_from_object ,
206- http_status_to_status_code ,
207214)
208215from opentelemetry .metrics import get_meter
216+ from opentelemetry .semconv .attributes .error_attributes import ERROR_TYPE
209217from opentelemetry .semconv .metrics import MetricInstruments
210218from opentelemetry .semconv .trace import SpanAttributes
211- from opentelemetry .trace .status import Status , StatusCode
219+ from opentelemetry .trace .status import StatusCode
212220from opentelemetry .util .http import get_excluded_urls , get_traced_request_attrs
213221
214222_logger = getLogger (__name__ )
@@ -243,6 +251,11 @@ class _InstrumentedFalconAPI(getattr(falcon, _instrument_app)):
243251 def __init__ (self , * args , ** kwargs ):
244252 otel_opts = kwargs .pop ("_otel_opts" , {})
245253
254+ _OpenTelemetrySemanticConventionStability ._initialize ()
255+ self ._sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability ._get_opentelemetry_stability_opt_in_mode (
256+ _OpenTelemetryStabilitySignalType .HTTP ,
257+ )
258+
246259 # inject trace middleware
247260 self ._middlewares_list = kwargs .pop ("middleware" , [])
248261 if self ._middlewares_list is None :
@@ -283,6 +296,7 @@ def __init__(self, *args, **kwargs):
283296 ),
284297 otel_opts .pop ("request_hook" , None ),
285298 otel_opts .pop ("response_hook" , None ),
299+ self ._sem_conv_opt_in_mode ,
286300 )
287301 self ._middlewares_list .insert (0 , trace_middleware )
288302 kwargs ["middleware" ] = self ._middlewares_list
@@ -382,9 +396,21 @@ def _start_response(status, response_headers, *args, **kwargs):
382396 raise
383397 finally :
384398 if span .is_recording ():
385- duration_attrs [SpanAttributes .HTTP_STATUS_CODE ] = (
386- span .attributes .get (SpanAttributes .HTTP_STATUS_CODE )
387- )
399+ if _report_old (self ._sem_conv_opt_in_mode ):
400+ duration_attrs [SpanAttributes .HTTP_STATUS_CODE ] = (
401+ span .attributes .get (SpanAttributes .HTTP_STATUS_CODE )
402+ )
403+ if _report_new (self ._sem_conv_opt_in_mode ):
404+ duration_attrs [
405+ SpanAttributes .HTTP_RESPONSE_STATUS_CODE
406+ ] = span .attributes .get (
407+ SpanAttributes .HTTP_RESPONSE_STATUS_CODE
408+ )
409+ if span .status .status_code == StatusCode .ERROR :
410+ duration_attrs [ERROR_TYPE ] = span .attributes .get (
411+ ERROR_TYPE
412+ )
413+
388414 duration = max (round ((default_timer () - start ) * 1000 ), 0 )
389415 self .duration_histogram .record (duration , duration_attrs )
390416 self .active_requests_counter .add (- 1 , active_requests_count_attrs )
@@ -409,11 +435,13 @@ def __init__(
409435 traced_request_attrs = None ,
410436 request_hook = None ,
411437 response_hook = None ,
438+ sem_conv_opt_in_mode : _HTTPStabilityMode = _HTTPStabilityMode .DEFAULT ,
412439 ):
413440 self .tracer = tracer
414441 self ._traced_request_attrs = traced_request_attrs
415442 self ._request_hook = request_hook
416443 self ._response_hook = response_hook
444+ self ._sem_conv_opt_in_mode = sem_conv_opt_in_mode
417445
418446 def process_request (self , req , resp ):
419447 span = req .env .get (_ENVIRON_SPAN_KEY )
@@ -446,10 +474,8 @@ def process_response(
446474 return
447475
448476 status = resp .status
449- reason = None
450477 if resource is None :
451478 status = "404"
452- reason = "NotFound"
453479 else :
454480 if _ENVIRON_EXC in req .env :
455481 exc = req .env [_ENVIRON_EXC ]
@@ -459,28 +485,18 @@ def process_response(
459485 if exc_type and not req_succeeded :
460486 if "HTTPNotFound" in exc_type .__name__ :
461487 status = "404"
462- reason = "NotFound"
463488 else :
464489 status = "500"
465- reason = f"{ exc_type .__name__ } : { exc } "
466490
467491 status = status .split (" " )[0 ]
468492 try :
469- status_code = int (status )
470- span .set_attribute (SpanAttributes .HTTP_STATUS_CODE , status_code )
471- otel_status_code = http_status_to_status_code (
472- status_code , server_span = True
473- )
474-
475- # set the description only when the status code is ERROR
476- if otel_status_code is not StatusCode .ERROR :
477- reason = None
478-
479- span .set_status (
480- Status (
481- status_code = otel_status_code ,
482- description = reason ,
483- )
493+ _set_status (
494+ span ,
495+ {},
496+ int (status ),
497+ resp .status ,
498+ span .kind == trace .SpanKind .SERVER ,
499+ self ._sem_conv_opt_in_mode ,
484500 )
485501
486502 # Falcon 1 does not support response headers. So
@@ -493,6 +509,9 @@ def process_response(
493509 # Check if low-cardinality route is available as per semantic-conventions
494510 if req .uri_template :
495511 span .update_name (f"{ req .method } { req .uri_template } " )
512+ span .set_attribute (
513+ SpanAttributes .HTTP_ROUTE , req .uri_template
514+ )
496515 else :
497516 span .update_name (f"{ req .method } " )
498517
0 commit comments