88 "context"
99 "errors"
1010 "fmt"
11+ "io"
12+ "os"
13+ "strconv"
1114
1215 "github.com/azure/azure-dev/cli/azd/pkg/azdext"
1316 "github.com/spf13/cobra"
@@ -18,6 +21,7 @@ type monitorFlags struct {
1821 projectName string
1922 name string
2023 version string
24+ sessionID string
2125 follow bool
2226 tail int
2327 logType string
@@ -34,23 +38,24 @@ func newMonitorCommand() *cobra.Command {
3438
3539 cmd := & cobra.Command {
3640 Use : "monitor" ,
37- Short : "Monitor logs from a hosted agent container ." ,
38- Long : `Monitor logs from a hosted agent container .
41+ Short : "Monitor logs from a hosted agent." ,
42+ Long : `Monitor logs from a hosted agent.
3943
40- Streams console output (stdout/stderr) or system events from an agent container.
44+ Streams console output (stdout/stderr) or system events from an agent session or container.
45+ Use --session to stream logs for a specific session, or omit it to use the container logstream.
4146Use --follow to stream logs in real-time, or omit it to fetch recent logs and exit.
4247This is useful for troubleshooting agent startup issues or monitoring agent behavior.` ,
43- Example : ` # Fetch the last 50 lines of console logs
44- azd ai agent monitor --name my-agent --version 1
48+ Example : ` # Stream session logs
49+ azd ai agent monitor --name my-agent --version 1 --session <session-id>
4550
46- # Stream console logs in real-time
47- azd ai agent monitor --name my-agent --version 1 --follow
51+ # Stream session logs in real-time
52+ azd ai agent monitor --name my-agent --version 1 --session <session-id> -- follow
4853
49- # Fetch system event logs
50- azd ai agent monitor --name my-agent --version 1 --type system
54+ # Fetch container console logs (legacy)
55+ azd ai agent monitor --name my-agent --version 1
5156
52- # Fetch last 100 lines with explicit account
53- azd ai agent monitor --name my-agent --version 1 --tail 100 --account-name myAccount --project-name myProject ` ,
57+ # Fetch system event logs from container (legacy)
58+ azd ai agent monitor --name my-agent --version 1 --type system ` ,
5459 RunE : func (cmd * cobra.Command , args []string ) error {
5560 if err := validateMonitorFlags (flags ); err != nil {
5661 return err
@@ -64,6 +69,14 @@ This is useful for troubleshooting agent startup issues or monitoring agent beha
6469 return err
6570 }
6671
72+ // When vnext is enabled, resolve session ID for session-based logstream.
73+ if flags .sessionID == "" {
74+ sessionID , vnext := resolveMonitorSession (ctx , flags .name )
75+ if vnext {
76+ flags .sessionID = sessionID
77+ }
78+ }
79+
6780 action := & MonitorAction {
6881 AgentContext : agentContext ,
6982 flags : flags ,
@@ -77,6 +90,7 @@ This is useful for troubleshooting agent startup issues or monitoring agent beha
7790 cmd .Flags ().StringVarP (& flags .projectName , "project-name" , "p" , "" , "AI Foundry project name" )
7891 cmd .Flags ().StringVarP (& flags .name , "name" , "n" , "" , "Name of the hosted agent (required)" )
7992 cmd .Flags ().StringVarP (& flags .version , "version" , "v" , "" , "Version of the hosted agent (required)" )
93+ cmd .Flags ().StringVarP (& flags .sessionID , "session" , "s" , "" , "Session ID to stream logs for" )
8094 cmd .Flags ().BoolVarP (& flags .follow , "follow" , "f" , false , "Stream logs in real-time" )
8195 cmd .Flags ().IntVarP (& flags .tail , "tail" , "l" , 50 , "Number of trailing log lines to fetch (1-300)" )
8296 cmd .Flags ().StringVarP (& flags .logType , "type" , "t" , "console" , "Type of logs: 'console' (stdout/stderr) or 'system' (container events)" )
@@ -94,15 +108,28 @@ func (a *MonitorAction) Run(ctx context.Context) error {
94108 return err
95109 }
96110
97- body , err := agentClient .GetAgentContainerLogStream (
98- ctx ,
99- a .Name ,
100- a .Version ,
101- DefaultAgentAPIVersion ,
102- a .flags .logType ,
103- a .flags .tail ,
104- a .flags .follow ,
105- )
111+ var body io.ReadCloser
112+ if a .flags .sessionID != "" {
113+ fmt .Fprintf (os .Stderr , "Streaming session logs for %s (session: %s)...\n " , a .Name , a .flags .sessionID )
114+ body , err = agentClient .GetAgentSessionLogStream (
115+ ctx ,
116+ a .Name ,
117+ a .Version ,
118+ a .flags .sessionID ,
119+ "2025-11-15-preview" ,
120+ a .flags .follow ,
121+ )
122+ } else {
123+ body , err = agentClient .GetAgentContainerLogStream (
124+ ctx ,
125+ a .Name ,
126+ a .Version ,
127+ DefaultAgentAPIVersion ,
128+ a .flags .logType ,
129+ a .flags .tail ,
130+ a .flags .follow ,
131+ )
132+ }
106133 if err != nil {
107134 // Suppress context deadline/cancellation errors (expected in non-follow timeout and Ctrl+C)
108135 if errors .Is (err , context .DeadlineExceeded ) || errors .Is (err , context .Canceled ) {
@@ -141,3 +168,42 @@ func validateMonitorFlags(flags *monitorFlags) error {
141168
142169 return nil
143170}
171+
172+ // resolveMonitorSession checks if vnext is enabled and resolves the session ID
173+ // from the .foundry-agent.json file. Returns the session ID and whether vnext is enabled.
174+ // If vnext is not enabled or the session cannot be resolved, returns empty string and false.
175+ func resolveMonitorSession (ctx context.Context , agentName string ) (string , bool ) {
176+ azdClient , err := azdext .NewAzdClient ()
177+ if err != nil {
178+ return "" , false
179+ }
180+ defer azdClient .Close ()
181+
182+ // Check if vnext is enabled
183+ vnextValue := ""
184+ azdEnv , err := loadAzdEnvironment (ctx , azdClient )
185+ if err == nil {
186+ vnextValue = azdEnv ["enableHostedAgentVNext" ]
187+ }
188+ if vnextValue == "" {
189+ vnextValue = os .Getenv ("enableHostedAgentVNext" )
190+ }
191+ enabled , err := strconv .ParseBool (vnextValue )
192+ if err != nil || ! enabled {
193+ return "" , false
194+ }
195+
196+ // Resolve session ID from .foundry-agent.json
197+ configPath , err := resolveConfigPath (ctx , azdClient )
198+ if err != nil {
199+ return "" , true
200+ }
201+ agentCtx := loadLocalContext (configPath )
202+ if agentCtx .Sessions != nil {
203+ if sid , ok := agentCtx .Sessions [agentName ]; ok {
204+ return sid , true
205+ }
206+ }
207+
208+ return "" , true
209+ }
0 commit comments