22from importlib_metadata import version as v
33from langtrace_python_sdk .constants import LANGTRACE_SDK_NAME
44from langtrace_python_sdk .utils import set_span_attribute
5- from langtrace_python_sdk .utils .llm import get_span_name
6- from langtrace_python_sdk .utils .silently_fail import silently_fail
5+ from langtrace_python_sdk .utils .llm import get_span_name , set_span_attributes
76from langtrace_python_sdk .constants .instrumentation .common import (
87 LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY ,
98 SERVICE_PROVIDERS ,
109)
1110from opentelemetry import baggage
1211from langtrace .trace_attributes import FrameworkSpanAttributes
13- from opentelemetry .trace import SpanKind
12+ from opentelemetry .trace import SpanKind , Span , Tracer
1413from opentelemetry .trace .status import Status , StatusCode
1514
1615
3332 "share_crew" : "bool" ,
3433 "step_callback" : "object" ,
3534 "task_callback" : "object" ,
36- "prompt_file" : "object " ,
37- "output_log_file" : "object " ,
35+ "prompt_file" : "str " ,
36+ "output_log_file" : "bool " ,
3837}
3938
4039task_properties = {
9089}
9190
9291
93- def patch_crew (operation_name , version , tracer ):
92+ def patch_crew (operation_name , version , tracer : Tracer ):
9493 def traced_method (wrapped , instance , args , kwargs ):
95-
9694 service_provider = SERVICE_PROVIDERS ["CREWAI" ]
9795 extra_attributes = baggage .get_baggage (LANGTRACE_ADDITIONAL_SPAN_ATTRIBUTES_KEY )
9896 span_attributes = {
@@ -104,52 +102,15 @@ def traced_method(wrapped, instance, args, kwargs):
104102 ** (extra_attributes if extra_attributes is not None else {}),
105103 }
106104
107- crew_config = {}
108- for key , value in instance .__dict__ .items ():
109- if instance .__class__ .__name__ == "Crew" :
110- if key in crew_properties and value is not None :
111- if crew_properties [key ] == "json" :
112- crew_config [key ] = json .dumps (value )
113- elif crew_properties [key ] == "object" :
114- crew_config [key ] = str (value )
115- else :
116- crew_config [key ] = value
117- elif instance .__class__ .__name__ == "Agent" :
118- if key in agent_properties and value is not None :
119- if agent_properties [key ] == "json" :
120- crew_config [key ] = json .dumps (value )
121- elif agent_properties [key ] == "object" :
122- crew_config [key ] = str (value )
123- else :
124- crew_config [key ] = value
125- elif instance .__class__ .__name__ == "Task" :
126- if key in task_properties and value is not None :
127- if task_properties [key ] == "json" :
128- crew_config [key ] = json .dumps (value )
129- elif task_properties [key ] == "object" :
130- crew_config [key ] = str (value )
131- else :
132- crew_config [key ] = value
133- if crew_config :
134- if instance .__class__ .__name__ == "Crew" :
135- if "inputs" in kwargs and kwargs ["inputs" ]:
136- crew_config ["inputs" ] = json .dumps (kwargs ["inputs" ])
137- span_attributes ["crewai.crew.config" ] = json .dumps (crew_config )
138- elif instance .__class__ .__name__ == "Agent" :
139- if "context" in kwargs and kwargs ["context" ]:
140- crew_config ["context" ] = json .dumps (kwargs ["context" ])
141- span_attributes ["crewai.agent.config" ] = json .dumps (crew_config )
142- elif instance .__class__ .__name__ == "Task" :
143- span_attributes ["crewai.task.config" ] = json .dumps (crew_config )
144-
145105 attributes = FrameworkSpanAttributes (** span_attributes )
146106
147107 with tracer .start_as_current_span (
148108 get_span_name (operation_name ), kind = SpanKind .CLIENT
149109 ) as span :
150- _set_input_attributes (span , kwargs , attributes )
151110
152111 try :
112+ set_span_attributes (span , attributes )
113+ CrewAISpanAttributes (span = span , instance = instance )
153114 result = wrapped (* args , ** kwargs )
154115 if result :
155116 span .set_status (Status (StatusCode .OK ))
@@ -158,6 +119,7 @@ def traced_method(wrapped, instance, args, kwargs):
158119 return result
159120
160121 except Exception as err :
122+ print ("Error" , err )
161123 # Record the exception in the span
162124 span .record_exception (err )
163125
@@ -170,7 +132,103 @@ def traced_method(wrapped, instance, args, kwargs):
170132 return traced_method
171133
172134
173- @silently_fail
174- def _set_input_attributes (span , kwargs , attributes ):
175- for field , value in attributes .model_dump (by_alias = True ).items ():
176- set_span_attribute (span , field , value )
135+ class CrewAISpanAttributes :
136+ span : Span
137+ crew : dict
138+
139+ def __init__ (self , span : Span , instance ) -> None :
140+ self .span = span
141+ self .instance = instance
142+ self .crew = {
143+ "tasks" : [],
144+ "agents" : [],
145+ }
146+
147+ self .run ()
148+
149+ def run (self ):
150+ instance_name = self .instance .__class__ .__name__
151+ if instance_name == "Crew" :
152+ self .set_crew_attributes ()
153+ set_span_attribute (self .span , "crewai.crew.config" , json .dumps (self .crew ))
154+
155+ elif instance_name == "Agent" :
156+ agent = self .set_agent_attributes ()
157+ # for key, value in agent.items():
158+ # set_span_attribute(self.span, key, value)
159+ set_span_attribute (self .span , "crewai.agent.config" , json .dumps (agent ))
160+ elif instance_name == "Task" :
161+ task = self .set_task_attributes ()
162+ # uncomment if you want to spread attributes for the UI instead of dumping the whole object
163+ # for key, value in task.items():
164+ # set_span_attribute(self.span, key, value)
165+ set_span_attribute (self .span , "crewai.task.config" , json .dumps (task ))
166+
167+ def set_crew_attributes (self ):
168+ for key , value in self .instance .__dict__ .items ():
169+ if key == "tasks" :
170+ self ._parse_tasks (value )
171+
172+ elif key == "agents" :
173+ self ._parse_agents (value )
174+ else :
175+ self .crew [key ] = str (value )
176+
177+ def set_agent_attributes (self ):
178+ agent = {}
179+ for key , value in self .instance .__dict__ .items ():
180+ if value is None :
181+ continue
182+ agent [key ] = str (value )
183+
184+ return agent
185+
186+ def set_task_attributes (self ):
187+ task = {}
188+ for key , value in self .instance .__dict__ .items ():
189+ if value is None :
190+ continue
191+
192+ if key == "agent" :
193+ task [key ] = value .role
194+ else :
195+ task [key ] = str (value )
196+ return task
197+
198+ def _parse_agents (self , agents ):
199+ for agent in agents :
200+ model = None
201+ if agent .llm is not None :
202+ if hasattr (agent .llm , "model" ):
203+ model = agent .llm .model
204+ elif hasattr (agent .llm , "model_name" ):
205+ model = agent .llm .model_name
206+ self .crew ["agents" ].append (
207+ {
208+ "id" : str (agent .id ),
209+ "role" : agent .role ,
210+ "goal" : agent .goal ,
211+ "backstory" : agent .backstory ,
212+ "cache" : agent .cache ,
213+ "config" : agent .config ,
214+ "verbose" : agent .verbose ,
215+ "allow_delegation" : agent .allow_delegation ,
216+ "tools" : agent .tools ,
217+ "max_iter" : agent .max_iter ,
218+ "llm" : str (model if model is not None else "" ),
219+ }
220+ )
221+
222+ def _parse_tasks (self , tasks ):
223+ for task in tasks :
224+ self .crew ["tasks" ].append (
225+ {
226+ "agent" : task .agent .role ,
227+ "description" : task .description ,
228+ "async_execution" : task .async_execution ,
229+ "expected_output" : task .expected_output ,
230+ "human_input" : task .human_input ,
231+ "tools" : task .tools ,
232+ "output_file" : task .output_file ,
233+ }
234+ )
0 commit comments