@@ -128,7 +128,7 @@ def on_start(self, span: Span, parent_context: Optional[Context] = None) -> None
128128 This method is called when a span starts and applies context propagation:
129129 1. Propagates all baggage keys as span attributes
130130 2. Propagates langfuse.ctx.* context variables as span attributes
131- 3. Merges langfuse.ctx.metadata.* keys into a single metadata JSON attribute
131+ 3. Distributes langfuse.ctx.metadata keys as individual langfuse. metadata.* attributes
132132
133133 Args:
134134 span: The span that is starting
@@ -180,39 +180,35 @@ def on_start(self, span: Span, parent_context: Optional[Context] = None) -> None
180180 except Exception as e :
181181 langfuse_logger .debug (f"Could not read context key '{ ctx_key } ': { e } " )
182182
183- # 3. Handle langfuse.ctx.metadata.* keys - merge into single metadata JSON
183+ # 3. Handle langfuse.ctx.metadata - distribute keys as individual attributes
184184 try :
185- # Get metadata as a single JSON object from context
186- metadata_value = context_api .get_value (
185+ # Get metadata dict from context
186+ metadata_dict = context_api .get_value (
187187 LANGFUSE_CTX_METADATA , context = current_context
188188 )
189- if metadata_value is not None :
190- if isinstance (metadata_value , str ):
191- # If it's already a JSON string, validate it
192- try :
193- json .loads (metadata_value ) # Validate JSON
194- metadata_json = metadata_value
195- except json .JSONDecodeError :
196- # If invalid JSON, wrap in quotes
197- metadata_json = json .dumps ({"value" : metadata_value })
198- elif isinstance (metadata_value , dict ):
199- # Convert dict to JSON string
200- metadata_json = json .dumps (metadata_value )
201- else :
202- # Convert other types to a wrapped JSON object
203- metadata_json = json .dumps ({"value" : str (metadata_value )})
204-
205- # Only propagate if not already set or different
206- existing_metadata = (
207- span .attributes .get ("metadata" )
208- if hasattr (span , "attributes" ) and span .attributes is not None
209- else None
210- )
211- if existing_metadata != metadata_json :
212- propagated_attributes ["metadata" ] = metadata_json
213- langfuse_logger .debug (
214- f"Propagated metadata to span '{ span .name } ': { metadata_json } "
189+ if metadata_dict is not None and isinstance (metadata_dict , dict ):
190+ # Set each metadata key as a separate span attribute with langfuse.metadata. prefix
191+ for key , value in metadata_dict .items ():
192+ attr_key = f"langfuse.metadata.{ key } "
193+
194+ # Convert value to appropriate type for span attribute
195+ if isinstance (value , (str , int , float , bool )):
196+ attr_value = value
197+ else :
198+ # For complex types, convert to JSON string
199+ attr_value = json .dumps (value )
200+
201+ # Only propagate if not already set or different
202+ existing_value = (
203+ span .attributes .get (attr_key )
204+ if hasattr (span , "attributes" ) and span .attributes is not None
205+ else None
215206 )
207+ if existing_value != attr_value :
208+ propagated_attributes [attr_key ] = attr_value
209+ langfuse_logger .debug (
210+ f"Propagated metadata key '{ key } ' = '{ attr_value } ' to span '{ span .name } '"
211+ )
216212 except Exception as e :
217213 langfuse_logger .debug (f"Could not read metadata from context: { e } " )
218214
0 commit comments