So recently I have been working on a solution where we have blended scripting languages being PowerShell and C#, and found logging to be a little painful in the sense that if you use a single file to track the process which would be ideal there is a good chance there will be write locks and etc. between the scripts. With that in mind I started digging deep into Application Insights for the C# solution, and tracking down the processes for using Application Insights in PowerShell, the process for both of the languages seem pretty straight forward, load the DLL add your instrument key from your Application Insights subscription, then start sending messages up to the service.
Great so we have a logging solution which will go across both languages with ease now the next step is to implement the logging, for a web site written in C# this is a matter of installing the nuget package, and configure the solution to use the correct subscription, it will then capture the cool things like time it takes for page loads and etc. using the default configuration, all in all about 20-30 minutes to capture basic audit information.
For PowerShell it’s not so straight forward as you need explicitly state each time you want to log something, so we need to update the script, this is where i started balking as the script in question were a mess of over 2000 lines over 2 different files, but i found that if i use the -Verbose switch on the top-level function it will return a detailed step by step of whats being completed, and with the standard PowerShell redirection “*>&1” it will pipe it out to a text file easily, great we are now back at writing it into a log file not application insights.
This got me thinking can i pipe the text streams from the function into another function? The simple answer is yes it is possible, great i can just push the text directly up to Application Insights fantastic, by default I get a GMT time stamp, and i know where it was invoked from.
But a text message out of context is as about as useful as disconnected log files, here is where i found out something about these messages which I hadn’t realized, that they are actually objects which contain the line where the script has thrown the message from, along with the PS1 file which it was invoked from. Great this makes it super easy, well not quite each of the different streams are a different object unique to the object type, with the exception of Write-Output which is actually a “System.String” object type which makes it hard to capture (not impossible tho).
So with the above in mind here is a sample script which shows the process of redirecting all of the different text stream’s from a function up to Application Insights, I also included a switch to have the results print back on the screen if it is still required to action it.
So i hear you think great you’re using Application Insights but i don’t have access to that, well here is the cool part you can change out the lines which refer to Application Insights for your favorite logging tool, or even have a default action which will stop the script if there is an exception detected in the script.