@@ -58,6 +58,7 @@ def lambda_handler(event, context):
58
58
from opentelemetry .instrumentation .aws_lambda .version import __version__
59
59
from opentelemetry .instrumentation .instrumentor import BaseInstrumentor
60
60
from opentelemetry .instrumentation .utils import unwrap
61
+ from opentelemetry .semconv .trace import SpanAttributes
61
62
from opentelemetry .trace import SpanKind , get_tracer , get_tracer_provider
62
63
63
64
logger = logging .getLogger (__name__ )
@@ -68,19 +69,25 @@ def instrumentation_dependencies(self) -> Collection[str]:
68
69
return _instruments
69
70
70
71
def _instrument (self , ** kwargs ):
71
- self ._tracer = get_tracer (__name__ , __version__ , kwargs .get ("tracer_provider" ))
72
-
73
- self ._tracer_provider = get_tracer_provider ()
72
+ """Instruments Lambda Handlers on AWS Lambda
73
+
74
+ Args:
75
+ **kwargs: Optional arguments
76
+ ``tracer_provider``: a TracerProvider, defaults to global
77
+ """
78
+ tracer = get_tracer (
79
+ __name__ , __version__ , kwargs .get ("tracer_provider" )
80
+ )
74
81
75
- lambda_handler = os .environ .get ("ORIG_HANDLER" , os .environ .get ("_HANDLER" ))
82
+ lambda_handler = os .environ .get (
83
+ "ORIG_HANDLER" , os .environ .get ("_HANDLER" )
84
+ )
76
85
wrapped_names = lambda_handler .rsplit ("." , 1 )
77
86
self ._wrapped_module_name = wrapped_names [0 ]
78
87
self ._wrapped_function_name = wrapped_names [1 ]
79
88
80
- wrap_function_wrapper (
81
- self ._wrapped_module_name ,
82
- self ._wrapped_function_name ,
83
- self ._functionPatch ,
89
+ _instrument (
90
+ tracer , self ._wrapped_module_name , self ._wrapped_function_name
84
91
)
85
92
86
93
def _uninstrument (self , ** kwargs ):
@@ -89,35 +96,50 @@ def _uninstrument(self, **kwargs):
89
96
self ._wrapped_function_name ,
90
97
)
91
98
92
- def _functionPatch (self , original_func , instance , args , kwargs ):
93
- lambda_context = args [1 ]
94
- ctx_aws_request_id = lambda_context .aws_request_id
95
- ctx_invoked_function_arn = lambda_context .invoked_function_arn
96
- orig_handler = os .environ .get ("ORIG_HANDLER" , os .environ .get ("_HANDLER" ))
99
+
100
+ def _instrument (tracer , wrapped_module_name , wrapped_function_name ):
101
+ def _instrumented_lambda_call (call_wrapped , instance , args , kwargs ):
102
+ orig_handler_name = "." .join (
103
+ [wrapped_module_name , wrapped_function_name ]
104
+ )
97
105
98
106
# TODO: enable propagate from AWS by env variable
99
107
xray_trace_id = os .environ .get ("_X_AMZN_TRACE_ID" , "" )
100
-
101
- lambda_name = os .environ .get ("AWS_LAMBDA_FUNCTION_NAME" )
102
- function_version = os .environ .get ("AWS_LAMBDA_FUNCTION_VERSION" )
103
-
104
108
propagator = AwsXRayFormat ()
105
109
parent_context = propagator .extract ({"X-Amzn-Trace-Id" : xray_trace_id })
106
110
107
- with self . _tracer .start_as_current_span (
108
- name = orig_handler , context = parent_context , kind = SpanKind .SERVER
111
+ with tracer .start_as_current_span (
112
+ name = orig_handler_name , context = parent_context , kind = SpanKind .SERVER
109
113
) as span :
110
- # Refer: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/faas.md#example
111
- span .set_attribute ("faas.execution" , ctx_aws_request_id )
112
- span .set_attribute ("faas.id" , ctx_invoked_function_arn )
113
-
114
- # TODO: fix in Collector because they belong resource attrubutes
115
- span .set_attribute ("faas.name" , lambda_name )
116
- span .set_attribute ("faas.version" , function_version )
117
-
118
- result = original_func (* args , ** kwargs )
114
+ if span .is_recording ():
115
+ lambda_context = args [1 ]
116
+ # Refer: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/faas.md#example
117
+ span .set_attribute (
118
+ SpanAttributes .FAAS_EXECUTION , lambda_context .aws_request_id
119
+ )
120
+ span .set_attribute (
121
+ "faas.id" , lambda_context .invoked_function_arn
122
+ )
123
+
124
+ # TODO: fix in Collector because they belong resource attrubutes
125
+ span .set_attribute (
126
+ "faas.name" , os .environ .get ("AWS_LAMBDA_FUNCTION_NAME" )
127
+ )
128
+ span .set_attribute (
129
+ "faas.version" ,
130
+ os .environ .get ("AWS_LAMBDA_FUNCTION_VERSION" ),
131
+ )
132
+
133
+ result = call_wrapped (* args , ** kwargs )
119
134
120
135
# force_flush before function quit in case of Lambda freeze.
121
- self ._tracer_provider .force_flush ()
136
+ tracer_provider = get_tracer_provider ()
137
+ tracer_provider .force_flush ()
122
138
123
139
return result
140
+
141
+ wrap_function_wrapper (
142
+ wrapped_module_name ,
143
+ wrapped_function_name ,
144
+ _instrumented_lambda_call ,
145
+ )
0 commit comments