88from microsoft_agents .hosting .core .middleware_set import Middleware , TurnContext
99from microsoft_agents_a365 .observability .core .agent_details import AgentDetails
1010from microsoft_agents_a365 .observability .core .execution_type import ExecutionType
11+ from microsoft_agents_a365 .observability .core .models .response import Response
1112from microsoft_agents_a365 .observability .core .request import Request
1213from microsoft_agents_a365 .observability .core .spans_scopes .input_scope import InputScope
14+ from microsoft_agents_a365 .observability .core .spans_scopes .output_scope import OutputScope
1315from microsoft_agents_a365 .observability .core .tenant_details import TenantDetails
1416
1517
@@ -32,7 +34,7 @@ def __init__(
3234 log_user_messages: Whether to log incoming user messages
3335 log_bot_messages: Whether to log outgoing bot messages
3436 """
35- self .logger = logger or logging .getLogger ("agents. observability" )
37+ self .logger = logger or logging .getLogger ("agents.observability" )
3638 self .log_user_messages = log_user_messages
3739 self .log_bot_messages = log_bot_messages
3840
@@ -43,12 +45,13 @@ async def on_turn(self, turn_context: TurnContext, logic: Callable[[TurnContext]
4345 if self .log_user_messages and turn_context .activity .text :
4446 input_scope = self ._create_input_scope (turn_context .activity )
4547 input_scope .__enter__ ()
46- self .logger .info (f"📥 User: { turn_context .activity .text } " )
48+ self .logger .info (f"📥 User input message: { turn_context .activity .text } " )
4749
4850 try :
4951 # Hook into outgoing messages
5052 if self .log_bot_messages :
51- turn_context .on_send_activities (self ._create_send_handler ())
53+ # Pass activity to handler so we can create agent/tenant details
54+ turn_context .on_send_activities (self ._create_send_handler (turn_context .activity ))
5255
5356 # Execute bot logic
5457 await logic ()
@@ -86,14 +89,45 @@ def _create_input_scope(self, activity: Activity) -> InputScope:
8689
8790 return InputScope .start (agent_details , tenant_details , request )
8891
89- def _create_send_handler (self ):
90- """Create handler for outgoing bot messages"""
92+ def _create_send_handler (self , incoming_activity : Activity ):
93+ """Create handler for outgoing bot messages
94+
95+ Args:
96+ incoming_activity: The incoming activity to extract agent/tenant details from
97+ """
9198
9299 async def send_handler (ctx , activities , next_send ):
93- # Log each outgoing message
94- for activity in activities :
95- if activity .text :
96- self .logger .info (f"📤 Bot: { activity .text } " )
100+ # Collect all outgoing message texts
101+ messages = [activity .text for activity in activities if activity .text ]
102+
103+ if messages :
104+ # Create OutputScope as a child of the current InputScope
105+ agent_details = AgentDetails (
106+ agent_id = incoming_activity .recipient .id
107+ if incoming_activity .recipient
108+ else "unknown" ,
109+ agent_name = incoming_activity .recipient .name
110+ if incoming_activity .recipient
111+ else None ,
112+ conversation_id = incoming_activity .conversation .id
113+ if incoming_activity .conversation
114+ else None ,
115+ )
116+
117+ tenant_details = TenantDetails (
118+ tenant_id = incoming_activity .conversation .tenant_id
119+ if incoming_activity .conversation
120+ and hasattr (incoming_activity .conversation , "tenant_id" )
121+ else "unknown"
122+ )
123+
124+ response = Response (messages = messages )
125+
126+ # Use OutputScope within a context manager - it will be a child of InputScope
127+ with OutputScope .start (agent_details , tenant_details , response ):
128+ # Log each message
129+ for message in messages :
130+ self .logger .info (f"📤 Bot output message: { message } " )
97131
98132 return await next_send ()
99133
0 commit comments