Command Logger#
TLDR, How to enable#
- Enable the feature with
appRunner.UseCommandLogger()
or useappRunner.UseDefaultMiddleware()
Command logging#
This feature logs information about the command just before the command method is executed.
The default behavior registers a [cmdlog]
directive that outputs to the console using CommandContext.Console.Out
.
example usage:
dotnet example.com [cmdlog] add 1 2
Outputs#
Command and arguments#
The command to be executed and the argument values as described in the parse directive.
command: LaunchRocket
arguments:
planets <Text>
value: mars, earth, jupiter, mercury, venus, saturn
inputs:
[argument] mars, earth, jupiter
[piped stream]
default: source=AppSetting key=--planets: mars, jupiter
options:
crew <Text>
value: Aaron, Alex
inputs: [prompt] Aaron, Alex
default: Bilal
username <Text>
value: Bilal
inputs:
default: source=EnvVar key=Username: Bilal
password <Text>
value: *****
inputs: [prompt] *****
default: source=EnvVar key=Password: *****
System information#
System information is included by default and can be excluded by setting excludeSystemInfo: true
.
The default set of information is:
Tool version = testhost.dll 16.2.0
.Net version = .NET Core 4.6.26614.01
OS version = Microsoft Windows 10.0.18363
Machine = MyComputer
Username = MyComputer\Me
Additional information can be provided by setting the additionalInfoCallback
parameter with a
Func<CommandContext, IEnumerable<(string key, string value)>>
. Any CommandContext state can be included.
AppConfig#
AppConfig can be included by setting includeAppConfig: true
. This
AppConfig:
AppSettings:
ArgumentTypeDescriptors: ArgumentTypeDescriptors:
ErrorReportingDescriptor > CommandDotNet.TypeDescriptors.BoolTypeDescriptor
ErrorReportingDescriptor > CommandDotNet.TypeDescriptors.EnumTypeDescriptor
ErrorReportingDescriptor > DelegatedTypeDescriptor<String>: 'Text'
ErrorReportingDescriptor > DelegatedTypeDescriptor<Password>: 'Text'
ErrorReportingDescriptor > DelegatedTypeDescriptor<Char>: 'Character'
ErrorReportingDescriptor > DelegatedTypeDescriptor<Int64>: 'Number'
ErrorReportingDescriptor > DelegatedTypeDescriptor<Int32>: 'Number'
ErrorReportingDescriptor > DelegatedTypeDescriptor<Int16>: 'Number'
ErrorReportingDescriptor > DelegatedTypeDescriptor<Decimal>: 'Decimal'
ErrorReportingDescriptor > DelegatedTypeDescriptor<Double>: 'Double'
ErrorReportingDescriptor > CommandDotNet.TypeDescriptors.ComponentModelTypeDescriptor
ErrorReportingDescriptor > CommandDotNet.TypeDescriptors.StringCtorTypeDescriptor
BooleanMode: Implicit
DefaultArgumentMode: Operand
DisableDirectives: False
GuaranteeOperandOrderInArgumentModels: False
Help: CommandDotNet.Help.AppHelpSettings
IgnoreUnexpectedOperands: False
DependencyResolver:
HelpProvider: CommandDotNet.Help.HelpTextProvider
TokenTransformations:
expand-clubbed-flags
split-option-assignments
MiddlewarePipeline:
TokenizerPipeline.TokenizeInputMiddleware
ClassModelingMiddleware.CreateRootCommand
CommandParser.ParseInputMiddleware
ClassModelingMiddleware.AssembleInvocationPipelineMiddleware
HelpMiddleware.DisplayHelp
BindValuesMiddleware.BindValues
ResolveCommandClassesMiddleware.ResolveCommandClassInstances
AppRunnerTestExtensions.InjectTestCaptures
CommandLoggerMiddleware.CommandLogger
ClassModelingMiddleware.InvokeInvocationPipelineMiddleware
ParameterResolvers:
CommandDotNet.CommandContext
CommandDotNet.Rendering.IConsole
System.Threading.CancellationToken
Replacing the default behavior#
Use writerFactory
parameter to conditionally provide a target for the log.
If the factory returns null, the command will not be logged.
How to use:
Change the target output#
writerFactory: ctx => Log.Info
Logs every command to logging framework. No [cmdlog]
directive
Enable via attribute#
writerFactory: ctx => ctx.ParseResult.TargetCommand.HasAttribute<EnableCommandLogger>() ? ctx.Console.Out.WriteLine : (Action<string>)null
Logs only commands attributed with your custom EnableCommandLoggerAttribute
. No [cmdlog]
directive
Enable via directive#
Allow user to enable as a directive
writerFactory: ctx => ctx.Tokens.TryGetDirective("cmdlog", out _) ? ctx.Console.Out.WriteLine : (Action<string>)null
Usage: dotnet example.com [cmdlog] add 1 2
Note
this is the default behavior.
Enable via root option#
Add an intercepor method to your root command with an --logcmd
option. This also makes the option visible to users via help.
public class RootApp
{
public Task<int> Interceptor(InterceptorExecutionDelegate next, CommandContext ctx,
[Option(Description="Output the command wiht arguments and system info")] bool cmdlog)
{
if(cmdlog)
{
CommandLogger.Log(ctx);
}
next();
}
}
used as dotnet example.dll --logcmd Add 1 2
Blended, Enable via root option or attribute#
- Always output to logs
- output to the console when...
- The user runs with the
[cmdlog]
directive - The command is attributed with your custom
EnableCommandLoggerAttribute
- The user runs with the
appRunner.UseCommandLogger(writerFactory: ctx =>
{
// EnableCommandLogger is just an example name you could implement
if (ctx.ParseResult.TargetCommand.HasAttribute<EnableCommandLogger>()
|| (bool)ctx.RootCommand.Options.FindOption("logcmd").Value)
{
return Log.IsInfoEnabled()
? log =>
{
Log.Info(log);
ctx.Console.Out.WriteLine(log);
}
: (Action<string>)ctx.Console.Out.WriteLine;
}
return Log.IsInfoEnabled()
? Log.Info
: (Action<string>)null;
});