11from opentelemetry .propagate import inject , extract
22from 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
412import json
5- import os
613
7- # create global OpenTelemetry tracer
8- tracer = trace .get_tracer (__name__ )
914
1015# OpenTelemetry Trace context store in metadata
1116TRACE_CARRIER = "trace_carrier"
1217
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+
1381def inject_to_metadata (request , metadata_attr = 'metadata' ):
1482 """
1583 Inject OpenTelemetry trace context into the metadata field of the request.
@@ -28,9 +96,7 @@ def inject_to_metadata(request, metadata_attr='metadata'):
2896 - If there is no metadata attribute in the request, an empty dict will be created for it as its attribute
2997 """
3098 try :
31- if request is None :
32- return
33- if is_opentelemetry_instrumented () == False :
99+ if request is None or traces_enable == False :
34100 return
35101
36102 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'):
48114 except :
49115 pass
50116
117+
51118def extract_from_metadata (request , metadata_attr = 'metadata' ):
52119 """
53120 Extract trace context from metadata of request object (dict or class instance).
@@ -74,7 +141,7 @@ def extract_from_metadata(request, metadata_attr='metadata'):
74141 return ctx
75142 except :
76143 return None
77-
144+
78145
79146def extract_from_request (request ):
80147 """
@@ -100,12 +167,13 @@ def extract_from_request(request):
100167 except :
101168 return None
102169
170+
103171def start_span (span_name , request , kind = trace .SpanKind .CLIENT ):
104172 """
105173 just start a new span in request trace context
106174 """
107175 try :
108- if is_opentelemetry_instrumented () == False :
176+ if not traces_enable :
109177 return
110178 # extract Trace context from request.metadata.trace_carrier
111179 ctx = extract_from_metadata (request )
@@ -114,31 +182,17 @@ def start_span(span_name, request, kind=trace.SpanKind.CLIENT):
114182 except :
115183 pass
116184
185+
117186def start_span_request (span_name , request , kind = trace .SpanKind .CLIENT ):
118187 """
119188 just start a new span in request trace context
120189 """
121190 try :
122- if is_opentelemetry_instrumented () == False :
191+ if not traces_enable :
123192 return
124193 # extract Trace context from request.metadata.trace_carrier
125194 ctx = extract_from_request (request )
126195 with tracer .start_as_current_span (span_name , context = ctx , kind = kind ) as span :
127196 pass
128197 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