diff --git a/CHANGELOG.md b/CHANGELOG.md index 6276a2d9..f8b6516f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change log +## 03/22/2023 + +- add datetime format specifier token option to LogFile + -log|--logFile [string] file name and path to save console output. + can optionally specify .net datetime format specifier inside '<>'. + example: collectsfdata-\.log + ## 02/05/2023 - migrate from default target framework .net472 to .net48 diff --git a/README.md b/README.md index e5610ca3..fdec78df 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ Options: and leave this blank. example: https://clusterkeyvault.vault.azure.net/ -rg|--azureResourceGroup [string] azure resource group name / used for log analytics actions. - -loc|--azureResourceGroupLocation [string] azure resource group location / used for log analytics actions. + -loc|--azureResourceGroupLocation [string] azure resource group location / used for MSAL and log analytics actions. -sub|--azureSubscriptionId [string] azure subscription id / used for log analytics actions. -tenant|--azureTenantId [string] azure tenant id for use with kusto AAD authentication -cache|--cacheLocation [string] Write files to this output location. e.g. "C:\Perfcounters\Output" @@ -142,7 +142,7 @@ Options: -cf|--containerFilter [string] string / regex to filter container names -dc|--deleteCache [bool] delete downloaded blobs from local disk at end of execution. -to|--stop [DateTime] end time range to collect data to. default is now. - example: "06/01/2021 09:01:23 -04:00" + example: "03/22/2023 18:24:01 -04:00" -mc|--etwManifestsCache [string] local folder path to use for manifest cache .man files. -ex|--examples [bool] show example commands -uris|--fileUris [string[]] optional comma separated string array list of files to ingest. @@ -152,6 +152,7 @@ Options: counter trace exception + sfextlog table setup any @@ -186,7 +187,9 @@ Options: workspace with LogAnalyticsCreate. default is PerGB2018 -debug|--logDebug [int] 0-disabled, 1-exception, 2-error, 3-warning, 4-info, 5-debug. use logdebug levels for troubleshooting utility - -log|--logFile [string] file name and path to save console output + -log|--logFile [string] file name and path to save console output. + can optionally specify .net datetime format specifier inside '<>'. + example: collectsfdata-.log -nf|--nodeFilter [string] string / regex Filter on node name or any string in blob url (case-insensitive comparison) -timeout|--noProgressTimeoutMin [int] no progress timer in minutes. set to 0 to disable timeout. @@ -197,7 +200,7 @@ Options: specify file name 'collectsfdata.options.json' to create default configuration file. -from|--start [DateTime] start time range to collect data from. default is -2 hours. - example: "06/01/2021 07:01:23 -04:00" + example: "03/22/2023 16:24:01 -04:00" -t|--threads [int] override default number of threads equal to processor count. -u|--unique [bool] default true to query for fileuri before ingestion to prevent duplicates -uf|--uriFilter [string] string / regex filter for storage account blob uri. diff --git a/configurationFiles/collectsfdata.schema.json b/configurationFiles/collectsfdata.schema.json index 6bef04d0..6b4aea1c 100644 --- a/configurationFiles/collectsfdata.schema.json +++ b/configurationFiles/collectsfdata.schema.json @@ -456,10 +456,11 @@ "$id": "#/properties/LogFile", "type": "string", "title": "LogFile", - "description": "path and file name to log output", + "description": "path and file name to log output. can optionally specify .net datetime format specifier inside '<>'. example: collectsfdata-.log", "default": "", "examples": [ - "c:\\temp\\collectsfdata.log" + "c:\\temp\\collectsfdata.log", + "c:\\temp\\collectsfdata-.log" ], "pattern": "^(.+)$" }, diff --git a/docs/configuration.md b/docs/configuration.md index 385f9c69..13381b74 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -136,7 +136,7 @@ To use a default configuration file without having to specify on the command lin - **any** - 'any' without other filters will enumerate all containers for blobs matching criteria. - **List** - bool. default false. if true, lists the blobs meeting all criteria for download but does not download the file. - **LogDebug** - int. default 4. if > 0, logs additional 'debug' output to console for troubleshooting. 0-disabled, 1-exception, 2-error, 3-warning, 4-info, 5-debug. -- **LogFile** - optional. string. default null. if populated with file and path, will log all console output to specified file. file is recreated every execution if exists. +- **LogFile** - optional. string. default null. if populated with file and path, will log all console output to specified file. file is recreated every execution if exists. can optionally specify .net datetime format specifier inside '<>'. example: collectsfdata-\.log. - **NodeFilter** - optional. string / regex. if populated uses client side searching for blobs after enumeration before download. - **NoProgressTimeoutMin** - optional. int. default 10. if no progress has been made during given timeout, utility will exit. set to 0 to disable. - **ResourceUri** - optional. string. used internally for resource tracking. diff --git a/src/CollectSFDataDll/Common/CommandLineArguments.cs b/src/CollectSFDataDll/Common/CommandLineArguments.cs index dc61b851..79845983 100644 --- a/src/CollectSFDataDll/Common/CommandLineArguments.cs +++ b/src/CollectSFDataDll/Common/CommandLineArguments.cs @@ -513,7 +513,9 @@ namespace CollectSFData.Common CommandOptionType.SingleValue); LogFile = CmdLineApp.Option("-log|--logFile", - "[string] file name and path to save console output", + "[string] file name and path to save console output." + + $"{newLine} can optionally specify .net datetime format specifier inside '<>'." + + $"{newLine} example: collectsfdata-.log", CommandOptionType.SingleValue); NodeFilter = CmdLineApp.Option("-nf|--nodeFilter", diff --git a/src/CollectSFDataDll/Common/ConfigurationOptions.cs b/src/CollectSFDataDll/Common/ConfigurationOptions.cs index ee5963ff..496b261b 100644 --- a/src/CollectSFDataDll/Common/ConfigurationOptions.cs +++ b/src/CollectSFDataDll/Common/ConfigurationOptions.cs @@ -245,7 +245,7 @@ namespace CollectSFData.Common return timeString; } - public bool CreateDirectory(string directory) + public static bool CreateDirectory(string directory) { try { @@ -988,7 +988,7 @@ namespace CollectSFData.Common } } - private void CheckLogFile() + public bool CheckLogFile() { if (LogDebug == LoggingLevel.Verbose && !HasValue(LogFile)) { @@ -999,9 +999,19 @@ namespace CollectSFData.Common if (HasValue(LogFile)) { LogFile = FileManager.NormalizePath(LogFile); - CreateDirectory(Path.GetDirectoryName(LogFile)); + + if(Regex.IsMatch(LogFile,@"<.+>")) + { + string timePattern = Regex.Match(LogFile, @"<(.+?)>").Groups[1].Value; + LogFile = Regex.Replace(LogFile, @"<.+?>", DateTime.Now.ToString(timePattern)); + Log.Info($"replaced datetime token {timePattern}: new LogFile name:{LogFile}"); + } + Log.Info($"setting output log file to: {LogFile}"); + return CreateDirectory(Path.GetDirectoryName(LogFile)); } + + return true; } private string CleanTableName(string tableName, bool withGatherType = false) diff --git a/src/CollectSFDataDll/Common/Instance.cs b/src/CollectSFDataDll/Common/Instance.cs index d6629055..55479395 100644 --- a/src/CollectSFDataDll/Common/Instance.cs +++ b/src/CollectSFDataDll/Common/Instance.cs @@ -55,7 +55,7 @@ namespace CollectSFData.Common Config.Validate(); } - Log.Config = Config; + Log.Open(); DiscoveredMaxDateTicks = DateTime.MinValue.Ticks; DiscoveredMinDateTicks = DateTime.MaxValue.Ticks; FileObjects = new FileObjectCollection(); diff --git a/src/CollectSFDataDll/Common/Log.cs b/src/CollectSFDataDll/Common/Log.cs index 92074b3b..6dc7855c 100644 --- a/src/CollectSFDataDll/Common/Log.cs +++ b/src/CollectSFDataDll/Common/Log.cs @@ -42,17 +42,6 @@ namespace CollectSFData.Common new DecoderExceptionFallback() ); - public static ConfigurationOptions Config - { - set - { - _config = value; - _logFile = CheckLogFile(_config.LogFile) ? _config.LogFile : string.Empty; - _logDebug = _config.LogDebug; - Open(); - } - } - public static bool IsConsole { get; set; } private static CancellationTokenSource _taskWriterCancellationToken => CustomTaskManager.CancellationTokenSource; @@ -199,6 +188,8 @@ namespace CollectSFData.Common { if (!_isRunning) { + _logFile = CheckLogFile() ? _config.LogFile : string.Empty; + _logDebug = _config.LogDebug; _taskWriter = new Task(TaskWriter, _taskWriterCancellationToken.Token); _taskWriter.Start(); _isRunning = true; @@ -213,11 +204,11 @@ namespace CollectSFData.Common } } - private static bool CheckLogFile(string logFile) + private static bool CheckLogFile() { try { - if (string.IsNullOrEmpty(logFile)) + if (string.IsNullOrEmpty(_config.LogFile)) { _logFileEnabled = false; return true; @@ -225,13 +216,11 @@ namespace CollectSFData.Common if (!_logFileEnabled) { - string directoryName = Path.GetDirectoryName(logFile); - if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName)) + if (_config.CheckLogFile() && !File.Exists(_config.LogFile)) { - Directory.CreateDirectory(directoryName); + File.Create(_config.LogFile).Close(); } - File.Create(logFile).Close(); _logFileEnabled = true; }