2222from opentelemetry .sdk .trace import ReadableSpan , Span
2323from opentelemetry .sdk .trace .export import BatchSpanProcessor
2424
25- from langfuse ._client .constants import LANGFUSE_TRACER_NAME
25+ from langfuse ._client .constants import (
26+ LANGFUSE_TRACER_NAME ,
27+ LANGFUSE_CTX_USER_ID ,
28+ LANGFUSE_CTX_SESSION_ID ,
29+ LANGFUSE_CTX_METADATA ,
30+ )
2631from langfuse ._client .environment_variables import (
2732 LANGFUSE_FLUSH_AT ,
2833 LANGFUSE_FLUSH_INTERVAL ,
3136from langfuse ._client .utils import span_formatter
3237from langfuse .logger import langfuse_logger
3338from langfuse .version import __version__ as langfuse_version
34- from langfuse ._client .client import (
35- LANGFUSE_CTX_USER_ID ,
36- LANGFUSE_CTX_SESSION_ID ,
37- LANGFUSE_CTX_METADATA ,
38- )
3939
4040
4141class LangfuseSpanProcessor (BatchSpanProcessor ):
@@ -143,10 +143,11 @@ def on_start(self, span: Span, parent_context: Optional[Context] = None) -> None
143143 # 1. Propagate all baggage keys as span attributes
144144 baggage_entries = baggage .get_all (context = current_context )
145145 for key , value in baggage_entries .items ():
146- # Check if this baggage entry is already present as a span attribute
147- if not hasattr (span .attributes , key ) or (
148- span .attributes is not None and span .attributes .get (key ) != value
149- ):
146+ # Only propagate user.id, session.id and langfuse.metadata.* as those are set by us on the baggage
147+ if key .startswith ("langfuse.metadata." ) or key in [
148+ "user.id" ,
149+ "session.id" ,
150+ ]:
150151 propagated_attributes [key ] = value
151152 langfuse_logger .debug (
152153 f"Propagated baggage key '{ key } ' = '{ value } ' to span '{ span .name } '"
@@ -160,16 +161,10 @@ def on_start(self, span: Span, parent_context: Optional[Context] = None) -> None
160161 if value is not None :
161162 # Convert context key to span attribute name (remove langfuse.ctx. prefix)
162163 attr_key = ctx_key .replace ("langfuse.ctx." , "" )
163-
164- # Only propagate if not already set on span
165- if not hasattr (span .attributes , attr_key ) or (
166- span .attributes is not None
167- and span .attributes .get (attr_key ) != value
168- ):
169- propagated_attributes [attr_key ] = value
170- langfuse_logger .debug (
171- f"Propagated context key '{ ctx_key } ' = '{ value } ' to span '{ span .name } '"
172- )
164+ propagated_attributes [attr_key ] = value
165+ langfuse_logger .debug (
166+ f"Propagated context key '{ ctx_key } ' = '{ value } ' to span '{ span .name } '"
167+ )
173168 except Exception as e :
174169 langfuse_logger .debug (f"Could not read context key '{ ctx_key } ': { e } " )
175170
@@ -184,24 +179,17 @@ def on_start(self, span: Span, parent_context: Optional[Context] = None) -> None
184179 for key , value in metadata_dict .items ():
185180 attr_key = f"langfuse.metadata.{ key } "
186181
187- # Convert value to appropriate type for span attribute
188- if isinstance (value , (str , int , float , bool )):
189- attr_value = value
190- else :
191- # For complex types, convert to JSON string
192- attr_value = json .dumps (value )
193-
194- # Only propagate if not already set or different
195- existing_value = (
196- span .attributes .get (attr_key )
197- if hasattr (span , "attributes" ) and span .attributes is not None
198- else None
182+ # Convert value to appropriate type for span attribute (naive or json stringify)
183+ attr_value = (
184+ value
185+ if isinstance (value , (str , int , float , bool ))
186+ else json .dumps (value )
187+ )
188+
189+ propagated_attributes [attr_key ] = attr_value
190+ langfuse_logger .debug (
191+ f"Propagated metadata key '{ key } ' = '{ attr_value } ' to span '{ span .name } '"
199192 )
200- if existing_value != attr_value :
201- propagated_attributes [attr_key ] = attr_value
202- langfuse_logger .debug (
203- f"Propagated metadata key '{ key } ' = '{ attr_value } ' to span '{ span .name } '"
204- )
205193 except Exception as e :
206194 langfuse_logger .debug (f"Could not read metadata from context: { e } " )
207195
0 commit comments