internal/scripts/async-logging2.ps1
$scriptBlock = { try { $script:___ScriptName = 'PSFramework.Logging' Import-Module (Join-Path ([PSFramework.PSFCore.PSFCoreHost]::ModuleRoot) 'PSFramework.psd1') while ($true) { # This portion is critical to gracefully closing the script if ([PSFramework.Runspace.RunspaceHost]::Runspaces[$___ScriptName].State -notlike "Running") { break } if (-not ([PSFramework.Message.LogHost]::LoggingEnabled)) { break } # Create instances as needed on cycle begin [PSFramework.Logging.ProviderHost]::UpdateAllInstances() #region Manage Begin Event #region V1 providers foreach ($___provider in [PSFramework.Logging.ProviderHost]::GetEnabled()) { if (-not $___provider.Initialized) { [PSFramework.Logging.ProviderHost]::LoggingState = 'Initializing' $___provider.LocalizeEvents() try { $ExecutionContext.InvokeCommand.InvokeScript($false, $___provider.BeginEvent, $null, $null) $___provider.Initialized = $true } catch { $___provider.Errors.Push($_) } } } #endregion V1 providers #region V2 provider Instances foreach ($___instance in [PSFramework.Logging.ProviderHost]::GetEnabledInstances()) { if ($___instance.Initialized) { continue } [PSFramework.Logging.ProviderHost]::LoggingState = 'Initializing' try { & $___instance.BeginCommand $___instance.Initialized = $true } catch { $___instance.Errors.Enqueue($_)} } #endregion V2 provider Instances [PSFramework.Logging.ProviderHost]::LoggingState = 'Ready' #endregion Manage Begin Event #region Start Event foreach ($___provider in [PSFramework.Logging.ProviderHost]::GetInitialized()) { try { $ExecutionContext.InvokeCommand.InvokeScript($false, $___provider.StartEvent, $null, $null) } catch { $___provider.Errors.Push($_) } } foreach ($___instance in [PSFramework.Logging.ProviderHost]::GetInitializedInstances()) { try { & $___instance.StartCommand } catch { $___instance.Errors.Enqueue($_) } } #endregion Start Event #region Message Event while ([PSFramework.Message.LogHost]::OutQueueLog.Count -gt 0) { $Entry = $null [PSFramework.Message.LogHost]::OutQueueLog.TryDequeue([ref]$Entry) if ($Entry) { [PSFramework.Logging.ProviderHost]::LoggingState = 'Writing' foreach ($___provider in [PSFramework.Logging.ProviderHost]::GetInitialized()) { if ($___provider.MessageApplies($Entry)) { try { $ExecutionContext.InvokeCommand.InvokeScript($false, $___provider.MessageEvent, $null, $Entry) } catch { $___provider.Errors.Push($_) } } } foreach ($___instance in [PSFramework.Logging.ProviderHost]::GetInitializedInstances()) { if ($___instance.MessageApplies($Entry)) { try { & $___instance.MessageCommand $Entry } catch { $___instance.Errors.Enqueue($_) } } } } [PSFramework.Message.LogHost]::LastLogged = [DateTime]::Now } #endregion Message Event #region Error Event while ([PSFramework.Message.LogHost]::OutQueueError.Count -gt 0) { $Record = $null [PSFramework.Message.LogHost]::OutQueueError.TryDequeue([ref]$Record) if ($Record) { [PSFramework.Logging.ProviderHost]::LoggingState = 'Writing' foreach ($___provider in [PSFramework.Logging.ProviderHost]::GetInitialized()) { if ($___provider.MessageApplies($Record)) { try { $ExecutionContext.InvokeCommand.InvokeScript($false, $___provider.ErrorEvent, $null, $Record) } catch { $___provider.Errors.Push($_) } } } foreach ($___instance in [PSFramework.Logging.ProviderHost]::GetInitializedInstances()) { if ($___instance.MessageApplies($Record)) { try { & $___instance.ErrorCommand $Record } catch { $___instance.Errors.Enqueue($_) } } } } [PSFramework.Message.LogHost]::LastLogged = [DateTime]::Now } #endregion Error Event #region End Event foreach ($___provider in [PSFramework.Logging.ProviderHost]::GetInitialized()) { try { $ExecutionContext.InvokeCommand.InvokeScript($false, $___provider.EndEvent, $null, $null) } catch { $___provider.Errors.Push($_) } } foreach ($___instance in [PSFramework.Logging.ProviderHost]::GetInitializedInstances()) { try { & $___instance.EndCommand } catch { $___instance.Errors.Enqueue($_) } } #endregion End Event #region Finalize / Cleanup # Adding $true will cause it to also return disabled providers / instances that are intitialized foreach ($___provider in [PSFramework.Logging.ProviderHost]::GetInitialized($true)) { if ($___provider.Enabled) { continue } try { $ExecutionContext.InvokeCommand.InvokeScript($false, $___provider.FinalEvent, $null, $null) } catch { $___provider.Errors.Push($_) } $___provider.Initialized = $false } foreach ($___instance in [PSFramework.Logging.ProviderHost]::GetInitializedInstances($true)) { if ($___instance.Enabled) { continue } try { & $___instance.FinalCommand } catch { $___instance.Errors.Enqueue($_) } $___instance.Initialized = $false } #endregion Finalize / Cleanup [PSFramework.Logging.ProviderHost]::LoggingState = 'Ready' # Skip sleeping if the next messages already await if ([PSFramework.Message.LogHost]::OutQueueLog.Count -gt 0) { continue } Start-Sleep -Milliseconds ([PSFramework.Message.LogHost]::NextInterval) } } catch { $wasBroken = $true } finally { #region Flush log on exit if (([PSFramework.Runspace.RunspaceHost]::Runspaces[$___ScriptName].State -like "Running") -and (-not [PSFramework.Configuration.ConfigurationHost]::Configurations["psframework.logging.disablelogflush"].Value)) { #region Start Event foreach ($___provider in [PSFramework.Logging.ProviderHost]::GetInitialized()) { try { $ExecutionContext.InvokeCommand.InvokeScript($false, $___provider.StartEvent, $null, $null) } catch { $___provider.Errors.Push($_) } } foreach ($___instance in [PSFramework.Logging.ProviderHost]::GetInitializedInstances()) { try { & $___instance.StartCommand } catch { $___instance.Errors.Enqueue($_) } } #endregion Start Event #region Message Event while ([PSFramework.Message.LogHost]::OutQueueLog.Count -gt 0) { $Entry = $null [PSFramework.Message.LogHost]::OutQueueLog.TryDequeue([ref]$Entry) if ($Entry) { [PSFramework.Logging.ProviderHost]::LoggingState = 'Writing' foreach ($___provider in [PSFramework.Logging.ProviderHost]::GetInitialized()) { if ($___provider.MessageApplies($Entry)) { try { $ExecutionContext.InvokeCommand.InvokeScript($false, $___provider.MessageEvent, $null, $Entry) } catch { $___provider.Errors.Push($_) } } } foreach ($___instance in [PSFramework.Logging.ProviderHost]::GetInitializedInstances()) { if ($___instance.MessageApplies($Entry)) { try { & $___instance.MessageCommand $Entry } catch { $___instance.Errors.Enqueue($_) } } } } } #endregion Message Event #region Error Event while ([PSFramework.Message.LogHost]::OutQueueError.Count -gt 0) { $Record = $null [PSFramework.Message.LogHost]::OutQueueError.TryDequeue([ref]$Record) if ($Record) { [PSFramework.Logging.ProviderHost]::LoggingState = 'Writing' foreach ($___provider in [PSFramework.Logging.ProviderHost]::GetInitialized()) { if ($___provider.MessageApplies($Record)) { try { $ExecutionContext.InvokeCommand.InvokeScript($false, $___provider.MessageEvent, $null, $Record) } catch { $___provider.Errors.Push($_) } } } foreach ($___instance in [PSFramework.Logging.ProviderHost]::GetInitializedInstances()) { if ($___instance.MessageApplies($Record)) { try { & $___instance.ErrorCommand $Record } catch { $___instance.Errors.Enqueue($_) } } } } } #endregion Error Event #region End Event foreach ($___provider in [PSFramework.Logging.ProviderHost]::GetInitialized()) { try { $ExecutionContext.InvokeCommand.InvokeScript($false, $___provider.EndEvent, $null, $null) } catch { $___provider.Errors.Push($_) } } foreach ($___instance in [PSFramework.Logging.ProviderHost]::GetInitializedInstances()) { try { & $___instance.EndCommand } catch { $___instance.Errors.Enqueue($_) } } #endregion End Event } #endregion Flush log on exit #region Final Event foreach ($___provider in [PSFramework.Logging.ProviderHost]::GetInitialized()) { try { $ExecutionContext.InvokeCommand.InvokeScript($false, $___provider.FinalEvent, $null, $null) } catch { $___provider.Errors.Push($_) } } foreach ($___instance in [PSFramework.Logging.ProviderHost]::GetInitializedInstances()) { try { & $___instance.FinalCommand } catch { $___instance.Errors.Enqueue($_) } } foreach ($___provider in [PSFramework.Logging.ProviderHost]::GetInitialized()) { $___provider.Initialized = $false } foreach ($___instance in [PSFramework.Logging.ProviderHost]::GetInitializedInstances()) { $___instance.Initialized = $false } foreach ($___provider in [PSFramework.Logging.ProviderHost]::Providers.Values) { if ($___provider.ProviderVersion -eq 'Version_1') { continue } $___provider.Instances.Clear() } #endregion Final Event if ($wasBroken) { [PSFramework.Logging.ProviderHost]::LoggingState = 'Broken' } else { [PSFramework.Logging.ProviderHost]::LoggingState = 'Stopped' } [PSFramework.Runspace.RunspaceHost]::Runspaces[$___ScriptName].SignalStopped() } } Register-PSFRunspace -ScriptBlock $scriptBlock -Name 'PSFramework.Logging' -NoMessage $exemptedProcesses = 'CacheBuilder64', 'CacheBuilder', 'ImportModuleHelp' # Do not start background Runspace if ... if ( -not ( # ... run in the PowerShell Studio Cache Builder (($Host.Name -eq 'Default Host') -and ((Get-Process -Id $PID).ProcessName -in $exemptedProcesses)) -or # ... run in Azure Functions ($env:AZUREPS_HOST_ENVIRONMENT -like 'AzureFunctions/*') ) ) { Start-PSFRunspace -Name 'PSFramework.Logging' -NoMessage } |