-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Add PowerShell logging tests for MacOS and Linux #6025
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
98580d0
c501ab2
39e4a6a
10e87e0
2a5e4c9
256085f
3d12959
8512f77
d5c6fb3
62091bb
fde9b0b
c0b1441
e2d5b36
733c5e3
c465bd2
d8cd56e
f7d8472
90b91aa
e3df650
401ec3c
ead984e
4eb358c
8ff9d13
0657488
c587b43
8ced4aa
6f9df98
5a3a74a
e0f58ad
8927e38
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,16 +33,11 @@ public static int Start(string consoleFilePath, [MarshalAs(UnmanagedType.LPArray | |
| { | ||
| System.Management.Automation.Runspaces.EarlyStartup.Init(); | ||
|
|
||
| // Set ETW activity Id | ||
| Guid activityId = EtwActivity.GetActivityId(); | ||
|
|
||
| if (activityId == Guid.Empty) | ||
| { | ||
| EtwActivity.SetActivityId(EtwActivity.CreateActivityId()); | ||
| } | ||
|
|
||
| PSEtwLog.LogOperationalInformation(PSEventId.Perftrack_ConsoleStartupStart, PSOpcode.WinStart, | ||
| PSTask.PowershellConsoleStartup, PSKeyword.UseAlwaysOperational); | ||
| #if !UNIX | ||
| // NOTE: On Unix, logging has to be deferred until after command-line parsing | ||
| // complete. On Windows, deferring the call is not needed. | ||
| PSEtwLog.LogConsoleStartup(); | ||
| #endif | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. The config file overriding should be done through an environment variable until the command-line parsing is moved to an earlier point.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Until we decide what changes we want, I think this is the simpler solution. |
||
|
|
||
| // Windows Vista and later support non-traditional UI fallback ie., a | ||
| // user on an Arabic machine can choose either French or English(US) as | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,233 @@ | ||
| # Copyright (c) Microsoft Corporation. All rights reserved. | ||
| # Licensed under the MIT License. | ||
| using namespace System.Text | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. copyright header is missing
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
|
|
||
| Set-StrictMode -Version Latest | ||
| $ErrorActionPreference = 'Stop' | ||
|
|
||
| Import-Module PSSysLog | ||
|
|
||
| <# | ||
| Define enums that mirror the internal enums used | ||
|
||
| in product code. These are used to configure | ||
| syslog logging. | ||
| #> | ||
| enum LogLevel | ||
| { | ||
| LogAlways = 0x0 | ||
| Critical = 0x1 | ||
| Error = 0x2 | ||
| Warning = 0x3 | ||
| Informational = 0x4 | ||
| Verbose = 0x5 | ||
| Debug = 0x14 | ||
| } | ||
|
|
||
| enum LogChannel | ||
| { | ||
| Operational = 0x10 | ||
| Analytic = 0x11 | ||
| } | ||
|
|
||
| enum LogKeyword | ||
| { | ||
| Runspace = 0x1 | ||
| Pipeline = 0x2 | ||
| Protocol = 0x4 | ||
| Transport = 0x8 | ||
| Host = 0x10 | ||
| Cmdlets = 0x20 | ||
| Serializer = 0x40 | ||
| Session = 0x80 | ||
| ManagedPlugin = 0x100 | ||
| } | ||
|
|
||
| <# | ||
| .SYNOPSIS | ||
| Creates a powershell.config.json file with syslog settings | ||
|
|
||
| .PARAMETER logId | ||
| The identifier to use for logging | ||
|
|
||
| .PARAMETER logLevel | ||
| The optional logging level, see the LogLevel enum | ||
|
|
||
| .PARAMETER logChannels | ||
| The optional logging channels to enable; see the LogChannel enum | ||
|
|
||
| .PARAMETER logKeywords | ||
| The optional keywords to enable ; see the LogKeyword enum | ||
| #> | ||
| function WriteLogSettings | ||
| { | ||
| param | ||
| ( | ||
| [Parameter(Mandatory)] | ||
| [ValidateNotNullOrEmpty()] | ||
| [string] $LogId, | ||
|
|
||
| [System.Nullable[LogLevel]] $LogLevel = $null, | ||
|
|
||
| [LogChannel[]] $LogChannels = $null, | ||
|
|
||
| [LogKeyword[]] $LogKeywords = $null | ||
| ) | ||
|
|
||
| $filename = [Guid]::NewGuid().ToString('N') | ||
| $fullPath = Join-Path -Path $TestDrive -ChildPath "$filename.config.json" | ||
|
|
||
| $values = @{} | ||
| $values['LogIdentity'] = $LogId | ||
|
|
||
| if ($LogChannels -ne $null) | ||
| { | ||
| $values['LogChannels'] = $LogChannels -join ', ' | ||
| } | ||
|
|
||
| if ($LogKeywords -ne $null) | ||
| { | ||
| $values['LogKeywords'] = $LogKeywords -join ', ' | ||
| } | ||
|
|
||
| if ($LogLevel) | ||
| { | ||
| $values['LogLevel'] = $LogLevel.ToString() | ||
| } | ||
|
|
||
| ConvertTo-Json -InputObject $values | Set-Content -Path $fullPath -ErrorAction Stop | ||
| return $fullPath | ||
| } | ||
|
|
||
| Describe 'Basic SysLog tests on Linux' -Tag @('CI','RequireSudoOnUnix') { | ||
| BeforeAll { | ||
| [bool] $IsSupportedEnvironment = $IsLinux | ||
| [string] $SysLogFile = [string]::Empty | ||
|
|
||
| if ($IsSupportedEnvironment) | ||
| { | ||
| if (Test-Path -Path '/var/log/syslog') | ||
| { | ||
| $SysLogFile = '/var/log/syslog' | ||
| } | ||
| elseif (Test-Path -Path '/var/log/messages') | ||
| { | ||
| $SysLogFile = '/var/log/messages' | ||
| } | ||
| else | ||
| { | ||
| # TODO: Look into journalctl and other variations. | ||
| Write-Warning -Message 'Unsupported Linux syslog configuration.' | ||
|
||
| $IsSupportedEnvironment = $false | ||
| } | ||
| [string] $powershell = Join-Path -Path $PSHome -ChildPath 'pwsh' | ||
| } | ||
| } | ||
|
|
||
| BeforeEach { | ||
| # generate a unique log application id | ||
| [string] $logId = [Guid]::NewGuid().ToString('N') | ||
| } | ||
|
|
||
| It 'Verifies basic logging with no customizations' -Skip:(!$IsSupportedEnvironment) { | ||
| $configFile = WriteLogSettings -LogId $logId | ||
| & $powershell -NoProfile -SettingsFile $configFile -Command '$env:PSModulePath | out-null' | ||
|
|
||
| # Get log entries from the last 100 that match our id and are after the time we launched Powershell | ||
| $items = Get-PSSysLog -Path $SyslogFile -Id $logId -Tail 100 -Verbose -TotalCount 3 | ||
|
|
||
| $items | Should -Not -Be $null | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BeNullOrEmpty is for strings; Log entries and it's collection are not strings and I don't think it makes sense to comment that fact that it is not a string. |
||
| $items.Length | Should -BeGreaterThan 1 | ||
| $items[0].EventId | Should -BeExactly 'Perftrack_ConsoleStartupStart:PowershellConsoleStartup.WinStart.Informational' | ||
| $items[1].EventId | Should -BeExactly 'Perftrack_ConsoleStartupStop:PowershellConsoleStartup.WinStop.Informational' | ||
| # if there are more items than expected... | ||
| if ($items.Length -gt 2) | ||
| { | ||
| # Force reporting of the first unexpected item to help diagnosis | ||
| $items[2] | Should -Be $null | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use -BeNullorEmpty? If yes please fix. If no please add a protection comment.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BeNullOrEmpty is for strings; Log entries and it's collection are not strings and I don't think it makes sense to comment that fact that it is not a string. |
||
| } | ||
| } | ||
|
|
||
| It 'Verifies logging level filtering works' -Skip:(!$IsSupportedEnvironment) { | ||
| $configFile = WriteLogSettings -LogId $logId -LogLevel Warning | ||
| & $powershell -NoProfile -SettingsFile $configFile -Command '$env:PSModulePath | out-null' | ||
|
|
||
| # by default, PowerShell only logs informational events on startup. With Level = Warning, nothing should | ||
| # have been logged. | ||
| $items = Get-PSSysLog -Path $SyslogFile -Id $logId -Tail 100 -TotalCount 1 | ||
| $items | Should -Be $null | ||
| } | ||
| } | ||
|
|
||
| Describe 'Basic os_log tests on MacOS' -Tag @('CI','RequireSudoOnUnix') { | ||
| BeforeAll { | ||
| [bool] $IsSupportedEnvironment = $IsMacOS | ||
| [bool] $persistenceEnabled = $false | ||
|
|
||
| if ($IsSupportedEnvironment) | ||
| { | ||
| # Check the current state. | ||
| $persistenceEnabled = (Get-OSLogPersistence).Enabled | ||
| if (!$persistenceEnabled) | ||
| { | ||
| # enable powershell log persistence to support exporting log entries | ||
| # for each test | ||
| Set-OsLogPersistence -Enable | ||
| } | ||
| } | ||
| [string] $powershell = Join-Path -Path $PSHome -ChildPath 'pwsh' | ||
| } | ||
|
|
||
| BeforeEach { | ||
| if ($IsSupportedEnvironment) | ||
| { | ||
| # generate a unique log application id | ||
| [string] $logId = [Guid]::NewGuid().ToString('N') | ||
|
|
||
| # Generate a working directory and content file for Export-OSLog | ||
| [string] $workingDirectory = Join-Path -Path $TestDrive -ChildPath $logId | ||
| $null = New-Item -Path $workingDirectory -ItemType Directory -ErrorAction Stop | ||
|
|
||
| [string] $contentFile = Join-Path -Path $workingDirectory -ChildPath ('pwsh.log.txt') | ||
| # get log items after current time. | ||
| [DateTime] $after = [DateTime]::Now | ||
| } | ||
| } | ||
|
|
||
| AfterAll { | ||
| if ($IsSupportedEnvironment -and !$persistenceEnabled) | ||
| { | ||
| # disable persistence if it wasn't enabled | ||
| Set-OsLogPersistence -Disable | ||
| } | ||
| } | ||
|
|
||
| It 'Verifies basic logging with no customizations' -Skip:(!$IsSupportedEnvironment) { | ||
| $configFile = WriteLogSettings -LogId $logId | ||
| & $powershell -NoProfile -SettingsFile $configFile -Command '$env:PSModulePath | out-null' | ||
|
|
||
| Export-PSOsLog -After $after -Verbose | Set-Content -Path $contentFile | ||
| $items = Get-PSOsLog -Path $contentFile -Id $logId -After $after -TotalCount 3 -Verbose | ||
|
|
||
| $items | Should -Not -Be $null | ||
| $items.Length | Should -BeGreaterThan 1 | ||
| $items[0].EventId | Should -BeExactly 'Perftrack_ConsoleStartupStart:PowershellConsoleStartup.WinStart.Informational' | ||
| $items[1].EventId | Should -BeExactly 'Perftrack_ConsoleStartupStop:PowershellConsoleStartup.WinStop.Informational' | ||
| # if there are more items than expected... | ||
| if ($items.Length -gt 2) | ||
| { | ||
| # Force reporting of the first unexpected item to help diagnosis | ||
| $items[2] | Should -Be $null | ||
| } | ||
| } | ||
|
|
||
| It 'Verifies logging level filtering works' -Skip:(!$IsSupportedEnvironment) { | ||
| $configFile = WriteLogSettings -LogId $logId -LogLevel Warning | ||
| & $powershell -NoProfile -SettingsFile $configFile -Command '$env:PSModulePath | out-null' | ||
|
|
||
| Export-PSOsLog -After $after -Verbose | Set-Content -Path $contentFile | ||
| # by default, powershell startup should only logs informational events. | ||
| # With Level = Warning, nothing should be logged. | ||
| $items = Get-PSOsLog -Path $contentFile -Id $logId -After $after -TotalCount 3 | ||
| $items | Should -Be $null | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| @{ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we add copyright header?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. none of the manifest files in the repo have copyright headers; they all have Copyright="" |
||
| ModuleVersion = '1.0.0' | ||
| GUID = '56b63338-045c-4697-a24b-5a756268c8b2' | ||
| Author = 'PowerShell' | ||
| CompanyName = 'Microsoft Corporation' | ||
| Copyright = 'Copyright (c) Microsoft Corporation. All rights reserved.' | ||
| Description = 'Provides a reader for powershell syslog and os_log entries' | ||
| RootModule = 'PSSysLog.psm1' | ||
| FunctionsToExport = @('Get-PSSysLog', 'Get-PSOsLog', 'Export-PSOsLog', 'Get-OsLogPersistence', 'Set-OsLogPersistence') | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😕 Is there no way to unify this for all platforms?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it is but I'll leave it open for feedback. I don't want.to change the Windows behavior without a little thought. The non-Windows code has to change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should do the config file overriding through an environment variable until the command-line parsing has been moved earlier. Then this
#if UNIXblock won't be needed.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is a final conclusion here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's still open. Experimental feature has it as a pending design issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it actually make sense to have all this output getting sent to the logging process if someone is running Powershell interactively?
Perhaps a command line option to tell Powershell that it's being run as a non-interactive or batch process and then logging of everything or anything above say "informational" could be sent to "syslog" via the standard "C" syslog functions.
That anything above "informational" option could actually be a configuration added to the system file "syslog.conf" or directory "syslog.d" to limit the output at that point instead of doing it inside Powershell. I currently do this myself to get rid of all the chatter from Powershell as follows:
Obviously this rule is dropping everything sent to the logger by Powershell. You probably don't want this but I'm not interested in any of the logging from it at the moment and using complex regular expression logging rules can slow down the logger.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vramm You can control the logging level for PowerShell in powershell.config.json. Take a look at 'Configuring Logging on non-Windows systems' in about_logging
As far as interactive versus batch/non-interactive, there is no concept in PowerShell from a logging perspective. However, you can start up PowerShell for your interactive sessions using -settingsFile to accomplish what you are looking for.