Main | Contact | Blog | Documentation

PowerShell Framework

The project dedicated to empowering your PowerShell scripting.

Logging Core Concepts

Back to: Logging

The PSFramework logging system is the most powerful logging solution in the PowerShell ecosystem. At its core, it separates the usual logging process into two individual segments:

Message

The message is what is generated by your code. It could be a progress status, an error, a piece of debugging info … or whatever else you want to send on its way. There are different ways to generate messages, but the main one is Write-PSFMessage, replacing Write-Verbose, Write-Host, Write-Warning, etc. .

For a more detailed discussion on what constitutes a message and differentiates it from output, see this blog post

The message is enriched by metadata - some you may provide, such as tags, some are provided by the system (callstack, file, line, …). Then, message policies may be applied to the message before it is finally queued for pickup.

Logging

Once a message has been queued for pickup, the logging part of the system comes into play. There are several concepts that are important here:

The in-memory log

All messages are automatically added to the in-memory message log. They are by default limited to the last 1028 entries and can be read using Get-PSFMessage. This log is unaffected by any of the aspects that affect Logging Providers.

Logging Providers

A Logging Provider is a plugin that contains code to handle messages. For example, the Azure Log Analytics Provider provides code to write the message content to Azure Log Analytics.

You can write your own Logging Provider, if you are confident in your coding, enabling you to customize your logging exactly to your needs.

Logging Provider Instances

An Instance of a Logging Provider is a configured copy of the Provider and ready to use. Most providers support having multiple instances active at the same time (for example writing the same message to multiple logfiles).

You can configure each instance separately, what messages should be written by it (e.g. excluding messages from a given module or only including messages with a given tag). This configuration can be done using Set-PSFLoggingProvider or using the Configuration System.

Logging Runspace

PSFramework starts a background runspace on import, that is dedicated to processing the logging sequence. Effectively, it makes sure all enabled instances actually get created, processes the message queue and sends off the each message to the instances they apply to.

It also implements error handling and cleanup when the process closes.

Consequences

By having a dedicated logging runspace it is guaranteed that only one thread writes logs at any given time, guaranteeing, that no parallel access happens. Messages can be written from any number of runspaces at the same time (the queue is threadsafe). This logging is inherently asynchronous so write latency of logs does not cost you code performance.

The configurability and extensibility also means you do not have to define your logging at coding time. You can later define it at the machine level. You can also combine many scripts and modules, all of which will integrate into your logging scheme without you having to modify it.

The asynchronous nature might also mean, that if the process is closed before the logging is done, messages might be lost. For example when run in a scheduled task or cron-job, this might risk losing some content. To avoid that, include a Wait-PSFMessage call at the end of scripts, which causes the script to wait until it is done processing all messages:

# At the end of your script to wait for messages
Wait-PSFMessage

Back to: Logging