1
1
from opentelemetry .propagate import inject , extract
2
2
from opentelemetry import trace
3
-
3
+ from opentelemetry .sdk .trace import TracerProvider
4
+ from opentelemetry .sdk .trace .export import BatchSpanProcessor
5
+ from opentelemetry .exporter .otlp .proto .http .trace_exporter import OTLPSpanExporter
6
+ from opentelemetry .sdk .trace .export import ConsoleSpanExporter
7
+ from opentelemetry .sdk .resources import Resource
8
+ from opentelemetry .instrumentation .fastapi import FastAPIInstrumentor
9
+ from fastapi import FastAPI
10
+ from fastdeploy .utils import (llm_logger )
11
+ from fastdeploy import envs
4
12
import json
5
- import os
6
13
7
- # create global OpenTelemetry tracer
8
- tracer = trace .get_tracer (__name__ )
9
14
10
15
# OpenTelemetry Trace context store in metadata
11
16
TRACE_CARRIER = "trace_carrier"
12
17
18
+ traces_enable = False
19
+ tracer = trace .get_tracer (__name__ )
20
+
21
+ def set_up ():
22
+ try :
23
+ # when TRACES_ENABLED=true start trace
24
+ global traces_enable
25
+ traces_enable = envs .TRACES_ENABLE .lower () == "true"
26
+ if not traces_enable :
27
+ llm_logger .warning ("Opentelemetry is DISABLED." )
28
+ return
29
+
30
+ llm_logger .info ("Opentelemetry is ENABLED, configuring..." )
31
+ # --- read env ---
32
+ service_name = envs .FD_SERVICE_NAME
33
+ host_name = envs .FD_HOST_NAME
34
+ # --- set attributes (Service Name, Host Name, etc.) ---
35
+ resource_attributes = {
36
+ "service.name" : service_name
37
+ }
38
+ if host_name :
39
+ resource_attributes ["host.name" ] = host_name
40
+
41
+ resource = Resource (attributes = resource_attributes )
42
+
43
+ # --- set Exporter ---
44
+ exporter_type = envs .TRACES_EXPORTER .lower ()
45
+ if exporter_type == "otlp" :
46
+ endpoint = envs .EXPORTER_OTLP_ENDPOINT # should be set
47
+ headers = envs .EXPORTER_OTLP_HEADERS # e.g., "Authentication=***,k2=v2"
48
+
49
+ otlp_exporter = OTLPSpanExporter (
50
+ endpoint = endpoint ,
51
+ headers = dict (item .split ("=" ) for item in headers .split ("," )) if headers else None
52
+ )
53
+ processor = BatchSpanProcessor (otlp_exporter )
54
+ llm_logger .info (f"Using OTLP Exporter, sending to { endpoint } with headers { headers } " )
55
+ else : # default console
56
+ processor = BatchSpanProcessor (ConsoleSpanExporter ())
57
+ llm_logger .info ("Using Console Exporter." )
58
+
59
+ # --- set Tracer Provider ---
60
+ provider = TracerProvider (resource = resource )
61
+ provider .add_span_processor (processor )
62
+ trace .set_tracer_provider (provider )
63
+ global tracer
64
+ tracer = trace .get_tracer (__name__ )
65
+ except :
66
+ llm_logger .error ("set_up failed" )
67
+ pass
68
+
69
+ def instrument (app : FastAPI ):
70
+ try :
71
+ set_up ()
72
+ if traces_enable :
73
+ llm_logger .info ("Applying instrumentors..." )
74
+ FastAPIInstrumentor .instrument_app (app )
75
+ except :
76
+ llm_logger .info ("instrument failed" )
77
+ pass
78
+
79
+
80
+
13
81
def inject_to_metadata (request , metadata_attr = 'metadata' ):
14
82
"""
15
83
Inject OpenTelemetry trace context into the metadata field of the request.
@@ -28,9 +96,7 @@ def inject_to_metadata(request, metadata_attr='metadata'):
28
96
- If there is no metadata attribute in the request, an empty dict will be created for it as its attribute
29
97
"""
30
98
try :
31
- if request is None :
32
- return
33
- if is_opentelemetry_instrumented () == False :
99
+ if request is None or traces_enable == False :
34
100
return
35
101
36
102
metadata = request .get (metadata_attr ) if isinstance (request , dict ) else getattr (request , metadata_attr , None )
@@ -48,6 +114,7 @@ def inject_to_metadata(request, metadata_attr='metadata'):
48
114
except :
49
115
pass
50
116
117
+
51
118
def extract_from_metadata (request , metadata_attr = 'metadata' ):
52
119
"""
53
120
Extract trace context from metadata of request object (dict or class instance).
@@ -74,7 +141,7 @@ def extract_from_metadata(request, metadata_attr='metadata'):
74
141
return ctx
75
142
except :
76
143
return None
77
-
144
+
78
145
79
146
def extract_from_request (request ):
80
147
"""
@@ -100,12 +167,13 @@ def extract_from_request(request):
100
167
except :
101
168
return None
102
169
170
+
103
171
def start_span (span_name , request , kind = trace .SpanKind .CLIENT ):
104
172
"""
105
173
just start a new span in request trace context
106
174
"""
107
175
try :
108
- if is_opentelemetry_instrumented () == False :
176
+ if not traces_enable :
109
177
return
110
178
# extract Trace context from request.metadata.trace_carrier
111
179
ctx = extract_from_metadata (request )
@@ -114,31 +182,17 @@ def start_span(span_name, request, kind=trace.SpanKind.CLIENT):
114
182
except :
115
183
pass
116
184
185
+
117
186
def start_span_request (span_name , request , kind = trace .SpanKind .CLIENT ):
118
187
"""
119
188
just start a new span in request trace context
120
189
"""
121
190
try :
122
- if is_opentelemetry_instrumented () == False :
191
+ if not traces_enable :
123
192
return
124
193
# extract Trace context from request.metadata.trace_carrier
125
194
ctx = extract_from_request (request )
126
195
with tracer .start_as_current_span (span_name , context = ctx , kind = kind ) as span :
127
196
pass
128
197
except :
129
- pass
130
-
131
- def is_opentelemetry_instrumented () -> bool :
132
- """
133
- check OpenTelemetry is start or not
134
- """
135
- try :
136
- return (
137
- os .getenv ("OTEL_PYTHONE_DISABLED_INSTRUMENTATIONS" ) is not None
138
- or os .getenv ("OTEL_SERVICE_NAME" ) is not None
139
- or os .getenv ("OTEL_TRACES_EXPORTER" ) is not None
140
- )
141
- except Exception :
142
- return False
143
-
144
-
198
+ pass
0 commit comments