@@ -231,6 +231,49 @@ def _to_proto_chat_item(item: ChatItem) -> agent_pb.agent_session.ChatContext.Ch
231231 return item_pb
232232
233233
234+ def _to_log_chat_item (item : ChatItem ) -> map [str , any ] | None :
235+ if item .type == "message" :
236+ return {
237+ "type" : item .type ,
238+ "id" : item .id ,
239+ "role" : item .role ,
240+ "content" : [content for content in item .content if isinstance (content , str )],
241+ "interrupted" : item .interrupted ,
242+ "transcript_confidence" : item .transcript_confidence ,
243+ "extra" : item .extra ,
244+ "metrics" : item .metrics ,
245+ }
246+
247+ elif item .type == "function_call" :
248+ return {
249+ "type" : item .type ,
250+ "id" : item .id ,
251+ "call_id" : item .call_id ,
252+ "arguments" : json .loads (item .arguments ),
253+ "name" : item .name ,
254+ }
255+
256+ elif item .type == "function_call_output" :
257+ return {
258+ "type" : item .type ,
259+ "id" : item .id ,
260+ "name" : item .name ,
261+ "call_id" : item .call_id ,
262+ "output" : json .loads (item .output ),
263+ "is_error" : item .is_error ,
264+ }
265+
266+ elif item .type == "agent_handoff" :
267+ return {
268+ "type" : item .type ,
269+ "id" : item .id ,
270+ "old_agent_id" : item .old_agent_id ,
271+ "new_agent_id" : item .new_agent_id ,
272+ }
273+
274+ return None
275+
276+
234277def _to_rfc3339 (value : int | float | datetime ) -> str :
235278 if isinstance (value , (int , float )):
236279 dt = datetime .fromtimestamp (value , tz = timezone .utc )
@@ -251,6 +294,40 @@ async def _upload_session_report(
251294 report : SessionReport ,
252295 http_session : aiohttp .ClientSession ,
253296) -> None :
297+ # emit logs
298+ chat_logger = get_logger_provider ().get_logger (
299+ name = "chat_history" ,
300+ attributes = {
301+ "room_id" : report .room_id ,
302+ "job_id" : report .job_id ,
303+ "room" : report .room ,
304+ "lk.enable_user_data_training" : report .enable_user_data_training ,
305+ },
306+ )
307+ chat_logger .emit (
308+ LogRecord (
309+ timestamp = int (report .audio_recording_started_at * 1e9 ),
310+ body = "chat started" ,
311+ attributes = {
312+ "chat.options" : dict (report .options ),
313+ "chat.report_timestamp" : report .timestamp ,
314+ },
315+ )
316+ )
317+ for item in report .chat_history .items :
318+ item_log = _to_log_chat_item (item )
319+ if item_log is not None :
320+ chat_logger .emit (
321+ LogRecord (
322+ timestamp = int (item .created_at * 1e9 ),
323+ body = "chat item" ,
324+ attributes = {
325+ "chat.item" : item_log ,
326+ },
327+ )
328+ )
329+
330+ # emit recording
254331 access_token = (
255332 api .AccessToken ()
256333 .with_observability_grants (api .ObservabilityGrants (write = True ))
@@ -259,7 +336,8 @@ async def _upload_session_report(
259336 jwt = access_token .to_jwt ()
260337
261338 header_msg = proto_metrics .MetricsRecordingHeader (
262- room_id = room_id , enable_user_data_training = report .enable_user_data_training
339+ room_id = room_id ,
340+ enable_user_data_training = report .enable_user_data_training
263341 )
264342 header_bytes = header_msg .SerializeToString ()
265343
@@ -279,22 +357,6 @@ async def _upload_session_report(
279357 # part.headers["Content-Length"] = str(len(chat_history_bytes))
280358
281359 # chat_history_pb = _to_proto_chat_ctx(report.chat_history)
282- chat_logger = get_logger_provider ().get_logger ("chat_history" )
283- for item in report .chat_history .items :
284- item_proto = _to_proto_chat_item (item )
285- item_json = MessageToJson (item_proto )
286- chat_logger .emit (
287- LogRecord (
288- timestamp = int (item .created_at * 1e9 ),
289- body = item_json ,
290- trace_id = 0 ,
291- span_id = 0 ,
292- trace_flags = 0 ,
293- severity_number = SeverityNumber .UNSPECIFIED ,
294- severity_text = "unspecified" ,
295- attributes = {"protobuf.message_type" : item_proto .DESCRIPTOR .full_name },
296- )
297- )
298360
299361 if report .audio_recording_path and report .audio_recording_started_at :
300362 try :
0 commit comments