11// Copyright (c) .NET Foundation and contributors. All rights reserved.
22// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33
4+ using System . Runtime . CompilerServices ;
45using System . Threading ;
56using System . Threading . Tasks ;
67
@@ -10,8 +11,17 @@ internal static class InvocationPipeline
1011 {
1112 internal static async Task < int > InvokeAsync ( ParseResult parseResult , CancellationToken cancellationToken )
1213 {
14+ using var invokeActivity = Activities . ActivitySource . StartActivity ( DiagnosticsStrings . InvokeMethod ) ;
15+ if ( invokeActivity is not null )
16+ {
17+ invokeActivity . DisplayName = parseResult . CommandResult . FullCommandName ( ) ;
18+ invokeActivity . AddTag ( DiagnosticsStrings . Command , parseResult . CommandResult . Command . Name ) ;
19+ invokeActivity . AddTag ( DiagnosticsStrings . InvokeType , DiagnosticsStrings . Async ) ;
20+ }
21+
1322 if ( parseResult . Action is null )
1423 {
24+ invokeActivity ? . SetStatus ( Diagnostics . ActivityStatusCode . Error ) ;
1525 return ReturnCodeForMissingAction ( parseResult ) ;
1626 }
1727
@@ -41,7 +51,9 @@ internal static async Task<int> InvokeAsync(ParseResult parseResult, Cancellatio
4151 switch ( parseResult . Action )
4252 {
4353 case SynchronousCommandLineAction syncAction :
44- return syncAction . Invoke ( parseResult ) ;
54+ var syncResult = syncAction . Invoke ( parseResult ) ;
55+ invokeActivity ? . SetExitCode ( syncResult ) ;
56+ return syncResult ;
4557
4658 case AsynchronousCommandLineAction asyncAction :
4759 var startedInvocation = asyncAction . InvokeAsync ( parseResult , cts . Token ) ;
@@ -52,23 +64,30 @@ internal static async Task<int> InvokeAsync(ParseResult parseResult, Cancellatio
5264
5365 if ( terminationHandler is null )
5466 {
55- return await startedInvocation ;
67+ var asyncResult = await startedInvocation ;
68+ invokeActivity ? . SetExitCode ( asyncResult ) ;
69+ return asyncResult ;
5670 }
5771 else
5872 {
5973 // Handlers may not implement cancellation.
6074 // In such cases, when CancelOnProcessTermination is configured and user presses Ctrl+C,
6175 // ProcessTerminationCompletionSource completes first, with the result equal to native exit code for given signal.
6276 Task < int > firstCompletedTask = await Task . WhenAny ( startedInvocation , terminationHandler . ProcessTerminationCompletionSource . Task ) ;
63- return await firstCompletedTask ; // return the result or propagate the exception
77+ var asyncResult = await firstCompletedTask ; // return the result or propagate the exception
78+ invokeActivity ? . SetExitCode ( asyncResult ) ;
79+ return asyncResult ;
6480 }
6581
6682 default :
67- throw new ArgumentOutOfRangeException ( nameof ( parseResult . Action ) ) ;
83+ var error = new ArgumentOutOfRangeException ( nameof ( parseResult . Action ) ) ;
84+ invokeActivity ? . Error ( error ) ;
85+ throw error ;
6886 }
6987 }
7088 catch ( Exception ex ) when ( parseResult . Configuration . EnableDefaultExceptionHandler )
7189 {
90+ invokeActivity ? . Error ( ex ) ;
7291 return DefaultExceptionHandler ( ex , parseResult . Configuration ) ;
7392 }
7493 finally
@@ -79,9 +98,18 @@ internal static async Task<int> InvokeAsync(ParseResult parseResult, Cancellatio
7998
8099 internal static int Invoke ( ParseResult parseResult )
81100 {
101+ using var invokeActivity = Activities . ActivitySource . StartActivity ( DiagnosticsStrings . InvokeMethod ) ;
102+ if ( invokeActivity is not null )
103+ {
104+ invokeActivity . DisplayName = parseResult . CommandResult . FullCommandName ( ) ;
105+ invokeActivity . AddTag ( DiagnosticsStrings . Command , parseResult . CommandResult . Command . Name ) ;
106+ invokeActivity . AddTag ( DiagnosticsStrings . InvokeType , DiagnosticsStrings . Sync ) ;
107+ }
108+
82109 switch ( parseResult . Action )
83110 {
84111 case null :
112+ invokeActivity ? . Error ( ) ;
85113 return ReturnCodeForMissingAction ( parseResult ) ;
86114
87115 case SynchronousCommandLineAction syncAction :
@@ -112,15 +140,20 @@ internal static int Invoke(ParseResult parseResult)
112140 }
113141 }
114142
115- return syncAction . Invoke ( parseResult ) ;
143+ var result = syncAction . Invoke ( parseResult ) ;
144+ invokeActivity ? . SetExitCode ( result ) ;
145+ return result ;
116146 }
117147 catch ( Exception ex ) when ( parseResult . Configuration . EnableDefaultExceptionHandler )
118148 {
149+ invokeActivity ? . Error ( ex ) ;
119150 return DefaultExceptionHandler ( ex , parseResult . Configuration ) ;
120151 }
121152
122153 default :
123- throw new InvalidOperationException ( $ "{ nameof ( AsynchronousCommandLineAction ) } called within non-async invocation.") ;
154+ var error = new InvalidOperationException ( $ "{ nameof ( AsynchronousCommandLineAction ) } called within non-async invocation.") ;
155+ invokeActivity ? . Error ( error ) ;
156+ throw error ;
124157 }
125158 }
126159
@@ -150,5 +183,38 @@ private static int ReturnCodeForMissingAction(ParseResult parseResult)
150183 return 0 ;
151184 }
152185 }
186+
187+ private static void Succeed ( this Diagnostics . Activity activity )
188+ {
189+ activity . SetStatus ( Diagnostics . ActivityStatusCode . Ok ) ;
190+ activity . AddTag ( DiagnosticsStrings . ExitCode , 0 ) ;
191+ }
192+ private static void Error ( this Diagnostics . Activity activity , int statusCode )
193+ {
194+ activity . SetStatus ( Diagnostics . ActivityStatusCode . Error ) ;
195+ activity . AddTag ( DiagnosticsStrings . ExitCode , statusCode ) ;
196+ }
197+
198+ private static void Error ( this Diagnostics . Activity activity , Exception ? exception = null )
199+ {
200+ activity . SetStatus ( Diagnostics . ActivityStatusCode . Error ) ;
201+ activity . AddTag ( DiagnosticsStrings . ExitCode , 1 ) ;
202+ if ( exception is not null )
203+ {
204+ activity . AddBaggage ( DiagnosticsStrings . Exception , exception . ToString ( ) ) ;
205+ }
206+ }
207+
208+ private static void SetExitCode ( this Diagnostics . Activity activity , int exitCode )
209+ {
210+ if ( exitCode == 0 )
211+ {
212+ activity . Succeed ( ) ;
213+ }
214+ else
215+ {
216+ activity . Error ( exitCode ) ;
217+ }
218+ }
153219 }
154220}
0 commit comments