From 09652cccd16d7de56ba7fe656251360d9aba5082 Mon Sep 17 00:00:00 2001 From: ranasaria <41588310+ranasaria@users.noreply.github.com> Date: Mon, 24 Sep 2018 23:55:59 -0700 Subject: [PATCH] Enhanced Logging for sqltoolsservice (#695) This change modifies the logging framework within sqltoolservice. Moves away from custom Logger object to start using .Net tracing framework. It supports for the static Trace and TraceSource way of logging. For all new code it is recommend that we log the log messages using the existing static Logger class, while the code changes will continue to route the older Trace.Write* calls from the process to same log listeners (and thus the log targets) as used by the Logger class. Thus tracing in SMO code that uses Trace.Write* methods gets routed to the same file as the messages from rest of SQLTools Service code. Make changes to start using .Net Frameworks codebase for all logging to unify our logging story. Allows parameter to set tracingLevel filters that controls what kinds of message make it to the log file. Allows a parameter to set a specific log file name so if these gets set by external code (the UI code using the tools service for example) then the external code is aware of the current log file in use. Adding unittests to test out the existing and improved logging capabilities. Sequences of checkins in development branch: * Saving v1 of logging to prepare for code review. Minor cleanup and some end to end testing still remains * Removing local launchSettings.json files * added support for lazy listener to sqltoolsloglistener and removed incorrect changes to comments across files in previous checkin * Converting time to local time when writing entries to the log * move the hosting.v2 to new .net based logging code * removing *.dgml files and addding them to .gitignore * fixing typo of defaultTraceSource * Addressing pull request feedback * Adding a test to verify logging from SMO codebase * propogating changes to v1 sqltools.hosting commandoptions.cs to the v2 version * Fixing comments on start and stop callstack methods and whitespaces * Commenting a test that got uncommented by mistake * addding .gitattributes file as .sql file was observed to be misconstrued as a binary file --- .gitattributes | 5 + .gitignore | 1 + sqltoolsservice.sln | 75 ++- .../Connection/ConnectionServiceCore.cs | 11 +- .../ReliableConnection/AmbientSettings.cs | 9 +- .../ReliableConnection/CachedServerInfo.cs | 3 +- .../ReliableConnectionHelper.cs | 14 +- .../ReliableSqlConnection.cs | 2 +- ...licy.DataTransferDetectionErrorStrategy.cs | 3 +- .../ReliableConnection/RetryPolicy.cs | 4 +- .../ReliableConnection/RetryPolicyFactory.cs | 6 +- .../ReliableConnection/RetryPolicyUtils.cs | 3 +- .../LanguageServices/BindingQueue.cs | 7 +- .../Microsoft.SqlTools.CoreServices.csproj | 6 +- .../Workspace/SettingsService.cs | 5 +- .../Credentials/CredentialService.cs | 3 +- .../Credentials/Win32/CredentialSet.cs | 7 +- src/Microsoft.SqlTools.Credentials/Program.cs | 19 +- .../GeneralRequestDetails.cs | 2 +- .../Extensibility/IHostedService.cs | 5 +- ...j => Microsoft.SqlTools.Hosting.v2.csproj} | 0 .../Protocol/JsonRpcHost.cs | 17 +- .../Protocol/MessageWriter.cs | 3 +- .../ServiceHost.cs | 5 +- .../Utility/CommandOptions.cs | 37 +- .../Utility/Logger.cs | 558 +++++++++++------- .../Utility/TaskExtensions.cs | 11 +- .../Hosting/IHostedService.cs | 3 +- .../Hosting/Protocol/MessageDispatcher.cs | 11 +- .../Hosting/Protocol/MessageWriter.cs | 3 +- .../Hosting/Protocol/ProtocolEndpoint.cs | 3 +- .../Microsoft.SqlTools.Hosting.csproj | 2 +- .../Utility/CommandOptions.cs | 37 +- .../Utility/GeneralRequestDetails.cs | 3 +- .../Utility/Logger.cs | 546 +++++++++++------ .../Utility/UtilityServiceHost.cs | 3 +- .../AuthenticationService.cs | 3 +- .../ResourceProviderService.cs | 5 +- .../AzureResourceManager.cs | 4 +- .../Program.cs | 15 +- .../Admin/Database/DatabaseTaskHelper.cs | 3 +- .../BatchParser/BatchParserWrapper.cs | 15 +- .../BatchParser/ExecutionEngineCode/Batch.cs | 4 +- .../ExecutionEngineCode/ExecutionEngine.cs | 8 +- .../Connection/ConnectionService.cs | 17 +- .../ReliableConnection/AmbientSettings.cs | 7 +- .../ReliableConnection/CachedServerInfo.cs | 3 +- .../ReliableConnectionHelper.cs | 20 +- .../ReliableSqlConnection.cs | 12 +- ...licy.DataTransferDetectionErrorStrategy.cs | 3 +- .../ReliableConnection/RetryPolicy.cs | 4 +- .../ReliableConnection/RetryPolicyFactory.cs | 6 +- .../ReliableConnection/RetryPolicyUtils.cs | 3 +- .../DisasterRecoveryService.cs | 3 +- .../RestoreOperation/RestoreDatabaseHelper.cs | 5 +- .../RestoreDatabaseTaskDataObject.cs | 5 +- .../RestoreOperation/RestoreOptionFactory.cs | 13 +- .../FileBrowser/FileBrowserService.cs | 11 +- .../Formatter/TSqlFormatterService.cs | 5 +- .../LanguageServices/BindingQueue.cs | 7 +- .../LanguageServices/LanguageService.cs | 43 +- .../Microsoft.SqlTools.ServiceLayer.csproj | 4 +- .../ObjectExplorer/Nodes/TreeNode.cs | 6 +- .../ObjectExplorer/ObjectExplorerService.cs | 27 +- .../SmoModel/DatabaseTreeNode.cs | 3 +- .../ObjectExplorer/SmoModel/ServerNode.cs | 3 +- .../SmoModel/SmoChildFactoryBase.cs | 10 +- .../SmoModel/SmoColumnCustomNode.cs | 3 +- .../Profiler/ProfilerSessionMonitor.cs | 5 +- .../Program.cs | 17 +- .../QueryExecution/Batch.cs | 4 +- .../QueryExecution/QueryExecutionService.cs | 4 +- .../Scripting/ScriptAsScriptingOperation.cs | 11 +- .../Scripting/ScripterCore.cs | 7 +- .../Scripting/ScriptingExtensionMethods.cs | 5 +- .../ScriptingListObjectsOperation.cs | 7 +- .../Scripting/ScriptingOperation.cs | 3 +- .../Scripting/ScriptingScriptOperation.cs | 15 +- .../Scripting/ScriptingService.cs | 12 +- .../Scripting/SmoScriptingOperation.cs | 15 +- .../ServiceHost.cs | 3 +- .../SmoScriptableOperationWithFullDbAccess.cs | 3 +- .../TaskServices/TaskService.cs | 7 +- .../Utility/ServiceLayerCommandOptions.cs | 2 +- .../Utility/TaskExtensions.cs | 11 +- .../Workspace/Workspace.cs | 7 +- .../Workspace/WorkspaceService.cs | 21 +- ...icrosoft.SqlTools.Hosting.UnitTests.csproj | 2 +- .../UtilityTests/LoggerTests.cs | 23 +- .../LanguageServer/PeekDefinitionTests.cs | 18 + ...Tools.ServiceLayer.IntegrationTests.csproj | 23 +- .../Program.cs | 3 +- ...t.SqlTools.ServiceLayer.Test.Common.csproj | 2 +- .../TestLogger.cs | 168 ++++++ .../Program.cs | 2 +- .../Connection/DatabaseLocksManagerTests.cs | 4 +- .../Profiler/ProfilerServiceTests.cs | 10 +- .../ServiceHost/LoggerTests.cs | 470 +++++++++++++-- .../Utility/CommandOptionsTests.cs | 110 ++-- test/ScriptGenerator/AdventureWorks.sql | Bin 0 -> 1969650 bytes .../AdventureWorksDbCreate.sql | Bin 0 -> 786752 bytes .../AdventureWorksDbReadWrite.sql | Bin 0 -> 146 bytes .../AdventureWorksStoredProceduresCreate.sql | Bin 0 -> 145832 bytes .../AdventureWorksTablesCreate.sql | Bin 0 -> 270752 bytes .../AdventureWorksViewsCreate.sql | Bin 0 -> 82500 bytes test/ScriptGenerator/CommandOptions.cs | 160 +++++ test/ScriptGenerator/Program.cs | 57 ++ .../ScriptGenerator/Properties/Resources.resx | 139 +++++ .../Properties/launchSettings.json | 8 + test/ScriptGenerator/ScriptGenerator.csproj | 23 + .../TurnOffClrStrictSecurityMode.sql | Bin 0 -> 292 bytes .../TurnOnClrStrictSecurityMode.sql | Bin 0 -> 292 bytes 112 files changed, 2262 insertions(+), 831 deletions(-) create mode 100644 .gitattributes rename src/Microsoft.SqlTools.Hosting.v2/{Microsoft.SqlTools.Hosting.csproj => Microsoft.SqlTools.Hosting.v2.csproj} (100%) create mode 100644 test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestLogger.cs create mode 100644 test/ScriptGenerator/AdventureWorks.sql create mode 100644 test/ScriptGenerator/AdventureWorksDbCreate.sql create mode 100644 test/ScriptGenerator/AdventureWorksDbReadWrite.sql create mode 100644 test/ScriptGenerator/AdventureWorksStoredProceduresCreate.sql create mode 100644 test/ScriptGenerator/AdventureWorksTablesCreate.sql create mode 100644 test/ScriptGenerator/AdventureWorksViewsCreate.sql create mode 100644 test/ScriptGenerator/CommandOptions.cs create mode 100644 test/ScriptGenerator/Program.cs create mode 100644 test/ScriptGenerator/Properties/Resources.resx create mode 100644 test/ScriptGenerator/Properties/launchSettings.json create mode 100644 test/ScriptGenerator/ScriptGenerator.csproj create mode 100644 test/ScriptGenerator/TurnOffClrStrictSecurityMode.sql create mode 100644 test/ScriptGenerator/TurnOnClrStrictSecurityMode.sql diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..c7a51de6 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +*.sql diff +*.cs diff +*.csproj diff +*.sln diff +*.resx diff \ No newline at end of file diff --git a/.gitignore b/.gitignore index e5302542..c7a5b1b7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ syntax: glob ### VisualStudio ### +*.dgml # Project.json lock file project.lock.json diff --git a/sqltoolsservice.sln b/sqltoolsservice.sln index c1b33806..196977da 100644 --- a/sqltoolsservice.sln +++ b/sqltoolsservice.sln @@ -54,8 +54,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Credenti EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Hosting", "src\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj", "{AAE1F8D1-F7AB-4ABE-A55B-D423393AB352}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Hosting.v2", "src\Microsoft.SqlTools.Hosting.v2\Microsoft.SqlTools.Hosting.csproj", "{BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.DataProtocol.Contracts", "src\Microsoft.SqlTools.DataProtocol.Contracts\Microsoft.SqlTools.DataProtocol.Contracts.csproj", "{220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.CoreServices", "src\Microsoft.SqlTools.CoreServices\Microsoft.SqlTools.CoreServices.csproj", "{444E79F1-477A-481A-9BE6-6559B32CE177}" @@ -86,6 +84,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Resource EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.ResourceProvider.DefaultImpl", "src\Microsoft.SqlTools.ResourceProvider.DefaultImpl\Microsoft.SqlTools.ResourceProvider.DefaultImpl.csproj", "{EFB39C03-F7D2-4E8D-BE51-09121CD71973}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScriptGenerator", "test\ScriptGenerator\ScriptGenerator.csproj", "{8EE5B06A-2EB2-4A47-812D-1D5B98D0F49A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SqlTools.Hosting.v2", "src\Microsoft.SqlTools.Hosting.v2\Microsoft.SqlTools.Hosting.v2.csproj", "{EF02F89F-417E-4A40-B7E6-B102EE2DF24D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -105,12 +107,36 @@ Global {AAE1F8D1-F7AB-4ABE-A55B-D423393AB352}.Integration|Any CPU.Build.0 = Debug|Any CPU {AAE1F8D1-F7AB-4ABE-A55B-D423393AB352}.Release|Any CPU.ActiveCfg = Release|Any CPU {AAE1F8D1-F7AB-4ABE-A55B-D423393AB352}.Release|Any CPU.Build.0 = Release|Any CPU + {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Integration|Any CPU.ActiveCfg = Release|Any CPU + {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Integration|Any CPU.Build.0 = Release|Any CPU + {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Release|Any CPU.Build.0 = Release|Any CPU + {444E79F1-477A-481A-9BE6-6559B32CE177}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {444E79F1-477A-481A-9BE6-6559B32CE177}.Debug|Any CPU.Build.0 = Debug|Any CPU + {444E79F1-477A-481A-9BE6-6559B32CE177}.Integration|Any CPU.ActiveCfg = Release|Any CPU + {444E79F1-477A-481A-9BE6-6559B32CE177}.Integration|Any CPU.Build.0 = Release|Any CPU + {444E79F1-477A-481A-9BE6-6559B32CE177}.Release|Any CPU.ActiveCfg = Release|Any CPU + {444E79F1-477A-481A-9BE6-6559B32CE177}.Release|Any CPU.Build.0 = Release|Any CPU + {BE04C532-C9AE-4C32-9283-F6629112228B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE04C532-C9AE-4C32-9283-F6629112228B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE04C532-C9AE-4C32-9283-F6629112228B}.Integration|Any CPU.ActiveCfg = Release|Any CPU + {BE04C532-C9AE-4C32-9283-F6629112228B}.Integration|Any CPU.Build.0 = Release|Any CPU + {BE04C532-C9AE-4C32-9283-F6629112228B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE04C532-C9AE-4C32-9283-F6629112228B}.Release|Any CPU.Build.0 = Release|Any CPU {835EDEB4-289B-4D6D-A9A0-609E43A87D6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {835EDEB4-289B-4D6D-A9A0-609E43A87D6E}.Debug|Any CPU.Build.0 = Debug|Any CPU {835EDEB4-289B-4D6D-A9A0-609E43A87D6E}.Integration|Any CPU.ActiveCfg = Debug|Any CPU {835EDEB4-289B-4D6D-A9A0-609E43A87D6E}.Integration|Any CPU.Build.0 = Debug|Any CPU {835EDEB4-289B-4D6D-A9A0-609E43A87D6E}.Release|Any CPU.ActiveCfg = Release|Any CPU {835EDEB4-289B-4D6D-A9A0-609E43A87D6E}.Release|Any CPU.Build.0 = Release|Any CPU + {BA3C9622-ABFF-45A2-91AA-CC5189083256}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BA3C9622-ABFF-45A2-91AA-CC5189083256}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BA3C9622-ABFF-45A2-91AA-CC5189083256}.Integration|Any CPU.ActiveCfg = Release|Any CPU + {BA3C9622-ABFF-45A2-91AA-CC5189083256}.Integration|Any CPU.Build.0 = Release|Any CPU + {BA3C9622-ABFF-45A2-91AA-CC5189083256}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BA3C9622-ABFF-45A2-91AA-CC5189083256}.Release|Any CPU.Build.0 = Release|Any CPU {F18471B5-2042-409D-BF2C-E5403C322DC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F18471B5-2042-409D-BF2C-E5403C322DC9}.Debug|Any CPU.Build.0 = Debug|Any CPU {F18471B5-2042-409D-BF2C-E5403C322DC9}.Integration|Any CPU.ActiveCfg = Debug|Any CPU @@ -171,26 +197,18 @@ Global {EFB39C03-F7D2-4E8D-BE51-09121CD71973}.Integration|Any CPU.Build.0 = Debug|Any CPU {EFB39C03-F7D2-4E8D-BE51-09121CD71973}.Release|Any CPU.ActiveCfg = Release|Any CPU {EFB39C03-F7D2-4E8D-BE51-09121CD71973}.Release|Any CPU.Build.0 = Release|Any CPU - {BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BBF1F8D1-F7AB-4ABE-A55B-D423393AB352}.Release|Any CPU.Build.0 = Release|Any CPU - {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D}.Release|Any CPU.Build.0 = Release|Any CPU - {444E79F1-477A-481A-9BE6-6559B32CE177}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {444E79F1-477A-481A-9BE6-6559B32CE177}.Debug|Any CPU.Build.0 = Debug|Any CPU - {444E79F1-477A-481A-9BE6-6559B32CE177}.Release|Any CPU.ActiveCfg = Release|Any CPU - {444E79F1-477A-481A-9BE6-6559B32CE177}.Release|Any CPU.Build.0 = Release|Any CPU - {BE04C532-C9AE-4C32-9283-F6629112228B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BE04C532-C9AE-4C32-9283-F6629112228B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BE04C532-C9AE-4C32-9283-F6629112228B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BE04C532-C9AE-4C32-9283-F6629112228B}.Release|Any CPU.Build.0 = Release|Any CPU - {BA3C9622-ABFF-45A2-91AA-CC5189083256}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BA3C9622-ABFF-45A2-91AA-CC5189083256}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BA3C9622-ABFF-45A2-91AA-CC5189083256}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BA3C9622-ABFF-45A2-91AA-CC5189083256}.Release|Any CPU.Build.0 = Release|Any CPU + {8EE5B06A-2EB2-4A47-812D-1D5B98D0F49A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8EE5B06A-2EB2-4A47-812D-1D5B98D0F49A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8EE5B06A-2EB2-4A47-812D-1D5B98D0F49A}.Integration|Any CPU.ActiveCfg = Debug|Any CPU + {8EE5B06A-2EB2-4A47-812D-1D5B98D0F49A}.Integration|Any CPU.Build.0 = Debug|Any CPU + {8EE5B06A-2EB2-4A47-812D-1D5B98D0F49A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8EE5B06A-2EB2-4A47-812D-1D5B98D0F49A}.Release|Any CPU.Build.0 = Release|Any CPU + {EF02F89F-417E-4A40-B7E6-B102EE2DF24D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF02F89F-417E-4A40-B7E6-B102EE2DF24D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF02F89F-417E-4A40-B7E6-B102EE2DF24D}.Integration|Any CPU.ActiveCfg = Debug|Any CPU + {EF02F89F-417E-4A40-B7E6-B102EE2DF24D}.Integration|Any CPU.Build.0 = Debug|Any CPU + {EF02F89F-417E-4A40-B7E6-B102EE2DF24D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF02F89F-417E-4A40-B7E6-B102EE2DF24D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -200,7 +218,11 @@ Global {87D9C7D9-18F4-4AB9-B20D-66C02B6075E2} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} {0F761F76-E0F3-472E-B539-1815CE2BC696} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} {AAE1F8D1-F7AB-4ABE-A55B-D423393AB352} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} + {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} + {444E79F1-477A-481A-9BE6-6559B32CE177} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} + {BE04C532-C9AE-4C32-9283-F6629112228B} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} {835EDEB4-289B-4D6D-A9A0-609E43A87D6E} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} + {BA3C9622-ABFF-45A2-91AA-CC5189083256} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} {F18471B5-2042-409D-BF2C-E5403C322DC9} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} {4F250E56-F8B4-4E69-AECC-4D31EDD891E7} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} {8339991B-6D11-45A4-87D0-DF3322198990} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} @@ -211,13 +233,10 @@ Global {6FEE7E14-8A1D-454E-8F7C-B63597801787} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} {70E63BC1-2C82-41C0-89D6-272FD3C7B0C9} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} {EFB39C03-F7D2-4E8D-BE51-09121CD71973} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} - {BBF1F8D1-F7AB-4ABE-A55B-D423393AB352} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} - {220E1DEC-32EC-4B3B-A1DB-159ECFDD3A8D} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} - {444E79F1-477A-481A-9BE6-6559B32CE177} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} - {BE04C532-C9AE-4C32-9283-F6629112228B} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} - {BA3C9622-ABFF-45A2-91AA-CC5189083256} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} + {8EE5B06A-2EB2-4A47-812D-1D5B98D0F49A} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} + {EF02F89F-417E-4A40-B7E6-B102EE2DF24D} = {2BBD7364-054F-4693-97CD-1C395E3E84A9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {B31CDF4B-2851-45E5-8C5F-BE97125D9DD8} EndGlobalSection -EndGlobal \ No newline at end of file +EndGlobal diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ConnectionServiceCore.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ConnectionServiceCore.cs index 229742ed..f5a72f87 100644 --- a/src/Microsoft.SqlTools.CoreServices/Connection/ConnectionServiceCore.cs +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ConnectionServiceCore.cs @@ -24,6 +24,7 @@ using Microsoft.SqlTools.CoreServices.LanguageServices.Contracts; using ConnectionType = Microsoft.SqlTools.DataProtocol.Contracts.Connection.ConnectionType; using Microsoft.SqlTools.Hosting.Extensibility; using System.Composition; +using System.Diagnostics; namespace Microsoft.SqlTools.CoreServices.Connection { @@ -317,7 +318,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection } catch (Exception ex) { - Logger.Instance.Write(LogLevel.Normal, "Failed to close temporary connections. error: " + ex.Message); + Logger.Write(TraceEventType.Information, "Failed to close temporary connections. error: " + ex.Message); } } @@ -1175,8 +1176,8 @@ namespace Microsoft.SqlTools.CoreServices.Connection } catch (Exception e) { - Logger.Instance.Write( - LogLevel.Error, + Logger.Write( + TraceEventType.Error, string.Format( "Exception caught while trying to change database context to [{0}] for OwnerUri [{1}]. Exception:{2}", newDatabaseName, @@ -1255,7 +1256,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection } catch (Exception ex) { - Logger.Instance.Write(LogLevel.Verbose, "Could not send Connection telemetry event " + ex.ToString()); + Logger.Write(TraceEventType.Verbose, "Could not send Connection telemetry event " + ex.ToString()); } }); @@ -1301,7 +1302,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection string error = string.Format(CultureInfo.InvariantCulture, "Failed opening a SqlConnection: error:{0} inner:{1} stacktrace:{2}", ex.Message, ex.InnerException != null ? ex.InnerException.Message : string.Empty, ex.StackTrace); - Logger.Instance.Write(LogLevel.Error, error); + Logger.Write(TraceEventType.Error, error); } return null; diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/AmbientSettings.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/AmbientSettings.cs index 230d09c1..7a7c8841 100644 --- a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/AmbientSettings.cs +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/AmbientSettings.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Reflection; using Microsoft.SqlTools.Hosting.Utility; @@ -350,13 +351,13 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection public void TraceSettings() { // NOTE: logging as warning so we can get this data in the IEService DacFx logs - Logger.Instance.Write(LogLevel.Warning, Resources.LoggingAmbientSettings); + Logger.Write(TraceEventType.Warning, Resources.LoggingAmbientSettings); foreach (KeyValuePair setting in _configuration) { // Log Ambient Settings - Logger.Instance.Write( - LogLevel.Warning, + Logger.Write( + TraceEventType.Warning, string.Format( Resources.AmbientSettingFormat, setting.Key, @@ -406,7 +407,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection } else { - Logger.Instance.Write(LogLevel.Error, string.Format(Resources.UnableToAssignValue, value.GetType().FullName, _type.FullName)); + Logger.Write(TraceEventType.Error, string.Format(Resources.UnableToAssignValue, value.GetType().FullName, _type.FullName)); } } } diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/CachedServerInfo.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/CachedServerInfo.cs index 384326fe..f6c47be8 100644 --- a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/CachedServerInfo.cs +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/CachedServerInfo.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Concurrent; using System.Data; using System.Data.SqlClient; +using System.Diagnostics; using System.Linq; using Microsoft.SqlTools.Hosting.Utility; @@ -270,7 +271,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection } catch { - Logger.Instance.Write(LogLevel.Error, String.Format(Resources.FailedToParseConnectionString, connection.ConnectionString)); + Logger.Write(TraceEventType.Error, String.Format(Resources.FailedToParseConnectionString, connection.ConnectionString)); return null; } } diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableConnectionHelper.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableConnectionHelper.cs index 77a3b4ad..ae6863ba 100644 --- a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableConnectionHelper.cs +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableConnectionHelper.cs @@ -429,7 +429,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection Validate.IsNotNull(nameof(connection), connection); if (!(connection.State == ConnectionState.Open)) { - Logger.Instance.Write(LogLevel.Warning, Resources.ConnectionPassedToIsCloudShouldBeOpen); + Logger.Write(TraceEventType.Warning, Resources.ConnectionPassedToIsCloudShouldBeOpen); } Func executeCommand = commandText => @@ -540,7 +540,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection return true; } - Logger.Instance.Write(LogLevel.Error, ex.ToString()); + Logger.Write(TraceEventType.Error, ex.ToString()); return false; } @@ -668,7 +668,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection }, (ex) => { - Logger.Instance.Write(LogLevel.Error, ex.ToString()); + Logger.Write(TraceEventType.Error, ex.ToString()); return StandardExceptionHandler(ex); // handled }, useRetry: true); @@ -739,7 +739,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection Validate.IsNotNull(nameof(connection), connection); if (!(connection.State == ConnectionState.Open)) { - Logger.Instance.Write(LogLevel.Error, "connection passed to GetServerVersion should be open."); + Logger.Write(TraceEventType.Error, "connection passed to GetServerVersion should be open."); } Func getServerInfo = commandText => @@ -788,8 +788,8 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection { //we don't want to fail the normal flow if any unexpected thing happens //during caching although it's unlikely. So we just log the exception and ignore it - Logger.Instance.Write(LogLevel.Error, Resources.FailedToCacheIsCloud); - Logger.Instance.Write(LogLevel.Error, ex.ToString()); + Logger.Write(TraceEventType.Error, Resources.FailedToCacheIsCloud); + Logger.Write(TraceEventType.Error, ex.ToString()); } }); @@ -892,7 +892,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection if (handledEx != null) { - Logger.Instance.Write(LogLevel.Error, String.Format(Resources.ErrorParsingConnectionString, handledEx)); + Logger.Write(TraceEventType.Error, String.Format(Resources.ErrorParsingConnectionString, handledEx)); return false; } diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlConnection.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlConnection.cs index 66d7102f..3fd74ada 100644 --- a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlConnection.cs +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/ReliableSqlConnection.cs @@ -441,7 +441,7 @@ SET NUMERIC_ROUNDABORT OFF;"; } catch (SqlException exception) { - Logger.Instance.Write(LogLevel.Error, Resources.UnableToRetrieveAzureSessionId + exception.ToString()); + Logger.Write(TraceEventType.Error, Resources.UnableToRetrieveAzureSessionId + exception.ToString()); } } diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs index d8919182..c9c562da 100644 --- a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs @@ -4,6 +4,7 @@ // using System.Data.SqlClient; +using System.Diagnostics; using Microsoft.SqlTools.Hosting.Utility; namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection @@ -30,7 +31,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection RetryPolicyUtils.AppendThrottlingDataIfIsThrottlingError(sqlException, err); if (RetryPolicyUtils.IsNonRetryableDataTransferError(err.Number)) { - Logger.Instance.Write(LogLevel.Error, string.Format(Resources.ExceptionCannotBeRetried, err.Number, err.Message)); + Logger.Write(TraceEventType.Error, string.Format(Resources.ExceptionCannotBeRetried, err.Number, err.Message)); return false; } } diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.cs index 37c4fc64..fbaaf10d 100644 --- a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.cs +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicy.cs @@ -244,7 +244,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection bool shouldRetry = canRetry && ShouldRetryImpl(retryState); - Logger.Instance.Write(LogLevel.Error, + Logger.Write(TraceEventType.Error, string.Format( CultureInfo.InvariantCulture, "Retry requested: Retry count = {0}. Delay = {1}, SQL Error Number = {2}, Can retry error = {3}, Will retry = {4}", @@ -267,7 +267,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection { bool shouldIgnoreError = ErrorDetectionStrategy.ShouldIgnoreError(retryState.LastError); - Logger.Instance.Write(LogLevel.Error, + Logger.Write(TraceEventType.Error, string.Format( CultureInfo.InvariantCulture, "Ignore Error requested: Retry count = {0}. Delay = {1}, SQL Error Number = {2}, Should Ignore Error = {3}", diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyFactory.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyFactory.cs index ce6fda81..db2d6c8f 100644 --- a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyFactory.cs +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyFactory.cs @@ -392,7 +392,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection internal static void DataConnectionFailureRetry(RetryState retryState) { - Logger.Instance.Write(LogLevel.Normal, string.Format(CultureInfo.InvariantCulture, + Logger.Write(TraceEventType.Information, string.Format(CultureInfo.InvariantCulture, "Connection retry number {0}. Delaying {1} ms before retry. Exception: {2}", retryState.RetryCount, retryState.Delay.TotalMilliseconds.ToString(CultureInfo.InvariantCulture), @@ -403,7 +403,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection internal static void CommandFailureRetry(RetryState retryState, string commandKeyword) { - Logger.Instance.Write(LogLevel.Normal, string.Format( + Logger.Write(TraceEventType.Information, string.Format( CultureInfo.InvariantCulture, "{0} retry number {1}. Delaying {2} ms before retry. Exception: {3}", commandKeyword, @@ -416,7 +416,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection internal static void CommandFailureIgnore(RetryState retryState, string commandKeyword) { - Logger.Instance.Write(LogLevel.Normal, string.Format( + Logger.Write(TraceEventType.Information, string.Format( CultureInfo.InvariantCulture, "{0} retry number {1}. Ignoring failure. Exception: {2}", commandKeyword, diff --git a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyUtils.cs b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyUtils.cs index c301b48b..4195ad1d 100644 --- a/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyUtils.cs +++ b/src/Microsoft.SqlTools.CoreServices/Connection/ReliableConnection/RetryPolicyUtils.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Data.SqlClient; +using System.Diagnostics; using System.Runtime.InteropServices; using Microsoft.SqlTools.Hosting.Utility; @@ -344,7 +345,7 @@ namespace Microsoft.SqlTools.CoreServices.Connection.ReliableConnection { if (azureSessionId != Guid.Empty) { - Logger.Instance.Write(LogLevel.Warning, string.Format( + Logger.Write(TraceEventType.Warning, string.Format( "Retry occurred: session: {0}; attempt - {1}; delay - {2}; exception - \"{3}\"", azureSessionId, retryState.RetryCount, diff --git a/src/Microsoft.SqlTools.CoreServices/LanguageServices/BindingQueue.cs b/src/Microsoft.SqlTools.CoreServices/LanguageServices/BindingQueue.cs index df3708ec..9c75a9aa 100644 --- a/src/Microsoft.SqlTools.CoreServices/LanguageServices/BindingQueue.cs +++ b/src/Microsoft.SqlTools.CoreServices/LanguageServices/BindingQueue.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using System.Linq; using Microsoft.SqlTools.Hosting.Utility; +using System.Diagnostics; namespace Microsoft.SqlTools.CoreServices.LanguageServices { @@ -319,7 +320,7 @@ namespace Microsoft.SqlTools.CoreServices.LanguageServices } catch (Exception ex) { - Logger.Instance.Write(LogLevel.Error, "Unexpected exception on the binding queue: " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unexpected exception on the binding queue: " + ex.ToString()); if (queueItem.ErrorHandler != null) { result = queueItem.ErrorHandler(ex); @@ -346,14 +347,14 @@ namespace Microsoft.SqlTools.CoreServices.LanguageServices bindTask .ContinueWith((a) => bindingContext.BindingLock.Set()) - .ContinueWithOnFaulted(t => Logger.Instance.Write(LogLevel.Error, "Binding queue threw exception " + t.Exception.ToString())); + .ContinueWithOnFaulted(t => Logger.Write(TraceEventType.Error, "Binding queue threw exception " + t.Exception.ToString())); } } catch (Exception ex) { // catch and log any exceptions raised in the binding calls // set item processed to avoid deadlocks - Logger.Instance.Write(LogLevel.Error, "Binding queue threw exception " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Binding queue threw exception " + ex.ToString()); } finally { diff --git a/src/Microsoft.SqlTools.CoreServices/Microsoft.SqlTools.CoreServices.csproj b/src/Microsoft.SqlTools.CoreServices/Microsoft.SqlTools.CoreServices.csproj index dd71a076..1d471c4b 100644 --- a/src/Microsoft.SqlTools.CoreServices/Microsoft.SqlTools.CoreServices.csproj +++ b/src/Microsoft.SqlTools.CoreServices/Microsoft.SqlTools.CoreServices.csproj @@ -1,4 +1,4 @@ - + Library @@ -29,8 +29,8 @@ - - + + diff --git a/src/Microsoft.SqlTools.CoreServices/Workspace/SettingsService.cs b/src/Microsoft.SqlTools.CoreServices/Workspace/SettingsService.cs index 94d73f52..e981b0a2 100644 --- a/src/Microsoft.SqlTools.CoreServices/Workspace/SettingsService.cs +++ b/src/Microsoft.SqlTools.CoreServices/Workspace/SettingsService.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -100,7 +101,7 @@ namespace Microsoft.SqlTools.CoreServices.Workspace { try { - Logger.Instance.Write(LogLevel.Verbose, "HandleDidChangeConfigurationNotification"); + Logger.Write(TraceEventType.Verbose, "HandleDidChangeConfigurationNotification"); // Propagate the changes to the event handlers var configUpdateTasks = ConfigChangeCallbacks.Select( @@ -109,7 +110,7 @@ namespace Microsoft.SqlTools.CoreServices.Workspace } catch (Exception ex) { - Logger.Instance.Write(LogLevel.Error, "Unknown error " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unknown error " + ex.ToString()); // Swallow exceptions here to prevent us from crashing // TODO: this probably means the ScriptFile model is in a bad state or out of sync with the actual file; we should recover here return; diff --git a/src/Microsoft.SqlTools.Credentials/Credentials/CredentialService.cs b/src/Microsoft.SqlTools.Credentials/Credentials/CredentialService.cs index 8e55d431..90c3155d 100644 --- a/src/Microsoft.SqlTools.Credentials/Credentials/CredentialService.cs +++ b/src/Microsoft.SqlTools.Credentials/Credentials/CredentialService.cs @@ -4,6 +4,7 @@ // using System; +using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading.Tasks; using Microsoft.SqlTools.Credentials.Contracts; @@ -165,7 +166,7 @@ namespace Microsoft.SqlTools.Credentials private async Task HandleRequest(Func> handler, RequestContext requestContext, string requestType) { - Logger.Write(LogLevel.Verbose, requestType); + Logger.Write(TraceEventType.Verbose, requestType); try { diff --git a/src/Microsoft.SqlTools.Credentials/Credentials/Win32/CredentialSet.cs b/src/Microsoft.SqlTools.Credentials/Credentials/Win32/CredentialSet.cs index 15f6e77c..e51b2d83 100644 --- a/src/Microsoft.SqlTools.Credentials/Credentials/Win32/CredentialSet.cs +++ b/src/Microsoft.SqlTools.Credentials/Credentials/Win32/CredentialSet.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using Microsoft.SqlTools.Utility; @@ -69,13 +70,11 @@ namespace Microsoft.SqlTools.Credentials.Win32 private void LoadInternal() { - uint count; - IntPtr pCredentials = IntPtr.Zero; - bool result = NativeMethods.CredEnumerateW(Target, 0, out count, out pCredentials); + bool result = NativeMethods.CredEnumerateW(Target, 0, out uint count, out pCredentials); if (!result) { - Logger.Write(LogLevel.Error, string.Format("Win32Exception: {0}", new Win32Exception(Marshal.GetLastWin32Error()).ToString())); + Logger.Write(TraceEventType.Error, string.Format("Win32Exception: {0}", new Win32Exception(Marshal.GetLastWin32Error()).ToString())); return; } diff --git a/src/Microsoft.SqlTools.Credentials/Program.cs b/src/Microsoft.SqlTools.Credentials/Program.cs index a7ee1a02..0301a8cf 100644 --- a/src/Microsoft.SqlTools.Credentials/Program.cs +++ b/src/Microsoft.SqlTools.Credentials/Program.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Diagnostics; using System.IO; using Microsoft.SqlTools.Credentials.Utility; using Microsoft.SqlTools.Hosting.Utility; @@ -32,16 +33,18 @@ namespace Microsoft.SqlTools.Credentials return; } - string logFilePath = "credentials"; + string logFilePath = commandOptions.LogFilePath; + if (string.IsNullOrWhiteSpace(logFilePath)) + { + logFilePath = "credentials"; + } if (!string.IsNullOrWhiteSpace(commandOptions.LoggingDirectory)) { - logFilePath = Path.Combine(commandOptions.LoggingDirectory, logFilePath); + logFilePath = Logger.GenerateLogFilePath(Path.Combine(commandOptions.LoggingDirectory, logFilePath)); } - // turn on Verbose logging during early development - // we need to switch to Normal when preparing for public preview - Logger.Initialize(logFilePath: logFilePath, minimumLogLevel: LogLevel.Verbose, isEnabled: commandOptions.EnableLogging); - Logger.Write(LogLevel.Normal, "Starting SqlTools Credentials Provider"); + Logger.Initialize(tracingLevel: commandOptions.TracingLevel, logFilePath: logFilePath, traceSource: "credentials"); + Logger.Write(TraceEventType.Information, "Starting SqlTools Credentials Provider"); // set up the host details and profile paths var hostDetails = new HostDetails( @@ -56,8 +59,8 @@ namespace Microsoft.SqlTools.Credentials } catch (Exception e) { - Logger.Write(LogLevel.Error, string.Format("An unhandled exception occurred: {0}", e)); - Environment.Exit(1); + Logger.WriteWithCallstack(TraceEventType.Critical, $"An unhandled exception occurred: {e}"); + Environment.Exit(1); } } } diff --git a/src/Microsoft.SqlTools.DataProtocol.Contracts/GeneralRequestDetails.cs b/src/Microsoft.SqlTools.DataProtocol.Contracts/GeneralRequestDetails.cs index 17dd01db..88b3307e 100644 --- a/src/Microsoft.SqlTools.DataProtocol.Contracts/GeneralRequestDetails.cs +++ b/src/Microsoft.SqlTools.DataProtocol.Contracts/GeneralRequestDetails.cs @@ -30,7 +30,7 @@ namespace Microsoft.SqlTools.DataProtocol.Contracts { result = default(T); // TODO move logger to a utilities project - // Logger.Instance.Write(LogLevel.Warning, string.Format(CultureInfo.InvariantCulture, + // Logger.Write(TraceEventType.Warning, string.Format(CultureInfo.InvariantCulture, // "Cannot convert option value {0}:{1} to {2}", name, value ?? "", typeof(T))); } } diff --git a/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IHostedService.cs b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IHostedService.cs index 0d02b754..c67e3537 100644 --- a/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IHostedService.cs +++ b/src/Microsoft.SqlTools.Hosting.v2/Extensibility/IHostedService.cs @@ -4,6 +4,7 @@ // using System; +using System.Diagnostics; using System.Threading.Tasks; using Microsoft.SqlTools.Hosting.Protocol; using Microsoft.SqlTools.Hosting.Utility; @@ -64,7 +65,7 @@ namespace Microsoft.SqlTools.Hosting.Extensibility RequestContext requestContext, string requestType) { - Logger.Instance.Write(LogLevel.Verbose, requestType); + Logger.Write(TraceEventType.Verbose, requestType); try { @@ -83,7 +84,7 @@ namespace Microsoft.SqlTools.Hosting.Extensibility RequestContext requestContext, string requestType) { - Logger.Instance.Write(LogLevel.Verbose, requestType); + Logger.Write(TraceEventType.Verbose, requestType); return await Task.Factory.StartNew(() => { try { diff --git a/src/Microsoft.SqlTools.Hosting.v2/Microsoft.SqlTools.Hosting.csproj b/src/Microsoft.SqlTools.Hosting.v2/Microsoft.SqlTools.Hosting.v2.csproj similarity index 100% rename from src/Microsoft.SqlTools.Hosting.v2/Microsoft.SqlTools.Hosting.csproj rename to src/Microsoft.SqlTools.Hosting.v2/Microsoft.SqlTools.Hosting.v2.csproj diff --git a/src/Microsoft.SqlTools.Hosting.v2/Protocol/JsonRpcHost.cs b/src/Microsoft.SqlTools.Hosting.v2/Protocol/JsonRpcHost.cs index 725b38f2..ed9e18a0 100644 --- a/src/Microsoft.SqlTools.Hosting.v2/Protocol/JsonRpcHost.cs +++ b/src/Microsoft.SqlTools.Hosting.v2/Protocol/JsonRpcHost.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -286,7 +287,7 @@ namespace Microsoft.SqlTools.Hosting.Protocol { // Log the error and send an error event to the client string message = string.Format("Exception occurred while receiving input message: {0}", e.Message); - Logger.Instance.Write(LogLevel.Error, message); + Logger.Write(TraceEventType.Error, message); // TODO: Add event to output queue, and unit test it @@ -297,7 +298,7 @@ namespace Microsoft.SqlTools.Hosting.Protocol // Verbose logging string logMessage = string.Format("Received message of type[{0}] and method[{1}]", incomingMessage.MessageType, incomingMessage.Method); - Logger.Instance.Write(LogLevel.Verbose, logMessage); + Logger.Write(TraceEventType.Verbose, logMessage); // Process the message try @@ -310,7 +311,7 @@ namespace Microsoft.SqlTools.Hosting.Protocol // TODO: Localize string mnfLogMessage = string.Format("Failed to find method handler for type[{0}] and method[{1}]", incomingMessage.MessageType, incomingMessage.Method); - Logger.Instance.Write(LogLevel.Warning, mnfLogMessage); + Logger.Write(TraceEventType.Warning, mnfLogMessage); if (incomingMessage.MessageType == MessageType.Request) { @@ -325,12 +326,12 @@ namespace Microsoft.SqlTools.Hosting.Protocol // General errors should be logged but not halt the processing loop string geLogMessage = string.Format("Exception thrown when handling message of type[{0}] and method[{1}]: {2}", incomingMessage.MessageType, incomingMessage.Method, e); - Logger.Instance.Write(LogLevel.Error, geLogMessage); + Logger.Write(TraceEventType.Error, geLogMessage); // TODO: Should we be returning a response for failing requests? } } - Logger.Instance.Write(LogLevel.Warning, "Exiting consume input loop!"); + Logger.Write(TraceEventType.Warning, "Exiting consume input loop!"); }, consumeOutputCancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap(); } @@ -355,7 +356,7 @@ namespace Microsoft.SqlTools.Hosting.Protocol { // If we hit an exception here, it is unrecoverable string message = string.Format("Unexpected occurred while receiving output message: {0}", e.Message); - Logger.Instance.Write(LogLevel.Error, message); + Logger.Write(TraceEventType.Error, message); break; } @@ -363,11 +364,11 @@ namespace Microsoft.SqlTools.Hosting.Protocol // Send the message string logMessage = string.Format("Sending message of type[{0}] and method[{1}]", outgoingMessage.MessageType, outgoingMessage.Method); - Logger.Instance.Write(LogLevel.Verbose, logMessage); + Logger.Write(TraceEventType.Verbose, logMessage); await protocolChannel.MessageWriter.WriteMessage(outgoingMessage); } - Logger.Instance.Write(LogLevel.Warning, "Exiting consume output loop!"); + Logger.Write(TraceEventType.Warning, "Exiting consume output loop!"); }, consumeOutputCancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap(); } diff --git a/src/Microsoft.SqlTools.Hosting.v2/Protocol/MessageWriter.cs b/src/Microsoft.SqlTools.Hosting.v2/Protocol/MessageWriter.cs index 27535561..5e048c5f 100644 --- a/src/Microsoft.SqlTools.Hosting.v2/Protocol/MessageWriter.cs +++ b/src/Microsoft.SqlTools.Hosting.v2/Protocol/MessageWriter.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using System.Diagnostics; using System.IO; using System.Text; using System.Threading.Tasks; @@ -34,7 +35,7 @@ namespace Microsoft.SqlTools.Hosting.Protocol // Log the JSON representation of the message string logMessage = string.Format("Sending message of type[{0}] and method[{1}]", messageToWrite.MessageType, messageToWrite.Method); - Logger.Instance.Write(LogLevel.Verbose, logMessage); + Logger.Write(TraceEventType.Verbose, logMessage); string serializedMessage = messageToWrite.Serialize(); // TODO: Allow encoding to be passed in diff --git a/src/Microsoft.SqlTools.Hosting.v2/ServiceHost.cs b/src/Microsoft.SqlTools.Hosting.v2/ServiceHost.cs index a7d11357..e343e515 100644 --- a/src/Microsoft.SqlTools.Hosting.v2/ServiceHost.cs +++ b/src/Microsoft.SqlTools.Hosting.v2/ServiceHost.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Microsoft.SqlTools.DataProtocol.Contracts; @@ -168,7 +169,7 @@ namespace Microsoft.SqlTools.Hosting internal async Task HandleInitializeRequest(InitializeParameters initParams, RequestContext requestContext) { - Logger.Instance.Write(LogLevel.Normal, "Service host received intialize request"); + Logger.Write(TraceEventType.Information, "Service host received intialize request"); // Call all initialize methods provided by the service components IEnumerable initializeTasks = initCallbacks.Select(t => t(initParams, requestContext)); @@ -194,7 +195,7 @@ namespace Microsoft.SqlTools.Hosting internal async Task HandleShutdownRequest(object shutdownParams, RequestContext requestContext) { - Logger.Instance.Write(LogLevel.Normal, "Service host received shutdown request"); + Logger.Write(TraceEventType.Information, "Service host received shutdown request"); // Call all the shutdown methods provided by the service components IEnumerable shutdownTasks = shutdownCallbacks.Select(t => t(shutdownParams, requestContext)); diff --git a/src/Microsoft.SqlTools.Hosting.v2/Utility/CommandOptions.cs b/src/Microsoft.SqlTools.Hosting.v2/Utility/CommandOptions.cs index bc56d254..364f0c6a 100644 --- a/src/Microsoft.SqlTools.Hosting.v2/Utility/CommandOptions.cs +++ b/src/Microsoft.SqlTools.Hosting.v2/Utility/CommandOptions.cs @@ -14,6 +14,11 @@ namespace Microsoft.SqlTools.Hosting.Utility /// public class CommandOptions { + // set default log directory + // refer to https://jimrich.sk/environment-specialfolder-on-windows-linux-and-os-x/ && https://stackoverflow.com/questions/895723/environment-getfolderpath-commonapplicationdata-is-still-returning-c-docum + // for cross platform locations + internal readonly string DefaultLogRoot = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + /// /// Construct and parse command line options from the arguments array /// @@ -23,6 +28,13 @@ namespace Microsoft.SqlTools.Hosting.Utility ErrorMessage = string.Empty; Locale = string.Empty; + //set default log directory + LoggingDirectory = DefaultLogRoot; + if (!string.IsNullOrWhiteSpace(ServiceName)) + { + LoggingDirectory = Path.Combine(LoggingDirectory, ServiceName); + } + try { for (int i = 0; i < args.Length; ++i) @@ -37,7 +49,12 @@ namespace Microsoft.SqlTools.Hosting.Utility switch (argName) { case "-enable-logging": - EnableLogging = true; + break; //ignore this old option for now for backward compat with older opsstudio code - to be removed in a future checkin + case "-tracing-level": + TracingLevel = args[++i]; + break; + case "-log-file": + LogFilePath = args[++i]; break; case "-log-dir": SetLoggingDirectory(args[++i]); @@ -76,12 +93,6 @@ namespace Microsoft.SqlTools.Hosting.Utility /// public string ErrorMessage { get; private set; } - - /// - /// Whether diagnostic logging is enabled - /// - public bool EnableLogging { get; private set; } - /// /// Gets the directory where log files are output. /// @@ -112,15 +123,21 @@ namespace Microsoft.SqlTools.Hosting.Utility var str = string.Format("{0}" + Environment.NewLine + ServiceName + " " + Environment.NewLine + " Options:" + Environment.NewLine + - " [--enable-logging]" + Environment.NewLine + - " [--log-dir **] (default: current directory)" + Environment.NewLine + - " [--help]" + Environment.NewLine + + " [--enable-logging ] (obsolete - present for backward compat. Logging is always on, except -tracing-level Off has the effect of disabling logging)" + Environment.NewLine + + " [--tracing-level **] (** can be any of: All, Off, Critical, Error, Warning, Information, Verbose. Default is Critical)" + Environment.NewLine + + " [--log-file **]" + Environment.NewLine + + " [--log-dir **] (default: %APPDATA%\\)" + Environment.NewLine + " [--locale **] (default: 'en')" + Environment.NewLine, + " [--help]" + Environment.NewLine + ErrorMessage); return str; } } + public string TracingLevel { get; private set; } + + public string LogFilePath { get; private set; } + private void SetLoggingDirectory(string loggingDirectory) { if (string.IsNullOrWhiteSpace(loggingDirectory)) diff --git a/src/Microsoft.SqlTools.Hosting.v2/Utility/Logger.cs b/src/Microsoft.SqlTools.Hosting.v2/Utility/Logger.cs index d8c62c43..47ba6877 100644 --- a/src/Microsoft.SqlTools.Hosting.v2/Utility/Logger.cs +++ b/src/Microsoft.SqlTools.Hosting.v2/Utility/Logger.cs @@ -5,86 +5,157 @@ using System; using System.Diagnostics; +using System.Globalization; using System.IO; -using System.Runtime.CompilerServices; -using System.Text; +using System.Threading; namespace Microsoft.SqlTools.Hosting.Utility { /// - /// Defines the level indicators for log messages. + /// Ordinal value of each LogEvent value corresponds to a unique event id to be used in trace. + /// By convention explicitly specify the integer value so that when this list grows large it is easy to figure out + /// enumeration corresponding to a numeric value. We could be reserving ranges of values for specific areas or logEvents. + /// Maximum value assignable to LogEvent enum value is 65,535. /// - public enum LogLevel + public enum LogEvent : ushort { - /// - /// Indicates a verbose log message. - /// - Verbose, - - /// - /// Indicates a normal, non-verbose log message. - /// - Normal, - - /// - /// Indicates a warning message. - /// - Warning, - - /// - /// Indicates an error message. - /// - Error + Default = 0, + IoFileSystem = 1, + OsSubSystem = 2, } /// - /// Provides a simple logging interface. May be replaced with a - /// more robust solution at a later date. + /// Provides a simple logging interface built on top of .Net tracing frameworks /// - public class Logger + public static class Logger { - private static LogWriter logWriter; + internal const SourceLevels defaultTracingLevel = SourceLevels.Critical; + internal const string defaultTraceSource = "sqltools"; + private static SourceLevels tracingLevel = defaultTracingLevel; + private static string logFileFullPath; - private static bool isEnabled; - - private static bool isInitialized = false; - - private static Lazy lazyInstance = new Lazy(() => new Logger()); - - public static Logger Instance + internal static TraceSource TraceSource { get; set; } + internal static string LogFileFullPath { - get + get => logFileFullPath; + private set { - return lazyInstance.Value; + //If the log file path has a directory component then ensure that the directory exists. + if (!string.IsNullOrEmpty(Path.GetDirectoryName(value)) && !Directory.Exists(Path.GetDirectoryName(value))) + { + Directory.CreateDirectory(Path.GetDirectoryName(value)); + } + + logFileFullPath = value; + ConfigureListener(); } } - + + private static SqlToolsTraceListener Listener { get; set; } + + private static void ConfigureLogFile(string logFilePrefix) => LogFileFullPath = GenerateLogFilePath(logFilePrefix); + /// - /// Initializes the Logger for the current session. + /// Calling this method will turn on inclusion CallStack in the log for all future traces /// - /// - /// Optional. Specifies the path at which log messages will be written. - /// - /// + public static void StartCallStack() => Listener.TraceOutputOptions |= TraceOptions.Callstack; + + /// + /// Calling this method will turn off inclusion of CallStack in the log for all future traces + /// + public static void StopCallStack() => Listener.TraceOutputOptions &= ~TraceOptions.Callstack; + + /// + /// Calls flush on defaultTracingLevel configured listeners. + /// + public static void Flush() + { + TraceSource.Flush(); + Trace.Flush(); + } + + public static void Close() + { + Flush(); + TraceSource.Close(); + Trace.Close(); + Listener = null; // Since we have closed the listener, set listener to null. + } + public static SourceLevels TracingLevel + { + get => tracingLevel; + set + { + // configures the source level filter. This alone is not enough for tracing that is done via "Trace" object instead of "TraceSource" object + TraceSource.Switch = new SourceSwitch(TraceSource.Name, value.ToString()); + // configure the listener level filter + tracingLevel = value; + Listener.Filter = new EventTypeFilter(tracingLevel); + } + } + + /// + /// Initializes the Logger for the current process. + /// + /// /// Optional. Specifies the minimum log message level to write to the log file. /// - public void Initialize( - string logFilePath = "sqltools", - LogLevel minimumLogLevel = LogLevel.Normal, - bool isEnabled = true) + /// + /// Optional. Specifies the log name prefix for the log file name at which log messages will be written. + /// + /// Optional. Specifies the tracesource name. + /// + public static void Initialize( + SourceLevels tracingLevel = defaultTracingLevel, + string logFilePath = null, + string traceSource = defaultTraceSource) { - Logger.isEnabled = isEnabled; - - // return if the logger is not enabled or already initialized - if (!Logger.isEnabled || Logger.isInitialized) + Logger.tracingLevel = tracingLevel; + TraceSource = new TraceSource(traceSource, Logger.tracingLevel); + if (string.IsNullOrWhiteSpace(logFilePath)) { - return; + logFilePath = GenerateLogFilePath(traceSource); } - Logger.isInitialized = true; + LogFileFullPath = logFilePath; + Write(TraceEventType.Information, $"Initialized the {traceSource} logger"); + } + /// + /// Initializes the Logger for the current process. + /// + /// + /// + /// Optional. Specifies the minimum log message level to write to the log file. + /// + /// + /// Optional. Specifies the log name prefix for the log file name at which log messages will be written. + /// + /// Optional. Specifies the tracesource name. + /// + public static void Initialize(string tracingLevel, string logFilePath = null, string traceSource = defaultTraceSource) + { + Initialize(Enum.TryParse(tracingLevel, out SourceLevels sourceTracingLevel) + ? sourceTracingLevel + : defaultTracingLevel + , logFilePath + , traceSource); + } + + /// + /// Configures the LogfilePath for the tracelistener in use for this process. + /// + /// + /// Returns the log file path corresponding to logfilePrefix + /// + public static string GenerateLogFilePath(string logFilePrefix = defaultTraceSource) + { + if (string.IsNullOrWhiteSpace(logFilePrefix)) + { + throw new ArgumentOutOfRangeException(nameof(logFilePrefix), $"LogfilePath cannot be configured if argument {nameof(logFilePrefix)} has not been set"); + } // Create the log directory - string logDir = Path.GetDirectoryName(logFilePath); + string logDir = Path.GetDirectoryName(logFilePrefix); if (!string.IsNullOrWhiteSpace(logDir)) { if (!Directory.Exists(logDir)) @@ -93,207 +164,280 @@ namespace Microsoft.SqlTools.Hosting.Utility { Directory.CreateDirectory(logDir); } - catch (Exception) + catch (Exception ex) { - // Creating the log directory is a best effort operation, so ignore any failures. + Write(TraceEventType.Error, LogEvent.IoFileSystem, $"Unable to create directory:{logDir}\nException encountered:{ex}"); } } } - // get a unique number to prevent conflicts of two process launching at the same time int uniqueId; try { uniqueId = Process.GetCurrentProcess().Id; } - catch (Exception) + catch (Exception ex) { + Write(TraceEventType.Information, LogEvent.OsSubSystem, $"Unable to get process id of current running process\nException encountered:{ex}"); // if the pid look up fails for any reason, just use a random number - uniqueId = new Random().Next(1000, 9999); + uniqueId = new Random().Next(1000, 9999); } // make the log path unique - string fullFileName = string.Format( - "{0}_{1,4:D4}{2,2:D2}{3,2:D2}{4,2:D2}{5,2:D2}{6,2:D2}{7}.log", - logFilePath, - DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, - DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, - uniqueId); - - if (logWriter != null) - { - logWriter.Dispose(); - } - - // TODO: Parameterize this - logWriter = - new LogWriter( - minimumLogLevel, - fullFileName, - true); - - Write(LogLevel.Normal, "Initializing SQL Tools Service Host logger"); + return $"{logFilePrefix}_{DateTime.Now.Year,4:D4}{DateTime.Now.Month,2:D2}{DateTime.Now.Day,2:D2}{DateTime.Now.Hour,2:D2}{DateTime.Now.Minute,2:D2}{DateTime.Now.Second,2:D2}{uniqueId}.log"; } - /// - /// Closes the Logger. - /// - public void Close() + private static void ConfigureListener() { - if (logWriter != null) + if (string.IsNullOrWhiteSpace(LogFileFullPath)) { - logWriter.Dispose(); + throw new InvalidOperationException("Listeners cannot be configured if LogFileFullPath has not been set"); } + Listener = new SqlToolsTraceListener(LogFileFullPath) + { + TraceOutputOptions = TraceOptions.DateTime | TraceOptions.ProcessId | TraceOptions.ThreadId, + Filter = new EventTypeFilter(TracingLevel), + }; + TraceSource.Listeners.Clear(); + TraceSource.Listeners.Add(Listener); + Trace.Listeners.Clear(); + Trace.Listeners.Add(Listener); } /// /// Writes a message to the log file. /// - /// The level at which the message will be written. + /// The level at which the message will be written. /// The message text to be written. - /// The name of the calling method. - /// The source file path where the calling method exists. - /// The line number of the calling method. - public void Write( - LogLevel logLevel, - string logMessage, - [CallerMemberName] string callerName = null, - [CallerFilePath] string callerSourceFile = null, - [CallerLineNumber] int callerLineNumber = 0) - { - // return if the logger is not enabled or not initialized - if (!Logger.isEnabled || !Logger.isInitialized) + public static void Write(TraceEventType eventType, string logMessage) => Write(eventType, LogEvent.Default, logMessage); + + /// + /// Writes a message to the log file with accompanying callstack. + /// + /// The level at which the message will be written. + /// The message text to be written. + /// + /// The callstack logging gets turned on globally and any other log writes that happens in the time window + /// while this log write is happening will also get callstack information logged. This is not considered + /// and trying to isolate the callstack logging to be turned of for just one call is unnecessarily complex. + /// + public static void WriteWithCallstack(TraceEventType eventType, string logMessage) => WriteWithCallstack(eventType, LogEvent.Default, logMessage); + + /// + /// Writes a message to the log file with accompanying callstack. + /// + /// The level at which the message will be written. + /// The event id enumeration for the log event. + /// The message text to be written. + /// + /// The callstack logging gets turned on globally and any other log writes that happens in the time window + /// while this log write is happening will also get callstack information logged. This is not considered + /// and trying to isolate the callstack logging to be turned of for just one call is unnecessarily complex. + /// + public static void WriteWithCallstack(TraceEventType eventType, LogEvent logEvent, string logMessage) + { + Logger.StartCallStack(); + Write(eventType, logEvent, logMessage); + Logger.StopCallStack(); + } + + /// + /// Writes a message to the log file. + /// + /// The level at which the message will be written. + /// The event id enumeration for the log event. + /// The message text to be written. + public static void Write( + TraceEventType eventType, + LogEvent logEvent, + string logMessage) + { + // If logger is initialized then use TraceSource else use Trace + if (TraceSource != null) + { + TraceSource.TraceEvent(eventType, (ushort)logEvent, logMessage); + } + else + { + switch (eventType) + { + case TraceEventType.Critical: + case TraceEventType.Error: + if (eventType == TraceEventType.Critical) + { + logMessage = $@"event={eventType}: {logMessage}"; + } + + Trace.TraceError(logMessage); + break; + case TraceEventType.Warning: + Trace.TraceWarning(logMessage); + break; + case TraceEventType.Information: + case TraceEventType.Resume: + case TraceEventType.Start: + case TraceEventType.Stop: + case TraceEventType.Suspend: + case TraceEventType.Transfer: + case TraceEventType.Verbose: + if (eventType != TraceEventType.Information) + { + logMessage = $@"event={eventType}: {logMessage}"; + } + + Trace.TraceInformation(logMessage); + break; + } + } + } + } + + /// + /// This listener has the same behavior as TextWriterTraceListener except it controls how the + /// options: TraceOptions.DateTime, TraceOptions.ProcessId and TraceOptions.ThreadId is written to the output stream. + /// This listener writes the above options, if turned on, inline with the message + /// instead of writing them to indented fields as is the case with TextWriterTraceListener. + /// This implementation also lazily initializes the underlying tracelistener + /// + /// + /// Implementation of this is a lazily initialize trace listener that is partly inspired + /// by: https://stackoverflow.com/questions/30664527/how-to-stop-streamwriter-to-not-to-create-file-if-nothing-to-write + /// + internal sealed class SqlToolsTraceListener : TraceListener + { + Lazy _lazyListener; + private TextWriterTraceListener Listener => _lazyListener.Value; + private bool IsListenerCreated => _lazyListener.IsValueCreated; + public SqlToolsTraceListener(string file, string listenerName = "") : base(listenerName) + { + // Wrapping around lazy to make sure that we do not create file if the log.Write events are getting filtered out. i.e. the log file actually gets created the first time an actual write to log file happens. + _lazyListener = new Lazy( + valueFactory: () => new TextWriterTraceListener(new StreamWriter(file, append: true), listenerName), + // LazyThreadSafetyMode.PublicationOnly mode ensures that we keep trying to create the listener (especially the file that write) on all future log.write events even if previous attempt(s) have failed + mode: LazyThreadSafetyMode.PublicationOnly + ); + } + #region forward actual write/close/flush/dispose calls to the underlying listener. + public override void Write(string message) => Listener.Write(message); + + public override void WriteLine(string message) => Listener.WriteLine(message); + + /// + /// Closes the so that it no longer + /// receives tracing or debugging output. + /// Make sure that we do not Close if the lazy listener never got created. + /// + public override void Close() + { + if (IsListenerCreated) + { + Listener.Close(); + } + } + + /// + /// Releases all resources used by the + /// No unmanaged resources in this class, and it is sealed. + /// No finalizer needed. See http://stackoverflow.com/a/3882819/613130 + /// We skip disposing if the lazy listener never got created. + /// + public new void Dispose() + { + if (IsListenerCreated) + { + Listener.Dispose(); + } + } + + /// + /// Flushes the output buffer for the . + /// Make sure that we do not Flush if the lazy listener never got created. + /// + public override void Flush() + { + if (IsListenerCreated) + { + Listener.Flush(); + } + } + #endregion + + public override void TraceEvent(TraceEventCache eventCache, String source, TraceEventType eventType, int id) + { + TraceEvent(eventCache, source, eventType, id, String.Empty); + } + + // All other TraceEvent methods come through this one. + public override void TraceEvent(TraceEventCache eventCache, String source, TraceEventType eventType, int id, string message) + { + if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, message, null, null, null)) { return; } - if (logWriter != null) - { - logWriter.Write( - logLevel, - logMessage, - callerName, - callerSourceFile, - callerLineNumber); - } + WriteHeader(eventCache, source, eventType, id); + WriteLine(message); + WriteFooter(eventCache); } - } - internal class LogWriter : IDisposable - { - private object logLock = new object(); - private TextWriter textWriter; - private LogLevel minimumLogLevel = LogLevel.Verbose; - - public LogWriter(LogLevel minimumLogLevel, string logFilePath, bool deleteExisting) + public override void TraceEvent(TraceEventCache eventCache, String source, TraceEventType eventType, int id, string format, params object[] args) { - this.minimumLogLevel = minimumLogLevel; + if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, format, args, null, null)) + { + return; + } - // Ensure that we have a usable log file path - if (!Path.IsPathRooted(logFilePath)) - { - logFilePath = - Path.Combine( - AppContext.BaseDirectory, - logFilePath); - } - - - if (!this.TryOpenLogFile(logFilePath, deleteExisting)) - { - // If the log file couldn't be opened at this location, - // try opening it in a more reliable path - this.TryOpenLogFile( - Path.Combine( - Environment.GetEnvironmentVariable("TEMP"), - Path.GetFileName(logFilePath)), - deleteExisting); - } + WriteHeader(eventCache, source, eventType, id); + if (args != null) + { + WriteLine(String.Format(CultureInfo.InvariantCulture, format, args)); + } + else + { + WriteLine(format); + } + WriteFooter(eventCache); } - public void Write( - LogLevel logLevel, - string logMessage, - string callerName = null, - string callerSourceFile = null, - int callerLineNumber = 0) + private void WriteHeader(TraceEventCache eventCache, String source, TraceEventType eventType, int id) + => Write(FormatHeader(eventCache, String.Format(CultureInfo.InvariantCulture, "{0} {1}: {2} : ", source, eventType.ToString(), id.ToString(CultureInfo.InvariantCulture)))); + + private void WriteFooter(TraceEventCache eventCache) { - if (this.textWriter != null && - logLevel >= this.minimumLogLevel) + if (eventCache == null) { - // System.IO is not thread safe - lock (this.logLock) - { - // Print the timestamp and log level - this.textWriter.WriteLine( - "{0} [{1}] - Method \"{2}\" at line {3} of {4}\r\n", - DateTime.Now, - logLevel.ToString().ToUpper(), - callerName, - callerLineNumber, - callerSourceFile); - - // Print out indented message lines - foreach (var messageLine in logMessage.Split('\n')) - { - this.textWriter.WriteLine(" " + messageLine.TrimEnd()); - } - - // Finish with a newline and flush the writer - this.textWriter.WriteLine(); - this.textWriter.Flush(); - } + return; } + + IndentLevel++; + if (TraceOutputOptions.HasFlag(TraceOptions.LogicalOperationStack)) + { + WriteLine("LogicalOperationStack=" + eventCache.LogicalOperationStack); + } + + if (TraceOutputOptions.HasFlag(TraceOptions.Callstack)) + { + WriteLine("Callstack=" + eventCache.Callstack); + } + + IndentLevel--; } - public void Dispose() + private string FormatHeader(TraceEventCache eventCache, string message) { - if (this.textWriter != null) + if (eventCache == null) { - this.textWriter.Flush(); - this.textWriter.Dispose(); - this.textWriter = null; + return message; } + + return $"{(IsEnabled(TraceOptions.DateTime) ? string.Format(CultureInfo.InvariantCulture, "{0} ", eventCache.DateTime.ToLocalTime().ToString("u", CultureInfo.InvariantCulture)) : string.Empty)}" + + $"{(IsEnabled(TraceOptions.ProcessId) ? string.Format(CultureInfo.InvariantCulture, "pid:{0} ", eventCache.ProcessId.ToString(CultureInfo.InvariantCulture)) : string.Empty)}" + + $"{(IsEnabled(TraceOptions.ThreadId) ? string.Format(CultureInfo.InvariantCulture, "tid:{0} ", eventCache.ThreadId.ToString(CultureInfo.InvariantCulture)) : string.Empty)}" + + message; } - private bool TryOpenLogFile( - string logFilePath, - bool deleteExisting) - { - try - { - // Make sure the log directory exists - Directory.CreateDirectory( - Path.GetDirectoryName( - logFilePath)); + private bool IsEnabled(TraceOptions opt) => TraceOutputOptions.HasFlag(opt); - // Open the log file for writing with UTF8 encoding - this.textWriter = - new StreamWriter( - new FileStream( - logFilePath, - deleteExisting ? - FileMode.Create : - FileMode.Append), - Encoding.UTF8); - - return true; - } - catch (Exception e) - { - if (e is UnauthorizedAccessException || - e is IOException) - { - // This exception is thrown when we can't open the file - // at the path in logFilePath. Return false to indicate - // that the log file couldn't be created. - return false; - } - - // Unexpected exception, rethrow it - throw; - } - } } } diff --git a/src/Microsoft.SqlTools.Hosting.v2/Utility/TaskExtensions.cs b/src/Microsoft.SqlTools.Hosting.v2/Utility/TaskExtensions.cs index 110d06d7..75ad0823 100644 --- a/src/Microsoft.SqlTools.Hosting.v2/Utility/TaskExtensions.cs +++ b/src/Microsoft.SqlTools.Hosting.v2/Utility/TaskExtensions.cs @@ -4,6 +4,7 @@ // using System; +using System.Diagnostics; using System.Text; using System.Threading.Tasks; @@ -41,8 +42,8 @@ namespace Microsoft.SqlTools.Hosting.Utility } catch (Exception e) { - Logger.Instance.Write(LogLevel.Error, $"Exception in exception handling continuation: {e}"); - Logger.Instance.Write(LogLevel.Error, e.StackTrace); + Logger.Write(TraceEventType.Error, $"Exception in exception handling continuation: {e}"); + Logger.Write(TraceEventType.Error, e.StackTrace); } }); } @@ -78,8 +79,8 @@ namespace Microsoft.SqlTools.Hosting.Utility } catch (Exception e) { - Logger.Instance.Write(LogLevel.Error, $"Exception in exception handling continuation: {e}"); - Logger.Instance.Write(LogLevel.Error, e.StackTrace); + Logger.Write(TraceEventType.Error, $"Exception in exception handling continuation: {e}"); + Logger.Write(TraceEventType.Error, e.StackTrace); } }); } @@ -93,7 +94,7 @@ namespace Microsoft.SqlTools.Hosting.Utility sb.AppendLine($"{e.GetType().Name}: {e.Message}"); sb.AppendLine(e.StackTrace); } - Logger.Instance.Write(LogLevel.Error, sb.ToString()); + Logger.Write(TraceEventType.Error, sb.ToString()); } } } \ No newline at end of file diff --git a/src/Microsoft.SqlTools.Hosting/Hosting/IHostedService.cs b/src/Microsoft.SqlTools.Hosting/Hosting/IHostedService.cs index 44e5030a..f905a073 100644 --- a/src/Microsoft.SqlTools.Hosting/Hosting/IHostedService.cs +++ b/src/Microsoft.SqlTools.Hosting/Hosting/IHostedService.cs @@ -4,6 +4,7 @@ // using System; +using System.Diagnostics; using System.Threading.Tasks; using Microsoft.SqlTools.Extensibility; using Microsoft.SqlTools.Hosting.Protocol; @@ -69,7 +70,7 @@ namespace Microsoft.SqlTools.Hosting protected async Task HandleRequestAsync(Func> handler, RequestContext requestContext, string requestType) { - Logger.Write(LogLevel.Verbose, requestType); + Logger.Write(TraceEventType.Verbose, requestType); try { diff --git a/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/MessageDispatcher.cs b/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/MessageDispatcher.cs index b5963b1b..7937e7ca 100644 --- a/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/MessageDispatcher.cs +++ b/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/MessageDispatcher.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -169,7 +170,7 @@ namespace Microsoft.SqlTools.Hosting.Protocol } catch (Exception ex) { - Logger.Write(LogLevel.Verbose, ex.ToString()); + Logger.Write(TraceEventType.Verbose, ex.ToString()); } } @@ -217,7 +218,7 @@ namespace Microsoft.SqlTools.Hosting.Protocol catch (MessageParseException e) { string message = string.Format("Exception occurred while parsing message: {0}", e.Message); - Logger.Write(LogLevel.Error, message); + Logger.Write(TraceEventType.Error, message); await MessageWriter.WriteEvent(HostingErrorEvent.Type, new HostingErrorParams { Message = message }); // Continue the loop @@ -232,7 +233,7 @@ namespace Microsoft.SqlTools.Hosting.Protocol { // Log the error and send an error event to the client string message = string.Format("Exception occurred while receiving message: {0}", e.Message); - Logger.Write(LogLevel.Error, message); + Logger.Write(TraceEventType.Error, message); await MessageWriter.WriteEvent(HostingErrorEvent.Type, new HostingErrorParams { Message = message }); // Continue the loop @@ -246,7 +247,7 @@ namespace Microsoft.SqlTools.Hosting.Protocol // Verbose logging string logMessage = string.Format("Received message of type[{0}] and method[{1}]", newMessage.MessageType, newMessage.Method); - Logger.Write(LogLevel.Verbose, logMessage); + Logger.Write(TraceEventType.Verbose, logMessage); // Process the message await this.DispatchMessage(newMessage, this.MessageWriter); @@ -312,7 +313,7 @@ namespace Microsoft.SqlTools.Hosting.Protocol if (!(e is AggregateException && ((AggregateException)e).InnerExceptions[0] is TaskCanceledException)) { // Log the error but don't rethrow it to prevent any errors in the handler from crashing the service - Logger.Write(LogLevel.Error, string.Format("An unexpected error occured in the request handler: {0}", e.ToString())); + Logger.Write(TraceEventType.Error, string.Format("An unexpected error occured in the request handler: {0}", e.ToString())); } } } diff --git a/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/MessageWriter.cs b/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/MessageWriter.cs index e77942b4..d8ba4bb8 100644 --- a/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/MessageWriter.cs +++ b/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/MessageWriter.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using System.Diagnostics; using System.IO; using System.Text; using System.Threading.Tasks; @@ -60,7 +61,7 @@ namespace Microsoft.SqlTools.Hosting.Protocol // Log the JSON representation of the message string logMessage = string.Format("Sending message of type[{0}] and method[{1}]", messageToWrite.MessageType, messageToWrite.Method); - Logger.Write(LogLevel.Verbose, logMessage); + Logger.Write(TraceEventType.Verbose, logMessage); string serializedMessage = JsonConvert.SerializeObject( diff --git a/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/ProtocolEndpoint.cs b/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/ProtocolEndpoint.cs index 56678b44..1dc64521 100644 --- a/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/ProtocolEndpoint.cs +++ b/src/Microsoft.SqlTools.Hosting/Hosting/Protocol/ProtocolEndpoint.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using Microsoft.SqlTools.Hosting.Protocol.Channel; @@ -254,7 +255,7 @@ namespace Microsoft.SqlTools.Hosting.Protocol { if (SendEventIgnoreExceptions) { - Logger.Write(LogLevel.Verbose, "Exception in SendEvent " + ex.ToString()); + Logger.Write(TraceEventType.Verbose, "Exception in SendEvent " + ex.ToString()); } else { diff --git a/src/Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj b/src/Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj index 8a4f3589..b159d5a6 100644 --- a/src/Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj +++ b/src/Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj @@ -6,7 +6,7 @@ false false false - $(DefineConstants);NETCOREAPP1_0 + $(DefineConstants);NETCOREAPP1_0;TRACE true true portable diff --git a/src/Microsoft.SqlTools.Hosting/Utility/CommandOptions.cs b/src/Microsoft.SqlTools.Hosting/Utility/CommandOptions.cs index bc56d254..364f0c6a 100644 --- a/src/Microsoft.SqlTools.Hosting/Utility/CommandOptions.cs +++ b/src/Microsoft.SqlTools.Hosting/Utility/CommandOptions.cs @@ -14,6 +14,11 @@ namespace Microsoft.SqlTools.Hosting.Utility /// public class CommandOptions { + // set default log directory + // refer to https://jimrich.sk/environment-specialfolder-on-windows-linux-and-os-x/ && https://stackoverflow.com/questions/895723/environment-getfolderpath-commonapplicationdata-is-still-returning-c-docum + // for cross platform locations + internal readonly string DefaultLogRoot = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + /// /// Construct and parse command line options from the arguments array /// @@ -23,6 +28,13 @@ namespace Microsoft.SqlTools.Hosting.Utility ErrorMessage = string.Empty; Locale = string.Empty; + //set default log directory + LoggingDirectory = DefaultLogRoot; + if (!string.IsNullOrWhiteSpace(ServiceName)) + { + LoggingDirectory = Path.Combine(LoggingDirectory, ServiceName); + } + try { for (int i = 0; i < args.Length; ++i) @@ -37,7 +49,12 @@ namespace Microsoft.SqlTools.Hosting.Utility switch (argName) { case "-enable-logging": - EnableLogging = true; + break; //ignore this old option for now for backward compat with older opsstudio code - to be removed in a future checkin + case "-tracing-level": + TracingLevel = args[++i]; + break; + case "-log-file": + LogFilePath = args[++i]; break; case "-log-dir": SetLoggingDirectory(args[++i]); @@ -76,12 +93,6 @@ namespace Microsoft.SqlTools.Hosting.Utility /// public string ErrorMessage { get; private set; } - - /// - /// Whether diagnostic logging is enabled - /// - public bool EnableLogging { get; private set; } - /// /// Gets the directory where log files are output. /// @@ -112,15 +123,21 @@ namespace Microsoft.SqlTools.Hosting.Utility var str = string.Format("{0}" + Environment.NewLine + ServiceName + " " + Environment.NewLine + " Options:" + Environment.NewLine + - " [--enable-logging]" + Environment.NewLine + - " [--log-dir **] (default: current directory)" + Environment.NewLine + - " [--help]" + Environment.NewLine + + " [--enable-logging ] (obsolete - present for backward compat. Logging is always on, except -tracing-level Off has the effect of disabling logging)" + Environment.NewLine + + " [--tracing-level **] (** can be any of: All, Off, Critical, Error, Warning, Information, Verbose. Default is Critical)" + Environment.NewLine + + " [--log-file **]" + Environment.NewLine + + " [--log-dir **] (default: %APPDATA%\\)" + Environment.NewLine + " [--locale **] (default: 'en')" + Environment.NewLine, + " [--help]" + Environment.NewLine + ErrorMessage); return str; } } + public string TracingLevel { get; private set; } + + public string LogFilePath { get; private set; } + private void SetLoggingDirectory(string loggingDirectory) { if (string.IsNullOrWhiteSpace(loggingDirectory)) diff --git a/src/Microsoft.SqlTools.Hosting/Utility/GeneralRequestDetails.cs b/src/Microsoft.SqlTools.Hosting/Utility/GeneralRequestDetails.cs index a407dc6e..b88cf3d0 100644 --- a/src/Microsoft.SqlTools.Hosting/Utility/GeneralRequestDetails.cs +++ b/src/Microsoft.SqlTools.Hosting/Utility/GeneralRequestDetails.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; namespace Microsoft.SqlTools.Utility @@ -29,7 +30,7 @@ namespace Microsoft.SqlTools.Utility catch { result = default(T); - Logger.Write(LogLevel.Warning, string.Format(CultureInfo.InvariantCulture, + Logger.Write(TraceEventType.Warning, string.Format(CultureInfo.InvariantCulture, "Cannot convert option value {0}:{1} to {2}", name, value ?? "", typeof(T))); } } diff --git a/src/Microsoft.SqlTools.Hosting/Utility/Logger.cs b/src/Microsoft.SqlTools.Hosting/Utility/Logger.cs index 6b515a17..843e8436 100644 --- a/src/Microsoft.SqlTools.Hosting/Utility/Logger.cs +++ b/src/Microsoft.SqlTools.Hosting/Utility/Logger.cs @@ -5,76 +5,157 @@ using System; using System.Diagnostics; +using System.Globalization; using System.IO; -using System.Runtime.CompilerServices; -using System.Text; +using System.Threading; namespace Microsoft.SqlTools.Utility { /// - /// Defines the level indicators for log messages. + /// Ordinal value of each LogEvent value corresponds to a unique event id to be used in trace. + /// By convention explicitly specify the integer value so that when this list grows large it is easy to figure out + /// enumeration corresponding to a numeric value. We could be reserving ranges of values for specific areas or logEvents. + /// Maximum value assignable to LogEvent enum value is 65,535. /// - public enum LogLevel + public enum LogEvent : ushort { - /// - /// Indicates a verbose log message. - /// - Verbose, - - /// - /// Indicates a normal, non-verbose log message. - /// - Normal, - - /// - /// Indicates a warning message. - /// - Warning, - - /// - /// Indicates an error message. - /// - Error + Default = 0, + IoFileSystem = 1, + OsSubSystem = 2, } /// - /// Provides a simple logging interface. May be replaced with a - /// more robust solution at a later date. + /// Provides a simple logging interface built on top of .Net tracing frameworks /// public static class Logger { - private static LogWriter logWriter; + internal const SourceLevels defaultTracingLevel = SourceLevels.Critical; + internal const string defaultTraceSource = "sqltools"; + private static SourceLevels tracingLevel = defaultTracingLevel; + private static string logFileFullPath; - private static bool isEnabled; + internal static TraceSource TraceSource { get; set; } + internal static string LogFileFullPath + { + get => logFileFullPath; + private set + { + //If the log file path has a directory component then ensure that the directory exists. + if (!string.IsNullOrEmpty(Path.GetDirectoryName(value)) && !Directory.Exists(Path.GetDirectoryName(value))) + { + Directory.CreateDirectory(Path.GetDirectoryName(value)); + } - private static bool isInitialized = false; + logFileFullPath = value; + ConfigureListener(); + } + } + + private static SqlToolsTraceListener Listener { get; set; } + + private static void ConfigureLogFile(string logFilePrefix) => LogFileFullPath = GenerateLogFilePath(logFilePrefix); /// - /// Initializes the Logger for the current session. + /// Calling this method will turn on inclusion CallStack in the log for all future traces /// - /// - /// Optional. Specifies the path at which log messages will be written. - /// - /// + public static void StartCallStack() => Listener.TraceOutputOptions |= TraceOptions.Callstack; + + /// + /// Calling this method will turn off inclusion of CallStack in the log for all future traces + /// + public static void StopCallStack() => Listener.TraceOutputOptions &= ~TraceOptions.Callstack; + + /// + /// Calls flush on defaultTracingLevel configured listeners. + /// + public static void Flush() + { + TraceSource.Flush(); + Trace.Flush(); + } + + public static void Close() + { + Flush(); + TraceSource.Close(); + Trace.Close(); + Listener = null; // Since we have closed the listener, set listener to null. + } + public static SourceLevels TracingLevel + { + get => tracingLevel; + set + { + // configures the source level filter. This alone is not enough for tracing that is done via "Trace" object instead of "TraceSource" object + TraceSource.Switch = new SourceSwitch(TraceSource.Name, value.ToString()); + // configure the listener level filter + tracingLevel = value; + Listener.Filter = new EventTypeFilter(tracingLevel); + } + } + + /// + /// Initializes the Logger for the current process. + /// + /// /// Optional. Specifies the minimum log message level to write to the log file. /// + /// + /// Optional. Specifies the log name prefix for the log file name at which log messages will be written. + /// + /// Optional. Specifies the tracesource name. + /// public static void Initialize( - string logFilePath = "sqltools", - LogLevel minimumLogLevel = LogLevel.Normal, - bool isEnabled = true) + SourceLevels tracingLevel = defaultTracingLevel, + string logFilePath = null, + string traceSource = defaultTraceSource) { - Logger.isEnabled = isEnabled; - - // return if the logger is not enabled or already initialized - if (!Logger.isEnabled || Logger.isInitialized) + Logger.tracingLevel = tracingLevel; + TraceSource = new TraceSource(traceSource, Logger.tracingLevel); + if (string.IsNullOrWhiteSpace(logFilePath)) { - return; + logFilePath = GenerateLogFilePath(traceSource); } - Logger.isInitialized = true; + LogFileFullPath = logFilePath; + Write(TraceEventType.Information, $"Initialized the {traceSource} logger"); + } + /// + /// Initializes the Logger for the current process. + /// + /// + /// + /// Optional. Specifies the minimum log message level to write to the log file. + /// + /// + /// Optional. Specifies the log name prefix for the log file name at which log messages will be written. + /// + /// Optional. Specifies the tracesource name. + /// + public static void Initialize(string tracingLevel, string logFilePath = null, string traceSource = defaultTraceSource) + { + Initialize(Enum.TryParse(tracingLevel, out SourceLevels sourceTracingLevel) + ? sourceTracingLevel + : defaultTracingLevel + , logFilePath + , traceSource); + } + + /// + /// Configures the LogfilePath for the tracelistener in use for this process. + /// + /// + /// Returns the log file path corresponding to logfilePrefix + /// + public static string GenerateLogFilePath(string logFilePrefix = defaultTraceSource) + { + if (string.IsNullOrWhiteSpace(logFilePrefix)) + { + throw new ArgumentOutOfRangeException(nameof(logFilePrefix), $"LogfilePath cannot be configured if argument {nameof(logFilePrefix)} has not been set"); + } // Create the log directory - string logDir = Path.GetDirectoryName(logFilePath); + string logDir = Path.GetDirectoryName(logFilePrefix); if (!string.IsNullOrWhiteSpace(logDir)) { if (!Directory.Exists(logDir)) @@ -83,207 +164,280 @@ namespace Microsoft.SqlTools.Utility { Directory.CreateDirectory(logDir); } - catch (Exception) + catch (Exception ex) { - // Creating the log directory is a best effort operation, so ignore any failures. + Write(TraceEventType.Error, LogEvent.IoFileSystem, $"Unable to create directory:{logDir}\nException encountered:{ex}"); } } } - // get a unique number to prevent conflicts of two process launching at the same time int uniqueId; try { uniqueId = Process.GetCurrentProcess().Id; } - catch (Exception) + catch (Exception ex) { + Write(TraceEventType.Information, LogEvent.OsSubSystem, $"Unable to get process id of current running process\nException encountered:{ex}"); // if the pid look up fails for any reason, just use a random number - uniqueId = new Random().Next(1000, 9999); + uniqueId = new Random().Next(1000, 9999); } // make the log path unique - string fullFileName = string.Format( - "{0}_{1,4:D4}{2,2:D2}{3,2:D2}{4,2:D2}{5,2:D2}{6,2:D2}{7}.log", - logFilePath, - DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, - DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, - uniqueId); - - if (logWriter != null) - { - logWriter.Dispose(); - } - - // TODO: Parameterize this - logWriter = - new LogWriter( - minimumLogLevel, - fullFileName, - true); - - Logger.Write(LogLevel.Normal, "Initializing SQL Tools Service Host logger"); + return $"{logFilePrefix}_{DateTime.Now.Year,4:D4}{DateTime.Now.Month,2:D2}{DateTime.Now.Day,2:D2}{DateTime.Now.Hour,2:D2}{DateTime.Now.Minute,2:D2}{DateTime.Now.Second,2:D2}{uniqueId}.log"; } - /// - /// Closes the Logger. - /// - public static void Close() + private static void ConfigureListener() { - if (logWriter != null) + if (string.IsNullOrWhiteSpace(LogFileFullPath)) { - logWriter.Dispose(); + throw new InvalidOperationException("Listeners cannot be configured if LogFileFullPath has not been set"); } + Listener = new SqlToolsTraceListener(LogFileFullPath) + { + TraceOutputOptions = TraceOptions.DateTime | TraceOptions.ProcessId | TraceOptions.ThreadId, + Filter = new EventTypeFilter(TracingLevel), + }; + TraceSource.Listeners.Clear(); + TraceSource.Listeners.Add(Listener); + Trace.Listeners.Clear(); + Trace.Listeners.Add(Listener); } /// /// Writes a message to the log file. /// - /// The level at which the message will be written. + /// The level at which the message will be written. + /// The message text to be written. + public static void Write(TraceEventType eventType, string logMessage) => Write(eventType, LogEvent.Default, logMessage); + + /// + /// Writes a message to the log file with accompanying callstack. + /// + /// The level at which the message will be written. + /// The message text to be written. + /// + /// The callstack logging gets turned on globally and any other log writes that happens in the time window + /// while this log write is happening will also get callstack information logged. This is not considered + /// and trying to isolate the callstack logging to be turned of for just one call is unnecessarily complex. + /// + public static void WriteWithCallstack(TraceEventType eventType, string logMessage) => WriteWithCallstack(eventType, LogEvent.Default, logMessage); + + /// + /// Writes a message to the log file with accompanying callstack. + /// + /// The level at which the message will be written. + /// The event id enumeration for the log event. + /// The message text to be written. + /// + /// The callstack logging gets turned on globally and any other log writes that happens in the time window + /// while this log write is happening will also get callstack information logged. This is not considered + /// and trying to isolate the callstack logging to be turned of for just one call is unnecessarily complex. + /// + public static void WriteWithCallstack(TraceEventType eventType, LogEvent logEvent, string logMessage) + { + Logger.StartCallStack(); + Write(eventType, logEvent, logMessage); + Logger.StopCallStack(); + } + + /// + /// Writes a message to the log file. + /// + /// The level at which the message will be written. + /// The event id enumeration for the log event. /// The message text to be written. - /// The name of the calling method. - /// The source file path where the calling method exists. - /// The line number of the calling method. public static void Write( - LogLevel logLevel, - string logMessage, - [CallerMemberName] string callerName = null, - [CallerFilePath] string callerSourceFile = null, - [CallerLineNumber] int callerLineNumber = 0) - { - // return if the logger is not enabled or not initialized - if (!Logger.isEnabled || !Logger.isInitialized) + TraceEventType eventType, + LogEvent logEvent, + string logMessage) + { + // If logger is initialized then use TraceSource else use Trace + if (TraceSource != null) + { + TraceSource.TraceEvent(eventType, (ushort)logEvent, logMessage); + } + else + { + switch (eventType) + { + case TraceEventType.Critical: + case TraceEventType.Error: + if (eventType == TraceEventType.Critical) + { + logMessage = $@"event={eventType}: {logMessage}"; + } + + Trace.TraceError(logMessage); + break; + case TraceEventType.Warning: + Trace.TraceWarning(logMessage); + break; + case TraceEventType.Information: + case TraceEventType.Resume: + case TraceEventType.Start: + case TraceEventType.Stop: + case TraceEventType.Suspend: + case TraceEventType.Transfer: + case TraceEventType.Verbose: + if (eventType != TraceEventType.Information) + { + logMessage = $@"event={eventType}: {logMessage}"; + } + + Trace.TraceInformation(logMessage); + break; + } + } + } + } + + /// + /// This listener has the same behavior as TextWriterTraceListener except it controls how the + /// options: TraceOptions.DateTime, TraceOptions.ProcessId and TraceOptions.ThreadId is written to the output stream. + /// This listener writes the above options, if turned on, inline with the message + /// instead of writing them to indented fields as is the case with TextWriterTraceListener. + /// This implementation also lazily initializes the underlying tracelistener + /// + /// + /// Implementation of this is a lazily initialize trace listener that is partly inspired + /// by: https://stackoverflow.com/questions/30664527/how-to-stop-streamwriter-to-not-to-create-file-if-nothing-to-write + /// + internal sealed class SqlToolsTraceListener : TraceListener + { + Lazy _lazyListener; + private TextWriterTraceListener Listener => _lazyListener.Value; + private bool IsListenerCreated => _lazyListener.IsValueCreated; + public SqlToolsTraceListener(string file, string listenerName = "") : base(listenerName) + { + // Wrapping around lazy to make sure that we do not create file if the log.Write events are getting filtered out. i.e. the log file actually gets created the first time an actual write to log file happens. + _lazyListener = new Lazy( + valueFactory: () => new TextWriterTraceListener(new StreamWriter(file, append: true), listenerName), + // LazyThreadSafetyMode.PublicationOnly mode ensures that we keep trying to create the listener (especially the file that write) on all future log.write events even if previous attempt(s) have failed + mode: LazyThreadSafetyMode.PublicationOnly + ); + } + #region forward actual write/close/flush/dispose calls to the underlying listener. + public override void Write(string message) => Listener.Write(message); + + public override void WriteLine(string message) => Listener.WriteLine(message); + + /// + /// Closes the so that it no longer + /// receives tracing or debugging output. + /// Make sure that we do not Close if the lazy listener never got created. + /// + public override void Close() + { + if (IsListenerCreated) + { + Listener.Close(); + } + } + + /// + /// Releases all resources used by the + /// No unmanaged resources in this class, and it is sealed. + /// No finalizer needed. See http://stackoverflow.com/a/3882819/613130 + /// We skip disposing if the lazy listener never got created. + /// + public new void Dispose() + { + if (IsListenerCreated) + { + Listener.Dispose(); + } + } + + /// + /// Flushes the output buffer for the . + /// Make sure that we do not Flush if the lazy listener never got created. + /// + public override void Flush() + { + if (IsListenerCreated) + { + Listener.Flush(); + } + } + #endregion + + public override void TraceEvent(TraceEventCache eventCache, String source, TraceEventType eventType, int id) + { + TraceEvent(eventCache, source, eventType, id, String.Empty); + } + + // All other TraceEvent methods come through this one. + public override void TraceEvent(TraceEventCache eventCache, String source, TraceEventType eventType, int id, string message) + { + if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, message, null, null, null)) { return; } - if (logWriter != null) - { - logWriter.Write( - logLevel, - logMessage, - callerName, - callerSourceFile, - callerLineNumber); - } + WriteHeader(eventCache, source, eventType, id); + WriteLine(message); + WriteFooter(eventCache); } - } - internal class LogWriter : IDisposable - { - private object logLock = new object(); - private TextWriter textWriter; - private LogLevel minimumLogLevel = LogLevel.Verbose; - - public LogWriter(LogLevel minimumLogLevel, string logFilePath, bool deleteExisting) + public override void TraceEvent(TraceEventCache eventCache, String source, TraceEventType eventType, int id, string format, params object[] args) { - this.minimumLogLevel = minimumLogLevel; + if (Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, format, args, null, null)) + { + return; + } - // Ensure that we have a usable log file path - if (!Path.IsPathRooted(logFilePath)) - { - logFilePath = - Path.Combine( - AppContext.BaseDirectory, - logFilePath); - } - - - if (!this.TryOpenLogFile(logFilePath, deleteExisting)) - { - // If the log file couldn't be opened at this location, - // try opening it in a more reliable path - this.TryOpenLogFile( - Path.Combine( - Environment.GetEnvironmentVariable("TEMP"), - Path.GetFileName(logFilePath)), - deleteExisting); - } + WriteHeader(eventCache, source, eventType, id); + if (args != null) + { + WriteLine(String.Format(CultureInfo.InvariantCulture, format, args)); + } + else + { + WriteLine(format); + } + WriteFooter(eventCache); } - public void Write( - LogLevel logLevel, - string logMessage, - string callerName = null, - string callerSourceFile = null, - int callerLineNumber = 0) + private void WriteHeader(TraceEventCache eventCache, String source, TraceEventType eventType, int id) + => Write(FormatHeader(eventCache, String.Format(CultureInfo.InvariantCulture, "{0} {1}: {2} : ", source, eventType.ToString(), id.ToString(CultureInfo.InvariantCulture)))); + + private void WriteFooter(TraceEventCache eventCache) { - if (this.textWriter != null && - logLevel >= this.minimumLogLevel) + if (eventCache == null) { - // System.IO is not thread safe - lock (this.logLock) - { - // Print the timestamp and log level - this.textWriter.WriteLine( - "{0} [{1}] - Method \"{2}\" at line {3} of {4}\r\n", - DateTime.Now, - logLevel.ToString().ToUpper(), - callerName, - callerLineNumber, - callerSourceFile); - - // Print out indented message lines - foreach (var messageLine in logMessage.Split('\n')) - { - this.textWriter.WriteLine(" " + messageLine.TrimEnd()); - } - - // Finish with a newline and flush the writer - this.textWriter.WriteLine(); - this.textWriter.Flush(); - } + return; } + + IndentLevel++; + if (TraceOutputOptions.HasFlag(TraceOptions.LogicalOperationStack)) + { + WriteLine("LogicalOperationStack=" + eventCache.LogicalOperationStack); + } + + if (TraceOutputOptions.HasFlag(TraceOptions.Callstack)) + { + WriteLine("Callstack=" + eventCache.Callstack); + } + + IndentLevel--; } - public void Dispose() + private string FormatHeader(TraceEventCache eventCache, string message) { - if (this.textWriter != null) + if (eventCache == null) { - this.textWriter.Flush(); - this.textWriter.Dispose(); - this.textWriter = null; + return message; } + + return $"{(IsEnabled(TraceOptions.DateTime) ? string.Format(CultureInfo.InvariantCulture, "{0} ", eventCache.DateTime.ToLocalTime().ToString("u", CultureInfo.InvariantCulture)) : string.Empty)}" + + $"{(IsEnabled(TraceOptions.ProcessId) ? string.Format(CultureInfo.InvariantCulture, "pid:{0} ", eventCache.ProcessId.ToString(CultureInfo.InvariantCulture)) : string.Empty)}" + + $"{(IsEnabled(TraceOptions.ThreadId) ? string.Format(CultureInfo.InvariantCulture, "tid:{0} ", eventCache.ThreadId.ToString(CultureInfo.InvariantCulture)) : string.Empty)}" + + message; } - private bool TryOpenLogFile( - string logFilePath, - bool deleteExisting) - { - try - { - // Make sure the log directory exists - Directory.CreateDirectory( - Path.GetDirectoryName( - logFilePath)); + private bool IsEnabled(TraceOptions opt) => TraceOutputOptions.HasFlag(opt); - // Open the log file for writing with UTF8 encoding - this.textWriter = - new StreamWriter( - new FileStream( - logFilePath, - deleteExisting ? - FileMode.Create : - FileMode.Append), - Encoding.UTF8); - - return true; - } - catch (Exception e) - { - if (e is UnauthorizedAccessException || - e is IOException) - { - // This exception is thrown when we can't open the file - // at the path in logFilePath. Return false to indicate - // that the log file couldn't be created. - return false; - } - - // Unexpected exception, rethrow it - throw; - } - } } } diff --git a/src/Microsoft.SqlTools.Hosting/Utility/UtilityServiceHost.cs b/src/Microsoft.SqlTools.Hosting/Utility/UtilityServiceHost.cs index e9e3a482..176d1c2d 100644 --- a/src/Microsoft.SqlTools.Hosting/Utility/UtilityServiceHost.cs +++ b/src/Microsoft.SqlTools.Hosting/Utility/UtilityServiceHost.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Reflection; using System.Threading.Tasks; @@ -120,7 +121,7 @@ namespace Microsoft.SqlTools.Utility /// private async Task HandleShutdownRequest(object shutdownParams, RequestContext requestContext) { - Logger.Write(LogLevel.Normal, "Service host is shutting down..."); + Logger.Write(TraceEventType.Information, "Service host is shutting down..."); // Call all the shutdown methods provided by the service components Task[] shutdownTasks = shutdownCallbacks.Select(t => t(shutdownParams, requestContext)).ToArray(); diff --git a/src/Microsoft.SqlTools.ResourceProvider.Core/AuthenticationService.cs b/src/Microsoft.SqlTools.ResourceProvider.Core/AuthenticationService.cs index 9ed88d42..5d6e1c31 100644 --- a/src/Microsoft.SqlTools.ResourceProvider.Core/AuthenticationService.cs +++ b/src/Microsoft.SqlTools.ResourceProvider.Core/AuthenticationService.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Composition; +using System.Diagnostics; using System.Threading.Tasks; using Microsoft.SqlTools.Extensibility; using Microsoft.SqlTools.Hosting; @@ -32,7 +33,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core public override void InitializeService(IProtocolEndpoint serviceHost) { - Logger.Write(LogLevel.Verbose, "AuthenticationService initialized"); + Logger.Write(TraceEventType.Verbose, "AuthenticationService initialized"); } public async Task SetCurrentAccountAsync(Account account, Dictionary securityTokenMappings) diff --git a/src/Microsoft.SqlTools.ResourceProvider.Core/ResourceProviderService.cs b/src/Microsoft.SqlTools.ResourceProvider.Core/ResourceProviderService.cs index f013faad..f4d0cb5a 100644 --- a/src/Microsoft.SqlTools.ResourceProvider.Core/ResourceProviderService.cs +++ b/src/Microsoft.SqlTools.ResourceProvider.Core/ResourceProviderService.cs @@ -5,6 +5,7 @@ using System; using System.Composition; +using System.Diagnostics; using System.Threading.Tasks; using Microsoft.SqlTools.Extensibility; using Microsoft.SqlTools.Hosting; @@ -32,7 +33,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core public override void InitializeService(IProtocolEndpoint serviceHost) { - Logger.Write(LogLevel.Verbose, "ResourceProvider initialized"); + Logger.Write(TraceEventType.Verbose, "ResourceProvider initialized"); serviceHost.SetRequestHandler(CreateFirewallRuleRequest.Type, HandleCreateFirewallRuleRequest); serviceHost.SetRequestHandler(CanHandleFirewallRuleRequest.Type, ProcessHandleFirewallRuleRequest); @@ -112,7 +113,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core private async Task HandleRequest(Func> handler, Func expiredTokenHandler, RequestContext requestContext, string requestType) { - Logger.Write(LogLevel.Verbose, requestType); + Logger.Write(TraceEventType.Verbose, requestType); try { diff --git a/src/Microsoft.SqlTools.ResourceProvider.DefaultImpl/AzureResourceManager.cs b/src/Microsoft.SqlTools.ResourceProvider.DefaultImpl/AzureResourceManager.cs index 2948381d..824de076 100644 --- a/src/Microsoft.SqlTools.ResourceProvider.DefaultImpl/AzureResourceManager.cs +++ b/src/Microsoft.SqlTools.ResourceProvider.DefaultImpl/AzureResourceManager.cs @@ -68,7 +68,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl } catch (Exception ex) { - Logger.Write(LogLevel.Error, string.Format(CultureInfo.CurrentCulture, "Failed to get databases {0}", ex)); + Logger.Write(TraceEventType.Error, string.Format(CultureInfo.CurrentCulture, "Failed to get databases {0}", ex)); throw; } } @@ -100,7 +100,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl } catch (Exception ex) { - Logger.Write(LogLevel.Error, string.Format(CultureInfo.CurrentCulture, "Failed to get databases {0}", ex.Message)); + Logger.Write(TraceEventType.Error, string.Format(CultureInfo.CurrentCulture, "Failed to get databases {0}", ex.Message)); throw; } diff --git a/src/Microsoft.SqlTools.ResourceProvider/Program.cs b/src/Microsoft.SqlTools.ResourceProvider/Program.cs index bc0c212d..cde1d33f 100644 --- a/src/Microsoft.SqlTools.ResourceProvider/Program.cs +++ b/src/Microsoft.SqlTools.ResourceProvider/Program.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Diagnostics; using System.IO; using Microsoft.SqlTools.Hosting.Utility; using Microsoft.SqlTools.ServiceLayer.SqlContext; @@ -31,16 +32,20 @@ namespace Microsoft.SqlTools.ResourceProvider return; } - string logFilePath = "SqlToolsResourceProviderService"; + string logFilePath = commandOptions.LogFilePath; + if (string.IsNullOrWhiteSpace(logFilePath)) + { + logFilePath = "SqlToolsResourceProviderService"; + } if (!string.IsNullOrWhiteSpace(commandOptions.LoggingDirectory)) { logFilePath = Path.Combine(commandOptions.LoggingDirectory, logFilePath); } // turn on Verbose logging during early development - // we need to switch to Normal when preparing for public preview - Logger.Initialize(logFilePath: logFilePath, minimumLogLevel: LogLevel.Verbose, isEnabled: commandOptions.EnableLogging); - Logger.Write(LogLevel.Normal, "Starting SqlTools Resource Provider"); + // we need to switch to Information when preparing for public preview + Logger.Initialize(tracingLevel: commandOptions.TracingLevel, logFilePath: logFilePath, traceSource: "resourceprovider"); + Logger.Write(TraceEventType.Information, "Starting SqlTools Resource Provider"); // set up the host details and profile paths var hostDetails = new HostDetails( @@ -55,7 +60,7 @@ namespace Microsoft.SqlTools.ResourceProvider } catch (Exception e) { - Logger.Write(LogLevel.Error, string.Format("An unhandled exception occurred: {0}", e)); + Logger.WriteWithCallstack(TraceEventType.Critical, $"An unhandled exception occurred: {e}"); Environment.Exit(1); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Admin/Database/DatabaseTaskHelper.cs b/src/Microsoft.SqlTools.ServiceLayer/Admin/Database/DatabaseTaskHelper.cs index 709249a8..6f14ec98 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Admin/Database/DatabaseTaskHelper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Admin/Database/DatabaseTaskHelper.cs @@ -11,6 +11,7 @@ using Microsoft.SqlTools.Utility; using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using System.Xml; @@ -221,7 +222,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin } catch(Exception ex) { - Logger.Write(LogLevel.Warning, $"Failed to disconnect Database task Helper connection. Error: {ex.Message}"); + Logger.Write(TraceEventType.Warning, $"Failed to disconnect Database task Helper connection. Error: {ex.Message}"); } } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/BatchParser/BatchParserWrapper.cs b/src/Microsoft.SqlTools.ServiceLayer/BatchParser/BatchParserWrapper.cs index 3564930b..48fd228d 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/BatchParser/BatchParserWrapper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/BatchParser/BatchParserWrapper.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.IO; using Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode; using System.Globalization; +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer.BatchParser { @@ -347,7 +348,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser if (args != null) { - Logger.Write(LogLevel.Verbose, SR.BatchParserWrapperExecutionError); + Logger.Write(TraceEventType.Verbose, SR.BatchParserWrapperExecutionError); throw new Exception(string.Format(CultureInfo.CurrentCulture, SR.BatchParserWrapperExecutionEngineError, args.Message + Environment.NewLine + '\t' + args.Description)); @@ -389,7 +390,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser catch (Exception e) { // adding this for debugging - Logger.Write(LogLevel.Warning, "Exception Caught in BatchParserWrapper.OnBatchParserExecutionFinished(...)" + e.ToString()); + Logger.Write(TraceEventType.Warning, "Exception Caught in BatchParserWrapper.OnBatchParserExecutionFinished(...)" + e.ToString()); throw; } } @@ -408,7 +409,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser if (args != null) { - Logger.Write(LogLevel.Normal, SR.BatchParserWrapperExecutionEngineError); + Logger.Write(TraceEventType.Information, SR.BatchParserWrapperExecutionEngineError); throw new Exception(SR.BatchParserWrapperExecutionEngineError); } @@ -419,7 +420,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser #if DEBUG if (args != null) { - Logger.Write(LogLevel.Normal, SR.BatchParserWrapperExecutionEngineBatchMessage); + Logger.Write(TraceEventType.Information, SR.BatchParserWrapperExecutionEngineBatchMessage); } #endif } @@ -429,7 +430,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser #if DEBUG if (args != null && args.DataReader != null) { - Logger.Write(LogLevel.Normal, SR.BatchParserWrapperExecutionEngineBatchResultSetProcessing); + Logger.Write(TraceEventType.Information, SR.BatchParserWrapperExecutionEngineBatchResultSetProcessing); } #endif } @@ -437,13 +438,13 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser public void OnBatchResultSetFinished(object sender, EventArgs args) { #if DEBUG - Logger.Write(LogLevel.Normal, SR.BatchParserWrapperExecutionEngineBatchResultSetFinished); + Logger.Write(TraceEventType.Information, SR.BatchParserWrapperExecutionEngineBatchResultSetFinished); #endif } public void OnBatchCancelling(object sender, EventArgs args) { - Logger.Write(LogLevel.Normal, SR.BatchParserWrapperExecutionEngineBatchCancelling); + Logger.Write(TraceEventType.Information, SR.BatchParserWrapperExecutionEngineBatchCancelling); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/BatchParser/ExecutionEngineCode/Batch.cs b/src/Microsoft.SqlTools.ServiceLayer/BatchParser/ExecutionEngineCode/Batch.cs index 87eda717..9e4e5532 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/BatchParser/ExecutionEngineCode/Batch.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/BatchParser/ExecutionEngineCode/Batch.cs @@ -723,7 +723,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode if (messageHandler == null) { - Logger.Write(LogLevel.Error, "Expected handler to be declared"); + Logger.Write(TraceEventType.Error, "Expected handler to be declared"); } if (null != connectionWrapper) @@ -736,7 +736,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode if (statementCompletedHandler == null) { - Logger.Write(LogLevel.Error, "Expect handler to be declared if we have a command wrapper"); + Logger.Write(TraceEventType.Error, "Expect handler to be declared if we have a command wrapper"); } commandWrapper.StatementCompleted -= statementCompletedHandler; } diff --git a/src/Microsoft.SqlTools.ServiceLayer/BatchParser/ExecutionEngineCode/ExecutionEngine.cs b/src/Microsoft.SqlTools.ServiceLayer/BatchParser/ExecutionEngineCode/ExecutionEngine.cs index 933a23a2..8aaefdfb 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/BatchParser/ExecutionEngineCode/ExecutionEngine.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/BatchParser/ExecutionEngineCode/ExecutionEngine.cs @@ -132,7 +132,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode catch (Exception ex) { // if anything goes wrong it will shutdown VS - Logger.Write(LogLevel.Error, "Exception Caught in ExecutionEngine.DoBatchExecution(Batch) :" + ex.ToString()); + Logger.Write(TraceEventType.Error, "Exception Caught in ExecutionEngine.DoBatchExecution(Batch) :" + ex.ToString()); result = ScriptExecutionResult.Failure; } } @@ -494,7 +494,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode } catch (Exception ex) { - Logger.Write(LogLevel.Warning, "Exception Caught in ExecutionEngine.DoScriptExecution(bool): " + ex.ToString()); + Logger.Write(TraceEventType.Warning, "Exception Caught in ExecutionEngine.DoScriptExecution(bool): " + ex.ToString()); throw; } } @@ -924,7 +924,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode } catch (SqlException ex) { - Logger.Write(LogLevel.Warning, "Exception Caught in ExecutionEngine.ConnectSqlCmdInternal(SqlConnectionStringBuilder): " + ex.ToString()); + Logger.Write(TraceEventType.Warning, "Exception Caught in ExecutionEngine.ConnectSqlCmdInternal(SqlConnectionStringBuilder): " + ex.ToString()); throw; } @@ -960,7 +960,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode } catch (SqlException ex) { - Logger.Write(LogLevel.Warning, "Exception Caught in ExecutionEngine.CloseConnection(SqlConnection): " + ex.ToString()); + Logger.Write(TraceEventType.Warning, "Exception Caught in ExecutionEngine.CloseConnection(SqlConnection): " + ex.ToString()); } } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs index 735eed29..215b83b4 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs @@ -21,6 +21,7 @@ using Microsoft.SqlTools.ServiceLayer.LanguageServices; using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts; using Microsoft.SqlTools.ServiceLayer.Utility; using Microsoft.SqlTools.Utility; +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer.Connection { @@ -333,7 +334,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection } catch (Exception ex) { - Logger.Write(LogLevel.Normal, "Failed to close temporary connections. error: " + ex.Message); + Logger.Write(TraceEventType.Information, "Failed to close temporary connections. error: " + ex.Message); } } @@ -982,7 +983,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection ConnectParams connectParams, RequestContext requestContext) { - Logger.Write(LogLevel.Verbose, "HandleConnectRequest"); + Logger.Write(TraceEventType.Verbose, "HandleConnectRequest"); try { @@ -1032,7 +1033,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection CancelConnectParams cancelParams, RequestContext requestContext) { - Logger.Write(LogLevel.Verbose, "HandleCancelConnectRequest"); + Logger.Write(TraceEventType.Verbose, "HandleCancelConnectRequest"); try { @@ -1052,7 +1053,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection DisconnectParams disconnectParams, RequestContext requestContext) { - Logger.Write(LogLevel.Verbose, "HandleDisconnectRequest"); + Logger.Write(TraceEventType.Verbose, "HandleDisconnectRequest"); try { @@ -1073,7 +1074,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection ListDatabasesParams listDatabasesParams, RequestContext requestContext) { - Logger.Write(LogLevel.Verbose, "ListDatabasesRequest"); + Logger.Write(TraceEventType.Verbose, "ListDatabasesRequest"); try { @@ -1409,7 +1410,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection catch (Exception e) { Logger.Write( - LogLevel.Error, + TraceEventType.Error, string.Format( "Exception caught while trying to change database context to [{0}] for OwnerUri [{1}]. Exception:{2}", newDatabaseName, @@ -1477,7 +1478,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection } catch (Exception ex) { - Logger.Write(LogLevel.Verbose, "Could not send Connection telemetry event " + ex.ToString()); + Logger.Write(TraceEventType.Verbose, "Could not send Connection telemetry event " + ex.ToString()); } } } @@ -1522,7 +1523,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection string error = string.Format(CultureInfo.InvariantCulture, "Failed opening a SqlConnection: error:{0} inner:{1} stacktrace:{2}", ex.Message, ex.InnerException != null ? ex.InnerException.Message : string.Empty, ex.StackTrace); - Logger.Write(LogLevel.Error, error); + Logger.Write(TraceEventType.Error, error); } return null; diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/AmbientSettings.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/AmbientSettings.cs index 3de3b634..46f621c2 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/AmbientSettings.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/AmbientSettings.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Reflection; using Microsoft.SqlTools.Utility; @@ -350,13 +351,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection public void TraceSettings() { // NOTE: logging as warning so we can get this data in the IEService DacFx logs - Logger.Write(LogLevel.Warning, Resources.LoggingAmbientSettings); + Logger.Write(TraceEventType.Warning, Resources.LoggingAmbientSettings); foreach (KeyValuePair setting in _configuration) { // Log Ambient Settings Logger.Write( - LogLevel.Warning, + TraceEventType.Warning, string.Format( Resources.AmbientSettingFormat, setting.Key, @@ -406,7 +407,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection } else { - Logger.Write(LogLevel.Error, string.Format(Resources.UnableToAssignValue, value.GetType().FullName, _type.FullName)); + Logger.Write(TraceEventType.Error, string.Format(Resources.UnableToAssignValue, value.GetType().FullName, _type.FullName)); } } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/CachedServerInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/CachedServerInfo.cs index 7ab2bd2b..a1548b6a 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/CachedServerInfo.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/CachedServerInfo.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Concurrent; using System.Data; using System.Data.SqlClient; +using System.Diagnostics; using System.Linq; using Microsoft.SqlTools.Utility; @@ -270,7 +271,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection } catch { - Logger.Write(LogLevel.Error, String.Format(Resources.FailedToParseConnectionString, connection.ConnectionString)); + Logger.Write(TraceEventType.Error, String.Format(Resources.FailedToParseConnectionString, connection.ConnectionString)); return null; } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs index b7d4620d..297cf28c 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs @@ -429,7 +429,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection Validate.IsNotNull(nameof(connection), connection); if (!(connection.State == ConnectionState.Open)) { - Logger.Write(LogLevel.Warning, Resources.ConnectionPassedToIsCloudShouldBeOpen); + Logger.Write(TraceEventType.Warning, Resources.ConnectionPassedToIsCloudShouldBeOpen); } Func executeCommand = commandText => @@ -540,7 +540,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection return true; } - Logger.Write(LogLevel.Error, ex.ToString()); + Logger.Write(TraceEventType.Error, ex.ToString()); return false; } @@ -612,14 +612,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection if (!string.IsNullOrWhiteSpace(filePath)) { // Remove filename from the filePath - Uri pathUri; if (!Uri.IsWellFormedUriString(filePath, UriKind.Absolute)) { // In linux "file://" is required otehrwise the Uri cannot parse the path //this should be fixed in dotenet core 2.0 filePath = $"file://{filePath}"; } - if (!Uri.TryCreate(filePath, UriKind.Absolute, out pathUri)) + if (!Uri.TryCreate(filePath, UriKind.Absolute, out Uri pathUri)) { // Invalid Uri return null; @@ -668,7 +667,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection }, (ex) => { - Logger.Write(LogLevel.Error, ex.ToString()); + Logger.Write(TraceEventType.Error, ex.ToString()); return StandardExceptionHandler(ex); // handled }, useRetry: true); @@ -701,8 +700,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection public static bool TryGetServerVersion(string connectionString, out ServerInfo serverInfo) { serverInfo = null; - SqlConnectionStringBuilder builder; - if (!TryGetConnectionStringBuilder(connectionString, out builder)) + if (!TryGetConnectionStringBuilder(connectionString, out SqlConnectionStringBuilder builder)) { return false; } @@ -739,7 +737,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection Validate.IsNotNull(nameof(connection), connection); if (!(connection.State == ConnectionState.Open)) { - Logger.Write(LogLevel.Error, "connection passed to GetServerVersion should be open."); + Logger.Write(TraceEventType.Error, "connection passed to GetServerVersion should be open."); } Func getServerInfo = commandText => @@ -788,8 +786,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { //we don't want to fail the normal flow if any unexpected thing happens //during caching although it's unlikely. So we just log the exception and ignore it - Logger.Write(LogLevel.Error, Resources.FailedToCacheIsCloud); - Logger.Write(LogLevel.Error, ex.ToString()); + Logger.Write(TraceEventType.Error, Resources.FailedToCacheIsCloud); + Logger.Write(TraceEventType.Error, ex.ToString()); } }); @@ -892,7 +890,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection if (handledEx != null) { - Logger.Write(LogLevel.Error, String.Format(Resources.ErrorParsingConnectionString, handledEx)); + Logger.Write(TraceEventType.Error, String.Format(Resources.ErrorParsingConnectionString, handledEx)); return false; } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs index 058c0c92..f498338e 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlConnection.cs @@ -360,18 +360,18 @@ SET NUMERIC_ROUNDABORT OFF;"; } /// - /// Adds an info message event listener. + /// Adds an info message event Listener. /// - /// An info message event listener. + /// An info message event Listener. public void AddInfoMessageHandler(SqlInfoMessageEventHandler handler) { _underlyingConnection.InfoMessage += handler; } /// - /// Removes an info message event listener. + /// Removes an info message event Listener. /// - /// An info message event listener. + /// An info message event Listener. public void RemoveInfoMessageHandler(SqlInfoMessageEventHandler handler) { _underlyingConnection.InfoMessage -= handler; @@ -436,7 +436,7 @@ SET NUMERIC_ROUNDABORT OFF;"; string sessionId = (string)command.ExecuteScalar(); if (!Guid.TryParse(sessionId, out _azureSessionId)) { - Logger.Write(LogLevel.Error, Resources.UnableToRetrieveAzureSessionId); + Logger.Write(TraceEventType.Error, Resources.UnableToRetrieveAzureSessionId); } } } @@ -444,7 +444,7 @@ SET NUMERIC_ROUNDABORT OFF;"; } catch (Exception exception) { - Logger.Write(LogLevel.Error, Resources.UnableToRetrieveAzureSessionId + exception.ToString()); + Logger.Write(TraceEventType.Error, Resources.UnableToRetrieveAzureSessionId + exception.ToString()); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs index 0efd9a04..b271ab9b 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.DataTransferDetectionErrorStrategy.cs @@ -4,6 +4,7 @@ // using System.Data.SqlClient; +using System.Diagnostics; using Microsoft.SqlTools.Utility; namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection @@ -30,7 +31,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection RetryPolicyUtils.AppendThrottlingDataIfIsThrottlingError(sqlException, err); if (RetryPolicyUtils.IsNonRetryableDataTransferError(err.Number)) { - Logger.Write(LogLevel.Error, string.Format(Resources.ExceptionCannotBeRetried, err.Number, err.Message)); + Logger.Write(TraceEventType.Error, string.Format(Resources.ExceptionCannotBeRetried, err.Number, err.Message)); return false; } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.cs index f8f4ed44..3f158602 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.cs @@ -244,7 +244,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection bool shouldRetry = canRetry && ShouldRetryImpl(retryState); - Logger.Write(LogLevel.Error, + Logger.Write(TraceEventType.Error, string.Format( CultureInfo.InvariantCulture, "Retry requested: Retry count = {0}. Delay = {1}, SQL Error Number = {2}, Can retry error = {3}, Will retry = {4}", @@ -267,7 +267,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { bool shouldIgnoreError = ErrorDetectionStrategy.ShouldIgnoreError(retryState.LastError); - Logger.Write(LogLevel.Error, + Logger.Write(TraceEventType.Error, string.Format( CultureInfo.InvariantCulture, "Ignore Error requested: Retry count = {0}. Delay = {1}, SQL Error Number = {2}, Should Ignore Error = {3}", diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyFactory.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyFactory.cs index bb75fbf5..99f505a9 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyFactory.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyFactory.cs @@ -392,7 +392,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection internal static void DataConnectionFailureRetry(RetryState retryState) { - Logger.Write(LogLevel.Normal, string.Format(CultureInfo.InvariantCulture, + Logger.Write(TraceEventType.Information, string.Format(CultureInfo.InvariantCulture, "Connection retry number {0}. Delaying {1} ms before retry. Exception: {2}", retryState.RetryCount, retryState.Delay.TotalMilliseconds.ToString(CultureInfo.InvariantCulture), @@ -403,7 +403,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection internal static void CommandFailureRetry(RetryState retryState, string commandKeyword) { - Logger.Write(LogLevel.Normal, string.Format( + Logger.Write(TraceEventType.Information, string.Format( CultureInfo.InvariantCulture, "{0} retry number {1}. Delaying {2} ms before retry. Exception: {3}", commandKeyword, @@ -416,7 +416,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection internal static void CommandFailureIgnore(RetryState retryState, string commandKeyword) { - Logger.Write(LogLevel.Normal, string.Format( + Logger.Write(TraceEventType.Information, string.Format( CultureInfo.InvariantCulture, "{0} retry number {1}. Ignoring failure. Exception: {2}", commandKeyword, diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyUtils.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyUtils.cs index a22549a7..c522a706 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyUtils.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicyUtils.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Data.SqlClient; +using System.Diagnostics; using System.Runtime.InteropServices; using Microsoft.SqlTools.Utility; @@ -344,7 +345,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection { if (azureSessionId != Guid.Empty) { - Logger.Write(LogLevel.Warning, string.Format( + Logger.Write(TraceEventType.Warning, string.Format( "Retry occurred: session: {0}; attempt - {1}; delay - {2}; exception - \"{3}\"", azureSessionId, retryState.RetryCount, diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/DisasterRecoveryService.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/DisasterRecoveryService.cs index 792b53df..6d01e4be 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/DisasterRecoveryService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/DisasterRecoveryService.cs @@ -4,6 +4,7 @@ // using System; using System.Data.SqlClient; +using System.Diagnostics; using System.Threading.Tasks; using Microsoft.SqlTools.Hosting.Protocol; using Microsoft.SqlTools.ServiceLayer.Admin; @@ -183,7 +184,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Failed to cancel restore session. error: " + ex.Message); + Logger.Write(TraceEventType.Error, "Failed to cancel restore session. error: " + ex.Message); await requestContext.SendResult(result); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseHelper.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseHelper.cs index d2f2d0d7..c99ac928 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseHelper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseHelper.cs @@ -15,6 +15,7 @@ using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts; using Microsoft.SqlTools.Utility; using System.Collections.Concurrent; using Microsoft.SqlTools.ServiceLayer.Utility; +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation { @@ -51,7 +52,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation } catch(Exception ex) { - Logger.Write(LogLevel.Warning, $"Failed to create restore config info. error: { ex.Message}"); + Logger.Write(TraceEventType.Warning, $"Failed to create restore config info. error: { ex.Message}"); response.ErrorMessage = ex.Message; } finally @@ -164,7 +165,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation response.ErrorMessage += Environment.NewLine; response.ErrorMessage += ex.InnerException.Message; } - Logger.Write(LogLevel.Normal, $"Failed to create restore plan. error: { response.ErrorMessage}"); + Logger.Write(TraceEventType.Information, $"Failed to create restore plan. error: { response.ErrorMessage}"); } return response; diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseTaskDataObject.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseTaskDataObject.cs index fea485b7..0816e05e 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseTaskDataObject.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreDatabaseTaskDataObject.cs @@ -15,6 +15,7 @@ using Microsoft.SqlTools.ServiceLayer.TaskServices; using Microsoft.SqlTools.ServiceLayer.Utility; using Microsoft.SqlTools.Utility; using Microsoft.SqlTools.ServiceLayer.Connection; +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation { @@ -316,7 +317,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation } catch(Exception ex) { - Logger.Write(LogLevel.Normal, $"Failed to execute restore task. error: {ex.Message}"); + Logger.Write(TraceEventType.Information, $"Failed to execute restore task. error: {ex.Message}"); throw ex; } finally @@ -903,7 +904,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation } catch(Exception ex ) { - Logger.Write(LogLevel.Normal, $"Failed to get restore db files. error: {ex.Message}"); + Logger.Write(TraceEventType.Information, $"Failed to get restore db files. error: {ex.Message}"); } return ret; } diff --git a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreOptionFactory.cs b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreOptionFactory.cs index 76c5ae61..508af7c3 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreOptionFactory.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DisasterRecovery/RestoreOperation/RestoreOptionFactory.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts; @@ -54,7 +55,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation } else { - Logger.Write(LogLevel.Warning, $"cannot find restore option builder for {optionKey}"); + Logger.Write(TraceEventType.Warning, $"cannot find restore option builder for {optionKey}"); return null; } } @@ -77,7 +78,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation } else { - Logger.Write(LogLevel.Warning, $"cannot find restore option builder for {optionKey}"); + Logger.Write(TraceEventType.Warning, $"cannot find restore option builder for {optionKey}"); } } @@ -115,7 +116,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation { var defaultValue = builder.DefaultValueFunction(restoreDataObject); builder.SetValueFunction(restoreDataObject, defaultValue); - Logger.Write(LogLevel.Warning, $"Failed tp set restore option {optionKey} error:{ex.Message}"); + Logger.Write(TraceEventType.Warning, $"Failed tp set restore option {optionKey} error:{ex.Message}"); } } @@ -128,13 +129,13 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation } catch (Exception) { - Logger.Write(LogLevel.Warning, $"Failed to set restore option {optionKey} to default value"); + Logger.Write(TraceEventType.Warning, $"Failed to set restore option {optionKey} to default value"); } } } else { - Logger.Write(LogLevel.Warning, $"cannot find restore option builder for {optionKey}"); + Logger.Write(TraceEventType.Warning, $"cannot find restore option builder for {optionKey}"); } } } @@ -171,7 +172,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation else { errorMessage = $"cannot find restore option builder for {optionKey}"; - Logger.Write(LogLevel.Warning, errorMessage); + Logger.Write(TraceEventType.Warning, errorMessage); } return errorMessage; diff --git a/src/Microsoft.SqlTools.ServiceLayer/FileBrowser/FileBrowserService.cs b/src/Microsoft.SqlTools.ServiceLayer/FileBrowser/FileBrowserService.cs index 34f06d46..ceea6709 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/FileBrowser/FileBrowserService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/FileBrowser/FileBrowserService.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Concurrent; using System.Data.SqlClient; +using System.Diagnostics; using System.Threading.Tasks; using Microsoft.SqlTools.Hosting.Protocol; using Microsoft.SqlTools.ServiceLayer.Connection; @@ -97,7 +98,7 @@ namespace Microsoft.SqlTools.ServiceLayer.FileBrowser } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unexpected exception while handling file browser open request: " + ex.Message); + Logger.Write(TraceEventType.Error, "Unexpected exception while handling file browser open request: " + ex.Message); await requestContext.SendResult(false); } } @@ -112,7 +113,7 @@ namespace Microsoft.SqlTools.ServiceLayer.FileBrowser } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unexpected exception while handling file browser expand request: " + ex.Message); + Logger.Write(TraceEventType.Error, "Unexpected exception while handling file browser expand request: " + ex.Message); await requestContext.SendResult(false); } } @@ -127,7 +128,7 @@ namespace Microsoft.SqlTools.ServiceLayer.FileBrowser } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unexpected exception while handling file browser validate request: " + ex.Message); + Logger.Write(TraceEventType.Error, "Unexpected exception while handling file browser validate request: " + ex.Message); await requestContext.SendResult(false); } } @@ -144,7 +145,7 @@ namespace Microsoft.SqlTools.ServiceLayer.FileBrowser } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unexpected exception while handling file browser close request: " + ex.Message); + Logger.Write(TraceEventType.Error, "Unexpected exception while handling file browser close request: " + ex.Message); await requestContext.SendResult(new FileBrowserCloseResponse() { Message = ex.Message }); } } @@ -204,7 +205,7 @@ namespace Microsoft.SqlTools.ServiceLayer.FileBrowser } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unexpected exception while closing file browser: " + ex.Message); + Logger.Write(TraceEventType.Error, "Unexpected exception while closing file browser: " + ex.Message); result.Message = ex.Message; } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Formatter/TSqlFormatterService.cs b/src/Microsoft.SqlTools.ServiceLayer/Formatter/TSqlFormatterService.cs index 61bea2dd..7f781aed 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Formatter/TSqlFormatterService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Formatter/TSqlFormatterService.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Composition; +using System.Diagnostics; using System.IO; using System.Threading.Tasks; using Microsoft.SqlServer.Management.SqlParser.Parser; @@ -39,7 +40,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Formatter public override void InitializeService(IProtocolEndpoint serviceHost) { - Logger.Write(LogLevel.Verbose, "TSqlFormatter initialized"); + Logger.Write(TraceEventType.Verbose, "TSqlFormatter initialized"); serviceHost.SetRequestHandler(DocumentFormattingRequest.Type, HandleDocFormatRequest); serviceHost.SetRequestHandler(DocumentRangeFormattingRequest.Type, HandleDocRangeFormatRequest); WorkspaceService?.RegisterConfigChangeCallback(HandleDidChangeConfigurationNotification); @@ -230,7 +231,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Formatter private async Task HandleRequest(Func> handler, RequestContext requestContext, string requestType) { - Logger.Write(LogLevel.Verbose, requestType); + Logger.Write(TraceEventType.Verbose, requestType); try { diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/BindingQueue.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/BindingQueue.cs index 71dfa99a..93b1a9f6 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/BindingQueue.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/BindingQueue.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.SqlTools.Utility; using System.Linq; using Microsoft.SqlTools.ServiceLayer.Utility; +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer.LanguageServices { @@ -320,7 +321,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unexpected exception on the binding queue: " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unexpected exception on the binding queue: " + ex.ToString()); if (queueItem.ErrorHandler != null) { result = queueItem.ErrorHandler(ex); @@ -347,14 +348,14 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices bindTask .ContinueWith((a) => bindingContext.BindingLock.Set()) - .ContinueWithOnFaulted(t => Logger.Write(LogLevel.Error, "Binding queue threw exception " + t.Exception.ToString())); + .ContinueWithOnFaulted(t => Logger.Write(TraceEventType.Error, "Binding queue threw exception " + t.Exception.ToString())); } } catch (Exception ex) { // catch and log any exceptions raised in the binding calls // set item processed to avoid deadlocks - Logger.Write(LogLevel.Error, "Binding queue threw exception " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Binding queue threw exception " + ex.ToString()); } finally { diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs index 23b547e9..78cc0311 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -250,7 +251,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices // Register a no-op shutdown task for validation of the shutdown logic serviceHost.RegisterShutdownTask(async (shutdownParams, shutdownRequestContext) => { - Logger.Write(LogLevel.Verbose, "Shutting down language service"); + Logger.Write(TraceEventType.Verbose, "Shutting down language service"); DeletePeekDefinitionScripts(); this.Dispose(); await Task.FromResult(0); @@ -573,7 +574,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unknown error " + ex.ToString()); // TODO: need mechanism return errors from event handlers } } @@ -599,7 +600,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unknown error " + ex.ToString()); // TODO: need mechanism return errors from event handlers } } @@ -613,7 +614,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices { try { - Logger.Write(LogLevel.Verbose, "HandleRebuildIntelliSenseNotification"); + Logger.Write(TraceEventType.Verbose, "HandleRebuildIntelliSenseNotification"); // Skip closing this file if the file doesn't exist var scriptFile = this.CurrentWorkspace.GetFile(rebuildParams.OwnerUri); @@ -642,7 +643,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unknown error " + ex.ToString()); } finally { @@ -672,7 +673,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unknown error " + ex.ToString()); await ServiceHostInstance.SendEvent(IntelliSenseReadyNotification.Type, new IntelliSenseReadyParams() {OwnerUri = rebuildParams.OwnerUri}); } } @@ -719,7 +720,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unknown error " + ex.ToString()); // TODO: need mechanism return errors from event handlers } } @@ -757,7 +758,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unknown error " + ex.ToString()); // TODO: need mechanism return errors from event handlers } } @@ -814,7 +815,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices catch (Exception e) { // Log the exception but don't rethrow it to prevent parsing errors from crashing SQL Tools Service - Logger.Write(LogLevel.Error, string.Format("An unexpected error occured while parsing: {0}", e.ToString())); + Logger.Write(TraceEventType.Error, string.Format("An unexpected error occured while parsing: {0}", e.ToString())); } }, ConnectedBindingQueue.QueueThreadStackSize); parseThread.Start(); @@ -848,15 +849,15 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } catch (ConnectionException) { - Logger.Write(LogLevel.Error, "Hit connection exception while binding - disposing binder object..."); + Logger.Write(TraceEventType.Error, "Hit connection exception while binding - disposing binder object..."); } catch (SqlParserInternalBinderError) { - Logger.Write(LogLevel.Error, "Hit connection exception while binding - disposing binder object..."); + Logger.Write(TraceEventType.Error, "Hit connection exception while binding - disposing binder object..."); } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unknown exception during parsing " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unknown exception during parsing " + ex.ToString()); } return null; @@ -869,7 +870,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices { // reset the parse result to do a full parse next time parseInfo.ParseResult = null; - Logger.Write(LogLevel.Error, "Unknown exception during parsing " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unknown exception during parsing " + ex.ToString()); } finally { @@ -878,7 +879,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } else { - Logger.Write(LogLevel.Warning, "Binding metadata lock timeout in ParseAndBind"); + Logger.Write(TraceEventType.Warning, "Binding metadata lock timeout in ParseAndBind"); } return parseInfo.ParseResult; @@ -907,7 +908,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unknown error in OnConnection " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unknown error in OnConnection " + ex.ToString()); scriptInfo.IsConnected = false; } finally @@ -1100,7 +1101,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices { // if any exceptions are raised looking up extended completion metadata // then just return the original completion item - Logger.Write(LogLevel.Error, "Exception in ResolveCompletionItem " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Exception in ResolveCompletionItem " + ex.ToString()); } finally { @@ -1196,7 +1197,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices catch (Exception ex) { // if any exceptions are raised return error result with message - Logger.Write(LogLevel.Error, "Exception in GetDefinition " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Exception in GetDefinition " + ex.ToString()); return new DefinitionResult { IsErrorResult = true, @@ -1211,7 +1212,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } else { - Logger.Write(LogLevel.Error, "Timeout waiting to query metadata from server"); + Logger.Write(TraceEventType.Error, "Timeout waiting to query metadata from server"); } } return (lastResult != null) ? lastResult : null; @@ -1586,7 +1587,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } catch (Exception e) { - Logger.Write(LogLevel.Error, string.Format("Exception while cancelling analysis task:\n\n{0}", e.ToString())); + Logger.Write(TraceEventType.Error, string.Format("Exception while cancelling analysis task:\n\n{0}", e.ToString())); TaskCompletionSource cancelTask = new TaskCompletionSource(); cancelTask.SetCanceled(); @@ -1657,9 +1658,9 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices continue; } - Logger.Write(LogLevel.Verbose, "Analyzing script file: " + scriptFile.FilePath); + Logger.Write(TraceEventType.Verbose, "Analyzing script file: " + scriptFile.FilePath); ScriptFileMarker[] semanticMarkers = GetSemanticMarkers(scriptFile); - Logger.Write(LogLevel.Verbose, "Analysis complete."); + Logger.Write(TraceEventType.Verbose, "Analysis complete."); await DiagnosticsHelper.PublishScriptDiagnostics(scriptFile, semanticMarkers, eventContext); } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.csproj b/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.csproj index af1f16f1..66dcaf76 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.csproj +++ b/src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.csproj @@ -1,4 +1,4 @@ - + netcoreapp2.1 @@ -9,7 +9,7 @@ false false false - $(DefineConstants);NETCOREAPP1_0 + $(DefineConstants);NETCOREAPP1_0;TRACE true true portable diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs index 9a6bb58c..823791f4 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs @@ -317,7 +317,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes protected virtual void PopulateChildren(bool refresh, string name = null) { - Logger.Write(LogLevel.Verbose, string.Format(CultureInfo.InvariantCulture, "Populating oe node :{0}", this.GetNodePath())); + Logger.Write(TraceEventType.Verbose, string.Format(CultureInfo.InvariantCulture, "Populating oe node :{0}", this.GetNodePath())); Debug.Assert(IsAlwaysLeaf == false); SmoQueryContext context = this.GetContextAs(); @@ -353,7 +353,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes { string error = string.Format(CultureInfo.InvariantCulture, "Failed populating oe children. error:{0} inner:{1} stacktrace:{2}", ex.Message, ex.InnerException != null ? ex.InnerException.Message : "", ex.StackTrace); - Logger.Write(LogLevel.Error, error); + Logger.Write(TraceEventType.Error, error); ErrorMessage = ex.Message; } } @@ -363,7 +363,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes { string error = string.Format(CultureInfo.InvariantCulture, "Failed populating oe children. error:{0} inner:{1} stacktrace:{2}", ex.Message, ex.InnerException != null ? ex.InnerException.Message : "", ex.StackTrace); - Logger.Write(LogLevel.Error, error); + Logger.Write(TraceEventType.Error, error); ErrorMessage = ex.Message; } finally diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerService.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerService.cs index 7bd85898..4f59976b 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerService.cs @@ -26,6 +26,7 @@ using Microsoft.SqlTools.ServiceLayer.Utility; using Microsoft.SqlTools.ServiceLayer.Workspace; using Microsoft.SqlTools.Utility; using Microsoft.SqlServer.Management.Common; +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer { @@ -119,7 +120,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer } catch(Exception ex) { - Logger.Write(LogLevel.Error, ex.Message); + Logger.Write(TraceEventType.Error, ex.Message); } } @@ -129,7 +130,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer /// The service host instance to register with public override void InitializeService(IProtocolEndpoint serviceHost) { - Logger.Write(LogLevel.Verbose, "ObjectExplorer service initialized"); + Logger.Write(TraceEventType.Verbose, "ObjectExplorer service initialized"); this.serviceHost = serviceHost; // Register handlers for requests serviceHost.SetRequestHandler(CreateSessionRequest.Type, HandleCreateSessionRequest); @@ -172,7 +173,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer { try { - Logger.Write(LogLevel.Verbose, "HandleCreateSessionRequest"); + Logger.Write(TraceEventType.Verbose, "HandleCreateSessionRequest"); Func> doCreateSession = async () => { Validate.IsNotNull(nameof(connectionDetails), connectionDetails); @@ -200,7 +201,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer internal async Task HandleExpandRequest(ExpandParams expandParams, RequestContext context) { - Logger.Write(LogLevel.Verbose, "HandleExpandRequest"); + Logger.Write(TraceEventType.Verbose, "HandleExpandRequest"); Func> expandNode = async () => { @@ -211,7 +212,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer ObjectExplorerSession session = null; if (!sessionMap.TryGetValue(uri, out session)) { - Logger.Write(LogLevel.Verbose, $"Cannot expand object explorer node. Couldn't find session for uri. {uri} "); + Logger.Write(TraceEventType.Verbose, $"Cannot expand object explorer node. Couldn't find session for uri. {uri} "); await serviceHost.SendEvent(ExpandCompleteNotification.Type, new ExpandResponse { SessionId = expandParams.SessionId, @@ -233,7 +234,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer { try { - Logger.Write(LogLevel.Verbose, "HandleRefreshRequest"); + Logger.Write(TraceEventType.Verbose, "HandleRefreshRequest"); Validate.IsNotNull(nameof(refreshParams), refreshParams); Validate.IsNotNull(nameof(context), context); @@ -241,7 +242,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer ObjectExplorerSession session = null; if (!sessionMap.TryGetValue(uri, out session)) { - Logger.Write(LogLevel.Verbose, $"Cannot expand object explorer node. Couldn't find session for uri. {uri} "); + Logger.Write(TraceEventType.Verbose, $"Cannot expand object explorer node. Couldn't find session for uri. {uri} "); await serviceHost.SendEvent(ExpandCompleteNotification.Type, new ExpandResponse { SessionId = refreshParams.SessionId, @@ -264,7 +265,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer internal async Task HandleCloseSessionRequest(CloseSessionParams closeSessionParams, RequestContext context) { - Logger.Write(LogLevel.Verbose, "HandleCloseSessionRequest"); + Logger.Write(TraceEventType.Verbose, "HandleCloseSessionRequest"); Func> closeSession = () => { Validate.IsNotNull(nameof(closeSessionParams), closeSessionParams); @@ -276,7 +277,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer bool success = false; if (!sessionMap.TryGetValue(uri, out session)) { - Logger.Write(LogLevel.Verbose, $"Cannot close object explorer session. Couldn't find session for uri. {uri} "); + Logger.Write(TraceEventType.Verbose, $"Cannot close object explorer session. Couldn't find session for uri. {uri} "); } if (session != null) @@ -326,7 +327,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer private void RunCreateSessionTask(ConnectionDetails connectionDetails, string uri) { - Logger.Write(LogLevel.Normal, "Creating OE session"); + Logger.Write(TraceEventType.Information, "Creating OE session"); CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); if (connectionDetails != null && !string.IsNullOrEmpty(uri)) { @@ -435,7 +436,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer } catch(Exception ex) { - Logger.Write(LogLevel.Warning, $"Failed to change the database in OE connection. error: {ex.Message}"); + Logger.Write(TraceEventType.Warning, $"Failed to change the database in OE connection. error: {ex.Message}"); // We should just try to change the connection. If it fails, there's not much we can do } return response; @@ -541,7 +542,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer private async Task SendSessionFailedNotification(string uri, string errorMessage) { - Logger.Write(LogLevel.Warning, $"Failed To create OE session: {errorMessage}"); + Logger.Write(TraceEventType.Warning, $"Failed To create OE session: {errorMessage}"); SessionCreatedParameters result = new SessionCreatedParameters() { Success = false, @@ -604,7 +605,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer response = await ExpandNode(session, expandParams.NodePath, forceRefresh); if (cancellationToken.IsCancellationRequested) { - Logger.Write(LogLevel.Verbose, "OE expand canceled"); + Logger.Write(TraceEventType.Verbose, "OE expand canceled"); } else { diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/DatabaseTreeNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/DatabaseTreeNode.cs index 1333204f..ff5a782d 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/DatabaseTreeNode.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/DatabaseTreeNode.cs @@ -5,6 +5,7 @@ using System; +using System.Diagnostics; using System.Globalization; using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlTools.Utility; @@ -70,7 +71,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { string error = string.Format(CultureInfo.InvariantCulture, "Failed to get IsAccessible. error:{0} inner:{1} stacktrace:{2}", ex.Message, ex.InnerException != null ? ex.InnerException.Message : "", ex.StackTrace); - Logger.Write(LogLevel.Error, error); + Logger.Write(TraceEventType.Error, error); ErrorMessage = ex.Message; return false; } diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/ServerNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/ServerNode.cs index 45bc5d32..2e135aad 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/ServerNode.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/ServerNode.cs @@ -6,6 +6,7 @@ using System; using System.Data.Common; using System.Data.SqlClient; +using System.Diagnostics; using System.Globalization; using System.Linq; using Microsoft.SqlServer.Management.Common; @@ -153,7 +154,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel exceptionMessage = ex.Message; } - Logger.Write(LogLevel.Error, "Exception at ServerNode.CreateContext() : " + exceptionMessage); + Logger.Write(TraceEventType.Error, "Exception at ServerNode.CreateContext() : " + exceptionMessage); this.ErrorStateMessage = string.Format(SR.TreeNodeError, exceptionMessage); return null; } diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs index 00d65495..78f33922 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoChildFactoryBase.cs @@ -38,7 +38,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { string error = string.Format(CultureInfo.InvariantCulture, "Failed expanding oe children. parent:{0} error:{1} inner:{2} stacktrace:{3}", parent != null ? parent.GetNodePath() : "", ex.Message, ex.InnerException != null ? ex.InnerException.Message : "", ex.StackTrace); - Logger.Write(LogLevel.Error, error); + Logger.Write(TraceEventType.Error, error); throw ex; } finally @@ -85,7 +85,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel /// Parent the nodes are being added to protected virtual void OnExpandPopulateNonFolders(IList allChildren, TreeNode parent, bool refresh, string name) { - Logger.Write(LogLevel.Verbose, string.Format(CultureInfo.InvariantCulture, "child factory parent :{0}", parent.GetNodePath())); + Logger.Write(TraceEventType.Verbose, string.Format(CultureInfo.InvariantCulture, "child factory parent :{0}", parent.GetNodePath())); if (ChildQuerierTypes == null) { @@ -127,7 +127,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { if (smoObject == null) { - Logger.Write(LogLevel.Error, "smoObject should not be null"); + Logger.Write(TraceEventType.Error, "smoObject should not be null"); } TreeNode childNode = CreateChild(parent, smoObject); if (childNode != null && PassesFinalFilters(childNode, smoObject) && !ShouldFilterNode(childNode, serverValidFor)) @@ -141,7 +141,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel { string error = string.Format(CultureInfo.InvariantCulture, "Failed getting smo objects. parent:{0} querier: {1} error:{2} inner:{3} stacktrace:{4}", parent != null ? parent.GetNodePath() : "", querier.GetType(), ex.Message, ex.InnerException != null ? ex.InnerException.Message : "", ex.StackTrace); - Logger.Write(LogLevel.Error, error); + Logger.Write(TraceEventType.Error, error); throw ex; } } @@ -313,7 +313,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel else { // Return true if cannot find the proeprty, SMO still tries to get that property but adding the property to supported list can make loading the nodes faster - Logger.Write(LogLevel.Verbose, $"Smo property name {propertyName} for Smo type {smoObj.GetType()} is not added as supported properties. This can cause the performance of loading the OE nodes"); + Logger.Write(TraceEventType.Verbose, $"Smo property name {propertyName} for Smo type {smoObj.GetType()} is not added as supported properties. This can cause the performance of loading the OE nodes"); return true; } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoColumnCustomNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoColumnCustomNode.cs index 9933acbc..9d02fe2b 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoColumnCustomNode.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoColumnCustomNode.cs @@ -4,6 +4,7 @@ // using System; +using System.Diagnostics; using System.Globalization; using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlTools.Utility; @@ -73,7 +74,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel } catch(Exception ex) { - Logger.Write(LogLevel.Error, $"Failed to get customized column name. error:{ex.Message}"); + Logger.Write(TraceEventType.Error, $"Failed to get customized column name. error:{ex.Message}"); } return string.Empty; } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Profiler/ProfilerSessionMonitor.cs b/src/Microsoft.SqlTools.ServiceLayer/Profiler/ProfilerSessionMonitor.cs index 42e6311d..15e11de5 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Profiler/ProfilerSessionMonitor.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Profiler/ProfilerSessionMonitor.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Data.SqlClient; +using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -61,7 +62,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler private List listeners = new List(); /// - /// Registers a session event listener to receive a callback when events arrive + /// Registers a session event Listener to receive a callback when events arrive /// public void AddSessionListener(IProfilerSessionListener listener) { @@ -283,7 +284,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler } catch (Exception ex) { - Logger.Write(LogLevel.Warning, "Failed to poll session. error: " + ex.Message); + Logger.Write(TraceEventType.Warning, "Failed to poll session. error: " + ex.Message); } finally { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Program.cs b/src/Microsoft.SqlTools.ServiceLayer/Program.cs index 6d89dc95..7a2e6070 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Program.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Program.cs @@ -7,6 +7,7 @@ using Microsoft.SqlTools.ServiceLayer.SqlContext; using Microsoft.SqlTools.ServiceLayer.Utility; using Microsoft.SqlTools.Utility; using System.IO; +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer { @@ -16,7 +17,7 @@ namespace Microsoft.SqlTools.ServiceLayer internal class Program { /// - /// Main entry point into the SQL Tools API Service Host + /// Main entry point into the SQL Tools API Service Layer /// internal static void Main(string[] args) { @@ -29,16 +30,20 @@ namespace Microsoft.SqlTools.ServiceLayer return; } - string logFilePath = "sqltools"; + string logFilePath = commandOptions.LogFilePath; + if (string.IsNullOrWhiteSpace(logFilePath)) + { + logFilePath = "sqltools"; + } if (!string.IsNullOrWhiteSpace(commandOptions.LoggingDirectory)) { logFilePath = Path.Combine(commandOptions.LoggingDirectory, logFilePath); } // turn on Verbose logging during early development - // we need to switch to Normal when preparing for public preview - Logger.Initialize(logFilePath: logFilePath, minimumLogLevel: LogLevel.Verbose, isEnabled: commandOptions.EnableLogging); - Logger.Write(LogLevel.Normal, "Starting SQL Tools Service Host"); + // we need to switch to Information when preparing for public preview + Logger.Initialize(tracingLevel: commandOptions.TracingLevel, logFilePath: logFilePath, traceSource: "sqltools"); + Logger.Write(TraceEventType.Information, "Starting SQL Tools Service Layer"); // set up the host details and profile paths var hostDetails = new HostDetails(version: new Version(1, 0)); @@ -50,7 +55,7 @@ namespace Microsoft.SqlTools.ServiceLayer } catch (Exception e) { - Logger.Write(LogLevel.Error, string.Format("An unhandled exception occurred: {0}", e)); + Logger.WriteWithCallstack(TraceEventType.Critical, $"An unhandled exception occurred: {e}"); Environment.Exit(1); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs index 8b40d7ec..fe2e1f36 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs @@ -251,7 +251,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution await BatchStart(this); } - // Register the message listener to *this instance* of the batch + // Register the message Listener to *this instance* of the batch // Note: This is being done to associate messages with batches ReliableSqlConnection sqlConn = conn as ReliableSqlConnection; if (sqlConn != null) @@ -460,7 +460,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution private DbCommand CreateCommand(DbConnection conn) { - // Register the message listener to *this instance* of the batch + // Register the message Listener to *this instance* of the batch // Note: This is being done to associate messages with batches ReliableSqlConnection sqlConn = conn as ReliableSqlConnection; DbCommand dbCommand; diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs index e64df616..b5f39fe1 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs @@ -18,7 +18,7 @@ using Microsoft.SqlTools.ServiceLayer.Workspace; using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; using Microsoft.SqlTools.ServiceLayer.Hosting; using Microsoft.SqlTools.Utility; - +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer.QueryExecution { @@ -875,7 +875,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution { // We don't particularly care if we fail to cancel during shutdown string message = string.Format("Failed to cancel query {0} during query service disposal: {1}", query.Key, e); - Logger.Write(LogLevel.Warning, message); + Logger.Write(TraceEventType.Warning, message); } } query.Value.Dispose(); diff --git a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptAsScriptingOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptAsScriptingOperation.cs index a3b7ff16..d2b5318a 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptAsScriptingOperation.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptAsScriptingOperation.cs @@ -16,6 +16,7 @@ using System.Globalization; using Microsoft.SqlServer.Management.SqlScriptPublish; using Microsoft.SqlTools.ServiceLayer.Utility; using Microsoft.SqlServer.Management.Sdk.Sfc; +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer.Scripting { @@ -103,7 +104,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting this.CancellationToken.ThrowIfCancellationRequested(); Logger.Write( - LogLevel.Verbose, + TraceEventType.Verbose, string.Format( "Sending script complete notification event for operation {0}", this.OperationId @@ -126,7 +127,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting { if (e.IsOperationCanceledException()) { - Logger.Write(LogLevel.Normal, string.Format("Scripting operation {0} was canceled", this.OperationId)); + Logger.Write(TraceEventType.Information, string.Format("Scripting operation {0} was canceled", this.OperationId)); this.SendCompletionNotificationEvent(new ScriptingCompleteParams { Canceled = true, @@ -134,7 +135,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting } else { - Logger.Write(LogLevel.Error, string.Format("Scripting operation {0} failed with exception {1}", this.OperationId, e)); + Logger.Write(TraceEventType.Error, string.Format("Scripting operation {0} failed with exception {1}", this.OperationId, e)); this.SendCompletionNotificationEvent(new ScriptingCompleteParams { OperationId = OperationId, @@ -568,7 +569,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting { //If you are getting this assertion fail it means you are working for higher //version of SQL Server. You need to update this part of code. - Logger.Write(LogLevel.Warning, "This part of the code is not updated corresponding to latest version change"); + Logger.Write(TraceEventType.Warning, "This part of the code is not updated corresponding to latest version change"); } // for cloud scripting to work we also have to have Script Compat set to 105. @@ -664,7 +665,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting this.CancellationToken.ThrowIfCancellationRequested(); Logger.Write( - LogLevel.Verbose, + TraceEventType.Verbose, string.Format( "Sending scripting error progress event, Urn={0}, OperationId={1}, Completed={2}, Error={3}", e.Current, diff --git a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScripterCore.cs b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScripterCore.cs index bbe47f6b..b29320e7 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScripterCore.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScripterCore.cs @@ -25,6 +25,7 @@ using Location = Microsoft.SqlTools.ServiceLayer.Workspace.Contracts.Location; using Microsoft.SqlServer.Management.Sdk.Sfc; using System.Text; using System.Data; +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer.Scripting { @@ -94,14 +95,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting } catch (ConnectionFailureException cfe) { - Logger.Write(LogLevel.Error, "Exception at PeekDefinition Database.get() : " + cfe.Message); + Logger.Write(TraceEventType.Error, "Exception at PeekDefinition Database.get() : " + cfe.Message); this.error = true; this.errorMessage = (connectionInfo != null && connectionInfo.IsCloud) ? SR.PeekDefinitionAzureError(cfe.Message) : SR.PeekDefinitionError(cfe.Message); return null; } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Exception at PeekDefinition Database.get() : " + ex.Message); + Logger.Write(TraceEventType.Error, "Exception at PeekDefinition Database.get() : " + ex.Message); this.error = true; this.errorMessage = SR.PeekDefinitionError(ex.Message); return null; @@ -822,7 +823,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting catch (Exception ex) { // log any exceptions determining if InMemory, but don't treat as fatal exception - Logger.Write(LogLevel.Error, "Could not determine if is InMemory table " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Could not determine if is InMemory table " + ex.ToString()); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingExtensionMethods.cs b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingExtensionMethods.cs index cc17761e..f872d74b 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingExtensionMethods.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingExtensionMethods.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Microsoft.SqlServer.Management.Sdk.Sfc; @@ -59,7 +60,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting IEnumerable objectTypes = publishModel.GetDatabaseObjectTypes(); Logger.Write( - LogLevel.Verbose, + TraceEventType.Verbose, string.Format( "Loaded SMO object type count {0}, types: {1}", objectTypes.Count(), @@ -70,7 +71,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting IEnumerable> databaseObjectsOfType = publishModel.EnumChildrenForDatabaseObjectType(objectType); Logger.Write( - LogLevel.Verbose, + TraceEventType.Verbose, string.Format( "Loaded SMO urn object count {0} for type {1}, urns: {2}", objectType, diff --git a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingListObjectsOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingListObjectsOperation.cs index 01d43fd8..f2f58938 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingListObjectsOperation.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingListObjectsOperation.cs @@ -17,6 +17,7 @@ using Microsoft.SqlTools.Hosting.Protocol; using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts; using Microsoft.SqlTools.Utility; using Microsoft.SqlTools.Hosting.Protocol.Contracts; +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer.Scripting { @@ -61,7 +62,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting List databaseObjects = publishModel.GetDatabaseObjects(); Logger.Write( - LogLevel.Verbose, + TraceEventType.Verbose, string.Format( "Sending list object completion notification count {0}, objects: {1}", databaseObjects, @@ -78,7 +79,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting } catch (Exception e) { - Logger.Write(LogLevel.Normal, string.Format("Scripting operation {0} was canceled", this.OperationId)); + Logger.Write(TraceEventType.Information, string.Format("Scripting operation {0} was canceled", this.OperationId)); if (e.IsOperationCanceledException()) { this.SendCompletionNotificationEvent(new ScriptingListObjectsCompleteParams @@ -89,7 +90,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting } else { - Logger.Write(LogLevel.Error, string.Format("Scripting operation {0} failed with exception {1}", this.OperationId, e)); + Logger.Write(TraceEventType.Error, string.Format("Scripting operation {0} failed with exception {1}", this.OperationId, e)); this.SendCompletionNotificationEvent(new ScriptingListObjectsCompleteParams { OperationId = this.OperationId, diff --git a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingOperation.cs index 32adbe63..b852f5e3 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingOperation.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingOperation.cs @@ -4,6 +4,7 @@ // using System; +using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using Microsoft.SqlTools.Utility; @@ -43,7 +44,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting { if (!this.cancellation.IsCancellationRequested) { - Logger.Write(LogLevel.Verbose, string.Format("Cancel invoked for OperationId {0}", this.OperationId)); + Logger.Write(TraceEventType.Verbose, string.Format("Cancel invoked for OperationId {0}", this.OperationId)); this.cancellation.Cancel(); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingScriptOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingScriptOperation.cs index 71f323bd..87b8dca6 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingScriptOperation.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingScriptOperation.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Data.SqlClient; +using System.Diagnostics; using System.Linq; using Microsoft.SqlServer.Management.SqlScriptPublish; using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts; @@ -64,7 +65,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting this.CancellationToken.ThrowIfCancellationRequested(); Logger.Write( - LogLevel.Verbose, + TraceEventType.Verbose, string.Format( "Sending script complete notification event for operation {0}, sequence number {1} with total count {2} and scripted count {3}", this.OperationId, @@ -83,7 +84,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting { if (e.IsOperationCanceledException()) { - Logger.Write(LogLevel.Normal, string.Format("Scripting operation {0} was canceled", this.OperationId)); + Logger.Write(TraceEventType.Information, string.Format("Scripting operation {0} was canceled", this.OperationId)); this.SendCompletionNotificationEvent(new ScriptingCompleteParams { Canceled = true, @@ -91,7 +92,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting } else { - Logger.Write(LogLevel.Error, string.Format("Scripting operation {0} failed with exception {1}", this.OperationId, e)); + Logger.Write(TraceEventType.Error, string.Format("Scripting operation {0} failed with exception {1}", this.OperationId, e)); this.SendCompletionNotificationEvent(new ScriptingCompleteParams { HasError = true, @@ -193,7 +194,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting PopulateAdvancedScriptOptions(this.Parameters.ScriptOptions, publishModel.AdvancedOptions); Logger.Write( - LogLevel.Normal, + TraceEventType.Information, string.Format( "Scripting object count {0}, objects: {1}", selectedObjects.Count(), @@ -214,7 +215,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting this.CancellationToken.ThrowIfCancellationRequested(); Logger.Write( - LogLevel.Verbose, + TraceEventType.Verbose, string.Format( "Sending scripting error progress event, Urn={0}, OperationId={1}, Sequence={2}, Completed={3}, Error={4}", e.Urn, @@ -245,7 +246,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting this.totalScriptedObjectCount = scriptingObjects.Count; Logger.Write( - LogLevel.Verbose, + TraceEventType.Verbose, string.Format( "Sending scripting plan notification event OperationId={0}, Sequence={1}, Count={2}, Objects: {3}", this.OperationId, @@ -270,7 +271,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting } Logger.Write( - LogLevel.Verbose, + TraceEventType.Verbose, string.Format( "Sending progress event, Urn={0}, OperationId={1}, Sequence={2}, Status={3}, Error={4}", e.Urn, diff --git a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingService.cs b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingService.cs index 820a330c..2d8b51da 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingService.cs @@ -4,26 +4,16 @@ // using System; -using System.IO; using System.Collections.Concurrent; -using System.Collections.Specialized; -using System.Data.SqlClient; using System.Diagnostics; -using System.Text; -using System.Threading; using System.Threading.Tasks; using Microsoft.SqlTools.Hosting.Protocol; using Microsoft.SqlTools.Hosting.Protocol.Contracts; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Hosting; -using Microsoft.SqlTools.ServiceLayer.Metadata.Contracts; using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts; using Microsoft.SqlTools.Utility; -using Microsoft.SqlServer.Management.Smo; -using Microsoft.SqlServer.Management.Common; -using Microsoft.SqlServer.Management.Sdk.Sfc; using Microsoft.SqlTools.ServiceLayer.Utility; -using Microsoft.SqlTools.ServiceLayer.LanguageServices; namespace Microsoft.SqlTools.ServiceLayer.Scripting { @@ -188,7 +178,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting } else { - Logger.Write(LogLevel.Normal, string.Format("Operation {0} was not found", operation.OperationId)); + Logger.Write(TraceEventType.Information, string.Format("Operation {0} was not found", operation.OperationId)); } await requestContext.SendResult(new ScriptingCancelResult()); diff --git a/src/Microsoft.SqlTools.ServiceLayer/Scripting/SmoScriptingOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/Scripting/SmoScriptingOperation.cs index 9ce935ea..f06f2e26 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Scripting/SmoScriptingOperation.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Scripting/SmoScriptingOperation.cs @@ -8,6 +8,7 @@ using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts; using Microsoft.SqlTools.Utility; using System; using System.Data.SqlClient; +using System.Diagnostics; using System.IO; using System.Reflection; using static Microsoft.SqlServer.Management.SqlScriptPublish.SqlScriptOptions; @@ -86,12 +87,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting catch (SqlException e) { Logger.Write( - LogLevel.Verbose, + TraceEventType.Verbose, string.Format("Exception getting server name", e)); } } - Logger.Write(LogLevel.Verbose, string.Format("Resolved server name '{0}'", serverName)); + Logger.Write(TraceEventType.Verbose, string.Format("Resolved server name '{0}'", serverName)); return serverName; } @@ -122,7 +123,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting { if (scriptOptionsParameters == null) { - Logger.Write(LogLevel.Verbose, "No advanced options set, the ScriptOptions object is null."); + Logger.Write(TraceEventType.Verbose, "No advanced options set, the ScriptOptions object is null."); return; } @@ -131,14 +132,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting PropertyInfo advancedOptionPropInfo = advancedOptions.GetType().GetProperty(optionPropInfo.Name); if (advancedOptionPropInfo == null) { - Logger.Write(LogLevel.Warning, string.Format("Invalid property info name {0} could not be mapped to a property on SqlScriptOptions.", optionPropInfo.Name)); + Logger.Write(TraceEventType.Warning, string.Format("Invalid property info name {0} could not be mapped to a property on SqlScriptOptions.", optionPropInfo.Name)); continue; } object optionValue = optionPropInfo.GetValue(scriptOptionsParameters, index: null); if (optionValue == null) { - Logger.Write(LogLevel.Verbose, string.Format("Skipping ScriptOptions.{0} since value is null", optionPropInfo.Name)); + Logger.Write(TraceEventType.Verbose, string.Format("Skipping ScriptOptions.{0} since value is null", optionPropInfo.Name)); continue; } @@ -168,13 +169,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting smoValue = Enum.Parse(advancedOptionPropInfo.PropertyType, (string)optionValue, ignoreCase: true); } - Logger.Write(LogLevel.Verbose, string.Format("Setting ScriptOptions.{0} to value {1}", optionPropInfo.Name, smoValue)); + Logger.Write(TraceEventType.Verbose, string.Format("Setting ScriptOptions.{0} to value {1}", optionPropInfo.Name, smoValue)); advancedOptionPropInfo.SetValue(advancedOptions, smoValue); } catch (Exception e) { Logger.Write( - LogLevel.Warning, + TraceEventType.Warning, string.Format("An exception occurred setting option {0} to value {1}: {2}", optionPropInfo.Name, optionValue, e)); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/ServiceHost.cs b/src/Microsoft.SqlTools.ServiceLayer/ServiceHost.cs index 3ab6adae..c0d1f6d4 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ServiceHost.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ServiceHost.cs @@ -17,6 +17,7 @@ using Microsoft.SqlTools.Utility; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Admin; using Microsoft.SqlTools.ServiceLayer.Utility; +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer.Hosting { @@ -144,7 +145,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting /// private async Task HandleShutdownRequest(object shutdownParams, RequestContext requestContext) { - Logger.Write(LogLevel.Normal, "Service host is shutting down..."); + Logger.Write(TraceEventType.Information, "Service host is shutting down..."); // Call all the shutdown methods provided by the service components Task[] shutdownTasks = shutdownCallbacks.Select(t => t(shutdownParams, requestContext)).ToArray(); diff --git a/src/Microsoft.SqlTools.ServiceLayer/TaskServices/SmoScriptableOperationWithFullDbAccess.cs b/src/Microsoft.SqlTools.ServiceLayer/TaskServices/SmoScriptableOperationWithFullDbAccess.cs index a3c57c82..2f584d6c 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/TaskServices/SmoScriptableOperationWithFullDbAccess.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/TaskServices/SmoScriptableOperationWithFullDbAccess.cs @@ -7,6 +7,7 @@ using Microsoft.SqlServer.Management.Smo; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.Utility; using System; +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer.TaskServices { @@ -66,7 +67,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TaskServices } catch (DatabaseFullAccessException databaseFullAccessException) { - Logger.Write(LogLevel.Warning, $"Failed to gain access to database. server|database:{ServerName}|{DatabaseName}"); + Logger.Write(TraceEventType.Warning, $"Failed to gain access to database. server|database:{ServerName}|{DatabaseName}"); throw databaseFullAccessException; } catch diff --git a/src/Microsoft.SqlTools.ServiceLayer/TaskServices/TaskService.cs b/src/Microsoft.SqlTools.ServiceLayer/TaskServices/TaskService.cs index b0614444..a777afd1 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/TaskServices/TaskService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/TaskServices/TaskService.cs @@ -11,6 +11,7 @@ using Microsoft.SqlTools.Hosting; using Microsoft.SqlTools.Extensibility; using Microsoft.SqlTools.Utility; using System.Linq; +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer.TaskServices { @@ -53,7 +54,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TaskServices public override void InitializeService(IProtocolEndpoint serviceHost) { this.serviceHost = serviceHost; - Logger.Write(LogLevel.Verbose, "TaskService initialized"); + Logger.Write(TraceEventType.Verbose, "TaskService initialized"); serviceHost.SetRequestHandler(ListTasksRequest.Type, HandleListTasksRequest); serviceHost.SetRequestHandler(CancelTaskRequest.Type, HandleCancelTaskRequest); TaskManager.TaskAdded += OnTaskAdded; @@ -66,7 +67,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TaskServices ListTasksParams listTasksParams, RequestContext context) { - Logger.Write(LogLevel.Verbose, "HandleListTasksRequest"); + Logger.Write(TraceEventType.Verbose, "HandleListTasksRequest"); Func> getAllTasks = () => { @@ -86,7 +87,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TaskServices internal async Task HandleCancelTaskRequest(CancelTaskParams cancelTaskParams, RequestContext context) { - Logger.Write(LogLevel.Verbose, "HandleCancelTaskRequest"); + Logger.Write(TraceEventType.Verbose, "HandleCancelTaskRequest"); Func> cancelTask = () => { Validate.IsNotNull(nameof(cancelTaskParams), cancelTaskParams); diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/ServiceLayerCommandOptions.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/ServiceLayerCommandOptions.cs index 43c5f6b3..5298b4cb 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Utility/ServiceLayerCommandOptions.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/ServiceLayerCommandOptions.cs @@ -9,7 +9,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility { class ServiceLayerCommandOptions : CommandOptions { - private const string ServiceLayerServiceName = "MicrosoftSqlToolsServiceLayer.exe"; + internal const string ServiceLayerServiceName = "MicrosoftSqlToolsServiceLayer.exe"; public ServiceLayerCommandOptions(string[] args) : base(args, ServiceLayerServiceName) { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/TaskExtensions.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/TaskExtensions.cs index a60b438b..0d611f58 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Utility/TaskExtensions.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/TaskExtensions.cs @@ -4,6 +4,7 @@ // using System; +using System.Diagnostics; using System.Text; using System.Threading.Tasks; using Microsoft.SqlTools.Utility; @@ -42,8 +43,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility } catch (Exception e) { - Logger.Write(LogLevel.Error, $"Exception in exception handling continuation: {e}"); - Logger.Write(LogLevel.Error, e.StackTrace); + Logger.Write(TraceEventType.Error, $"Exception in exception handling continuation: {e}"); + Logger.Write(TraceEventType.Error, e.StackTrace); } }); } @@ -79,8 +80,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility } catch (Exception e) { - Logger.Write(LogLevel.Error, $"Exception in exception handling continuation: {e}"); - Logger.Write(LogLevel.Error, e.StackTrace); + Logger.Write(TraceEventType.Error, $"Exception in exception handling continuation: {e}"); + Logger.Write(TraceEventType.Error, e.StackTrace); } }); } @@ -94,7 +95,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility sb.AppendLine($"{e.GetType().Name}: {e.Message}"); sb.AppendLine(e.StackTrace); } - Logger.Write(LogLevel.Error, sb.ToString()); + Logger.Write(TraceEventType.Error, sb.ToString()); } } } \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Workspace/Workspace.cs b/src/Microsoft.SqlTools.ServiceLayer/Workspace/Workspace.cs index a4813d7b..29de3f91 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Workspace/Workspace.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Workspace/Workspace.cs @@ -13,6 +13,7 @@ using Microsoft.SqlTools.Utility; using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; using System.Runtime.InteropServices; using Microsoft.SqlTools.ServiceLayer.Utility; +using System.Diagnostics; namespace Microsoft.SqlTools.ServiceLayer.Workspace { @@ -121,7 +122,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace this.workspaceFiles.Add(keyName, scriptFile); } - Logger.Write(LogLevel.Verbose, "Opened file on disk: " + resolvedFile.FilePath); + Logger.Write(TraceEventType.Verbose, "Opened file on disk: " + resolvedFile.FilePath); } return scriptFile; @@ -165,7 +166,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace canReadFromDisk = resolvedFile.CanReadFromDisk; } - Logger.Write(LogLevel.Verbose, "Resolved path: " + filePath); + Logger.Write(TraceEventType.Verbose, "Resolved path: " + filePath); return new ResolvedFile(filePath, canReadFromDisk); } @@ -213,7 +214,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace this.workspaceFiles.Add(keyName, scriptFile); - Logger.Write(LogLevel.Verbose, "Opened file as in-memory buffer: " + resolvedFile.FilePath); + Logger.Write(TraceEventType.Verbose, "Opened file as in-memory buffer: " + resolvedFile.FilePath); } return scriptFile; diff --git a/src/Microsoft.SqlTools.ServiceLayer/Workspace/WorkspaceService.cs b/src/Microsoft.SqlTools.ServiceLayer/Workspace/WorkspaceService.cs index 4df336d6..a2970043 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Workspace/WorkspaceService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Workspace/WorkspaceService.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -132,7 +133,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace // Register an initialization handler that sets the workspace path serviceHost.RegisterInitializeTask(async (parameters, contect) => { - Logger.Write(LogLevel.Verbose, "Initializing workspace service"); + Logger.Write(TraceEventType.Verbose, "Initializing workspace service"); if (Workspace != null) { @@ -144,7 +145,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace // Register a shutdown request that disposes the workspace serviceHost.RegisterShutdownTask(async (parameters, context) => { - Logger.Write(LogLevel.Verbose, "Shutting down workspace service"); + Logger.Write(TraceEventType.Verbose, "Shutting down workspace service"); if (Workspace != null) { @@ -227,14 +228,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace } } - Logger.Write(LogLevel.Verbose, msg.ToString()); + Logger.Write(TraceEventType.Verbose, msg.ToString()); var handlers = TextDocChangeCallbacks.Select(t => t(changedFiles.ToArray(), eventContext)); return Task.WhenAll(handlers); } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unknown error " + ex.ToString()); // Swallow exceptions here to prevent us from crashing // TODO: this probably means the ScriptFile model is in a bad state or out of sync with the actual file; we should recover here return Task.FromResult(true); @@ -247,7 +248,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace { try { - Logger.Write(LogLevel.Verbose, "HandleDidOpenTextDocumentNotification"); + Logger.Write(TraceEventType.Verbose, "HandleDidOpenTextDocumentNotification"); if (IsScmEvent(openParams.TextDocument.Uri)) { @@ -268,7 +269,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unknown error " + ex.ToString()); // Swallow exceptions here to prevent us from crashing // TODO: this probably means the ScriptFile model is in a bad state or out of sync with the actual file; we should recover here return; @@ -281,7 +282,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace { try { - Logger.Write(LogLevel.Verbose, "HandleDidCloseTextDocumentNotification"); + Logger.Write(TraceEventType.Verbose, "HandleDidCloseTextDocumentNotification"); if (IsScmEvent(closeParams.TextDocument.Uri)) { @@ -304,7 +305,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unknown error " + ex.ToString()); // Swallow exceptions here to prevent us from crashing // TODO: this probably means the ScriptFile model is in a bad state or out of sync with the actual file; we should recover here return; @@ -320,7 +321,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace { try { - Logger.Write(LogLevel.Verbose, "HandleDidChangeConfigurationNotification"); + Logger.Write(TraceEventType.Verbose, "HandleDidChangeConfigurationNotification"); // Propagate the changes to the event handlers var configUpdateTasks = ConfigChangeCallbacks.Select( @@ -329,7 +330,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace } catch (Exception ex) { - Logger.Write(LogLevel.Error, "Unknown error " + ex.ToString()); + Logger.Write(TraceEventType.Error, "Unknown error " + ex.ToString()); // Swallow exceptions here to prevent us from crashing // TODO: this probably means the ScriptFile model is in a bad state or out of sync with the actual file; we should recover here return; diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/Microsoft.SqlTools.Hosting.UnitTests.csproj b/test/Microsoft.SqlTools.Hosting.UnitTests/Microsoft.SqlTools.Hosting.UnitTests.csproj index 63dcfea2..f28f4d44 100644 --- a/test/Microsoft.SqlTools.Hosting.UnitTests/Microsoft.SqlTools.Hosting.UnitTests.csproj +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/Microsoft.SqlTools.Hosting.UnitTests.csproj @@ -12,6 +12,6 @@ - + \ No newline at end of file diff --git a/test/Microsoft.SqlTools.Hosting.UnitTests/UtilityTests/LoggerTests.cs b/test/Microsoft.SqlTools.Hosting.UnitTests/UtilityTests/LoggerTests.cs index ca85117c..126d6ac3 100644 --- a/test/Microsoft.SqlTools.Hosting.UnitTests/UtilityTests/LoggerTests.cs +++ b/test/Microsoft.SqlTools.Hosting.UnitTests/UtilityTests/LoggerTests.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Diagnostics; using System.IO; using System.Linq; using Microsoft.SqlTools.Hosting.Utility; @@ -30,28 +31,28 @@ namespace Microsoft.SqlTools.Hosting.UnitTests.UtilityTests .ToList() .ForEach(File.Delete); - Logger logger = new Logger(); - // initialize the logger - logger.Initialize( + Logger.Initialize( logFilePath: Path.Combine(Directory.GetCurrentDirectory(), "sqltools"), - minimumLogLevel: LogLevel.Verbose); + tracingLevel: SourceLevels.Verbose); + + // Write a test message. + string logMessage = $"Message from {nameof(LoggerDefaultFile)} test"; + Logger.Write(TraceEventType.Information, logMessage); // close the logger - logger.Close(); + Logger.Close(); // find the name of the new log file - string logFileName = Directory.GetFiles(Directory.GetCurrentDirectory()) - .SingleOrDefault(fileName => - fileName.Contains("sqltools_") - && fileName.EndsWith(".log", StringComparison.OrdinalIgnoreCase)); + string logFileName = Logger.LogFileFullPath; // validate the log file was created with desired name Assert.True(!string.IsNullOrWhiteSpace(logFileName)); if (!string.IsNullOrWhiteSpace(logFileName)) { Assert.True(logFileName.Length > "sqltools_.log".Length); - Assert.True(File.Exists(logFileName)); - + Assert.True(File.Exists(logFileName), $"the log file: {logFileName} must exist"); + //Ensure that our log message exists in the log file + Assert.True(File.ReadAllText(logFileName).Contains(logMessage, StringComparison.InvariantCultureIgnoreCase), $"the log message:'{logMessage}' must be present in the log file"); // delete the test log file if (File.Exists(logFileName)) { diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageServer/PeekDefinitionTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageServer/PeekDefinitionTests.cs index e42a4242..8312e68a 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageServer/PeekDefinitionTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageServer/PeekDefinitionTests.cs @@ -105,6 +105,24 @@ GO"; Cleanup(locations); } + [Fact] + public void LoggerGetValidTableDefinitionTest() + { + TestLogger test = new TestLogger() + { + TraceSource = System.Reflection.MethodInfo.GetCurrentMethod().Name, + EventType = System.Diagnostics.TraceEventType.Information, + TracingLevel = System.Diagnostics.SourceLevels.All, + }; + + test.Initialize(); + GetValidTableDefinitionTest(); // This should emit log.from SMO code base + test.LogMessage = "OnScriptingProgress ScriptingCompleted"; //Log message to verify. This message comes from SMO code. + test.Verify(); // The log message should be absent since the tracing level is set to Off. + test.Cleanup(); + + } + /// /// Test get definition for a invalid table object with active connection /// diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Microsoft.SqlTools.ServiceLayer.IntegrationTests.csproj b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Microsoft.SqlTools.ServiceLayer.IntegrationTests.csproj index 023f87e1..88330b73 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Microsoft.SqlTools.ServiceLayer.IntegrationTests.csproj +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Microsoft.SqlTools.ServiceLayer.IntegrationTests.csproj @@ -1,26 +1,27 @@ - + netcoreapp2.1 - false + false portable Microsoft.SqlTools.ServiceLayer.IntegrationTests Microsoft.SqlTools.ServiceLayer.IntegrationTests true + $(DefineConstants);TRACE - - ../../bin/ref/Newtonsoft.Json.dll - - - ../../bin/ref/Moq.dll - - - ../../bin/ref/Castle.Core.dll - + + ../../bin/ref/Newtonsoft.Json.dll + + + ../../bin/ref/Moq.dll + + + ../../bin/ref/Castle.Core.dll + diff --git a/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Program.cs b/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Program.cs index 1462df66..bc471b04 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Program.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Program.cs @@ -4,6 +4,7 @@ // using System; +using System.Diagnostics; using Microsoft.SqlTools.ServiceLayer.TestDriver.Driver; using Microsoft.SqlTools.ServiceLayer.TestDriver.Utility; using Microsoft.SqlTools.Utility; @@ -24,7 +25,7 @@ namespace Microsoft.SqlTools.ServiceLayer.PerfTests return 0; } - Logger.Initialize("testdriver", LogLevel.Verbose); + Logger.Initialize(logFilePath: Logger.GenerateLogFilePath("testdriver"), traceSource: "perftests", tracingLevel: SourceLevels.Verbose); return TestRunner.Instance.RunTests(args, "Microsoft.SqlTools.ServiceLayer.PerfTests.").Result; } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/Microsoft.SqlTools.ServiceLayer.Test.Common.csproj b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/Microsoft.SqlTools.ServiceLayer.Test.Common.csproj index d12c40d4..29891e27 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/Microsoft.SqlTools.ServiceLayer.Test.Common.csproj +++ b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/Microsoft.SqlTools.ServiceLayer.Test.Common.csproj @@ -5,7 +5,7 @@ false false false - $(DefineConstants);NETCOREAPP1_0 + $(DefineConstants);NETCOREAPP1_0;TRACE false diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestLogger.cs b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestLogger.cs new file mode 100644 index 00000000..7d1fee7a --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestLogger.cs @@ -0,0 +1,168 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Utility; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text.RegularExpressions; +using Xunit; + +namespace Microsoft.SqlTools.ServiceLayer.Test.Common +{ + public class TestLogger + { + private string logFilePath; + private string logMessage; + private string logContents; + private string logFileName; + private string topFrame; + + public bool ShouldVerifyCallstack { get; set; } = false; + public string TestName { get => testName ?? TraceSource; set => testName = value; } + public string TraceSource { get; set; } = "sqltoolsTest"; + public string LogMessage { get => logMessage ?? $"{TestName} test message"; set => logMessage = value; } + public string LogFilePath { get => logFilePath ?? Logger.GenerateLogFilePath(Path.Combine(Directory.GetCurrentDirectory(), TraceSource)); set => logFilePath = value; } + public TraceEventType EventType { get; set; } = TraceEventType.Information; + public SourceLevels TracingLevel { get; set; } = SourceLevels.Critical; + public bool DoNotUseTraceSource { get; set; } = false; + + private List pendingVerifications; + private string testName; + + public string CallstackMessage { get => $"Callstack=\\s*{TopFrame}"; } + + public string LogFileName { get => logFileName ?? Logger.LogFileFullPath; set => logFileName = value; } + public void Initialize() => + Logger.Initialize(TracingLevel, LogFilePath, TraceSource); // initialize the logger + public string LogContents + { + get + { + if (logContents == null) + { + Logger.Close(); + Assert.True(!string.IsNullOrWhiteSpace(LogFileName)); + Assert.True(LogFileName.Length > "{TraceSource}_.log".Length); + Assert.True(File.Exists(LogFileName)); + logContents = File.ReadAllText(LogFileName); + } + return logContents; + } + set => logContents = value; + } + + public string TopFrame { get => topFrame ?? "at System.Environment.get_StackTrace()"; set => topFrame = value; } + + public List PendingVerifications + { + get + { + if (pendingVerifications == null) + { + pendingVerifications = new List(); + } + return pendingVerifications; + } + set => pendingVerifications = value; + } + + public void Write() + { + // write test log + if (DoNotUseTraceSource) + { + TraceSource savedTraceSource = Logger.TraceSource; + Logger.TraceSource = null; + Logger.Write(EventType, LogMessage); + Logger.TraceSource = savedTraceSource; + } + else + Logger.Write(EventType, LogMessage); + } + + public void WriteWithCallstack() + { + // write test log with callstack + Logger.WriteWithCallstack(EventType, LogMessage); + ShouldVerifyCallstack = true; + } + + public void Verify(bool expectLogMessage = true) => Verify(ShouldVerifyCallstack, expectLogMessage); + + public void Verify(bool shouldVerifyCallstack, bool expectLogMessage = true) => Verify(EventType, LogMessage, CallstackMessage, shouldVerifyCallstack, expectLogMessage); + + public void Verify(TraceEventType eventType, string message, string callstackMessage, bool shouldVerifyCallstack = false, bool expectLogMessage = true) + { + if (expectLogMessage) + { + Assert.True(File.Exists(Logger.LogFileFullPath) && Regex.IsMatch(LogContents, $@"\b{eventType}:\s+\d+\s+:\s+{message}", RegexOptions.Compiled)); + } + else + { + Assert.False(File.Exists(Logger.LogFileFullPath) && Regex.IsMatch(LogContents, $@"\b{eventType}:\s+\d+\s+:\s+{message}", RegexOptions.Compiled)); + } + if (shouldVerifyCallstack) + { + VerifyCallstack(callstackMessage, expectLogMessage); + } + } + + /// + /// Perform all the pending verifications + /// + public void VerifyPending() + { + foreach (var pv in PendingVerifications) + { + pv.Invoke(); + } + } + + public void VerifyCallstack(bool expectLogMessage = true) => VerifyCallstack(CallstackMessage, expectLogMessage); + + public void VerifyCallstack(string message, bool expectLogMessage = true) + { + if (expectLogMessage) + { + Assert.True(File.Exists(Logger.LogFileFullPath) && Regex.IsMatch(LogContents, $"{message}", RegexOptions.Compiled)); + } + else + { + Assert.False(File.Exists(Logger.LogFileFullPath) && Regex.IsMatch(LogContents, $"{message}", RegexOptions.Compiled)); + } + } + + + public static void VerifyInitialization(SourceLevels expectedTracingLevel, string expectedTraceSource, string logFilePath, bool isLogFileExpectedToExist, int? testNo = null) + { + string FailureMessagePrefix = testNo.HasValue ? $"For Test No:{testNo.Value.ToString()}," : string.Empty; + Assert.False(string.IsNullOrWhiteSpace(logFilePath), $"{FailureMessagePrefix} LogFilePath should not be null or whitespaces"); + Assert.True(expectedTracingLevel == Logger.TracingLevel, $"{FailureMessagePrefix} expected Tracing Level did not match the configured value"); + if (isLogFileExpectedToExist) + { + Assert.True(File.Exists(logFilePath), $"{FailureMessagePrefix} logFilePath:{logFilePath} must exist"); + } + else + { + Assert.False(File.Exists(logFilePath), $"{FailureMessagePrefix} {logFilePath} must not exist"); + } + Assert.True(string.Compare(expectedTraceSource, Logger.TraceSource.Name, ignoreCase: true) == 0, $"{FailureMessagePrefix} expected Trace Source Name did not match the configured value"); + } + + public void Cleanup() => Cleanup(Logger.LogFileFullPath); + + public static void Cleanup(string logFileName) + { + if (File.Exists(logFileName)) + { + Logger.Close(); + File.Delete(logFileName); + } + } + + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.TestDriver.Tests/Program.cs b/test/Microsoft.SqlTools.ServiceLayer.TestDriver.Tests/Program.cs index 7a68ea28..3ea3a2f5 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.TestDriver.Tests/Program.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.TestDriver.Tests/Program.cs @@ -31,7 +31,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests return 0; } - Logger.Initialize("testdriver", LogLevel.Verbose); + Logger.Initialize("testdriver", TraceEventType.Verbose); int returnCode = 0; Task.Run(async () => diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/DatabaseLocksManagerTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/DatabaseLocksManagerTests.cs index 8ef90b97..75ef5cdc 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/DatabaseLocksManagerTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/DatabaseLocksManagerTests.cs @@ -12,8 +12,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection { public class DatabaseLocksManagerTests { - private string server1 = "server1"; - private string database1 = "database1"; + private const string server1 = "server1"; + private const string database1 = "database1"; [Fact] public void GainFullAccessShouldDisconnectTheConnections() diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Profiler/ProfilerServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Profiler/ProfilerServiceTests.cs index d359d611..7eb6ed9e 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Profiler/ProfilerServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Profiler/ProfilerServiceTests.cs @@ -43,7 +43,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Profiler return Task.FromResult(0); }); - // capture listener event notifications + // capture Listener event notifications var mockListener = new Mock(); mockListener.Setup(p => p.EventsAvailable(It.IsAny(), It.IsAny>(), It.IsAny())).Callback(() => { @@ -163,7 +163,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Profiler return Task.FromResult(0); }); - // capture listener event notifications + // capture Listener event notifications var mockListener = new Mock(); mockListener.Setup(p => p.EventsAvailable(It.IsAny(), It.IsAny>(), It.IsAny())).Callback(() => { @@ -212,7 +212,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Profiler profilerService.SessionMonitor.PollSession(1); - // confirm that no events were sent to paused listener + // confirm that no events were sent to paused Listener Assert.False(recievedEvents); // unpause viewer @@ -229,7 +229,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Profiler Thread.Sleep(250); } - // check that events got sent to listener + // check that events got sent to Listener Assert.True(recievedEvents); requestContext.VerifyAll(); @@ -244,7 +244,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Profiler bool sessionStopped = false; string testUri = "profiler_uri"; - // capture listener event notifications + // capture Listener event notifications var mockSession = new Mock(); mockSession.Setup(p => p.GetTargetXml()).Callback(() => { diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/LoggerTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/LoggerTests.cs index 0ed5e85a..d11ce268 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/LoggerTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ServiceHost/LoggerTests.cs @@ -2,9 +2,10 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; +using System.Diagnostics; using System.IO; -using System.Linq; +using System.Reflection; +using Microsoft.SqlTools.ServiceLayer.Test.Common; using Microsoft.SqlTools.Utility; using Xunit; @@ -15,48 +16,447 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ServiceHost /// public class LoggerTests { - /// /// Test to verify that the logger initialization is generating a valid file + /// Verifies that a test log entries is succesfully written to a default log file. /// [Fact] public void LoggerDefaultFile() { - // delete any existing log files from the current directory - Directory.GetFiles(Directory.GetCurrentDirectory()) - .Where(fileName - => fileName.Contains("sqltools_") - && fileName.EndsWith(".log", StringComparison.OrdinalIgnoreCase)) - .ToList() - .ForEach(File.Delete); - - // initialize the logger - Logger.Initialize( - logFilePath: Path.Combine(Directory.GetCurrentDirectory(), "sqltools"), - minimumLogLevel: LogLevel.Verbose); - - // close the logger - Logger.Close(); - - // find the name of the new log file - string logFileName = Directory.GetFiles(Directory.GetCurrentDirectory()) - .SingleOrDefault(fileName => - fileName.Contains("sqltools_") - && fileName.EndsWith(".log", StringComparison.OrdinalIgnoreCase)); - - // validate the log file was created with desired name - Assert.True(!string.IsNullOrWhiteSpace(logFileName)); - if (!string.IsNullOrWhiteSpace(logFileName)) + TestLogger test = new TestLogger() { - Assert.True(logFileName.Length > "sqltools_.log".Length); - Assert.True(File.Exists(logFileName)); + TraceSource = MethodInfo.GetCurrentMethod().Name, + EventType = TraceEventType.Information, + TracingLevel = SourceLevels.Verbose, + }; - // delete the test log file - if (File.Exists(logFileName)) - { - File.Delete(logFileName); - } + test.Initialize(); + test.Write(); + test.Verify(); + test.Cleanup(); + } + + /// + /// Test to verify that the logger initialization works using various possibilities. + /// + [Fact] + public void LoggerTestInitialization() + { + int? testNo = 1; + //Test 1: Initialization with all defaults. Logfile names get autogenerated with the well known prefix. + { + SourceLevels expectedTracingLevel = Logger.defaultTracingLevel; + string expectedTraceSource = Logger.defaultTraceSource; + Logger.Initialize(); + bool isLogFileExpectedToExist = ((uint)expectedTracingLevel >= (uint)SourceLevels.Information); + TestLogger.VerifyInitialization(expectedTracingLevel, expectedTraceSource, Logger.LogFileFullPath, isLogFileExpectedToExist, testNo++); + TestLogger.Cleanup(Logger.LogFileFullPath); } + + //Test 2: Initialization with TracingLevel set to Critical. Logfile names get autogenerated with the well known prefix. Before we do a write at Critical level the logfile must not get even created. + { + SourceLevels expectedTracingLevel = SourceLevels.Critical; + string expectedTraceSource = Logger.defaultTraceSource; + Logger.Initialize(expectedTracingLevel); + bool isLogFileExpectedToExist = ((uint)expectedTracingLevel >= (uint)SourceLevels.Information); + TestLogger.VerifyInitialization(expectedTracingLevel, expectedTraceSource, Logger.LogFileFullPath, isLogFileExpectedToExist, testNo++); + TestLogger.Cleanup(Logger.LogFileFullPath); + } + + //Test 3: Initialization with TraceSourceName set to specified name. Logfile names get autogenerated with the well known prefix. + { + SourceLevels expectedTracingLevel = Logger.defaultTracingLevel; + string expectedTraceSource = nameof(LoggerTestInitialization); + Logger.Initialize(traceSource:expectedTraceSource); + bool isLogFileExpectedToExist = ((uint)expectedTracingLevel >= (uint)SourceLevels.Information); + TestLogger.VerifyInitialization(expectedTracingLevel, expectedTraceSource, Logger.LogFileFullPath, isLogFileExpectedToExist, testNo++); + TestLogger.Cleanup(Logger.LogFileFullPath); + } + + + //Test 4: Initialization with logfile set to specified random filepath. + { + SourceLevels expectedTracingLevel = Logger.defaultTracingLevel; + string expectedTraceSource = Logger.defaultTraceSource; + string logFilePath = Path.Combine(Path.GetRandomFileName(), nameof(LoggerTestInitialization)); + Logger.Initialize(traceSource: expectedTraceSource, logFilePath: logFilePath); + Assert.True(string.Compare(logFilePath, Logger.LogFileFullPath, ignoreCase: true) == 0, "The logfile path of the Logger should be the one specified"); + bool isLogFileExpectedToExist = ((uint)expectedTracingLevel >= (uint)SourceLevels.Information); + TestLogger.VerifyInitialization(expectedTracingLevel, expectedTraceSource, logFilePath, isLogFileExpectedToExist, testNo++); + TestLogger.Cleanup(Logger.LogFileFullPath); + } + + //Test 5: Initialization with logfile generated from log directory and LogFilePrefix using Logger.GenerateLogFielPath method. + { + SourceLevels expectedTracingLevel = Logger.defaultTracingLevel; + string expectedTraceSource = Logger.defaultTraceSource; + string logFilePath = Logger.GenerateLogFilePath(Path.Combine(Directory.GetCurrentDirectory(), nameof(LoggerTestInitialization))); + Assert.True(string.Compare(Path.GetDirectoryName(logFilePath), Directory.GetCurrentDirectory(), ignoreCase: true) == 0, "The directory path of the logfile should match the directory path specified"); + Logger.Initialize(traceSource: expectedTraceSource, logFilePath: logFilePath); + Assert.True(string.Compare(logFilePath, Logger.LogFileFullPath, ignoreCase: true) == 0, "The logfile path of the Logger should be the one specified"); + bool isLogFileExpectedToExist = ((uint)expectedTracingLevel >= (uint)SourceLevels.Information); + TestLogger.VerifyInitialization(expectedTracingLevel, expectedTraceSource, Logger.LogFileFullPath, isLogFileExpectedToExist, testNo++); + TestLogger.Cleanup(Logger.LogFileFullPath); + } + + #region TracingLevel Settings + //Test 6: Initialization tracingLevel specified as a null string. + { + string tracingLevel = null; + SourceLevels expectedTracingLevel = Logger.defaultTracingLevel; + string expectedTraceSource = Logger.defaultTraceSource; + Logger.Initialize(tracingLevel); + bool isLogFileExpectedToExist = false; + TestLogger.VerifyInitialization(expectedTracingLevel, expectedTraceSource, Logger.LogFileFullPath, isLogFileExpectedToExist, testNo++); + TestLogger.Cleanup(Logger.LogFileFullPath); + } + + //Test 7: Initialization tracingLevel specified as an empty string. + { + string tracingLevel = null; + SourceLevels expectedTracingLevel = Logger.defaultTracingLevel; + string expectedTraceSource = Logger.defaultTraceSource; + Logger.Initialize(tracingLevel); + bool isLogFileExpectedToExist = false; + TestLogger.VerifyInitialization(expectedTracingLevel, expectedTraceSource, Logger.LogFileFullPath, isLogFileExpectedToExist, testNo++); + TestLogger.Cleanup(Logger.LogFileFullPath); + } + + //Test 8: Initialization tracingLevel specified as an invalid string. + { + string tracingLevel = "invalid"; + SourceLevels expectedTracingLevel = Logger.defaultTracingLevel; + string expectedTraceSource = Logger.defaultTraceSource; + Logger.Initialize(tracingLevel); + bool isLogFileExpectedToExist = false; + TestLogger.VerifyInitialization(expectedTracingLevel, expectedTraceSource, Logger.LogFileFullPath, isLogFileExpectedToExist, testNo++); + TestLogger.Cleanup(Logger.LogFileFullPath); + } + + //Test 9: Initialization with logfile set to empty string. + { + SourceLevels expectedTracingLevel = SourceLevels.All; + string expectedTraceSource = Logger.defaultTraceSource; + string logFilePath = string.Empty; + Logger.Initialize(traceSource: expectedTraceSource, logFilePath: logFilePath, tracingLevel:expectedTracingLevel); + bool isLogFileExpectedToExist = ((uint)expectedTracingLevel >= (uint)SourceLevels.Information); + TestLogger.VerifyInitialization(expectedTracingLevel, expectedTraceSource, Logger.LogFileFullPath, isLogFileExpectedToExist, testNo++); + TestLogger.Cleanup(Logger.LogFileFullPath); + } + //Test 10: Initialization with logfile set to null. + { + SourceLevels expectedTracingLevel = SourceLevels.All; + string expectedTraceSource = Logger.defaultTraceSource; + string logFilePath = null; + Logger.Initialize(traceSource: expectedTraceSource, logFilePath: logFilePath, tracingLevel: expectedTracingLevel); + bool isLogFileExpectedToExist = ((uint)expectedTracingLevel >= (uint)SourceLevels.Information); + TestLogger.VerifyInitialization(expectedTracingLevel, expectedTraceSource, Logger.LogFileFullPath, isLogFileExpectedToExist, testNo++); + TestLogger.Cleanup(Logger.LogFileFullPath); + } + //Test 11: Initialization with LogDirectory in Logger.GenerateLogFilePath set to empty string. + { + SourceLevels expectedTracingLevel = SourceLevels.All; + string expectedTraceSource = Logger.defaultTraceSource; + string logFilePath = Logger.GenerateLogFilePath(Path.Combine(string.Empty, nameof(LoggerTestInitialization))); + Logger.Initialize(traceSource: expectedTraceSource, logFilePath: logFilePath, tracingLevel: expectedTracingLevel); + Assert.True(string.Compare(logFilePath, Logger.LogFileFullPath, ignoreCase: true) == 0, "The logfile should match the path specified"); + bool isLogFileExpectedToExist = ((uint)expectedTracingLevel >= (uint)SourceLevels.Information); + TestLogger.VerifyInitialization(expectedTracingLevel, expectedTraceSource, Logger.LogFileFullPath, isLogFileExpectedToExist, testNo++); + TestLogger.Cleanup(Logger.LogFileFullPath); + } + #endregion + + } + + /// + /// Test to verify that there is no log file created if TracingLevel is set to off. + /// + [Fact] + public void LoggerTracingLevelOff() + { + TestLogger test = new TestLogger() + { + TraceSource = MethodInfo.GetCurrentMethod().Name, + EventType = TraceEventType.Information, + TracingLevel = SourceLevels.Off, + }; + + test.Initialize(); + test.Write(); + Assert.False(File.Exists(Logger.LogFileFullPath), $"Log file must not exist when tracing level is: {test.TracingLevel}"); + test.Verify(expectLogMessage: false); // The log message should be absent since the tracing level is set to Off. + test.Cleanup(); + } + + /// + /// Test to verify that the tracinglevel setting filters message logged at lower levels. + /// Verifies that a test log entries logged at Information level are not present in log when tracingLevel + /// is set to 'Critical' + /// + [Fact] + public void LoggerInformationalNotLoggedWithCriticalTracingLevel() + { + TestLogger test = new TestLogger() + { + TraceSource = MethodInfo.GetCurrentMethod().Name, + EventType = TraceEventType.Information, + TracingLevel = SourceLevels.Critical, + }; + + test.Initialize(); + test.Write(); + test.Verify(expectLogMessage:false); // The log message should be absent since the tracing level is set to collect messages only at 'Critical' logging level + test.Cleanup(); + } + + /// + /// Test to verify that WriteWithCallstack() method turns on the callstack logging + /// + [Fact] + public void LoggerWithCallstack() + { + TestLogger test = new TestLogger() + { + TraceSource = MethodInfo.GetCurrentMethod().Name, + EventType = TraceEventType.Warning, + TracingLevel = SourceLevels.Information, + }; + + test.Initialize(); + test.WriteWithCallstack(); + test.Verify(); // This should verify the logging of callstack fields as well. + test.Cleanup(); + } + + /// + /// Test to verify that callstack logging is turned on, it does not get logged because tracing level filters them out. + /// + [Fact] + public void LoggerWithCallstackFilteredOut() + { + TestLogger test = new TestLogger() + { + TraceSource = MethodInfo.GetCurrentMethod().Name, + EventType = TraceEventType.Information, + TracingLevel = SourceLevels.Error, + }; + + test.Initialize(); + test.WriteWithCallstack(); + test.Verify(expectLogMessage:false); // The log message and corresponding callstack details should be absent since the tracing level is set to collect messages only at 'Error' logging level + test.Cleanup(); + } + + /// + /// No TraceSource test to verify that WriteWithCallstack() method turns on the callstack logging + /// + [Fact] + public void LoggerNoTraceSourceWithCallstack() + { + TestLogger test = new TestLogger() + { + TraceSource = MethodInfo.GetCurrentMethod().Name, + EventType = TraceEventType.Warning, + TracingLevel = SourceLevels.Information, + DoNotUseTraceSource = true, + }; + + test.Initialize(); + test.WriteWithCallstack(); + test.Verify(); // This should verify the logging of callstack fields as well. + test.Cleanup(); + } + + /// + /// No TraceSrouce test to verify that callstack logging is turned on, it does not get logged because tracing level filters them out. + /// + [Fact] + public void LoggerNoTraceSourceWithCallstackFilteredOut() + { + TestLogger test = new TestLogger() + { + TraceSource = MethodInfo.GetCurrentMethod().Name, + EventType = TraceEventType.Information, + TracingLevel = SourceLevels.Error, + DoNotUseTraceSource = true, + }; + + test.Initialize(); + test.WriteWithCallstack(); + test.Verify(expectLogMessage: false); // The log message and corresponding callstack details should be absent since the tracing level is set to collect messages only at 'Error' logging level + test.Cleanup(); + } + + /// + /// Tests to verify that upon changing TracingLevel from Warning To Error, + /// after the change, messages of Error type are present in the log and those logged with warning type are not present. + /// + [Fact] + public void LoggerTracingLevelFromWarningToError() + { + // setup the test object + TestLogger test = new TestLogger() + { + TraceSource = MethodInfo.GetCurrentMethod().Name, + }; + TestTracingLevelChangeFromWarningToError(test); + } + + /// + /// Tests to verify that upon changing TracingLevel from Error To Warning, + /// after the change, messages of Warning as well as of Error type are present in the log. + /// + [Fact] + public void LoggerTracingLevelFromErrorToWarning() + { + // setup the test object + TestLogger test = new TestLogger() + { + TraceSource = MethodInfo.GetCurrentMethod().Name, + }; + TestTracingLevelChangeFromErrorToWarning(test); + } + + /// + /// When not use TraceSource, test to verify that upon changing TracingLevel from Warning To Error, + /// after the change, messages of Error type are present in the log and those logged with warning type are not present. + /// + [Fact] + public void LoggerNoTraceSourceTracingLevelFromWarningToError() + { + // setup the test object + TestLogger test = new TestLogger() + { + TraceSource = MethodInfo.GetCurrentMethod().Name, + DoNotUseTraceSource = true, + }; + TestTracingLevelChangeFromWarningToError(test); + } + + /// + /// When not use TraceSource, test to verify that upon changing TracingLevel from Error To Warning, + /// after the change, messages of Warning as well as of Error type are present in the log. + /// + [Fact] + public void LoggerNoTraceSourceTracingLevelFromErrorToWarning() + { + // setup the test object + TestLogger test = new TestLogger() + { + TraceSource = MethodInfo.GetCurrentMethod().Name, + DoNotUseTraceSource = true, + }; + TestTracingLevelChangeFromErrorToWarning(test); + } + + private static void TestTracingLevelChangeFromWarningToError(TestLogger test) + { + test.Initialize(); + Logger.TracingLevel = SourceLevels.Warning; + string oldMessage = @"Old Message with Tracing Level set to Warning"; + test.LogMessage = oldMessage; + // Initially with TracingLevel at Warning, logging of Warning type does not get filtered out. + Assert.Equal(SourceLevels.Warning, Logger.TracingLevel); + { + test.EventType = TraceEventType.Warning; + test.Write(); + test.PendingVerifications.Add(() => + { + test.Verify(eventType: TraceEventType.Warning, message: oldMessage, callstackMessage: null, shouldVerifyCallstack: false, expectLogMessage: true); + }); + } + // and logging of Error type also succeeeds + { + test.EventType = TraceEventType.Error; + test.Write(); + test.PendingVerifications.Add(() => + { + test.Verify(eventType: TraceEventType.Error, message: oldMessage, callstackMessage: null, shouldVerifyCallstack: false, expectLogMessage: true); + }); + } + + //Now Update the tracing level to Error. Now logging both of Warning type gets filtered and only Error type should succeed. + Logger.TracingLevel = SourceLevels.Error; + Assert.Equal(SourceLevels.Error, Logger.TracingLevel); + string newMessage = @"New Message After Tracing Level set to Error"; + test.LogMessage = newMessage; + + // Now with TracingLevel at Error, logging of Warning type gets filtered out. + { + test.EventType = TraceEventType.Warning; + test.Write(); + test.PendingVerifications.Add(() => + { + test.Verify(eventType: TraceEventType.Warning, message: newMessage, callstackMessage: null, shouldVerifyCallstack: false, expectLogMessage: false); + }); + } + // but logging of Error type succeeds + { + test.EventType = TraceEventType.Error; + test.Write(); + test.PendingVerifications.Add(() => + { + test.Verify(eventType: TraceEventType.Error, message: newMessage, callstackMessage: null, shouldVerifyCallstack: false, expectLogMessage: true); + }); + } + + test.VerifyPending(); + test.Cleanup(); + } + + private static void TestTracingLevelChangeFromErrorToWarning(TestLogger test) + { + test.Initialize(); + Logger.TracingLevel = SourceLevels.Error; + string oldMessage = @"Old Message with Tracing Level set to Error"; + test.LogMessage = oldMessage; + // Initially with TracingLevel at Error, logging of Warning type gets filtered out. + Assert.Equal(SourceLevels.Error, Logger.TracingLevel); + { + test.EventType = TraceEventType.Warning; + test.Write(); + test.PendingVerifications.Add(() => + { + test.Verify(eventType: TraceEventType.Warning, message: oldMessage, callstackMessage: null, shouldVerifyCallstack: false, expectLogMessage: false); + }); + } + // But logging of Error type succeeeds + { + test.EventType = TraceEventType.Error; + test.Write(); + test.PendingVerifications.Add(() => + { + test.Verify(eventType: TraceEventType.Error, message: oldMessage, callstackMessage: null, shouldVerifyCallstack: false, expectLogMessage: true); + }); + } + + //Now Update the tracing level to Warning. Now logging both of Error type and Warning type should succeed. + Logger.TracingLevel = SourceLevels.Warning; + Assert.Equal(SourceLevels.Warning, Logger.TracingLevel); + string newMessage = @"New Message After Tracing Level set to Warning"; + test.LogMessage = newMessage; + + // Now with TracingLevel at Warning, logging of Warning type does not get filtered out. + { + test.EventType = TraceEventType.Warning; + test.Write(); + test.PendingVerifications.Add(() => + { + test.Verify(eventType: TraceEventType.Warning, message: newMessage, callstackMessage: null, shouldVerifyCallstack: false, expectLogMessage: true); + }); + } + // and logging of Error type also succeeds + { + test.EventType = TraceEventType.Error; + test.Write(); + test.PendingVerifications.Add(() => + { + test.Verify(eventType: TraceEventType.Error, message: newMessage, callstackMessage: null, shouldVerifyCallstack: false, expectLogMessage: true); + }); + } + + test.VerifyPending(); + test.Cleanup(); } } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/CommandOptionsTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/CommandOptionsTests.cs index c0a2a3f0..29c45eef 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/CommandOptionsTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Utility/CommandOptionsTests.cs @@ -14,29 +14,6 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility /// public class CommandOptionsTests { - [Fact] - public void LoggingEnabledWhenFlagProvided() - { - var args = new string[] {"--enable-logging"}; - ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); - Assert.NotNull(options); - - Assert.True(options.EnableLogging); - Assert.False(options.ShouldExit); - Assert.Equal(options.Locale, string.Empty); - } - - [Fact] - public void LoggingDisabledWhenFlagNotProvided() - { - var args = new string[] {}; - ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); - Assert.NotNull(options); - - Assert.False(options.EnableLogging); - Assert.False(options.ShouldExit); - Assert.Equal(options.Locale, string.Empty); - } [Fact] public void UsageIsShownWhenHelpFlagProvided() @@ -63,16 +40,56 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility [Fact] public void DefaultValuesAreUsedWhenNoArgumentsAreProvided() { - var args = new string[] {}; - ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); - Assert.NotNull(options); - - Assert.False(options.EnableLogging); - Assert.False(options.ShouldExit); - Assert.True(string.IsNullOrWhiteSpace(options.LoggingDirectory)); - Assert.Equal(options.Locale, string.Empty); + int? testNo = 1; + // Test 1: All defaults, no options specified + { + var args = new string[] { }; + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); + VerifyCommandOptions(options, testNo++); + } + // Test 2: All defaults, -logDir as null + { + var args = new string[] { "--log-dir", null }; + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); + VerifyCommandOptions(options, testNo++); + } + // Test 3: All defaults, -logDir as empty string + { + var args = new string[] { "--log-dir", string.Empty }; + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); + VerifyCommandOptions(options, testNo++); + } + // Test 4: All defaults, -log-file as null + { + var args = new string[] { "--log-file", null }; + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); + VerifyCommandOptions(options, testNo++, logFilePath: null); + } + // Test 5: All defaults, -log-file as empty string + { + var args = new string[] { "--log-file", string.Empty }; + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); + VerifyCommandOptions(options, testNo++, logFilePath: string.Empty); + } } - + + private static void VerifyCommandOptions(ServiceLayerCommandOptions options, int? testNo = null, string errorMessage = "", string tracingLevel = null, string logFilePath = null, bool shouldExit = false, string locale = "", string logDirectory = null) + { + Assert.NotNull(options); + string MsgPrefix = testNo != null ? $"TestNo:{testNo} ::" : string.Empty; + Assert.True(errorMessage == options.ErrorMessage, $"{MsgPrefix} options:{nameof(errorMessage)} should be '{errorMessage}'"); + Assert.True(tracingLevel == options.TracingLevel, $"{MsgPrefix} options:{nameof(tracingLevel)} should be '{tracingLevel}'"); + Assert.True(logFilePath == options.LogFilePath, $"{MsgPrefix} options:{nameof(logFilePath)} should be '{logFilePath}'"); + Assert.True(shouldExit == options.ShouldExit, $"{MsgPrefix} options:{nameof(shouldExit)} should be '{shouldExit}'"); + Assert.False(string.IsNullOrWhiteSpace(options.LoggingDirectory)); + if (string.IsNullOrWhiteSpace(logDirectory)) + { + logDirectory = Path.Combine(options.DefaultLogRoot, options.ServiceName); + } + Assert.True(logDirectory == options.LoggingDirectory, $"{MsgPrefix} options:{nameof(logDirectory)} should be '{logDirectory}'"); + Assert.True(options.Locale == locale, $"{MsgPrefix} options:{nameof(locale)} should be '{locale}'"); + } + [Theory] [InlineData("en")] [InlineData("es")] @@ -107,7 +124,6 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility // Asserting all options were properly set Assert.NotNull(options); - Assert.False(options.EnableLogging); Assert.False(options.ShouldExit); Assert.Equal(options.Locale, string.Empty); } @@ -124,5 +140,33 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility Assert.False(options.ShouldExit); Assert.Equal(options.LoggingDirectory, logDir); } + + + [Fact] + public void TracingLevelSet() + { + string expectedLevel = "Critical"; + var args = new string[] { "--tracing-level", expectedLevel }; + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); + + // Asserting all options were properly set + Assert.NotNull(options); + Assert.False(options.ShouldExit); + Assert.Equal(options.TracingLevel, expectedLevel); + } + + + [Fact] + public void LogFilePathSet() + { + string expectedFilePath = Path.GetRandomFileName(); + var args = new string[] { "--log-file", expectedFilePath }; + ServiceLayerCommandOptions options = new ServiceLayerCommandOptions(args); + + // Asserting all options were properly set + Assert.NotNull(options); + Assert.False(options.ShouldExit); + Assert.Equal(options.LogFilePath, expectedFilePath); + } } } diff --git a/test/ScriptGenerator/AdventureWorks.sql b/test/ScriptGenerator/AdventureWorks.sql new file mode 100644 index 0000000000000000000000000000000000000000..2b11b96c6d4d98eb20a12ce57c4eb6ac50539838 GIT binary patch literal 1969650 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�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 literal 0 HcmV?d00001 diff --git a/test/ScriptGenerator/AdventureWorksDbCreate.sql b/test/ScriptGenerator/AdventureWorksDbCreate.sql new file mode 100644 index 0000000000000000000000000000000000000000..c7baf563eb744e2570a664c16f042088f3f5f684 GIT binary patch literal 786752 zcmeFaYp*0(cAj@W8}NUaZhe9 zw;fMD^>VEpu_H3_RAyE6@E~zcW=8D2_PXCPyhbuub=+@ z=|4aH{^>tG{i~<{{^`Ga`sLGaFYkZ+^gp!MPnM&9^Yni%FM7-{l{fg z;Qamq_3NiUe)@9x``Ob^pFVr~#d7wu`t|a^WB11wj9))} zw@~%!>CZ2;y}5jP_4Lj19%_%VgZiI5yv`q)328IUoWuu_LHaodHMUz<=oqW zPp_W-^s?f2%lX^agcolw@LBiQ3vJ;4s|D*{EpUIeeEzGaAC^yVpZ>Sy?@!<1@!7(M zpAK03>gn6%+&@{kB&Od!{cag8W`DUrVU_O|7{6NRd%LXi-Ll%BU5>HBKY9A2<;>qN zF#gNazgu2^zR2yrF0%R6B1g32uP;Y`zsUBFp8o0bf>VF9jQKwn8UEen+uNtVT%f&P zR{xg^1xGsY&z2E?yUhL%i$3uA?-woj;pyMJTNzDcbn}@H5X1-ZoSj8_t(3*d-tohxto@+ju((jga{`~1*ENgzV$nd-6GqQXf zXMeY>@Y_X`UN3g~+jlTA~g-QsWbk8c;6zh7wA)A0$f z^jPV>Uaa%GWew!oIsU^%!W_Z-{`#T;kG0?tleO>o$zoe*15pca{|FyqgnNDAfA?d5 zwNOutd9(1Tjz7`{@S#Llbn*4FCQ<2ki&mm1-3A}0pa1K!-ftHTe7mgq!-56!Al?&C z;RaFtaXx^2CHnBION9SnSsQNra(S`3R`EFc$yt82tOCEuGJaUzk;0$6qx}*3N2JvA zUH1t;ESP=2WGKH``1Dx2EZ>BEe7C%?1$`76fT#Ggi)P>@{`Yp~v3Q{mTa=Vg{CimEcD^Zyt*cna6j_AD#kB#Xd&k!~`tw^WIuXwZQ2cD}}^I|kc-8U!o}0w@a1#ua`=g4$i+@j#8)7Y5D7=D*yfR{oh=^ah4v-Zj8f6;+Sw2=B3Hb&Tov7x~lmfZyr@`u@vzQbK3U_0p5+ z`JkN`vS#f+dj6ZI|LF$nza0mx@t2oX;T!9Jcgfj^%GDv#V$u1^Sb`zm;xRaWdy(O2 zTi}P63=iKIe`6YS0rxR<1Xou1%Z0mSdhr~OS@8_#w%B|~UTm{2b3vjYR$~_k?~2WQ zJT9Hb^Fwm4`?|4izytp9E|-Rn^i9X8`SE!9JgkrS`W!EQ{mR4lPyhE4^Ik16@9&pb z_wO&g-~YB~BE4s<=Fb+s(l7S)A+9!1rQ$_?y~O%Iz4*To7b4rYi{$Atk&pb>r_UEZ z^TmSe*Oy*C{rsQ*!zaG|bQ$5h|FJq=IrhzRbtIo>@8j&*h!1;gi|yOxYQ?t;zg{hL zyuHx!&4uQ#mnipUx$5)Ta*kP_El0^OJ@&=&?aSr(mkZ~5dC^S=Iv&z~>jKVRm3@or6E zyB_#39~$1g`+K!~Kb8R3vOZttMGDXet2|4^h|LXPCqK_TF z&o25|=YI^JLYcUh9h}4c7yqC+j6Y+89WMR=AA@iBYLOkE$MabHv3;%W^;R7l*Q;+@ z1^D6betvn!N7e{zbx+@lt80ApLF=O(>i*}>9X`uHee;(WPGQX*$5CH_JnHk>-~4p( z2aLK0e#L`*ieApVaNvalFC2K`zzYXnIPk)O7Y@8|;DrM(9C+ct3kO~}@WO!?4!m&S zg##}fc;Ubc2VOYv!hshKyl~)!11}tS;lK+AUO4c=ffo+EaNvalFC2K`zzYXnIPk)O z7Y@8|;DrM(9C+ct3kO~}@WO!?4!m&Sg##}fc;Ubc2VOYvW8}d4{_0M{_I}gcbLc(e z+yl=Y=$XS^^4{T?`y1=Y0vXfaxxe$9%RS;A1uA#kXAIx7BFApMdp2+$_0E0#zgV6f z0G_WdcZPnx+{fx&`P{qAGXZ$I0C$OgyWBU*vuhdui-k&_2EbDSzFf|8fBl=wJ)u8a zo+tpkpD#y+z#ab_{c1V>b~*a91sWr`xBQ#sILCm@{q}E`PjHaWJcXKBZ(|Q>j&c7joa5OGuP>OrUf@A5 zn8FqK30>SX%^03;fmD8Rp_qH!-z;Mp1y8w;o%vw$^JN?uN;w+sD4x*p)iMg1`Md}2 zK6uuyX(AV`ZdODw{z8c5mJ$Uo?qObT4o+lssdeK)k1Y0e=`@_@M4^egO87&D2p(h( z;Kg^~CU+6K{}U6&Jg4RncQWs6tYkglfxYWX_kClF(jW6l^59P0Ieq)$!XI%|e!_TP zeLDyDc73A?d91#vq3R<4$?I>|x8xvQB4_k1^PaD7*hlpC+lze#himH_!^kPAK{M+( zH$>mDVeRDGOAVBnS#OqeF^@GuZ}$tw^B!+c@_ze#vG_f7g3naB)SG%^sU}~f7NlN4 zYsQ)YK8b(NX_?PoYKE;J9P3Bp$j>+SUOephQRhY?tO0)F$avQUr+Ixj;t#$0w?M>C z;5W>ZT`PRzxO%ZSM|hoo)T;AX&}%_fU)O^#{tr9ThoeF2S?Pqbu6RqY$hZwR(LMVF zXfJV-qc8qX-t5=7KW_i`^`a&CV08t5oVcSsk6l*nd4FurqZkV;e3d!kEFV-S;jw(i z#y=!Z>i=jn9~-ARpL$F{HlG5Ywm5-V#ke#2Qd&?Gyh`wvo-^tj7wYxBaR~po=rT%$F(@uwPZbye&R@EB+k-ycJM$rxhD&lj4yOwmDkLRY%;#LQ)m8@lC_ zbc=`bWu22B=StvAzY2J38}hl^{e0pooJ41Vjm*l1q%EA5&)BQ@_B>A8tF=Riu;WdxxNbCeO+~q<6P11@W@5DvfJ}L`OY!)mUo^UQe9^5@79=zT6nN(-cy=gb4|O#DR#K5P0m9}OSC7o0}=;LX=7-oWoYo}q2w z%^vThhc)wJ7BsSUUhW}KwmF7gbh-EVD8I++yUg42li0$qRQ1@x`m?$KI`s*`f%Wgh zV|m+Yh7WiZjz#X>$Dmtl`rRR*?D($^1lvwi?ur~V1u92TD=SKOF*UgW=d3PLGl}qgP+x27LEI7b--qBOIPOg$; z`RxmE(tgphaSZ)`^yFv^{vAKL&1pI;Z9{*d1mIKXy@f8iAke`3nl6rkF+DTJ@W+dt zE}@+<*XUx*8M>eun_ts~pYwWNVuA4P^2cGdlUtF=$bL=_XUV9NAaPDi2af0pu{Q-Lf=(uCyacn-=BL{idb55=d z5v#;eJd6a+lb^He3Ba#BObA&kx}j8&n!k$W@pV1}cQ|%SkL{>ugWlu?t-wY$@CIGy zb841xEPGC&$v*Ww_Y9n`7S1JVx?0wtpTW5v-Exk)k8|q4I8Qu1&zQW#iEN#<$q|Y3 z`O_zLnT`3gbzna)yyVxOA8~~TUk!Ny@@8Y93j;?fBqt}dqr+FbG{gLxKeEnWBS!duEp@-er)Ygnw<2kPl zg0DNYvkLl$-Re=v%hCIyA6o1WAZuV2E!rHurpvR&qYLABbJ@M|U^0$3=iD2w^g2G~ znET_=n?4>~_wi?E`8eJl;2wPC-Qk;0ug6CgaA)jG@hf}y%DJ4}V+4=XA^d*Hk@!Ye z0G#Wk{<8BNZjJeXwOb$C?F#Rtm1G3_@$;E?bf$kF`-)&Yj;E{2ZwU7}u@iRtcV24` zJzwBFI;gFTD}TOVN(I2tenuNK&nUUJH;N`k2>#E@mv8uSd)< z@9Q{9o5#C+l8bgfqR$>Z)7&RK50Bt?9gjUfq73@{dAvr7$T-@Cca{hE_`IN(G4LSr zJqMd8at$^yW9_%IPUebCx~~=zS2E7%GRG19p^EAHs!omeGUF+6?u&&7!HaAr z+`&J~vmV>fhg{WgWOz#jSaabmF&g{0jh^7rp@ECnhPZcY+dsU8ULxJSaC#qHtmWh$ zeAc%_Ke<8!o!vg=!g&29%K8>|O_bd41b?q?f4(D@C zN%?e%YICUtIbSQ&1;Z};c-P~;KJedzN3FCs*Xw!EZf!C44){e?vT!m6Y{_w~a~3!G zmCQ~akG%p$lsutNTcXDx_1(_b^zZ9h=N<5|d*j%;Cybuy@4{`y^Ost3#DCN^=9Etf z{@g#g#$WlY@j_ql2f$#xb3N;#N8bZwWRBra@hts~&}QB+?y-ed^#`w%k->-hwT|J# z7+){y2jipim7Y4^>wWRlCaO=<*Cb+Zvp@t*YZAC3EZ zUrccHK7KSBS;zkPY@WOJvvZ#ao!r%rZghJ=H_XS$ct-fxq&{rx+xGNeEBh}NUw76X zv6EyUyzk+wA1xbN+t=Ek_IgSmg3PfO`?l-*8Swo)1EBkx8DIDDGbUIs$`frBoV8`Y zyC=+EY>i8fkRxmQfSz-{m;e0O^u=fSPFz5y=VFa!TveohB(>RypEH)|A#Ig{K|D+JXSvLe|(gD=mbQ|%Vs?Csn}2S-rfRw zniswXzqGb1a=CMI<0&zCV4p)%z89F+@+4!N{%{6E`#OgQaSlH+kKM#LIz!~Qc^&0& zTY7GZ-RjzYjT{bDJki zL(h%%tLB)wUVLwUynnoU96#1JH0KAk#k?Pb4fOue7=wwk>+{`r&CXX|X`Eiq@3lnc zkM;W4-&DVqeDVvr0?g^Y1E0X!yt^lj&S>UwTzi)n`ZsiqY{xzfPo=sx-uyzlnT>aT z=&?TkdgbqHjeMHRMq8l|MojEB4P3mRdmF}keseB8woxAO+h)Mx?|5~dqAQuR<_G=vK9)W=K8zj! zH6d#p%^h*5eDr9}h=bS1s6FY7v;PpC=(VW)#8>gDUe!m*vD*J(yuhmbbA&pc&zw7> zpCi7<{P^+m62E~Bn7@ak*4p;nv@HD)ayQl)-}^aaPv-~!XkS8U9_hsBd-wYSoxkQd z>mD;tkGY>ifPd`nb6) z(mN;D_PR!-LJf?!Ah%X`^Z?|g-S&ZtUn4JP9R6WXzN2iObA2mOI9R$S-rji3b2_*~ z$MYS}907;uc|Q-%$9*L@wC2THkM{aX(f4(JIQ9Ucu5x~C6L|KxLb16<@F-fktc`u_ zL@VEFpTqlnI;_!0ul@7ui(E4vXqDH1AK&Sxgg!^&Q^IHbJh*lL!*}!SwQoY_IA^U@ z@n0S9G_uB#efP28f_{3f&e}k~r>~?IaG&p3zi0#Ogos?w7;Pmw2F31`@Y-W|g>Qv+ z{WDJ<%^Ajf4*9t5Y!8b2UotCm;E??xeYbq%{-BHmJ~o(4(Bq5-A83Jga!=m#J=gMk zUOV3dBK=BP-+SnB%ZMyg)Oe(|ivXyiU(tZ3Jl0l$Yb&V_{`re{%E% z8C`JYKiL4!1@?URXC6W3o)v4?j_$KY%>grGBf3=hYs=~m=aEC<({tB;ob|kpexK_; z#2s*84f%`)bv)2Bvjx3H_kD7<}-Cy4)y&qS*2G}c}?Td$p)-2;%vmEYt>=-xQ z&vyiST+h5b@`PjXL4U}8`!5$CWbC6i2Gz(vI&#djF@Axkab{hU5yx)l(MSinO0MA^ zY3MoPLHEzd>uBuA-{Y|(PVfsaHtHd~WqppTv&x|Ry7+@5yq-@3IwHTQ$wvH$x%kAy zC%cEG2jI-yoY(&WWlk5puaSQES+oORK2>fLf4I&!h%E&REi9iR9_RUm&TVrKb<}l6 zKZkZfVUP8t3xx+Uy^fDEg3h(>7Y?j|Jg}*}@@x<42l=B{3!UqAg|S^jdj|e2zi}4# zDY>?51Xf=I{&ZNJ>%IUO@YQ&3+)JIgjeDg#u`!Q?di8`ATmxNVrh~i+s2C z0H2&MdE851;1XVbKD9HK5Cg5W2tzM!dq@6XE7%8-2YJy^Y!=q zEGs`ow}FbSn_JIx8_%CS1BrqoU98AVzQHSKO#ig|EOJQnmTMH$+WI!;0}op!+wJfe z&seit^;>Nc&$-+pA9OYNm7f&v?(4vVb(2?`N6cynqD0mV&g}o~IGb0;PB_F2cDujH$)5Fesb zJW+^ifXFENruE}rg^zvZg+4GYHKR3vXQPW5V~sQ3H{=-N4C_*Vjq4hNj8Q$$32gfB zte-V6W|M2&p=VtyL|(3q9`NiB?xE~_BbQi@h!Y!-=jUchW9}G89cN< zD0Xe{`!nawIs9Fo{ZUeOE&V6D;;-oF13d>6cJHu`{=M{NYp+Ci=kZR==ecFwp2RV* zYrN~Y&-vOqUZc)BdA?S9rrm$YYezx{-K%SK?2YS@2VISSMTcF%-uY~e^;~Q;(Y$yO zIP!uW9M^Eox_dk@&Xv5&#$qGBqdUNmUyN6d)>fR2UM4=)JaDj&!8z+BeQu9U(RXY< z@?$*TdF36Ov35gu$e;0Jd8setmu4VE8L^6(%1D0s!;Zass)Dv-rsZsWp|Ppg zF})85Ukc}n#fiytKO@Z1exV6F>^O#hj2~-n@CI(i*7&ncacOlyAi3R5F&Yo^{yH>&lVv*$W`?1GP0_4SCZ9X@>MK1j}t|3~=p zx<*)|5@&sxm)G~MCmGY<9k0&g2jCI*Ut`i2@krHs+6ES2PbKFoU)C<*6?#pL(fP(W z;-7sCax);I z;W7NOFSNcsJgbN8Pug4b**axY$Ln?+)r*-AfKE8y;|F?%ekLar|J!jluETZWy7lck z7iN9zK0XM|VC}KD7XN0hjFzs)Z+~0OoE=#2+e3g3b136Bk*BZEXRlpEHgF7m!)p1< zXY?$((&a<7l6;8qa$!H0M;3X_uLX|qSS#yxeS{vWu<_We|3AXBAEEv_7mWKD^`~bu zYyIJS_!a)9X3ce~&Lit!_KkMl>w~)8#h-K@>BESHNP-N;d0Y5A)$RH4(_h$!&oiB# z51+Zm`17Qd=fh8)vX4JLJU$JX-^PFa`Vs$$kk5yoI(;91yxsHRQ>#T+`?Z9(mzYW( z9;?I}^cl&Y#mV@SQPI_2_c@Oof&5Pxu@k)t=j8h~_U5XmE5z?)p6}I1>Gjt6{slgp zT6N7wC=6xLPrrhvWY@7Z9^4^D{2lRN-kX7!>v_q;xATY)`|C;LdOdK6%{UiNMhxn( z@Fzz;wEGe>Fnb$?4bni8{x=Uki_6Hx=vHd2z_fq(elX3O_hZi(D~MG@EbDP8Gj}3` zuh;;O&-6y*d*>yxKpRr?lD(0eJsm%z98vaV&}h4Gu*Sn7P%-Pm7@Pax-`2Gft0 ztdsYS`nsogYy9LfcyQ(%j(BD{MV--QR=7e>e92h-SR>;pd;Qt>u`q8x-%d_WKHl@~ z_`uOm>^;xH-;s^|j2I?gt+O2_QtQ0NKDuwtto}a2r^04dMpz@%cXhiYbqzk_9c^CX zFGuwGB_s6=-J`bPoybCt!(4caUy_$2Rrm$`mUaEM&vk2`ktc=4$ISbT)|S@7#Z(R-zG1o(7;i3{+)aOCrTO_2JNcW_8t>3*-*1k%{)u3VdQ%ySHU z7|)rj6KOks;}~=6{d^t@$wj)hB?b{Cu{Ls%lCykfO^)SVoyDh&V;zG(^muq4UnQS} z2_E=jtJD#1%f-+s1x^E1!79N7wPn;gVM-?-=s}aY4_RYmLhD5<0)3 zjY>C~18jU_;+j1Hd?h?c9-f#p@6!R3U2q+yI54mGAp=L;kXHOBln7_cCCB;t0Bs2x z>pPk;>&0hZpSVRf#PL1fggi4YeXN-*;7#;Gd7AUq*e(ZlO$PIx`$0q@A)Cr1fC(N8ol{yuVA z>jmqkrlIR%51vfH{xdYA>GWNoEpmwuaIf82|1W*|u(ucfmXC#IGOln?o60(|A#;1L zSLIwClWzq<8DTr2f8^=4HL(Xcxz@RJc=A+OYm}q$t^qC2;e~p5cAfdPr87K#dx93O zAFx9@a?w8#ht{;se5duX`oG8btsg4C$jq)^&!bhpU$Crcd!&rrGv+yZRk3N*Q?6sN z8*QDV$4@hF%)b-kdagWPzv}&FpZNpUypWOiJd{my+&pic8|>wC?-Se1h0WQ3gDrMS z;Bz12`QQ((=4<9kUc<&u;nC_9Urvq~A7a0SE_@#+ue=7vPK4r%II3Io{;c_w_AAW& z9{m=Nj-UkgYw&LVeH>%Vo3Q1qg+5k{F`q(*J70-y z{;?WXo*09ypgnLISGj-ZiZ%ySERi$F(>xO2HBe3ZK+~UYp|cBmLPscBFl%Ph%Ym4 z&sg4}9o`@xWNglAFD~P-{p7MGL*_z*5(7sgG5RpyPmnrR+0x1C{DAgZ9Y!oQV(;U? z{l*>E9uD>-p+OwT<@>y%6aSc(z1W$~^*uU)DM#R^{3w_s@9Ow=E$_X{`s#Pr%RU2r zwl=B#b?mb1*AMKi%=hb5e~GLbT|h42N>n8O==Ra;7kN1AN6q9YOmqA7^*?AppY$c@ ze|V*j@tZlNIF0tqv2j1Ic{+NnKOlY<*TluX(A>tmZ(=mx)py|eJR#)^Ewi}noaj97 z@R3X)zLjHmg2aZIZNrzmuK9f6!Mh`P;~K}Y26*_7BY53c1;4%q+$nmI@49x?A0uaY zjE7=(A)liI(64_|Zu>>a;OFLhR@_s!w@d+^k8BbJz+v9NugNLje7Lrmx~1FeQPtPX8e^ZVW7u^Z$!KG&Ok zh-2eD2jF2Z#%l~l1#=GLraH*l{_W)>tZ(iRt~oRNIJlpIK5^aaP%UnHIp#^oA=pS8bq z4nF#UR_3{ha5$R8(b%(}tx9jH*O`yL`3`TA^K^UddjuGd29d4o*XzOqMslNGk5z8u zxZ`@=F~{{fW3;E9cf_8c3pF%lekUuSbI^cIIp6$2`rtEp3H$HFf$xs<-Zwnw z2#cJ7_|9D5vfA4Pdd=VC2Rawb_W8jcbZvp0vg;SLfX`Ty$OmhvU@FZO4;d9e8)TZ#`dxuV51R+FIr$ZyM{Z=m~mVdn>e2 z<%F#F^&6Sh^%lmFU5)$zM|3TA2xYvGJJ+`26X`OL>5Xv{I=427{YIy?=im>Y3jTa9 zdloWAU52;(QNOY;4Sj^0sjauZ&bWPzc5FL7?g&$zF>XrO`e(i-7_X|%?R#P4ag^6(PiYmQr&h>${&M|_&eo)=gmPcEXr`mGzuyge9^KUOd#RnM!ybGr^K0fHa{DfXK zre3VWk@%nF)9BXqyz{Gn@NJoQE?Qu*sTJrMDVv^G z#BW8P;(xZbSW-f+=AilgX|nabTymZFIWAZR7CtGqx3AM@?<0Ut_@Sp8b-MU*yFScp zdsaUj@fj&S!hZYCro@H!rFE=N*ScbVv`bPy&vk!R=JzYM*QfArd)KFch0gMhZ%U2B zclBnhLAcLY9k*5>N*UK`28Qer7!j z&SZ_=PnxeGJnHN8I?nYryq;2Pt^EnM_RYeh;G65vdhgyR8D|nLi>GuEuMi=EK(@~ycjN&2!k^cHsW|bTo}-SP-**OYfEGRi z1N{gbp8@!Oa9CsPkJ^i!J*y!6IpT%#?0OjcKz@0_2lj&dtb|09@B{uGtv}P5Bb2>5TjoMn@%wl#w2`N$M~cqEgY-J1fA}@}EF*thg*n(U@9}qx+xiq? zM~Cr&eJyN&@74``c1`^?cD%@$@uTbh4zi)HwZ~p-UB{0a4T^!e zf6pphQTKQ!e}JcOFY;3#*7vODUQPJsy;0~~dIMV3G0)LC?A|%_oUYTvc=bt(sQ3V% zZsluWVOx+E z^I*^Cpo{9Q^WayXcaGkQ_eb=4|4Jy9-tJS0syPck%;)Kg)V);wS>>$dJ!AMhCCz;D z6Mc#Ki7>ra>Np4J@f0nhrUNeW-0~O-);d1(>)LyAJogB#uN~qixNm8^ZwgB$x3jP5 z`^={G3Fb)Lrx9Cst+lNS)2h%M0c)k#fj-f5fiAQbc|<1gGJM$jwf%foy;|F(KFXTQ z`|w$Z@8EBL)9>ttHqOoM<$Ml?-*m4<;v@9(hkuCv^WFMbje=%;q3_yl*AsB1OJ~pd zOnjcjg(Leko{OKpr10CD2R)oK4#uj`Sndyo-jZwj1R14f^gP4$avn>{XWp%k0}sfl zO)?7J?Z2vDAjjR;Q}Fug=nZk<-0w>vH}uy18#CLC+pOR96&Is7ZQ z^E`5-11-~6vBI^vUAkP^$XxKhHg{ZCz2F`e<{1&pA<$)Q7L4GjIvWnTcaOb@&zV~| zlW+gHaF!Qcm!Rg1%tyHa$2@)H>DfF63ym$}f4UrgEIfq=vmD2q+`qfyPw6j z$!NG9R5{PBIZKZhM7+*R);#iqSVkX@{m=Y^xX<+FeB9BK_kNOgO9Y1IXi{=4zT^Lm zpTwYyL3e<|J9Pv5=z30y|9j4}N?i{xBkbfF-M9ApkQfI~j5j??K(}Xg0M-Ugt^wT4 z4Q)_;W^QU-^273VBYgebdM|4qBX5b{dBIovi(-lPkVEv?$C`{u+z+2R2j=_oj&++g z@UV)tQ@*`I+0mdb4()(kK1dkOZ*L#W64G5L|&WFP(v*Yoh< zYj_NQ=$&+ZW?CCVRaqr(Imkww(7Ae2bj%>*qtp&lH?6Y{E{R8M7*Jn~=&UpsS%r%!NeLurL z@!}WBi-*Y4xDa{5yN|^~X@(D7x3v557_`85{DIf4Y6i!7Ij`4L=rdjb`tlM=dTfzl z;@$WxWOx%DkDTlU*e?o9o|jE0GCbwDII#|&=tqIyY~I#C!WVGIQ}mi8_DgRepMlAh zW~OCuVc`(8pAjIL|}!Md@tB*x|9X{%PZAx#TVkMzNO2@ zT8*o9nHgN|uVwA?xL5~o*Om6rYrZw3-(2MOb>YFfZ@{tj8tMmQyFcMOdPDv-`V%6u z=YWJiu~za}_~PEbnOx>Lb$%l^BCEPSK4aQ*u7!_-o|2TlxUQFgYn|0cGM9Pbyyxvx zB9rXl(sQHh(#t$JG}6RTd_(d-x=#2G<;8K=>R6_SNsZfMu{m+!>nCaDzi|`WCMMxo zYHZoQ@^!p@tiADaK+B-(NX3GlLQCgc@Q5cFpHIb6akl^1C5wEl@9_rm1StFc z3-E!Lj7{Fyvn}&>#{el~%HGgle$dY;1R?efwFb*294X%j- zi*?XhAb|(=gf(G{;;2Tk4q3v8H)B~b_&auf{a8MA%`=|qOG5$2_`_n+NBN>Y?*H}$ zyjH)>t4g+`98-@u{yw@{>)uB{3m&|l^L?a43EXFYgF3s_XLJ~OZ0l3=rsOhXj)tEd zue;#y)i?48GZggOUhdiFN}#v$2|t2XqOayfNR@TR`xni}*81CF&>4CjjBB|WRv7&> zzvW79G#+0e9`c|poDoQxy@xzqq~ad@+KYSkhv6yms<@Zf9Ut%diF?Q$Jra|`O>E!| z$Jj5G+G*4gXRQ6#nEzsx6(3!ReiFyT+-!guQ{WQ5$&MXwACR;j_*1Y{*U>9vhMMt z{I4s`^MUf8J?155kH_%etcpIsBde{fsXy^oJH}({{To1;??0T&5NOM4mGqyDqa4=lA80_vdJfW3S!Z#++22mwt=ANi!S! z_eb)0zU;v5Sk@yi;OCYGtcT~~*ee2eY?!gHFFIQ`bjw=DzHy{kId@#m)8@9B7y}IK z0$=X4?#6qa6JKf!K8>~93m8kwIKNjsF_Yy=gX?%ceLue8&%_-bmak1Lx$QY=!h_q_ z>KxW}9Ju8gL+IiC%ryq=DszMT*}0FqK0!>x#<$mev@!Vo=<5~uCu^wi6kDI$uw#3_ zPurRKNqnA?GbgLK$~xvBXsEeBqB;3&w-KO=CU)s&8|!I$YDI8*G=9)FTtANnmj)B>nY}^`tJSfTj%)L_@y#|Bl zmM_*y@iDP$=H&%H(O3RsTj*@!apDEi#CE$6!k6q_bI5Oe_jT}ZL^}K~pR-2vggi0! zjQ&V3u~3}6p0@7MmYz{l_3H!Fm8=ncsUAMjJ=Di$S=;r`Tp!qn9e*eM@Edyby4UrA z@ajA+_qjfB`?~1PIv3{{ktAFpIw-H_TptJzta0Y@jUG_FD`W2sEj=`@^>LgVVXx(T z3s2YUNiSY7J;*h0Z@mT=T+_E2_q5DD;MHDl$POUz66;hnVtn3mrx_26o<>jj)azS3Eo;{K-VXxO z_WDWJd$`r>SF%9(Sn%|sHD}hN>KL!O-Cn?!;e2FtsE`+ne^c!wmGT2>}xdyIezq>+L4?O??-N!y#W4JF8a`Yq_Nv) zZ@^=5Ngs!?<9u;8XVim@=Wo-4>|scak~n;%2joA02zmgmy*3H$T({!-g)-;5EVhY{ zG)5pjWsR)rGd;~5w=TifX zzFs_T!RMA*amIt{x!%4uycp{idlTz*lp%UiK3$*98Ln51u^sPF{u*dAT`(>(?wl^L zerj~qM0a@!f2#{y_#ajmw4>66>-gNF3rJ$kgVKfD*WS~G^*ZVTakJ}!aTHl@<2(MJ z%!wExUdg+{8zUKc*VvmNJK$I6;s=S_;3=O<{^CTWp=Z*42WMgzc=qiYdwZ8_p4Y0@ zxZR^~0(RJr@AhVia78bl)BjQT=lzrPglZhc`=R4RC|6P~&v44_2 zQpYoUYids^RB_*4$EbgPJ*LTt#xeO5Av>`!dX9D@YkP^siOn4%N+i6Sn!3q zojH9RG$SY8wF|Ve*1{Jn$H%Sb^>Nqi>*aY;p7;Kq!VGHiO?!i0YslR9jK-q*9!Gw3 z`KVo)K{f+F+fCv~LeJns zba79wup{>BY;~%7{EyV9;DtVE)7a)#pFSmdso6?Qd2Ri`KW=%E!JvQWmG%?;#$TqM zz;D4nedGH6FrSYd{a`-+-8jb1q(H>39ozLZcFwW%th?{^JQ#AG_$Q3*81K~zj1eDv z$ri?TjQ1=A#)u~|#yxnU$T&zuF5JgCiPz(AkvMO}xBK`#nzv&*47gLTIgHtunxnth zYW!~;t`U8IJNhCAdu&yg#$S$5Z+OaUL1Iph_k5M(*d#o~&saZ<&xU1;ah)W2q<3r%lh&Mdyn4l|1`%mZdJH_+)>d9I+!3F!>?$w|55#krtywjhu52pJd_0u_M zSkH>|onuc^8APITJN1Tk;eOT{(Rraf(8jG@>Z`Rqb91e+=ow{&Ovo>5CG^&~fjyHk z^Q!ZF^1i@tF6Y$~^a0y7zb@TTkKh&gb@|)1zO$-h^c~vR^Yo`+fp>It2J5;m6)bp! z6@(MTlP@lGXa7mg!wqRN{%A3tySoQ5TCNU$Up4!0}v{ zEA&Dua6=*V?~mPkE?fCWZEU<}4Cv*_%)ijHt?egPx=%WG0Zz;Zw(@tC=xV_>7AQmL zr9&0TK^InKjmsxuC|3Vwku`P=RQ#aV75EGce$T1=yS8lgTk?R9<34?OTQ!gVXscJ@ zHJ+g3i5{_&gT4!M)k~r%cpzemAj+Jz3&E;@0^Guhbv?&6Iha_ZFuPsG z&y@f0Y+#Og->A>j2l#quKZfZw=yNcMIA>_L?g`9ee&UUs2QlpD6S*IPmM{N9=Cb1hSS^6GhPJ$W?VtYWX8 z*o;8`Ks{SJXAYNp!pei-3zXX^-_QUq#D6?o&B~lDuQ}sfVlbu%tmJBXvokQZoji^4Y}Ygd+cQ1tOvo^?9~=;dtS!= zP@-J|k!!~K5zobsQ5&+?!nnJi-y3VqudRKzH2`ZjUIAuW1xc@{wuXLIE{5haO$;2=CJ33 z=i6kDFPSj3kNre?lEK?`@q(;bdxGfexOVwNaO0T$q+p!2sTHt+?4hwQ!ZUI*lKId= zZZ{j-wW|1#{(?PxR_pNaTi~Sc%^C3=?b}@T)q-C})f!Yd#?&_6@pE+)@ao>({1}d3HO$Jx|mXX*IpL1Q}i$&&n`W<-HI6o0T z;*&Yj=~DaQ$@LhA&A`*>&UKydUSU7Ri4p7f{$r0ZW{X9aIzar(TG$!tKeGVPwP0TePi_I2aDj!w<#_Pq5tF^TBPnmz}VfEal z6YEVK&J&A@CUkNB{4C@7Ixb?b)UHI`?#s-FvB*97jXGXD#YU=cwm&~P@IIVx{s9j5 zQT3%f==OPwU)6r$LvV&?_sMnlc%`nxYhLk>!MgL^5##^&*U!h%T>9B@MnB01S@-ot zuZq|9M7sYwr)$xv(N`kH@KZioqZKx}&drf~+56-8xoa;K zFXI`>_~;Ygi)!Ud{#Ey7kY`&Xs*hysHDBK+4uKPW1hV@*$a!-XzN%Be>3N*F!M%GG z$UHuJj^`Xlvg|Q;&?d=wbFI?-0`L?0C^hJeZt>av2YHSC5A#N9pKT6ECFy<&^kTeD zjh5yb71AcF&pLUp_2x7M2kJTKu#Un9aowGKA@vJS@dGOVksUg*KBwL>LVtz-Sda1E z74#|eWKDGq9T@4dkAfZ-eDBdgpI9R`TXq=%gJbFyHVbd(dIXHF}lFRY%5Iej!Z!Cd@L$6t8bwf2Rs*ZQ-*26NUvN9-ay_p8rsrDVc7 z(g;sOEAMkr;mIfUApe)nA`naVC6l&ww{67{ao-MM;!N7_jpFkCr`r%lAF5s zC3!^N^^f@HTXR1kxX&H_#Ghg(TfBO2*z^2XcgQ_TckG=KgYt5B6=QQGYj8z6ep{Yo z1aYA7<4*US(T+Lie&g}lQE*TEFp8K@7X)L1-(6SPuh*HyMDXJHeC)`l8r$Q)*Ei_c z7Dm|{hduyneXMUf&V0&JQ={MUsOyAdQ4a(}6$6aRf(d!@9=I?Xu4cTLbT~E|$ zIv%|qazEBO_qkS2kMad~Ih%LCk>PD~eDrnQ=SBbDUUHs2+To=3HqT){OFu(% z29?t2c0cc&ZGC9225&20(@yjIkfq=FCtvCyb{W4+E)2i)1<`%{rFt{kiN`vAoYx+h zlUfp(j_rOYE3eKz{w@wc$o{v>{`!-W3wPta$tv0oztNBAYLi(k;LCkuagR~DUL zp{3gjc)QPX-S2SE4ZZ?;xnAd0rd)#?X#_9p%ETBV9sWf7q2|CpAusG$oW+j0oM%tn z(RnhAoG-nBC-SQFLp@M8Mj; zdH`*S=fuZ3ZRx{zcjg=4}Qs4*0kSm?U7IOwYOvLLHC;PtR3ws4KSY>ua`5b z^bX)^Rts=sk7ubNW_b;Ej9yKElu3C@_$kc!Ps>hVBrx$=7kz2a=|$~^^muRg!VB5QIz@bBx5I3KSEjJF#Y zUTM9lue&BYs=`BdZK{*X03zTb{1-t796moKYvUcSAg` z$rSBle$h-d+i4hSc1PE!17m)3jIY;d);N#9$8Zg2V8j!4-8g6a_^{U(8_sxqjYoZ6 zZm3VK)N?%S5S_5^I={Ch^Lsw5oxZ)STj%A2-|y`Y>5b?U@z;5Arxo;fyX74Ezx8ni z13u>^j4_sU7_oC@6By&~oeE>T4lj)E<1*KKUB~suS}p63J}&dg95Wlcga}Y9;?&}&NI$sUVO-U9&6|2JoXyYdV6?g4)4x0FJ-;> zigB&+zVXa4&r&C1^W!}4$IE)o^I6)`hIOgm@_H3+T zPiCkUZ|bgCu=c&aA3bN8_x|=ByIS+5a=!4>b)#d6YvVk=)l2#L`$No|&%tx7=hWUD z&OOSf?#rO?+4@^5vwr@*@|fGa_q=4)HD42NM_Jh09p`)sd|m7JSSw)PRr{&miJAH; zDS`)BeYbr3FZeT{aDI#@x7H@aWN@iGW?iSStJYj5eD3;U&V%OHSum?y=vMmhw%Z!Y zUQOu6Uek-CR_^vAPrClXM`~n!Gv|FGO8nxS&%jS?&$?&%o#$d@KkV5x*X!ByK*sl^ zhkWHW{dqrnYQ0C$qvm}$dir{gp@$VdBt5m>Bj}-4`;heX^&UeHdBca3kG(0^JEDhY zri0g6UjwZ2gXd#O`2y>|v+MP>j_6>w#qD(1=h=&ivuFN@ch3R2&WbJc8p7D;{_yj> zwZAyZ%i*wK0B(b^HJEG@#av?X{*UMvCZuKv<*8S;tpBQ#49ktf|={SyE_zClycqM;L zko-B`+9X>I%=&WI-Xx&6nuEQuIG+vd5*o;dPnp`19;!o zv#eXMzK7`6dJmtCEN{P-m206@YZ|-p1017fn(q~g?+*oA`tXbO`t<0Nw)9!4ZVOxd z&2isnORs&nf>H1yPxPB#p-nG{5$Nl>KkSqbr#Cu8U6FD=2u58Se)NUcrYy@P@0Xoi}_N=Kk{L&>)cmelo-#kapro@I2@}H@();Kq5ZhWI$z9FUo9j1IQM2050KgMdbi#a-h0OI zjJ+T|SH8Ah=srtd_2ZNg>vfv1t>^ve=lMCK4;{$M^|JSd-7q;5UiY3{>8o^%&-+Gm z&<9`9S2Q+#NT8!vURUnA!e{LQ?bA>5+d`x4y>{902O7MuekFanwG5rt<=W@5hI?Ap zvN)b+{^WWcr}@5};AvjdV+m)}f#R>c;d}TQuI79ErSLj0?LqpC3+1F#kM8>WA$_U&KUe0A4d?J+ z*6cY@fYYA^#(KtbbkSI%Jos)- z*Y9;+2dzV-v_N-fde6a1YhwsPn2Po{ElFq#QjsNb`p@)C`>`Ayt zN1Hjq2`5;%oZm zJnW_B9qHTSaRHBWxP()s|L7>3*BWxZ-)~a-zi+#@@shQ$Ml97{3U_E_ZFM0wuDrRo zWNyD76Myvd$Bh43{(JAwkC*=={_Y<-jzzcWbHyTkl{KzDq1#o(psL5zU(S>b6E&*; zqWz`MfXwpZ9-@2MWZ-u@G^;aKl>apb6LZ;1STPsc;TwKG7#at;`p6xF#Ew2bYkJH% z^BNKlb+%t34i&$}fqX7CcH$2!8f%!deHJL=%(3p70~%kD`y4iL8QnRPPYMg&NiJA@ zH0T!2c+5G}U&KG?ua~-(d8LEOeD4{c_-Nu!-t~!R^3sxP*BRGAXGXa0+17r8GdT(L z(I+9&cDaKO_Q%tF-YjQ3J#d-b$>i70(X!ym_MT<@{OtHl*IYBtaS2bvea#c(v+kE$ z^Rs`v%MDII3wH~`YuTo2#U`-I^~o=bzwz#;g*Ubq8qx_~NjSYn$D#STmS+hGLE(OZS%< z19A@C;XJViJ+9b=UCggVpo7*f<=eWf=Y9k$avn4%)^#1bHV-;8ulvAj^S}+>694)< zJY#SIkNLe@86&T|&N2sha1Yqv7yYxxA1?D=`li;6wJ*{s+gIPZyb3PzN}ON!SM&!x z2Iv>jcK6!+N*Bf`UpqaDlhy@qu@iIqn z$LGBSZnp)X6kICtb8x#Z2QKvIHNurf&mH4CgWL6SgiA*Ge0;kcgbO9|9xU_n9(}&8 z^L6i6jox8FnZsC)#}?P{@R5)5VOg{D@;Ha*shGiCOtC-x!8-P1&*=6x@7ET$dB4xR z#{+fWS-ctbW|m*o*ijc|WA#CO9PqLCy}aM&rmgdSb0jPiIhxDfKmVti-iMFZz-OGV z0g`9V@g=t01}}M3a`|pEsSn0u@{O91yCb`Qj7^x6_1gBht{{%WqrA^^Xnf4t-<95s zK98)%oWH|WKgJk9WP`q=x`JmrQ&;r37g~dJ;z-3WXhs&>ydT@c6L;LygE9Brn?HY6 zjB>&60GIb!-SFmu({bHkF0`(hgd4o!8?=vh$g%Tv1AOguLvs1@vG5R|B6q8D80!Z7 z&tBa?eE~msZZL9=zVi&WN7W5HPfDM6tzO{Q8AfWswO&>=b?o+fp~nck+*p4Q4bkLU zvB$AGnosNe&Aqre%X`6+@5B)@=uRhjA+qqfTi903b1&uWzIFFSHt6>3jiGuJiHEwIlYva=zxIZdk`Y_wQi?HI_O9T;FbDZsK;wHFC;yA?AiK^Vbq0PjhWN4nyTiyA zpF#!|c#gNOk^A^a_-7BMkKKz~<~v>H>f>7PM*T)FO8)P0k_k66jnoJb9>U7!anilkVejOctkG-?>z1Sl~Zi3GVU--o5^kRXV7xuc> z^Q`<3p3;x#JXPjne#EhP%&%M!Sp3$&^I;L&jV=|_r~&BCNDb7X$!Br&4h!_foCs+0 zEdGoYOP`P>6oiY;BkxGebspFJ&dsab0y>BfpTC0-9sBEHS@cO$w_vy8#XR#OAToyE zWTJ}(kM_pEH@E@b^D&HIjIl+%?`uWRjC0}8Q9g|yC+_q(8J*=$40Qdh&L$_d|4Zf? zeY{N{sON$^@7Ndk`Q*T=C>^7&q&{(NeNgf6ye`gk3%>>q*l~2zb>3c%>#J^|k$9j_ zGJZ-4`cHobT9q?>-BB0jdz4cfi6cF0;F7_nH_ox(Zhv6hQw>~dk?u>8UY|e8m*3v( zxSi$k2s5@PKiR+f9GLKOtuwP4zON0wM9I=L&PI>a{mN+6LpaK_9jYQ&UrWFj?9~KS zBaJnIwGnG~T-ckdJag@>&SDGJC*V@oHpcqo=y%}aE6>*_=p;OgO^XdYBjSyDYtI!K zXT;DRoi}n;IaJK#S3)|q_9^Pvt@X$^3%@!%ud14zP5;09Lwo~X27Vm%_Tp#LW9xNSa+ zds`sme;9}V0`K?&@ZdOk0b}Sk+Yc0<@jR8t$hYJeTO8JW0|&5Te%{4Lyy`f3xK54p zcap~AjFTtKg{Kus_2uL`pD%yim-k$Ud3$*moeXjE+EQ|Oj=NTmb?)I{yfne>dJ#Y9 zuvybFh8SBC<`dq`F`Pj@z)xO@K4{l<1(#X&yT%@Nzea9#Azs9%+hL43nUD%|sZf{6 zZs?A(CgY5=HP$$Z)Qtc9?=}SIJj)0m5VO(y?$eoN4K(_H^AF&`UtaK!c%J^PyqMVs zG&0|Oug{;aMK2DmavlB?pY7*#`tUY2#&P*BCxH*2usJ#`;A{=Yp0Q3h_-*}yzucHP z+$nl)j`{?Dk=dC!`U!FSYQfd-tc*nFxLFB88{?pL>~+95ZQ||a{JPIk=j}_bdmK4W zZxi@rl%1A3@BDTDgY)VK@}rNO7z9;$#b-*XF{;-EoL7I&NY(pee-Xz5OO=251fKY) z?iaNi_~MnQ^q=TsAV2Wvn;rz0N1b6n^l7RXdNsuVTtI{J@R6bBr;piGEOP zu?DdrPmc)YtV@4}3K8I#jDF4fi4JC$b>cI>8oEASR?nIENBQY*qw!-O4&L!P9K6&qK1k;p9Q+2cmKs#sOk9Wr*7AY-Imi2>k3JsJEBJf1-za6qI>ZcTM*w{@Y>@$u##t*UlcvjvuIT5oBr*? z+s`PUKYaVy(z_=|ecl*<$etoQ-l<^nJ@K5_L0wHQkM7zFDjfiZdn}Z>5a{@B?qJm^nPx+Z^Wjy?HPaV0l|8s!Xa z(J%Ri)Pjrg_}gOk@Lqkk1fvp z8N2LCzwl@EJ^6sSu)d5Dofhq9ZCC68G5Z&`*Gp1!`n#9K55~^+>n0}qyqOw*-@HnB zK*!ui*;C*=abmR3-e1-~e7<;-k)QSbVp?1WTQ)4R|W^`1Zc5%Jmgz47Fp)lWQ*30&>H zpTER&aNS@VpT>Be{1jU1#kKZ)`;hTRo@V9LCx1Bp5xX&dp+~VPWS~t!Kb52LEjij~ zAISrahZ!?or?Kuqd&$4>r|MR(k>+^Z)AyoN(8kV;c|Rt7jq<K^)%ChQ)Bh*ddVjMvSpE+C-d@AG zR{!Cf3dT|WcfZ;b{=~@wYLP@AZ=J*fTKiaV*E|55K(8>sQ@;$}9e4Jdp;6kk z8N{{R2D|Do=Dlrr0zXS%KaM?;6?A;@qyL!f@reE-dyF=3<%gEkYwK_BtM@bf&*dxg zI9T)~{#~Qz!^OWDt=D8!^n5DzRsQ~*ob>x@6nWVg&x*dtYdpWzzYiPlwlXXFk7P$Q zA>QrzWqMKB>w3;F(i=VNz5h6$>GoWgSp>M#M#R0)2UyMXg~4=p^f*VFZOkfzDL_v`LlEK z`?34;wSOu4&&cr8lV56{e;oDa)&`6IBl)@Ser`+FG1P!L&*!|n=V_czT+Pe#><}{c z(nsZfj`YPvZRs`s zkA3J*n_hT@9_78$7`{m}_egthS;^(Y$t$`$yJl1VGW;+7LXOFS`TVKr8~O5?`~8rS zvLRQ#elORDwx^>#MHD1^cdaUAV*EXHJbZe{t8&XaC+KCdZL)KR?C?&U1&TzhSX{ehB*)iMHc& zYP|jo#`WTvbYMTmo}M?LKgvI|h|@f)2A+^lfH|Ly|9#gM>yq<@E13Xp_U4<%s zH1kS@GNqy`OsMN$>X%Y&=Y+}f9tiShrLqA`p(_?XZ8KMZj@}gMi*V{ zJh_jDmwBmQ_^i$c;DlE`LuiZ#UH5=g@|R!t(SP$)Y#AKnNy)0?@YwZz=GMns-)D2( zw!U(Rl(+g?G2@#5!KR3H$^f_}gZQB>|L?tibl_vH9~qomzwf6<2G8UF-1p;KZ@X{) z2+rtNfj!o;M9Ij%^=&NS__dfol;)(f6(Gb5Md)ex9 z#yaA;@+_L+Ltq}oQ|)NX0iUl=wLZE0E$jD~@!a)0|H->*{SVK7qGqk%V+j(*-_L5eQTN6DX_zDp9jY8+xFZ6{bfC% z7FMjSjU{G!y)YvOgo`7GwlQ)6k(}2#y7X~_!m%Q^h zyvyqtZ+|<$@n$LB;|vGyf%h8z9B=CmpAB{nZ=OltWlAqt*iexd{ukQz`MQQP!;kvi zn_`Z%0tlLNQevT_)D^-_|zZV3p(nYMbSHe>dTwS<6 zKXZP619;-Cc$Sx5tJB~6B*?`3yW%(I^{e~xi=r7l&`eg=*W%b2+IW6&p9kKLqD?N2 z_1qcyKCZmb74#Ti5Pe4@N^Z%$=kzhZUiX&YeRWg2I7{n{-uvf=*h%NLeSvUvZU1X; z^1k_@E7$tB=O@*_1UGY!%0$z=ylIQ-$j{)(X`N?_svp5RhJT9&31H9RXyUrh;msg#KKgWA7KiP*1O}P)syy_@F zIS*%s-+q1)xU>8u=eD}C#(lP?$9hh1CO<*j@qWlZ>#y^Z*a?2E?1VWVE%?jO#>nc=tZ9|CvgA98N%AJ(|f*7Vq|{s9}0f5`f0{lmwrU--pFZOQ+$ ze35(<|MkTsFRk1pwF`9;SN-rOjLY-&g^0h*{p7t?@>SkVVg9lSi)U@BJ)z;I%TjAq@26SpN2jKeX(< zM#L@xXreP$c%pM9dwXN@idZ%BY3v!uCt>@WFy^hq@HwBywZiA<)0W@eC%iwu&7(W5 zkFvGSZ+Lx;-=l3NM^ILUZ`HEn`0!d=X06#Aj>du+LpP-QvwYvyWAJDHdM*A7&(zn$ z|A=>_$_U~^`Y&WSi8Y01{3B8}rer?v#t8DAzLxoA#wUmD zLT|@v%dayu0xR^4*B9zIdS7_mdcB@~iGBW_Ki6j!MbD$hm<2zTK;ga5PxbHK{Rp31 zQ0teyNaI@n@4db~+rIvX?T5(kT7RGakI`rQvbBEnxt_tJZQiQS#+HJ+r_cBBXLz)3 zJCF2d{+2?~rGMJ@XXec7@#W9-s&#%}{u$YQrWrxJfxbb11`o`A3%34RUq{@F#| zc^5eq%*3CppEJG_ZF1z?`uLu#z0EDk-m_ltf4}wk9cSqsW8Xf%gSM=X^ebz3%k1?#vyw<-r|E*i7PrJT-SpElxkHLR@RP_F1@ZWt-AD92Z;bZWh z{On`$-+fjem;b@xWALB6{+RzhyV8C5bnW7Ejj`G14DNYxEr#FVG&l07`5XNj>KC4$ zvOZ57@R^+j2S3#BStHxeS@7n(dvz0ES$8`|yyxpuy}35_pO@FEuhULO1rM#S@uJes zr@X{-q+@%2OUG;sw0TX4I~uyrhK{c<{OHd!Frvp!}Nf!lM*{%ss;c<;+ zjqua;0+DaqmvcQ12l<{C7>@a4?>{n%+@p_%ciuxb!jbRxXwU{a68*XhoQ?cBk9_bp zz=qFt9zId^ftfrW&$C+$Zh@H+8qXs;?3+DKv-AA^9`M;kHaqWcuJh}i^Ye6MTTgO;8s%jg_k?#ztN)pur%`se=nKBDAuUH|xHQ|>3?8M5GkWYMN* zls2~iJ1E`PN6(J-3&FX=<~Pw`}*Rq3c^-@>CNMT*kv`sTI(>o z__CjR)G>SuvgAG@c`%+=hpC5d-e9m7!}EH_Q&9-&?5M}w-y;G(f9}so(i8dhXYqM+n>Nsn#CrDnSCwX={@~|7*?N{H* z6DK0iT{TRI$JaE0@W4NEwD+P59-fnU3c>>nn$9qoR32%FzjubS@i}JU~k!M(U zT3vsH0bRtXT34AI!PVc$GoalIF5d7F`0BszkFUQ0et)>co=5Njuk{GH>{osST)aY_ z!+uXa!`D0luASIkw_)%1vbX!gUH|U={p^^0=KlC{*VrTAQX@PDE^+<-eBgNukAO=p z(rcxA=>u0Eay{>!c5L2xfBt$u%KhP51zVThlMin$asK}JQsF#8&t5H1&AhB}@26+v zJNM@U`DU)a-&1a6W537ze|tW8`m0Obmpq={3ED-zSG2nR2;*A*KZE=FQm@`0?zfkk z`~GmL!m~fH?Dzfo!0(kl0xmh@BjCDE8;$RN_x<_s`ayiKuDCzG^gh#{zNbD=;XeW{ z-S9`iwcfT@a!)?khq^yp>y`V%WH;4huTN5K8|;(zbY2mPcyu6ybOy}Qrf_0H}I zm+PXBfNOnqe?D-9 zcm!NJ>yLoT^%->S-uVvo)g$1NPd)-J`#K&0m%iB};Id=n5pcOC{Rp_+`}GL8RHxa8 zdSAbe2G^d5d)0+Jz2gyZzkCoM)ZhE_fx7z-Wdk{K4y;_ti7(;{I@{jUNG* zeDV=+x&HVFxW@VW^Ot=V&&BszpU)oKbFcS%tyLK3`hDuQd(Y5q`+fG9gmce+--w@n zbv!oq`+DDT*6-Ut&o%#9ANBqC+xc>izw|t)?pU|@YtQEX{2lR=zvHoyza5VmfA`PB z-*FF^`y$X5_TOdC=<9d1ORHnN7Oq~cWyD$7;@B2!{Yu(>>Pj7JM%2?43 z9@=T07a#VyjQeunCH%cFtfi7u_b* zr8&Nx=UaSlT|4sdcSysB{q^Nq#<70s^AW$`JG}Ic*yy`^O^K%kapX(qin^qZ3k#hp zSn!^+(3JZwIkqoDkPV) zX9hZU&4Vs;&Vdt<@Ey>rebAN5TH?CpH@slIah!0@%ctxa-K{PSP{A+wlyBj<)YCuJ z7dW>t$y|8cZJK=yYdL4uc0YC5FJpL~M~y`S@CY9ZZ}?pL6TXU9hg0&1UicisK<2!5 z{7sX$GN6irX5b;S`Ew>qufQ>Id5^{Uj)yLv)p2xA@k3qUsfryMy^ef$rO{TxAK&+$ z>4x3-%qDv6fv5c7Mb4G(dv2{aB^%GvIr2Ad#vPtuiVjfi!yVqaI)mTfN+~??II_z% zJn>=;yoh%sASdSnPj9KdF`sk1)44$h8ACqCG4HJ!f8WFV9eX4LAL9eK1)g(n(V5@@ zKl~jk@vY`D_1C)M*sBlTv>6iF(bO{osm2Z z9;@r%QR|eRJHGT4`p9g0EI`r~Gr>$>S;y2H@OC|(2rFd%D<5gkQRI5f2k28>tK-8u z>OSkCYhDd1*hG!u^}fB={P0G6liP8}RG_L;tj%jKA9atb7BT86GyVr8v>#+$uN9n*9u~(+-evgLvoTSj^d)d3|bM3Qu z3I9tsTuI-_6C?|gc0Jy02Mx%U_}XQ`EO|OU3j-a&mvy~Crogf8`g+l}T9dKpfLB$8 z3g+HV*J<#xegeHMTkpEdGb7<0`i`vQPx_kHhogN_A!Q!$G7r4-x;BqBGOyF0c^!wo z9&2RY=!0kXm=&I^k$Izkt}(#Nn6g3SQDc~!F{LMcjQ(TPZ7dcG4R>No9H-~jk0+;4 zgVco_oB1DntvP1!+QLJt^d0&!KXWvC*7bty1^Le5IrsC6ov0UuBM|p+98^njTeXYG|j^{mf5PoVM`^;O>>*!I}J>#AG%ID{`i_Q}) zjW{jLSuEb>Z}Ik8jCXtmdo->-OKa*4G!h+mO=+Mu=FVX4SFh+U_JYEA_z$he2#@H{$3GzF{ld4QRjV4i%W+owG)f15E_aV+@__NYz5-|f0+HRq{8xnc#C z=#Vi=tO_pr6h5i1#0w*wvPFk;EFC%U%`s*XFIf}M!X7-}d!FhBI8vQsJdcwx`0X5{ z@`Oe>O+BIP0yFl@d8(c@Oh&I^GVTZ_bfbgzhq_$oN75zkcBl-|hj0%($<2(fIjXFp zKgTjsRzyJZE%}a2p%IxGkMtYBhsXZTWMu4jMt{3NKpXhX9TeD@HlQ5A8xBFSze&lu z^pDh0dlvpSUGajP1n(CsG;1Ua!Vc1~g;!b2DDjlfpB7eX(clqaa4J z!#`}UUTgkgGq>RkEb#_sbv8bkbJB@?gWr~xGcf$!+Jb>?5MPRx!b4lfcNiP?@Gu76 z24lqIT0CFtE8Gai=qvui8ZJlifyTnbIAa5z3fZAcUOSn^`f)vCJvyeI!4Esyqdo$e zIF)Nza?O#!3Y_rubNI901};Agg~lLra&)Z29eEgiHQM!lYt8AOl4BHKwJ&HgSH{2B zjPyK+DDc^N&}@AQZ}jou!#XBHna^U#nsd60e%hVuyEb@fC#)6ivp+NDMZxu(1=B4Y za@zHH<1zBi3mq`WVXfI5&r2;DDc&6hQjg3=`Jlg9Y5u-1pBcYhyTc3*KAyb9bJUgN z7&+!px9LmIctiWABmauW%E;%9cF9Li@WyBp`pphp^$9IQ56uP5Gv;~dm}ezsp5>)B z%<9+}@~}SW+y$n(4?fXx=5!jO@7n3u@4~ajexks7v6C z&2iN*@lO8^zu>OEsCp#u8(gH{Il(!8t5<*au*xqn1K9Er|B~5C9bSP;;Bz)3h<4}+ zddxGHsKtmC_)RJ&C?PXryme?QslbL`@T&7m9I^%@l_PNl{jft_zIhKeW7qr@-?~l) zhO^&Dh>ny!h|gp7V~hba{9p6~ZAV8xzJ8qP1FiK({Zsq-pQ@kF@u&1kx;^L*dd$Qo z`NRI~|9h=IaIq78+@sgW7a))G>*Gu6_2tEP`29KbyLR{b(5Cw_k1_{6KtrGd-?gQITz8B?;K&ZN4qG^`JI5dFi(kS}2ZbZQync8d zm*invy1;SGM|gPLo2~0>`r5w#2t0|Hp&NPS`ldFBobrM;{t{zHTBC!^BVuKibFcw> z>Bjk-g-5JEKd0}g{TA>942`w;L}M%wI1pJ6z0du99*0lH?V8`=_B=1XTjm?_Q#qp-tZ&IRB7ZEg_OEoF_c`_1PH@>EdqCJH z`Szkc;M;ixw&V9Nm(lDwrz?OgS>0@fUI=+Fl==Ix@C6Q$)8N;0{LHw(L8ACX=VEVO zF<{pO>kHRs_<_FM_Afw{k8!T#a2{F80B(;0Qfnz#nkg4G7)5%K?tj_v9t7 z&}J-+CO`xmxd?o&09u>&rL2;oD_|S3uB0cf>&*qp3#F2fCHtEVIl_yov!X zKw^d+6Fd*Tjx(<>XXttmfvCf<7<>YFQSJLYNAw4I8E<$_ByxA(95IFL9LW;vz(?Pa z@0`)U;Zwl{Kg1JZzy)1|68$Z_f;R7Uw|Cyp!D-aBVZMjz1t>=LTbFt7(M z8~}SX99=qE;Yv10dGeLoVK zq`5t;5G+>bv`8ihkpALBJo@H#!+T&&CcpUt`97;Pml1SMZT^A8!n;^K=LLdGvXl zk34!Eh}Jnjyy`h~#~oc4U$iE3qz50%Sh&LroAF({3v8_21BLy3a-Tu z*Cz^h+&T~O_?#;keh&_jL*H8{tkf=DpQAg`rO-XD4u^wN){ib{y{sQvVrR)O-Fr}Q zsVxeo{3@8Shsau=vDVFe*Ka_V_@@sLeG1%+Ct?;RcnomKn(9Z*9qozO#@xsxaf#fdD>8|!LQ8DoRvgJ&I=_fKd5(8r$F{={uCk7E;IYTTtN50} z)AR9V<{D_fGAMXRGBy?-_-@Rtk=o9DZ1E}lQ?_J19Rk{4>uJ;DeJG5kesNaxn!J@G zIUc&pc0I!mwQ)T%9*^wJS;toByf!Dc89NyFBVq^j3jtX-wiCHVR_pK4gXq|}w+PsE z^(`<1D{|hhDPL~YSFbmAj>6CQkmy2ujxvXTJ$E4HM1F;5Vr1-7{~5n?jsNzf^l4%T zUh%#0}KEo(WOCl!p5wmlf((`a9NHsiISzDB1l_{pJ?e`xpk zHU6#Xve#H^;+N`PxA;P#hM&TyIr1W7BHzfuapjLZp1xM;h4Vv~zM|Hk;(4yGt~G+2 zx>vl4oPwL<%05TjYM%J5ebJi7)*MBPHbUos-U@Xa_Cx23N}0@*kv2OsvqM# zbuF-{IDKaw@=Vu-cCs4IS?56o^{wYwPq@PA_-DPq<~uwxhID*Ke$bcU4{p<$v1e1g z9H_HzW6uNHkP9z6M9R<4j?tgk9f58#66o+ZJHm5m=NuM8d`!0!KC(}d*a0`_wwuMc zCjUL}cks#g$QhW-C9mKd6gf}ay}w!5nX7JWVKHM4OKoB28n}W7^w7_R@5gY>0n#6# z=PvF@gZQPMs0SPquG%Qi<&!#w<}go=c^;mLi{J5O=H2oG{P-ST@eO&wr%}hV-uigg zCFGp**dp{ObKj$n!cs4lD?Fnsq@3wBo#7pGg-O3Pydx)o53vVqM*9kG@e836@DBP3)&PF#Yu55PHNx*>usdH{nfR<2VInJNP;S6q<2dqHZCBUSW^sjPG!g#+ z9bO5L2il!_!3x+I{N=dohyKW?^R94uj=%K|Dm+Uvr2k{&-a)9zB)-H!av|c z)a&>X{i6OhV`sLc?Zy|P#r4A4>f81cHmFb35BAT-WBSN+jP(*kZ2G+HX2FM0r_eVf zTfmdhQ^k7t4$kbiVjMkrI@Qc43*kO+e175+S-bZ=@MJq+@}FFc>WeIij)awx%=M8h2DX4VlL8xQ*`0!&q5;@ zdz}V~;4~{U3M~TzFyi_F-@T^K-O$WKv%rDtIcNiG|NrcrX^taFl4h?ojh>mF{#z*2 z{f{*H>g5L!U1_8{mU|)L_`f#piY}y08K7uUhfo<`&y%vuXDPB(j z21O@Z;+S~E&t4(oH**&{@h-2CgNWb+2um@8ppRFkQC0l7Go-&y-1XO9?H3oCeLZ>I{oysalG%G1>NURY_`Xy6Fpc;3 zsdfFeS3#mZl0gq0B0nqYwXzj`Kl5DkhRp%i~V-{g4^6v%A)8-H6d z`JLCE<4{X@pPuD9^`pM{dVk)-d;N!w5MJ~ZakX{wfchs~9+8Qv3_Q<8S8rqrd_1e5 zcCkM1=k=^x;InR61$;U>zw_fRRQr6cgXb&JIWp3v;Y07@x3SRu;W-R7)^*y5J`wr& zO)so#dGTd%^E)!ce(_~wa2*xB^NP-qIWdsec|UfI{~|LzNP6-q{K#o6(X&{W^Zn#W z{Lg#*c;8!O7pHt2T}OMxx7Hqb7>lu4ekY5I-bg3@n*ErFS>bsnvLiuckKL1ViT~t- zx=padf8kbnmDr6R^1in7ds~!`|Cw>#moavqV=S>0cy!EqWn%g%3Ggvm zN8VX}Unf48*wi;PrB!wsz^C(Y;QD zPwKMtoejiA4s$0m$8IA|+0FN>CdG%^_auAexA^gFewVJwJo8JgT0cs5_FrZ1gWxr7wHw^MFw_Dy%)PPi=E8N=nd>T~&Ip11g%4$M@Os$V(p88zWzMMgI7Cq>~(Yw+^#=>$9f! zqs+FB9U{Xhb85>RlZp3=MQtB=;v)GVRce%cysNM5i015dwO9POw@2AAGLNxYc1r$) zZgh?Pjf?co%qWrZ{hT~VEG1^&jVUzkx_kfc$cwWv^JdmzUtc1d z*6njca^H8##>P&)j=vI9u1`PZq-&I!X#AGU>J)m3^LOp)xrp*(JI--JGkccUiSsYx z&R99k{ei!~eEX>@ay-F5qT6iV@^M2s(%HaA}G9*`$r>UorReaBH(a3e#le~&I z&P89_;i(MD^sWq^QI{RYo@w0Ip7@m=tYg{BrYB}5t~pK1B<|9O;#2Phu-^2uOXtz} zKv_~}LL>EuGjMCfD0AW`>%8AOo+2;Eu;jb-rS{A6PRtd2T%Y+RJh*z&^>BYT;#3b$ zeU(?qn;sFLSOaT+lA5G1%Pxu4ydS&72U!o_ZU>~CWen~}Gc!~4u3VNjC+MB_UjNVx zPjO?z)Y^CLR5~OMV#nA+J9-Y^^`|C9mc)UlwIx$>E^}96GW|*T(^yRRO5|IkM;T^+ zpL${WBKeZIifoZJcJ}?mjq|VmMxO7;65EHjn%1m5$3Xfs@Gc8`;n^yQ9O4s%hft-Ok`1huMx1{&im18pFd^u=n!AsYXH}zx?P;VBa1Y?FXI>| ziL*MJ3IF7qI?UG|d{c}*=* z$_|s+=_I?d#HZOumwh5r@S|H^%V&<)%s2D-QSF0bv*dH=j{Lk{Sh{!y65iw5x<5TS zy;sl7sp5s#X1i5>DnD0j&8hHIkCG*N#;5PeXVPVI+QWy5!OwXne^Mi~ z&sx8gZS_auGj`9q@!E50iJupB4f1oYoPE~m>@oRQJ`PWFzWQc(t3!I1F<(5X1l(x` z|JZGgtISi8Ep{%r85F$mdK$Ox5lbd4!QHgf81#fLwnkQZBzXjnf-x;wnURfr@VECO zaebWkwY&F!aqkJ)z`Z`w<^Caekm7fqxgVD`c!1aNK{oF@8tHqtSEtXuJ2=Q6d6k1J z^*cF`!TSJ}(fgkG8()>KP^U8Si5esXhrd|keQ@GqPiXjwb8uW2oxF!%`r20-(VtiF zX1(`s;Ui{bY{6Lp{^4)dan|YjvNbYd7dkZ_We>?SV~a{g459 z@r^OVSq1xiUcpD7#n;#boWza1!HxWW0w0@=dU$;qTi`!`OFy&{v#~qzi0`qHciX@x zwp`=Rdn%=^ocfqfeWuyvR37}=<2iOi7T$}T`dMEf7j`kPqM!HDVO!&k85G+BuQiDm zb50p{c9M=VFp0@?XG46ioryPe@3c#9?K%77#^-(e^Heu#VYd%+ps|^})3)fe(_cFx zr@D+bSAJo{qw9Q4F0A^`wM(ApZN4X`$Y9@tW@=LMg}9|=Xs^V7k0;}glYR6@N7w4R z_}w~z+{&Cf6gbidBNrl%Yb(cupX)L@Yjf%X@nJ1c7UKhXt%@^U{f-W^?aF7oXFZV@ zy_EXJXD7fP?e$uIWTH1%L+SB(rj0VM^sHs%XmS?2^}2w~^|Ac%YW!&(Uh4`p(l1l* z;DNrpXZ-13b>@0BbCCW{J{g<9InE*62Mc{+>3!G;{W(`7W}O9}#Tape z&GoA|T*(NZHI9)2=Bw{{V);=s6q zZmbad0U`I}CuwILb|c4L<(cyxPs72&=;Y@}$p`f(wvylY(t2Y~^;$vwbggkc%r_k}P zA>YT};jy=`c0hOdKqEa9TUkrc-}}ESE?(z2afJZ{BZ6IfApE>xo_*KkIgas-}5rDa-R*J z>6oWEsv9}J&Xj0w55po=C#X^BzxtQ%%NZWsZ%tZ`#4vj(99afAH!l;pg+mrso? z<7A8pbSQf(KY5TE318w7`dB?Pu6Jt~Gs2bsNqxp9=9>J7JMFC8(CGb@y5JKU;cu?Y z`9Y1H&*F?7dxmn88=U@XC-|ZlI>t82uN?Ykv@fz?SJ$WZLqi+)86N)da2}}`1K)lO zpVZ;VdGAAGj@|55wk;jU9^(vWEHQ&27kM<;Fqp*{_4xb95R}d zd@lEyUlNDlB1>#A+wU{q^f;`2vwTLsRed98(LH$!4dWYo_k2TFI|J*D@yzn_AXdO9 z%B)SoXFD33zGqF${X|)I z`_q&cQ;z{w0sBOkH8xYn<4^P4c=s9%p97a?Vp^Y+%*tJLt6~7T z@rCts%+2KaQ$M__sl2bvlQ-I^Y5w&krkR=y>xyGub})DatL*x8@@aeGiG33BA}{0wn|-F&hSAqJ9_?U^qmwfp5r7w& zwZp&aM`8-T$$``b{49>~G3IK|+d0?biWcofcLe&r0rR1$eLaCB~xuh%YPF`n^D7yxe2pC-JZC zskUQ1MLOdc`HZH>T{VdaKqq{jI7(l>pMeoC#tph9wo?~~8{otpe`kLPZL6?x4qmQX zaxTdIX3R`ED^qsk%32;Blsom78uBcMnc0;add{W!9GiEV`M=NqDac>X=fhTc9^d@i z*r5ldHd$*jE7Ccc(VQ7sQ?=048tMBz?A+Zy%137% z*N?Af{nytOE7F-?8`s67Y$0rvzt%<0)BDP4toSt4OlZ*1FC8vDr2&hWLl)`e**46O z9j-lBI(|-q$t858@ADGLjuFm0%Y@>y<%%zp2ymV?%kRkJ^HKASX$9wwan_OdeZ9{m zB%9El^~&S(Zh7)jsoJ9Y!#C*qE9u0{i2=_3(V<*bytpgdkn zTj5xEN1xNu9o%U0X}n!d{JUH4Cj!>>Jfj#-&H7@?9h_RbgVTY4qb0w2W-^}RiV?5t zM>`Ooz@4UfS2$gJgzH}_u90FyXFV|he6~OH{SHoi?%+I)cn9bE19x!cXRofk)t)Lw z4d}H&p)6ixv4XcAytKu-94P>eb=W_cRm@Qh%gF--Av)eOkCrrzR6e zJM%nK)<@si-)B0na6Aii=F5GIz-PU<7iWYkzjo<#go97+Recbyzo@!IQPns4C+p`r zlP4d~>vQT~@=IU)P<3NZ;mn@&;2F+I!w&wpf7)kV&$GOD>-m0T;JnLkpV&{lkr&ow ze=84Mc|EVER*dVN3)HvM5zh0US?_bLd0#kB*51L5s=i)%cwX-)PvFWk%jxS*N51%! z`_E>1m`6I?(;!yEmsu8zfMsrKnHBETyTZwi9UV@KIy`y7^L^zv#tF}<243~nyyJ5= zeiv{0Y3z(e`E;uG3w>yCeYWhTJ$VK>@Hq~xt2{N-`Wiayp2qd556H9jS^5-kreAx% z>!q7sSM>_Wjt)=Z-@%nvYvUB zb?iF&dh?F+$V}JLVK$-1#E+q4eK1#{6FAiENs&jp@tx+ttKJGXuJ}yHXlL__8AN^4 z7kK79F;w%9bdUk~Ooz{I1E1*_XDc11{T&@5ZAS;|0-xnUUb@Z<=boMsuAPw_xba(a z6cZZo_%Z%PA12xIS4|%Nb(;GF@4uNVg600h=mM7gN3F<8s&b(C7WfH|(`fNn5iHKl z0{2~?S;*hoW&W8m}HXZE%gFW*N$>u3DnO(J%OXCBRXR2o)uooc zKRZk9?3}`TVg!$h33TQcd$5lP#o+Rq@2D8@j1&3`@H%%G{m#{x5l{Mg4$2vCjwkVa z))>1H_YKhIC;G)MvwnW>$h^An=rg<LAD_mF+Zs3i6Om;~P2s%4J^$qDfOgAz`_2kK z(f8cA=$HM8Z@R+h7yHBt_cL27+RIgjcs<+Si~~wMn)Adqdk$WE!d-CtFYwVX)@QODzO|lx2d_Eb;&^Kkb-lHe-SW6ztyj4F zkAlYz?yum2&#{|x2$h5$5&HM_=X&L-H`f*ML)k5LV1~OtTGtz&E8PCSgX6~)?)<;P z-8byu#M26Q?%%Q}h)_709uS2*!Ztjv5lKLH-UC(fC; zJ3R5gSu!=q4qo*tXFj2m_4EbSuW+tGS@n=1bsnz3lfQv;YO{mm-yNI^vxD>fayvL) z@9>hJ?{nnbp1Og)?px_-z{z6d51dmj;H9tYsUADHb7{{z*F$|=Z>FE>80YZ#EOsmT z$Gnbz>HC}=N6x^B1iu}0t~12XTIacwpu=;1LI3s41wQDc{IB{{qv6T+jNq2D0 zF?MjSSMK24p|gWiPj_(RzvMajJv$@%5p;M>-UrUPkZ|}H{9k2#@|5`T+5mQ?E_!Ce zehwd0{tEY+=L%;|=?}xvs~LJ2?5<;nA1#iyfS30M2>uc5ZJ@9XU(^FHX$Qw%z|&{hwPPtNBiC*dKcT~Y2pw*ZVWQ@G6CPkCUDV!#)wtd# zoGN97r~dRG=MTKgoR+0iWdUBE9M8F;|eqtRFq@1~Tk$RqKRZ09m_O!n9zkYD` zfgfIoZwfPbKJ&Qa;Q=N}>cSb169(iAzr-YyzzvV8Bl$O8F9R#L69y zN=d&nzB2!EUEzl3y=&aFtvp_P=e`Z%S{b^e^c7x9A3Wm(>44*(9p0&)c@BU*PyCe3 zb20Wac7));i$2|D0`Mr68$(w zF$PBu#xB0c)uh-3eeo~;Gq*Zs@Vrj8;(7P~9&ePB*vFpoGd^GAmEX-B>*tD>`1D+q zPbOnm_=!ioI_pQ@ArHWdoW>iR&Uoz0;nVG6j9^{wMd{YW&gMHF%vm`rxs#8TOh-FB zuM>dJs?N_kh@LyV*v0GY#F&wl>!VyZ+2MIzkSYO3rb{)-^=ZzdcX;xn8=Uor8skT{9bYNuvi=1kb()p7L6kp+bBC9BF$TFxPaM$Kj3eq`X5Y>+c$};tC;k%8_@tiY`zLpJ-amx(u_OGn zi)Tk2!@tANxgdAhaQCx*XD-jZkR3aC%x}o)b$?!!T{0W)@Ho}eE5tY6mLE}?S#88K zkLbtXW!`n(X5wPcWKUc1IETRBsSfbdE_lK3U+P#&2E^-P;2{}!)!+Ac`bla`;n;(# zGWwl9=C#s2Kj$5yPP;JuD+hK_=8hRZq`upe@w&AS?&fmGLL%jKAH`Jy{pLOd{h9pa z-7$lw?j6qwk$kw}8J|QyRFPA^(*x+!9+`LX2i==Y+v7pUQ+~2H`R8xz z*$t1nvf`oT{F!a|AO*ke{eId^|H+U0w$6A|GkEbSI%Fa~tvJ;C8(!|WsC*9|SMrr< zwkOh(FC#zaEUtvy@XRD?iFKEKAM~j+H$3N~uAjXNJ#TpK`#V4Jw74<1>W609(>g)C z*r$z`GoEt?{)>L%F%>vlc5d-I)8_2I%#mc$iC^ZHuAg|+xicQ8!DJS(VX3$ z_~ED6Mg4;3?%{+758h+iF+Pb={xLV5`7w>Kp4t_D;xYH!@Vwul^P`W^rHHe$oOZ3w zFL-x3{X9|U2PN{5d^q#7Uv_@td4`kPRxx9pAm3+uQlqgAw9a_WD4m~p>__f+#7oyt zKXRq*hUfD$I=|rE<#hkm`B96QV#)TieqI^w{KVsQ=7#6~q4UGO>;lNGGe0WQ7@y*i z?KeE@MCS(&qMc5E=I1=!^%Kvz=Zwd7XXMO$#*79(GVI3B`G{Q@c67D_4}0D4oFmya z1c%?`JG13kPOpoiW%!9_oxkA`pPe6dirtUT9jXlSujG;Yu+C3BuCv)2M@;dU3y5QC zLh2HIj5`zXjeD1lS$N6`1?n#}z$1!ocmYkSKl`)S&-1{}&-%hn>xM_48}&mD zROAd$*_8(eRV`N7fN% z{PT=ulvH~#f8vL_Ud((94wz>=VwdHf1;<9YLsdEp73_az{wcQeCV;~mc{_T@kMku5hopJ~zgSzpMa8=m*Qrsh#!#3PDsc=SK? z^HT)a)BeW{vct>yAbN=hhr+|odpu(ZZsJi%`P3Y*cq$wk5=-Mxt_K)ZR9^Xc&QIPF zpJc`Ov*Mu_{LCXb`5C`Ep4WfDbAF*O?(q_5`rY%dJROvI5IK>3{E0pJJR_EH9}ON7 zQgzwcpYbZ{;m`bW12;VM z@BF;-PiL}ocHQ_p`eFaBpVxP&JkA(*bqjhDQd0r+%I{;dlIZ#Kj%^6P;o_+>@A1}m{(E%Ut*3vW7Yhrx- zNt{tP!Ha&*mGH+CXFMz}9`bp5qKx$SGak_kp1Tw9vkn>FEWx6KzT=|{m zawaC^B-(a(+NI`lx;63!kA2}8ujX>*fsTikxwoi$;xs4wTm#N&@dMc7&uN|y9?`=0 zV~tqrKF&UYe%4*?uiN1zUWi}x;(S2;$N~C0`mOwehuy^EN*?_5yYuH6k9tHj(v`(C zAC%Kmfv#it8P{Iz2hWwriT}=c^o7okdV_vMjrXE7{soQHtt=Ud^YUAQxh)1Z#S-|oZN4-?PD z&s`RE$tTgC@OXd3v+lAV3+;|uvg1FlZh+6OSUL4 zpG*VKPtt>De0mzU;^lk-Ec#x~C*lv{Y{xHn^YxYB5pOp{H&Gk|K25;XV(9h~c z6*A7kkLq#4;~nLtZaN>-{r>px#1B09)aOFF^TKe5NvGx#wzTHUcQ(;9NF{iys02k^9K;*ChS;}LOn9vM7hh+5HQ>1CiRN(15{6%dbUhjD31Jg_Rk>i{ylSgYGi=6C&M*Wc0z1R)UzS->}9_ME_ zJnG?S7x9>!b1!eVsB+R@$ZVsZI^jP*>2$;M4lD0^*ALi-Jo1WA=T-4Z^b%*D@9GO| z=(Vx6dM2(pPmDd$)Hnf;cu8&UJfok_Nr0bo2v!1*c)8(`wVYnj7vx7IQ17X_&=`N> zcTS)@^}?pokRKiVe12`c=Co|Y!;3dO_Zur7bMg((_~hEYagEH#iN(D(xYv*MqkhRh zV`;>S|C|}XD}Lg!x4rRmzUum!w?ygcp8J79IJC$GPy0AJ?Zxe%3Sozu|EmY=_4rmAz26 zP3i>sIm#(Nr#f>>d$MYf)gIHd(J>Lq{EN}&aK8LHE#To5APD6b^kma)BGc@ z&v;z-@g5DAXY@BY&}rb(j6a4v*fAJvlca z*XsTW>k|8l9Ujz2Kfn_S#bY0^!%L2sF<$lScvPnw9{$4{<}Lm-UhGH8&@B^woB}$F zU_(ABX#5b_K5L+3RqdeGiAVl|XMbRdyy0O@@SFg_OI^aAXF0k40-k=LD;S@~^%;-* zZNbZRJmkY0?5b}3_@22DFMSL={vLl~Pwqq+@zhUyp7A^{pvUV6tc#r5^Nh!RdEy4o zJmPx)O-@ciM!e+19goQjJWj8ig3|x+-&s!ckJDh*JKdun=Px%r&Kx^G@1sFi@Yelp z{J@@h#Org`8P89ebvf0~IqQt)99ecDtI&@#;hUUf4{~A`^2mDwJlF79g!?%2yw3Xy z#Ip{PCpSFr#sM$<&Yp1<7q@p*;tLr!OZ@bDkj8GoXm^MrDWXZ~T~wJKHp z%)Xd&0Hv63_TVZzkwb%HrpJeN;>AL$$Vkk`*^R-p4Nf2G2aAe%|q@ zgV;sClOM#3ayoT&Sz}Mnk$GkW{@`3W^920Pc-dE(zu+mSr+jC;?BjC2?{h5h`<)-> zt%(=v8F`F;SokIk3c59a3nF%-xiyt^ogdhFkhKKFN zvtD~$hWxwZ(XqfwzhzE?pP!T@=Ek4+-9Faw$O7z1T%YmmW8{!==5s-?=N-?JCA3mM zsucXN7qX60mOZKKT|f6b-sgJ5<9-S7A}9WaAM^7K5BqdK_<273cgHiH%br#+>*tLh z8QbM_KM?<&?ZP>3m(%MV@!uH_`rsvAyl*G|JL9nz<0@6`>3w$bA2~JtB+iUau8Qb) zeNJ|Gt!>0|AGe$5y`RN-*=JghnD#lUEtdDLc76ws`SpfJ*04VN>B8d*_o`p`<@2}M zzXy+J37qlRFHq08dPiK63rN6j0N?NV?d<}-bIb`3t1{Pml@VV23m)H`vFFDc_l;dn z@kZ;{E9wWa;{3rWnstJVMo#Q@=SS`FT9s$s;_?3zJn!d(2EHfiIO*EyN8RlE_e=rI z)Zp#yqJC(BUR^)&tb;p#?DMeate<$?^UJQjEa_ix+RMotNiNeLR=m@Gn%)T>_c!eD z&iaW*B<=8$537FSaTY?2e6An$f>YXe^%IX7a?ekjDKGUaeizRb#IAdRa!}I&ZS2_9Y-wluXfzC4X^NBu0+xU~b&3XBZ$Jy?kAHKylqkc?6 zcRcFSDyRF0o19JrGe5fRji1lPUimrgo%uOYt$5hkdsg@MD~D*?{PY}$FonL@!S!w z{Or?bJo>;+PW$v34_Tcl5-;j!pFZQsi>w*(?9*pF=a3c8K7GdXxy&n`efo^Y`S?yh z`}7%)bLt(Qefo^&T(HV%pFZO;EAIH&r_XrC*~-s8&1^sZB>$M(cl@k^XFSdocX;;c zGagrIcX;;cGamW5!?RDH@i=GaY-5g3q~{EKvk zbBD(X{|%43Id*ttV*5T6^~QQ z8=m{I6^|3C8y@G$JG*fG`G)67-O7*tcEfWnAV$Zy#;Z3x&QFZ(5zl$>Y)|(OD?jcN zyYb`Pc*oB>lg|7&b==`OMV|4fN;^E_#A|wE#3atRb7qIfePTB}?6$+>O2Q3~>xMf# zs=y7;`E&IH*L81r+#kB*$3EtUN49fUz#M0uW73tzpV*V@aXUQjVcGFJ?^m36xdybu z3%_;0A|6*xZg}f{C3t%|!*AWMh{vve$M2*c{RtVkuVjZ8ezShT<2uMXeO4Wu^$Q+x zcE=mfO$#sId_DR-`}X-=3&QCm~zVUPJp~7NEtimME^_AUSNbqCL zy6+Dj*H?D@yxz$5734(6=qEq8bH#1eFnFE|vuoqJD)tl)Ezfv(%}AuKiASd;Uc6&r z&kvf)$(6E>$9?yEe#-8?in}JlkCSk&li=BteoQG;!mgiq?6+=so||?&PJpc@0-|;-7#)!_PWF)ZFBxQleksnYZv~ zk8tA0by)F;YxtSB_J?qI<#*4@{5xetQ+3!eD^jqwMmfH-FnHC_p%$AD*F zS@Dubp4pHCthBa)hrHg4Hu5Vx;(EnncG=^d;*%~!J=^n3e9~v(hh)a8c-GzBbqiyb z`&h)IKiDhahhKJbhM#`Np4Ly|1iaB2yb?D1op?)5WzC2yp3l1=vZ$X-cle5Yca9u! zieK=!&lo)CmwdCqScDrC`uRn{!$!A>Xp@H~>yZsKLq z)yDk)Eq}d=^Vz@h<$i%tPUD2@rX&1U(T_ciL+PO{O-ke zb&Q=`hbyz6(R?y*NT2I|?kz|Ab0+uwP!v+=V@osRZ-SAL#bJMvZcwcg5$`(4KM%D?u(oMp}WDnIvgjCSy> zX4Tg{`AOeZ{>sy_@93{JPSn@F-|gw&oJWrOCJtx2{c672*=o|`Q#*6s^DE`#b3P;e z#KX*2IXT}R*DI$dFWt_@gK^v8#sk+qM>@vC>X%%#!o$j7gaL-0oyK#2O z^n|{By?$TgN58LeXuQF7jKk#D-kz)7lwq}-_FU~2d(L*#o~zw*<~7?*d#?7;p6}Xc z<*R*Gzi6M8ul8T-lJ+M?cK-4cVXGg1b)P!P={|Rr=lOc=##Q#6zH49BKBxV{>-FMi zo_Al_<@bHAr@QYk>$0z0`6m9U8=a21?|!hu{k!Zl%A@@0HD)gVe_x)NFZuOH@QppS z1NRYlJ~PULB!7lH<(J5rIfOdY`_vuI728q%`+Bc4tn^QGxNgF=&PbX4F;{#>xO};; zw1c1c{ssTcU*EFZdfpg6?$0w%>(@CpdXaZM-ps$V{PX&MRXY1TUG1a3>-nwyXg$Bx zR;TmHpVN;$_ww`k@-csvf8D<%PN<;kK6I5c>*u(76%Sma?Da=F#1vNpt1by=W*p(t z=f0p3uKl^LKfTFPWt{_&Oev_YR}m( zzRujm{c)pT^w(=TiNyGexq6My*K|gCoC80hGs^Qholze4O}l)5t=A~e=X7Ry*l(@% z=Y4rTr8COoeQ?p0-=D?L=X6GS_|BBi;xIZG&!5v7<#Av6^LYN8&M1%fZvH%eKBqIv z<1>|iF3;z5MtQt%=;!i$PG^+I?{E9LJfG7U<>C2hwg|UpVJxT@flD*m*;ajqdZjRUB4h6M!0yV_&J>qyxW&+ z9}zh-Pww}LpVLo#ew%*ILq_>aukbZ5xI1&Svv98OjMsgn=k|1mqr*>n0{*`i`;&we} z)^14W-RPsf+}R{N^83Em3v$guZ2qtO9qD{aoCmt>c=}BKHs#Hv*IdzrO#)Bck9>dJIZ;2 zpXqZBzvlI-m-J8Ym458@NA;c9O};$8XVfeHqIdOkHvPrtJ;wFYIh||q$(3=v^nDIx z#boyH@2)@do%OoQ$>%FZIbDB(pZKop)tA%E_vp`aSLiV3^f-Ja=TkcR_jDe9((APT zWS{?O@Kax|d0@;(yu0)7bND^KRyz0fYo5CPbp7$UzQ)@+pWDCI>p0emx{edMz3zO9 z!#_@*(T|_=jb53f*e~SXA$XYYpVN<=-=**Ufyg<^&!--hKXCoXXP|$jUhBSCzTSuP zEA06#zx=DviNA~!?fFf+{kzkj^N8!M>pb&$o{sjh-hR{mqx}DV^hf)6{q)z_=R|+q zM<^G&k#E$umA?77_Dy5&kLUYYz4~0Q_}#w$t-ADDp72c{VL$lIcnf{~%X4hllP62R z-So_O+KQ=V_l&)@Rbx8$jKi2V~k zoNV>{GJbeE&j|mlz7^lZ;mkMiU&VLS*Yk(2?|1e3_4K*V=bQ4+_W3sb_*cL4#0=#R zT)*?Zp1)SF@QuFT{Y zVEq4Ohd=*CSXTRWgWrt4c9Q}H|kLYBdb&i$JX+QGr`V-$1 z9B=L9ulr1*uXbafwY%?*=dkVQ@SW*9xO%O2G+(1&e!V> zE8ol&JTH2^zQz+tck=L@Q7heOw}R(0c;T{0@9y&bTZ?~T3@pgFDbAQtwzF*Jt;CJi)aiDKK;**)|i%VagxWs!i zoV$be@NqrVu!GN`EIN5UrO)muc%CCE-?Cfa-kY_q=Sj0&9`OI;x6fTthk*0cZ+T&v z6^>^+9MAcQZ0>jEX>23?_+_TgXA`BPU;KPB*Iw{AF(};s{Wf0Yo9VDSV7)SFiIk}FGSCxm) zOZ9k*zf!YiI)Tr8|Lb?X{G2?sL%qV+`|^3>Vf>Nb#%1e=xZYqBDN^ZWdmU^7kd`^Ss<-2}{8xQO=SdVwTZh_~qw|e;C^pC){=hmm;TGD@a0|j#-52!o>Yy`yic25vvdj`I><>Z@Xv3z zg}(KTxaJ+Q1$zRQ4&MXL`q(Y;89C#}*g0`a73RIfZN(K3V!*hKf4y&tSV%mN{t6s9 zm0!K)c&>ccV%UZCJ};L~X9Ui9bisY@>srTV`|!Hkhws;dPV67MVMpNcSLo0BvZlv> z?3wkkXX-#^Yw&u$Ge?Z^Ox-|VD=H?yUE@8`uud5M$Ek z6q9S+R&w|nhjW~BT?>CjemGMjvp)V!y$WCY3iMYytFL*-=~n6qvQ@rE&Y6DTmA_c9 zC~`uv+duH+i{EKnaT~aq!qc(!WAtK1CMrXR=LJI_tLlN$Cft2E_0aD`h&;1j zm^gNF20pKMt~LtD9p_JKa_o-#MK**FWnX zp9+L8wx>S|#lHHh=!Aasn&n|?+Q}o|qJx#u%Xwf2AN5K+XFcCH5jmmb=k~}pBCh67 z=enXFI?g9M_{cYM&U9i2^Q-I``hmyqJokp#Jbp(?{LbfGfKv^2b_*Q;;hV&H!F|37 z)+CpmC*cAItinIOJ3{)&N9ReuB_#Q7A7>ps$o1ZbO-*#ZH809;u|w)u@{ag}Z{YTE zqLc`++VAu=p0T3)CZuP5p3YPAB$v&RXRR9qSuamq>uVd6E5>bNJtX^Up{> z`nn%?zs>!o&Xd#@)?<152;Xz2t+6L7sob2-;E`I79Kikl75`^_#SfM!c>IX>fh#{J zEZ!IRkKZ`;^`XP}YWMZThcg>?;63H^^8kFWi#yuT$8Np;8|QQtB&xi#Zj>FeueUyQ zxP2=77dsWv;#1X9hshRu6nj3NzNo)qXMEV<_61;Aob~FJ^;ivf>R#Z9pBWy%a~-MI z&#Y%>1{{v?#FuoZtdITE#{)O^`o3QJ^BjfujdSdb544+byu&#l`HX#>jJlkWpE(9N z(dPFnu$t;DeE$9f>txlp(6Jt(rG6=S691!|WZGUH;j=uUpYNl}zA1EOIkTQj#twep zGIqdj?0(6SzyB8D!~@Y~Jox-U;GPp^Jw3%!1HRvnNKr2)BjMzt{hK`XoT}z7>+l-q z`ilvK8jDu^16%r>5CNxhLEpMvbW%?|AHeU*<9A6Qk97FXALx*o(D9tp36p(2o)aE_ zS+B5>@u1zPQ_!J~vp)7=&K}{=p>yB?zU_?o;ygw>C(d&YVBN-7*n#sF*0D-?s7b)> z6wnbK|IToB+|sdLWj%85;Ap$!%emVQjt4StI2S1|_Qv~G6Ra+r`UD;Pi5;wa#3NSX z+mnFeFY_+-Cvh0~9Or@0`I7HUX2K&DxNZffz=;#{ol5BGA{IawB=B3sSP_4DvSvL) zPV;pBo|LSofOu4h_ch-P1|7Q~x&iV6;}Zz)ces45N5JK)9Qh8e4wpXO z>~z>iX*brEJ(=M5@YsK}vrr-!I>bcqrBCjSaNpPdeZ7>7%Yu6~36G#>!8tG5$w|Kv zKFY~_4}6xBRl-L(|M5HhSx)N$^5CJ8hyDefSx%{w>1a~xjWJKoM>z5WCm#BG=mY0> z!SNh$`&ox$pPZv~xb*qFWn<8o2T!uQm~G{#wDDH3CusR*-Q{OtA>(i{{TZ~6|% zUv%`cJFgKQ`A0g|6Lw@X9qGI8EBe+G);n3op4JoKOm2O>@>4%Xc<9r?Ydv1HZxNr! zZ2VYHh<^HYheIDY6{5qT58VAx=$Jdei9^twxfRzQbuz3%JH2j-QmM-HTv z@7%}DQ>GW*ulnG*KJ)HaXZ+qv<{RP=DWq?`@I0W)!*w9!q#sdLqL=4+@Wo#Rr~0ZF z_Uv$YIfspK>9a2vj?dWds;_cFN4U}=XZQv#edDCBm%edQ^0*I!j(RaU!k1l#zu9-V z$Mm(801Y~vsh#&{IQwMa{6DUj4m+j}=XA{VOxEBiPv%9gF!c3I^Q`AQs>3wg$ZK{RP^VAtRs z?)1vJx^s4}&+@Is*lm?l`>*!l#ESK?1N&*ZhVm7h`2x7{!)^z>@{9KLibjWPPtGe? zU-7Ix*Y(o%1OqzsXZQy0Z!Bhq44iWb)(38VS?Lsfzka5#J)twM5B$7d`$T^29DPgv zz_n}XTkw&u>)2ldr|UU2>R+O0XJJyUQ#0(w_q7pM1=pU*JMG|87|yD_eibq7~|tTC=v{uQqLD_r?kxbm-XKk zo|S)vEB^{t{uQqLD_r?kxbm-X000 zSN;{Q{3~4fSGe-8aOGd&%D=*0@72&AC$3-N>bt_#m(%Dm{?&JdtM3X|-xaRDD_r?k zxbm-XF|gCiT$;YDC3Rlh*t~@JT zdDi?@o)xY&AiAi-gVBE)Hz@CeGcMrzQ*j#?9FfJu$%K7#Pd4OLx6MQ!Ebg@{^q=mtG1j2 za<{JZICtZr~U2=*%9*E z`;+l2^6^_ZJ1btpo!^{j_!~QL+7EyCk^Yvxc7Z>7yO!UaF!&p~Tzx|hKAquj<>0g& zyPzHZ9c&hSd}wd>eJTL2r5idq2ld*Rr$*92 zW?n0wXWH((eP6zQa-sM}8*+wk~MSYMSmP32-%!O!aZ1cXmPGiH@R8;ih zf8JLvZO&`y<1yclJzej9nfv+8AfeFbHE>Ui0+-JY4xbgyNrmu{zR|hzb?3`{A>(?l z7gFVnu*k#xex5&Y{uV1_2ffnqIvr2780mA8!WqIIE{DV*yuI#5wZX1sQ!^Jjquuli z^>T(IH}}ntbUbHZ-od{`A8cOFa+24;spNgV=X2}&6MgR+p*oCmdOcx!Si@LA6P``bG^xLVmayl(+2 zijJ>Or~ zJKwDE%&W7$r@V6#gU(q0o%>e$r#e}6c#IRS_>k2zeeZN+&f|U0g2;>HFVH=l3OKHJ zUVKjHo%Q;K`H?tswm?qKRq&YqcewK;^=w=Z4c3ovqIL)8a|=5-*4@LY^ecVrzJog* ztm~ROiv2?9X;|m?-euygqrc!l}>edag|E z=u;ndaN>UlCyMv*{rcqNEGOFU=&;}2!Px=t;K|>aK9za5{@uJ_-e$Kn(`R45gR`&S z!Rfy{IQ4c1CrWm3uHWw9aNWWE{KhIjJL=tf^J`u2=kiuK=LFbjwh#Nc9ULk5aPnoP zqK6h~RTH)TGw8Fj5X@zs0dq>B3Ue}wyE1Yw!9Uadh*7cmT?ABW~*7Z!~_?%-5Z&h}>ebDpq+#tLUn+tFbv*}>nf zpYN{sWJE9bImB+^c_R}%J$-1(cbg09^!zXa%W)INmd!7KDQGRwE(i!ECC-6(BxSK8NYiT!mHRv zzLA3K3epc9Ul%;^vZl2xO)EA?{>+3uc5D$&`%snhpHj{*xA>dKkVVLPwXE$?x8%_ z0W);eKk;7j7!L){diD3dKj?(M8WcS1)t{3RR@ZvZ7z>{D>hHO1UvC{Kc-Ctd?;q{! zwSU30Uc2Oe=g1Q;72NgS?^@^ZwLbEUe&JLCDRNF9JLmI@oMQ2Q!L@VF?L(i>KeDRe z%Hx$W;IU`m+B4_-MPGa7`6HpvzF7K+H|gXRpF8MsGJU!}`ijq|VMloA7;mX_k%vzl zvp)4K@N^wc>^fhrG`W7%mpNbfn2$am6Z-L}@~Ah{e)Q^o=|Lk9_T~ z9iH|2o&7=gm;IIXfoHw;^jsN?z*)!o(QeGJBRuQ18&}XrzS_CqS+6}gZywic&w^*Y zal($IulE(+58U+RCXdhmgd_F-2he2h2ap7o=B?C(3ccJ}j+aF(z6 z!1~xNaP6NuUF)?!JC82E^8j}ojQW}nz(;*~f)ILneWv6wj)9N*+TVdkU*+_3@xVv< zjaR1C(ZBipW5Gj5eN(5SFL!7lCp(y~uki|e)GME(-pe=m~uE3%ecRqx{Az>qq&$z6N}h-#7+7`i1K<(jVnFzF9xZZya)pJ<6~B z{hSK#=odd<$Ndqr{N_9N+mCe2ckevubhN+MV>?{?bLYuONBgG_M;@X9eZ8Jsbj%ar zqy5=0yMC14{9*kle?C|1b&5_OeAbWl_dFT+D8Kmze6+v$=5D#`o97yE2a9n1V;-_T zaQ))v|AEhXX=l!fNBY`1&nYf@YGXfoV%~@>(P_f#$&BF&fVAd^~QPTj#_V>abMrpOPBM)QGVmxeSKfA{WHH5 zeeF-BAL(d+_w_{w>Z~L4`g+chgo_vYoPq(*+);4l&U{gD?VmZK;Mza)Lcz7a`|&QP z_IKai;o9GQcZaLL`|A$Z{^{GrSNpqP?(4O``{EAQUhaQ8T>JZ+tPa^b)Z_Kh z{?<+4qy0Ir#{TX@J00!sezU{1zx&D#*Z%GwJ6!v_Pwa5*?|!huwZHcnb-4D=lVxLP zu3sR(`@X(j`@6sEaP9B@uEVvL`@0U;{_gKOTsyjtD>$o_XSBa{A2~<+Tld-TKqLRS z^F({PU+eU>{|eWh+{Ymu>uo;o&pG`_Uwalj>($r&UGYU~@ZH~axbfpYuH?7wXMb1g zQ>)$Ib+~`Kzw2=5lhtD#v%UaVU+j# z?o(%+YIA1Hdb%GTC706+h)XdJEM@|Tw zY>)xh75jp|p1AT|@`xWh zMegac|CZ)FS&UUV4|o5}>n@{|_@7TO^V@Ur)%M;mmiuAhhJN-PXNaPezqm$5A0V2c zOOEr2O=?{Dk;SaxH`b=laGi$ru5}{8KhPmt{b!|T-%G8N2UE57fdjP&8dx5lyvKUz z!;gyUebl^0Mt)0=wbV-KAiK4Sx(y9<0T#OGjQsQgau|4Y=auWUE7u5p-RaOVd`M_mG)8d7;5tEXZV|eP>yBJ`#3Yk38y#yvB_&sJ`aY z>U&No{8WUote!g=w1@c}I>s9|qqq56JDaDjBhr{eZ}RWod+r1EH{OkX?H#(<bSVi)kjmyY#H#hDg0_aq9-)z zSNdQ3U?bqz3<+Wzc*iHKPt5W+`xfd_=-}_-t-R$A*P`oLH~j#W)B<@bJ27JnY3Fi1Rt`pqDs_P2?5c(1bt#dhC{OE61^u^Fd-49r1;BgGOoz z>#$>bDn7(MiFsnm8Oh#`&YYS7ca65^H9o5K>a)^vZWw)~5B9uw>w!sMThFxv`IUi`~wF)v{B@zrIp7ksnz9-+z;}nb9;62*J z8aDqGG;g-ROXVkW7C9=OW*?37&@)_P2D+({bB%q^R-f26a}X8So`DSfBtM85;+m^e z$m%-&{s}+l0`yKFBKp3^CvkJ~@gJ@CQ+fU(N7BYQb4ib)-g{n^p5{!InGQWT=fb}D1Y4nxzRtX^myC<_&G1F$ zc^&q!&+rcMtqt~TGt-e@WDp#!m2_*AeIHS?gZY#($Zm;DH^j$;5#@DD#DJ z4{v^0n;vESB%bGW&*-nV3y+;%GmprUb1-nNOWMl#h(EC*^&0_g(w7Z2g4RQygq4U1fNR zXDnsbC6YWh@%&EPzm^vq>cjiE$_WSh(^G!0ZJpe+_Gl^vTRfBJaO2kciGSny}CWf1>zD|&X257#42+D-TYpIS6cgP>+J|kYY|6RTj?@8?F?~eCcw~~jtl>SCMWv|TN-sSn3 zorq6jfEjYF&$G-WPxoKXiOhWp9N1 z)jx?XY{rDDj!uh-KkezNC1t+{rVU3U7E zeaqj@2FU2SuQa)Hig~VNs{-go|H?cVQjH=nqB0b98? zvc$*uB)oX<=XBvye(cwuUge0j5q*p)WUM_1@r?mI5;JRPJIU_xvSgjgOj?6O8@kYMTOXNZBpp!K=v6`A+^vnk=S+fx| zc->>TYQ`!@{9@hHPef~KfU+cpcz>o*J}W+vSv{~0`BM4B%G42iQDOt?vwws8DSdQs z-tK*-ViJ8<9?C(aA)B9S*u`Vvs?!edRsD;vu@Sb0hP~0)=2=~?S!3yw8Kl!*?frgy z-{}1`*6+06kKdWz-lz8G_(dD7F|wPxQ-h7~bq18y`!)v8Jp=WMm?r#}t-K1E~m&OCPwag|<$?W}vV zZTmfL$R|y57QaB5-{@Mrt&KIy=vQUXr>Wuil^=dPTe5bRVPF6ExU&u4!Og6v-=Em# z-a}?tUiF++@3AI6iP?8!ru!}aeaB|6beijWkI`M6^s~$R8GF?i>Ro(Cy~w_*W}ft$ zaV8ayIQ49W*qdv4@7*;6Wp6O!R*W0h<`p%TOyPXYdX{`tE_H?${^mV&IIqusz}X|Z zt=ApR)v8HkYGx8voBz~-)L8db_K(a3(bZVjzU1D%<~{YroEuN^<{VL{*>=vS&ST?s zrkU@%_$&YTEH%+Oh8I)Q+`PsPu8#U0?CYp1+fQtJLc#r|1-ST{E#}m#`{fQ^ICCcKB*B! zi?b4Ak~pv@ci*#r)($tEl~3$M3`x)WfTeS$Odnf1BZ^0wBPPhX>6tbN&jPkraCWsUvBqVsKLlguEj z#~$M>p*K%HMNO-o@4I_Z<#()4g%8{Xnr4ae==w3#OkrlkC=* z-_>`#*2Zh-A;Ee+kn4HTd5q;Te|*mwJ?o9n9%oN+pu_AGKS7am&1d+t+_ODAmmIIF zJoD{n`xBj&A9(mHy)ZdQe%3)1V7^Umh@IQL8?HnR^f->3`s*)ufp1USTxzQL}E zo%1Y&1mn6Mlg==yHHjzIhhOH8SF^ybhMjut2a>_t!)d^ym>-nOcXA=e@A+6P;sSlz{7 z=l#IB9r-MI z)n~B{auB=7}WhoTOY-S0zz0UO`{bx9xkALrK<(=0%cq2dS)6;!O*AGv> zw}+ui+;a_&xQ1Gc{i>#{v6sCQbpvUj{bWzn<)Cib1Fa3~S=*@d>-D33?HMIs?z7p| zpZnU8uKlF?Zu%8Ai;eedMmp>@S%01*M*Ux}@ARp2sX@xBKa-zx9h`mq3I5DKb0B*5 zKGgM^<>>21dUH;n`|e2pIi5MiykQ+nzr{B8cx_Xi91Ych4U!e$JsNv;TbW3;FR^5e$F-Yw-mY=Li zY*AC3+p~|fuF(5uI_3yz`TAZqxwgNSMqZ18z1mH&krF_jTQY(9R7qBwBL~ln=xm6 zL#7k0=Q8O_^k-7ae3V*DU3g`iGcV>X{5tk6>AjP0uVujgWADKy$!Gh~x`$k2?yO7c zfsNn?z0o$&xA*tNacYt=oc;hUVgY*a<{Xo{Vm#p!>zci0Udwy)-ZlATPE%W7+k2Er zIgqF97yAOMYk86R)!OWhGf&)n-(|7B(xZ?`o9WB@eEp11W+Cc?`(WhK&+pl6wYl`> zYo$AXWlvfDdX8&s5%>6oJhQGL54}BpndAJnZq=pJ^m@R3jlGvxW}PvVYo)zk6Vvg5 zxqF*0XFI)vOBNXu>Y_|o;TeDBLLcsv_d3aJgOwKcM=xh#?p@3|cAY62)30@VPHU_^ zvwjs5?u*T9<)KnAe^L7@rXsVtgGIhrr^JizUelg!78%GpYYFm1SNxN|yA98?|NHc* zzw0^3?2p%S?&+N3?kT<1=4aiz-+wiIV}zQ+zC_(uS$nQoH@+j|O7~>vPvtz(``oUp z%==jNyvg{Z=izU1Ej^jsq;8($V5LhAA$eky*G$0VE%4WMTD_mjmf2DIy?5{P>gRM< zosr=g-ONX!@hy38bi=E9{yXyGM{Mgp>U;8@>8^SE%(k2(uzy8Qd|xv(`0N><>%F5j z+tGZ-F6?WWHQb*%N5T!B`+U$}Ke7FXL+{Zr4y}cF% zfr9vCY3`xxu=DJ-?jz5$-ntfBTAxx6GM~?TPJ3_qBef!SP_}pXUa#q4+jXz?-VAWI z#i_5~=G^yqpL69MI=33}9-Z5~hOB?=9Au69jHkH7U}CT4o}bXY+4^U6Z?=D4&u(+& zdwu=ff8U{Vx7Ry*opa?qd2V*bgYVVwTg`TlgB^+C+_Qnso`Y)}-=iNe%X)2;>q)nD zUWXd*hhhJ-exCPEhx$x@^!gtCsT}O-Z*ugrSM;`rWzZC%lM#uakQ=zzo8S8Jb9( zzmbjexxB_Q{C(1`$N8_+tN47^H%0e0yL`u1a~xn>YZdim&d*iP+w6#ctZ}~@Z+9(e z%=6tfn_lzJ*OA8D{+!MzkM)flbPw_5`VTd`_sY?C*^|6Ob6*RHI&+cdDJviO#t*;E z-PNb(e)G9(Jr}+&m-%(8d-`eJ=T&TfO5<5P?DK2xwIeP4bia;7?8lzt_2eG!Pjy>k zZZEfeoA@D?tu^*0cK7?75GVbe+Qdw@UpwD}B<}31eebFMg8g!j2YT3dA}4*zyy>wC z&iCm$d!jQsygG+G?^n7{zeRJ5IsEfX&esvcJjwcfFU;d-m&cmJYV}d+*ns@Tp4nso+!ls0Prn&#?wR$ZKspzt20n&r< zzyUd+L2qS7XJ(AtyiXqo&N{56jb6#*wFGPnJ@Jtvv^hu0XYKJ;?th;@+r3*?_rfcG zK3lM^MT%O(U+71jqX)c)2Q6*jU)pHLQ{6pT!gi73AHP{L*F>-dUUr6=ZJ|H3x!m^a z^euMudkwJUo)-M>>-7J9jr5T_pPN|u(U*)PWY*>Kj|R@%(kfK8=7*N4^j)*{XTtq)k1xx#1EQ@`kE?hBC0 znwHr=_3XY5n>nxKdS~jTGru&?d^&#B&%MmVVD&@fO7CGk_k*WDQkR)C^O+g+M|aK+ zjO55gY`b@N4`V%jrSq8{_-oI2MelCInI5rw(ntB@Lu2sO`jtL*#h?3LJMTY;PwlNO zQ%$k4??KPF(B3Dy$o>8^z-J!m#o>uO<`UVS7@;rUzi%y@ z{XECd4xcr8X8$>=9ZmhI?D4OA_2+)ouINUr>}^Gl>T|U9onA+*R^8a^CGPlHAnOeL zoExkuk%2xOTPH8>vLXA}8)w;WIZLlLPl!M;*BrdXX19%eksrTsuC7<1f0OA|{b#1= z_5NG+9lqbJ=W|WC)o<3G>a}#7NwlH%ta`(1?7V)quKQX#tX=Cdo-uyuXV^jC3#WFU z>#b`(udmKYpV!kJ{w+pt_0wn1FvnKC%*=PHk3C1p7hhZdu%c1FuVuXdN$uLzs&{Hr z*7jN?%<~)Ktm~DSNbPa$d$nd)TW)?z-5_4A7w^}SxmQ%}$gGiBoEkpX-d*hjUw<)4 zAU(a4-_|$wS5>={r_Mg=BVYcG?ay=TD_*gG`O3IReYCgi^+4CG>oNnkmVjL|2>r=@ zS;Z@OSb+#NPP&&SFPq9rp-(n~ywB z{m6Ppe7<7~Xp;x>M^0X+PI(2g>|(6oH~fcx(aoAGos&PIi$Cp$W4-|+rj-306XvbF zi6PGOw9RW9h6lER4*#M%zCnL{LJXPrdtZc3$%?(7%Ypynd$7v3Nb@Y_SeMwrTEves zBg zbCme`oCiILb4-3p@2Bz;W1Qg=Wxa=G&U)Uv)k%6j=Qcg?b6V(Qp6M@igoC|tw(re` z)tgca^~3jQ`T0ny9)0B0$M!N>?=r(tzp3ES9XkTs<62|gr*Y=(J|VR?ec+C3{h_|d zi`XYOsQuO>tX?w~H4pjhGk4moBQ{uzp4y$?cf2)6PBmLyt8Se8L~K>pN8MY|FRZig z+8sMd!#?mXe(c+OfHuNb)L`VwOz1pvv)h?o>RD!+*q07PO~j+QLz+KO1#Z<+JN zdzO3BfTnr&J-bVj*vgDH_Wi`>$sRYIU(+tzIWv+Qc;4$ZCtGUU``-JGYfY#;B<9Ia zVui}H&*Ph}RvP@oj76NG2l`ds!tdA8)`!-r*w(s#m;IGJVw>a<*A>B$pRvK;uW|q! za>Mf`?E_8i=5M?k*^5W-!yWIWm-fe>T$3H=ymxSv6>XiJJ8yE)nAz1BbWpeN@nb$Y zUkizzcbR)FiJiM{(Fs_-8)@HT$Q180!@j)2U)TZ~_>s7g_NkW;4agf?fhQ$ts1vb8 zPIfuVw)z3RlwFyWeXhIsg7xx*H+kxuY_F!qer}`Jw9&=>@M@m3R-hB|beU40m@Rrv zIWu8-^^1RF)B8D&{Jwu~bE3|Gu(k^xu$(`h&q<(IzL@=W@;UJMZeNq6YcIoN#w315 zGk&9wIcHv>ldqv&H6-_VBwi8=(qwIH72l@jpiQr(+9&y2yydSv(5RdZPdJSIuItxh z?>!#G�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 AvH$=8 literal 0 HcmV?d00001 diff --git a/test/ScriptGenerator/AdventureWorksStoredProceduresCreate.sql b/test/ScriptGenerator/AdventureWorksStoredProceduresCreate.sql new file mode 100644 index 0000000000000000000000000000000000000000..689f061aa95ffd1340157bb23f7db205226961ce GIT binary patch literal 145832 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 I-rDE?11lg^fB*mh literal 0 HcmV?d00001 diff --git a/test/ScriptGenerator/AdventureWorksTablesCreate.sql b/test/ScriptGenerator/AdventureWorksTablesCreate.sql new file mode 100644 index 0000000000000000000000000000000000000000..8d974042e99bf12bbddfc607fa89847b65a8e067 GIT binary patch literal 270752 zcmeHwZF3#Bk?wrGw`%_bzeP@**isVTB(>QpTBIzk^+J=B6|XAAl1N%&EJ|FGlBNCe z_uhV{*+K(o%mDLpI5RxO62&tI=mEMLPd6G3;Q#&Kr`2AyU2Rm)tIg`D`cNHLZ>!7d zeRWQMJ*(c)|G!ih)jz9$tNwTOUG=2?|Eub^>Su$VzO4R5G=haDdM&E8!TU76oN`U5HtFNkW=--{{ z>*{v(7kYA={{9>NzD>XXOiwqeo$3+&)@}Q$ZZCScPv2}-kLe8$sssA}Y4wnP_UP#o z`lNd&rGKC@PpIBDwc~(lZP8zk>GOl?9{t;{c8$7s>FGAT2erV3&FWiv3-h;~3%BZa z{4aw;csscCoOlEI;BVcc{pzRc7IETB`u7EW_qcBP2DS7_-A=S>hg$N0c#qaSsC(_o z2|vF4+=BgDGLQx2bY6X`-xszauD3}NJfs@$>vle-|4&I1oRl|fp5G$67gXXs>BSpr z`ERII&*=B>sE0>X{@sn*kXHN6QM32tgm#yvf!R{l!uc~9*+x}tzypH%-%&yMS-Jep3Z7bkVA z@t$4c{WBU%Piv0erB4s(X_G7-(VNhFrgHRoTyU$8u13ivmB4tyQ<1;l>J5@Uw0(~> zV3#=lpw?$-)lT(2>3GPU_=)J@4%L4^qivJ^|B2rBJ?R(zze{}qqCo$lb6fNbW2;@W zp%-`SvR@E)9uS55RQDFOY?G*9{5_`sx2u29)4$WdC#2i=NV32Tj5Fvo{(^?@)gv65 zzfGT>P&;?1RXisBx(`SW;1x<95dEiA^5AoC{IZ+Ww}({r8I@oe9@L-jQhDGAmwsHg zNtZTJ#^0BuO~CPgQj3<4$?aUw znydLEBVl!j{Fo$z@x4dV`Bd9e$jHY_yNrznurvFF8JCLITk-&ae;Nn>a)pCzF&&oP zqq^s{9hbMJ+kKAGrCio+pI_KO&Co*Vk-c%7oioQ5Vd zZ{Tg-t@|u!_JI2TGd*Dq{YadALx10@tpj{I_Ussg;j3s|%%=|T^)>Ms8i4o1w_&eX zWM<2GiJpYUO861_vtVZ*FT$d?_95WOmH7~urNFC#=LCO_J(VVpB;Vusk;daOVTV1g zK3pMW?zmlsHv(_CbpCvwY!Wc#Ey)(v1hXsHXg8yV)j1=yc}JeXG5rAN`ts{GQJD6O zx(i>NKNs>$P)S==Jd;^}YK|RSP52<%7J*7Q6SjSU+Z4%Q8*wUl2XmOGi(8B%yDV<83-`D8+$qsR!r8-`B)djt`07$)CXa z=6NtYU$md28}Jt3Q=>NGQcSHZ7VsT$;Vt<`66b()wGZ7EOSoV6>9|*q*pK2~9aCHG zQNJJ`;f{-{=x@^6@*~wgthvJ8%l#|d5e{9{m;@h3%RD8uJt}obu|$sLAkNs29%2>e z^urMr-6MZSq`yh`b$K3Gh;9djW4?`$G3$E_C9#|o#kC(+?uY3J^!WZkJU3l?3(unw z5^|}`cSxg+Pgllao(*3?hGT_fIV5igG0iU)U0a~6z| z54Bft-6#ctrocQm5SljPo%EA!a5Tp1vpI6RO2xrs0lSMO(Ufrb@ zVdXX5oryVCWztb~_9kO#5bPRV_|XFX3-JGVYliRw+N#=EM@gLO)=D}HTI8<{e69VOTNoN z`*Hkzhn~yfR6o0@IpXY{dn$qB8xmdwcl ztA-&?clZ2bT5HUoBj)>F%yMw8iv?)g)$Xs8EQeQ3HlUOz&I*J(u$?W)nQ8dE?o(Ix z#h1}o-YQ}!51+&K{`le78pBqIRKod(-#Wh(#`bz=J)c)F?#}vf^gpO)?k9Cd;t^%6 zAx3*ManR<(Q0RvhG$9zfqQ*f38v``|b%h9-|xJV!VI18HMp&+dG_`BKA z)T*GS9H08YXLI1B4%yGtG;e6<#eLe-q-l0NU1(J^hm>3ns?;|kvF^6Ejq=*smRs8~ zXA|1ew2y!fNzGXfUgp`Eq4=heZF$+3tL7!5dHRHuo2He%_rv?HnI~AeMl_C37WKbb z4wssI9ly^_+;E zwZ*wd-;w5FSNTP6%7`fAOf^2CyzRuUFz*gCsh_Du*fWR>ig%ySKSCs!*8uFS?Q||8 z{6Rj66DLh!7a;mBXJ?k?H6kw&^AKbw9@V?%FFw=4><(v!@_xs3i?B}UC|2U_aPwHp7P8ZVh z^2f65vgP{znPsWg+$G%wpJjCeqr9YEbJo$TdL-nYOYc+SIT1#o zg|hM7ZjU5}ofYUs|6E?7);*_pi?rv0IKeAkkULJC@0K6Dyoj$a>w~KkVZ<{LiFcoM z`t*g~dahYM*M!HOf1YeNe-p7vj1{?8M0_!hQ}(%YWcnwh`kE>|$7%omHz^*ad{eu; zjD-Fkt4&|5RD8n0pXlTTIYm8n7R1tV&gNN&es(F5+)$X<{FXIRP7^7eSA>zajCGtL z=IEL)DMWN-WGwYZ!M^i$tTVx1#T@oky_?mxgUuOEzNIL&AzfE39*|FqdF45IwwUMe zdu7hiw6c6XRmc4$r9H=^}JS&*3W+G>p0CY)WYdhX;kRi{ zbJngKJ;K4U5!&sV_IZ+SDZEWacURYz{@MnV+kmndi(YB=<)=Nr4?+B3le{%VAD10z z0Vm~lSnMR>TPktKD{hd)eR6V_td!#WHu=s~ckAo{-Ia+OWFHd8_^wKh_{a52?x2-- zHs5j^m*N{Xx2Q#rDHa#E!O?q0qjZ-_aY=o5u24nf{1NpGyt#XIPv%pqu|+jCmvDDy znO?$YKO+75NG*I$)c--$r=*4LcQ$kzS-k~L zZ|m>f{a0c6R8$=~5~uWo^~j5>D9uhCvEgXF%Sp(k==$&z*;Kjryu7yD2>TOR4XoL6 zdvfV4FQ()8sx=oUTp&US&rLrUeeFJ5Xr{aN6~u^rD=zk3g8+2oyjIyQ7NQ%r+PAy+PPY7tFVsi*NN`n6IK_xv_a~w?F(+s z=DU5rr`ed3Y&=2^s3bBL`NmB?CsRgEcMFrIxwbB2TNgc>b&_W!{h)L~`xMKuE5pvJ zp3t~JY~!5nM1`-)e=mny-K=nmE6x%-y>n#+RZ4Af_j_xQll`Hd|8Rsf&X33Hb?#}g zt|!R)y(HRfZDpq@Xvq%4^xDZ5c>#TI6UG@RXXM4Sw<4TNa+a*VO}UH%xOWX4JEnN5 zjEug!1T0+%CB>@{8`Uj(`vtupYmaZ})8pzlglJFb_wOjGi5TyXb&PYLzO#L)I~BaC zFX>zBy{w~O)){MG*3^Gn;b)_!x=U}^rN8;vZ-@>k0da6|^$xWPcfY?TxmZP$-yO+uJ6 zqJjH55ru$!Vf`5M;yh1xlT}O|;{t8N`Y`T;WZcSY8}BTDln^nKy*atDBFwZul6+68 zHn%*t=DoVbvgf3%u4^r$J!+>A3^*0{@ptspZ~GU7aL;LN27Gj_`jT)C^Ew}iAS*=v zz;WrfH7C4H`&#}&bvFpcZey8jL+4$_) z{*Au*E3GwtL;vm&&fO-o+MwTes=v|i+w}X-^c!d0J)+<2mGSSdYOhSzzTG;x;GA9| zmt8JWx@2Wv>cR(<`s@4y&0XONIKRsLgDL7``>Hu?{!7A{W720mLy?p*QYDmsH0d)IT}vFF0Rcd7jqMnGRKGOBI{{^fH+QS@ND%tCy!`+BOd%S{mVUr z#6sK+LJHXPJ&H;0k|jr$xy~=J^(MrZkUxEJrit%s92px&+A<8p*M3HNhqa8RdCpCW zp@sOX*9#FXdqw^+P5}9lMl1GIU`BUS&^M144tq6^hC|%uHPf>7RSQY6PTV)*pjYd7 zElqR>^R1Hgd_-!G>yz+!eeTH9Jc*#W%=06PO})F)QN8M)UKIvE(IT9yr)&6})Ze6O z`RnW4XPgW7lI#-V(TF%B-u#qo)Wdq**ckw~DUy7r`cq=vYgIN=>+gZbchTnV_EFOo zYHO=FwpHwc?tbRM8ta|i3ptaI{AmR7Y0AjRix&8GLti$J#&uwe-|iS`!rNAaD`TLK zivakol6S5#YKj=;&+gV3 zC>>p}e14uIfAD zDCO)FNJT4F<+C>FEiyB4%6g7`y4!^OcdTu|*fzkQOY0FGj+%!wIuSR$X~>r1gTpkt zgu^jJ&^SB18-C%A3yjHqLP**7gt#7OfdV(>X?jK;w(%)Z1ad*1xPb$s{w+~#r?g$i z7^O#Lb@l0@={JWN@=pl4|3$4ugfqX^K4IApjqyoXosU=1$rLL8gE;brY!2e8uFrDz zD)RZQnr-WNp)`1G9bDz(I!ndRMUzs9i#9x_mBWV=k;Td(&Ys#PS{rq4ZmyoLv9=s* zS9i9kM&@lAx5%kECyC!oOpZC=v^@MyMvtD^cf(;vxepQx^7^Y&We6= z*2P>uu$}{C<1-2Po+HgC$>MkML|ymt$^tPa>oJyWIN$6mXf(csP(&9QWxe;rEX2jY_0 z8Js@RbT?hUS3qHofEx;706?~e$_ z0%XTI^)dQjg#`275LL$X*h}XjKK5!W>fa~a8&HX)Q#FQ_|I~Fh1ibwvrK7%T?>V!B3&d>o3jWBj}HRrxqp|(xy zWSDW`K0>i4SU0rVDCb zquh3^ZmlwHX&w+Zy`iy!X!kkkGa{Op-QRRiG|d-hc~WI$l=ZhjTO2O_0lj`{a#e-~p5}tHNo;J#B1ezxTVHFl946c!fv%6z{IK&CRlTn47FL*K-doJRL zZ_9IYeLuB)j*J*Ftck4Tu-D|;cUs#Qcjr^equeB)^ab_i4gH3 zbgx496?c9=*6aCJ2JsHrE6nu;R~13?WhQO)wKv2($Ro7|ITY@R%o*ogwv;X1H5yJ6 z4a3;!O^>npqb=snFbEjZm9dnEpVxytVViBt2}?=O#zvjgd)K%#P252~j_j6O&phLq zr^TOPuqPFvvEy}3UfgS1qkTh}w(K`qE15Xkjqfu`MbwZV$16M5PX6@Uaclbvs)-1# zi@>>vo{Ko9X)Jwa9P5yc*(r?}8?#gIU1Rn%F&lg65JiWN#AiGDvyip#2t<*63GLh( z2G8yJ*6L={aX;rUkB(dI>#~iMHm}FVN&Bs9l$<6?^6U(rQ7SuN2%Nk_Ioa2L&sw*P zYJZNM!><%l>bhH3erS&8my(RkR;N4<*L}A0T0-p7H4qnU>-|u8=D!zO&zR+6g>5Za zW85?`Zl}Hx8GF&!Sf+hG&6gBrxiS{o;8}To%s$Bjxy3K*jP4V%J?<^+jg@BzJDSKT z_GwDSx4$-RMF3nbdYBjZuwH$^4*LFWwP+2|Mn5Ml^We5oao~Fof-r6H+l5>o%#VZhHvcOpus+Ovp<|#5#tzkRQuuZ0%vHL6b& z)v1=KFl^^)C68&*-$rr}eo~xOw$qeI82sP1l2=wk$(5wM&V_ zhr-q7x2zF%DhP{{*0GQGjCRHy)BhJVMuypEJ!ec!amAsiT|!2Yok`UVK{d8@LA_OB zk`Z^QWW6En1;L{HO#jYnuL@_mKcT{F+?QZ-G(&NUE7d3*^o`r5sWUr+k9`NN`*OueB_IBED%Cb>t zZ8;EWd0gLAwM)_U2lV$o#a)0&IJ?*8T9byS>a6X^CPlO!)=@6pwt#3CPKJ3xzQgy# z|BdSJ^bfN5lK$6acj(i1v=U^O#=alaVwvrd1RqiP-RdWby1K8k>ZN82X+Z~mhk4;v-HnA{$tC$VlGh)yXOZK3r5`dk~Es5W_(AL=16z1w4L_a zGo6ZO`i#cFdG!n7oXl)*I+|DE7rFyYB6rC!pTqHaFH|D#@-y9q4oR#GU zxAzvUZui(0ai-rLT8QXW0y4H zeLZiK?4Q0T?9X`}F4p0YKc$u>jf4KILB^l9O6j^!X#EsXZFgQQZcKGI^NEjaBT*_3 zEVVn{UR_ML4)}cv2tV0%>LSy0XGGTVz2x!Lw&Cn4@Ud_hv%C&^0WJ+B39ZQPlV=nbE7!tt%#l~e3Q zyde7uYXK{9La24wg76_e+ca`kr$b7QY7Or`yM08x`Dn~oG0)7I9Y3Kl)c*Fc)$I|m z@Q$^%c;l)po<9b(R@*jBmk_=0Zo&Mw3%$@TS?^q1q3Kv5jlw!-W{c1Semi!XtSwR= zm$Y?C)sS(LhiE%j{y+N^7xUz9Hy?xMzv{ZUC2ts-@LS5_ gv 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¨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 + /// The command-line options helper class. + /// + public class CommandOptions + { + private const string DefaultFilePrefix = "AdventureWorks"; + /// + /// Construct and parse command line options from the arguments array + /// + public CommandOptions(string[] args) + { + ErrorMessage = string.Empty; + try + { + for (int i = 0; i < args.Length; ++i) + { + string arg = args[i]; + if (arg.StartsWith("--") || arg.StartsWith("-")) + { + // Extracting arguments and properties + arg = arg.Substring(1).ToLowerInvariant(); + string argName = arg; + switch (argName) + { + case "-filepathprefix": + case "fp": + FilePathPrefix = args[++i]; + break; + case "-numberofdatabases": + case "-numberofdbs": + case "ndb": + { + if (int.TryParse(args[++i], out int n)) + { + Databases = n; + } + else + { + ErrorMessage += $@"Argument for NumberOfDatabases:'{args[i]}' is not a valid integer"; + } + break; + } + case "-tablesmultiplier": + case "tm": + { + if (int.TryParse(args[++i], out int n)) + { + TablesMultiplier = n; + } + else + { + ErrorMessage += $@"Argument for NumberOfTables:'{args[i]}' is not a valid integer"; + } + break; + } + case "-storedproceduresmultiplier": + case "spm": + { + if (int.TryParse(args[++i], out int n)) + { + StoredProceduresMultiplier = n; + } + else + { + ErrorMessage += $@"Argument for NumberOfStoredProcedures:'{args[i]}' is not a valid integer"; + } + break; + } + case "-viewsmultiplier": + case "vm": + { + if (int.TryParse(args[++i], out int n)) + { + ViewsMultiplier = n; + } + else + { + ErrorMessage += $@"Argument for NumberOfTables:'{args[i]}' is not a valid integer"; + } + + break; + } + case "h": + case "-help": + ShouldExit = true; + return; + default: + ErrorMessage += string.Format("Unknown argument \"{0}\"" + Environment.NewLine, argName); + break; + } + } + } + } + catch (Exception ex) + { + ErrorMessage += ex.ToString(); + return; + } + finally + { + if (!string.IsNullOrEmpty(ErrorMessage) || ShouldExit) + { + Console.WriteLine(Usage); + ShouldExit = true; + } + } + } + + /// + /// Contains any error messages during execution + /// + public string ErrorMessage { get; private set; } + + /// + /// Whether the program should exit immediately. Set to true when the usage is printed. + /// + public bool ShouldExit { get; private set; } + + /// + /// Get the usage string describing command-line arguments for the program + /// + public string Usage + { + get + { + var str = $@"{ErrorMessage}" + Environment.NewLine + + " Options:" + Environment.NewLine + + $@" [--filepathprefix **] (default {DefaultFilePrefix})" + Environment.NewLine + + $@" [-fp **] (default {DefaultFilePrefix})" + Environment.NewLine + + " [--NumberOfDatabases **] (default 1)" + Environment.NewLine + + " [-ndb **] (default 1)" + Environment.NewLine + + " [--TablesMultiplier **] (default 1)" + Environment.NewLine + + " [-tm **] (default 1)" + Environment.NewLine + + " [--ViewsMultiplier **] (default 1)" + Environment.NewLine + + " [-vm **] (default 1)" + Environment.NewLine + + " [--StoreProceduresMultiplier **] (default 1)" + Environment.NewLine + + " [-spm **] (default 1)" + Environment.NewLine + + " [--help]" + Environment.NewLine; + return str; + } + } + + public int Databases { get; private set; } = 1; + public int TablesMultiplier { get; private set; } = 1; + public int StoredProceduresMultiplier { get; private set; } = 1; + public int ViewsMultiplier { get; private set; } = 1; + public string FilePathPrefix { get; private set; } = DefaultFilePrefix; + } +} diff --git a/test/ScriptGenerator/Program.cs b/test/ScriptGenerator/Program.cs new file mode 100644 index 00000000..8e2f0481 --- /dev/null +++ b/test/ScriptGenerator/Program.cs @@ -0,0 +1,57 @@ +using ScriptGenerator.Properties; +using System; +using System.IO; +using System.Text.RegularExpressions; + +namespace ScriptGenerator +{ + + class Program + { + internal const string DefaultFileExtension = "Sql"; + static readonly Regex ExtractDbName = new Regex(@"CREATE\s+DATABASE\s+\[(?\w+)\]", RegexOptions.Compiled | RegexOptions.IgnoreCase); + static readonly Regex CreateTableRegex = new Regex(@"(?CREATE\s+TABLE\s+.*)(?\](?![\.])[\s\S]*?CONSTRAINT\s+\[\w+?)(?\](?![\.]))", RegexOptions.Compiled | RegexOptions.IgnoreCase); + static readonly Regex AlterTableConstraintRegex = new Regex(@"(?ALTER\s+TABLE\s+.*?)(?\](?![\.])\s*\b(?:ADD|WITH|CHECK)\b[\s\S]*?CONSTRAINT\s+\[\w+?)(?\](?![\.]))", RegexOptions.Compiled | RegexOptions.IgnoreCase); + static readonly Regex CreateViewRegex = new Regex(@"(?CREATE\s+VIEW\s+.*?)(?\](?![\.])[\s\S]*?\bAS\b)", RegexOptions.Compiled | RegexOptions.IgnoreCase ); + static readonly Regex CreateProcedureRegex = new Regex(@"(?CREATE\s+PROCEDURE\s+.*?)(?\](?![\.])[\s\S]*?(?:@|WITH|AS))", RegexOptions.Compiled | RegexOptions.IgnoreCase); + static void Main(string[] args) + { + CommandOptions options = new CommandOptions(args); + for (int d = 1; d <= options.Databases; d++) + { + using (StreamWriter writer = new StreamWriter(Path.ChangeExtension($@"{options.FilePathPrefix}{d}", DefaultFileExtension))) + { + string oldDbName = ExtractDbName.Match(Resources.AdventureWorks).Groups["dbName"].Value; + string newDbName = $@"{oldDbName}{d}"; + //Turn Off Strict Clr Mode + writer.WriteLine(Resources.TurnOffClrStrictSecurityMode); + + //Put all original objects in the 'newDbName' database + writer.WriteLine(Resources.AdventureWorks.Replace(oldDbName, newDbName)); + + // Multiple copies of Create Table statements + for (int t = 1; t <= options.TablesMultiplier; t++) + { + string tablesScript = Resources.AdventureWorksTablesCreate.Replace(oldDbName, newDbName); + tablesScript = CreateTableRegex.Replace(tablesScript, "${begin}" + t + "${middle}" + t + "${end}"); + writer.WriteLine(AlterTableConstraintRegex.Replace(tablesScript, "${begin}"+ t + "${middle}" + t + "${end}")); + } + // Multiple copies of Create View statements + for (int v = 1; v <= options.ViewsMultiplier; v++) + { + string viewScript = Resources.AdventureWorksViewsCreate.Replace(oldDbName, newDbName); + writer.WriteLine(CreateViewRegex.Replace(viewScript, "${begin}" + v + "${end}")); + } + // Multiple copies of Create Procedure statements + for (int s = 1; s <= options.StoredProceduresMultiplier; s++) + { + string spScript = Resources.AdventureWorksStoredProceduresCreate.Replace(oldDbName, newDbName); + writer.WriteLine(CreateProcedureRegex.Replace(spScript, "${begin}" + s + "${end}")); + } + //Turn On Strict Clr Mode + writer.WriteLine(Resources.TurnOnClrStrictSecurityMode); + } + } + } + } +} diff --git a/test/ScriptGenerator/Properties/Resources.resx b/test/ScriptGenerator/Properties/Resources.resx new file mode 100644 index 00000000..352b55a8 --- /dev/null +++ b/test/ScriptGenerator/Properties/Resources.resx @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\AdventureWorks.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + + + ..\AdventureWorksStoredProceduresCreate.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + + + ..\AdventureWorksTablesCreate.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + + + ..\AdventureWorksViewsCreate.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + + + ..\TurnOffClrStrictSecurityMode.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + + + ..\TurnOnClrStrictSecurityMode.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + + \ No newline at end of file diff --git a/test/ScriptGenerator/Properties/launchSettings.json b/test/ScriptGenerator/Properties/launchSettings.json new file mode 100644 index 00000000..2276a4c4 --- /dev/null +++ b/test/ScriptGenerator/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "ScriptGenerator": { + "commandName": "Project", + "commandLineArgs": "-vm 59 -spm 8 -tm 15 -ndb 200" + } + } +} \ No newline at end of file diff --git a/test/ScriptGenerator/ScriptGenerator.csproj b/test/ScriptGenerator/ScriptGenerator.csproj new file mode 100644 index 00000000..b3f80b52 --- /dev/null +++ b/test/ScriptGenerator/ScriptGenerator.csproj @@ -0,0 +1,23 @@ + + + + Exe + netcoreapp2.1 + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + diff --git a/test/ScriptGenerator/TurnOffClrStrictSecurityMode.sql b/test/ScriptGenerator/TurnOffClrStrictSecurityMode.sql new file mode 100644 index 0000000000000000000000000000000000000000..7d18b5a07d3b07a92b0c85b0fd93b782cea4859c GIT binary patch literal 292 zcma)$y$ZrW5QM*4@Ey{nvCulDM6pp&0)mKyc*X;b!JL0Dug>iQh|TTp?CgE>c^9n6 zN!W0vq$A+CvZYUtDGRGPPpOq$9W6U`7a9(DYHo5nZBp%y(jV$e_T2S0ays>i^j1H6 zyGt3Ef25mC-BSFqNOLC4#4Jq7j9lv?CdpZw>vw{RlhQ;_Q1zk*n_~8u(`$Z-8u`P& F*&FE9WA literal 0 HcmV?d00001 diff --git a/test/ScriptGenerator/TurnOnClrStrictSecurityMode.sql b/test/ScriptGenerator/TurnOnClrStrictSecurityMode.sql new file mode 100644 index 0000000000000000000000000000000000000000..df67662bde4b3102df4a800cde284bdba76659a4 GIT binary patch literal 292 zcma)$y$ZrW5QM*4@Ey{nvCulDM6ofT1OyQY@r(yC1{42YUY%@e!Qysj=VoX2^G;b4 z6R_n>Mnj9^%8nre<|NiT9JA4zO4(4eC+9-N5l_KQ8%{r=*iyLDwCY}SYm*b|R9^E- zx{=rkk?P7^6PC