Quantcast
Channel: ConfigMgr – Adam, the Automator
Viewing all articles
Browse latest Browse all 19

Building Logs for CMTrace with PowerShell

$
0
0

This post is part of the #PSBlogWeek PowerShell blogging series. #PSBlogWeek is a regular event where anyone interested in writing great content about PowerShell is welcome to volunteer for. The purpose is to pool our collective PowerShell knowledge together over a 5-day period and write about a topic that anyone using PowerShell may benefit from. #PSBlogWeek is a Twitter hashtag so feel free to stay up to date on the topic on Twitter at the #PSBlogWeek hashtag. For more information on #PSBlogWeek or if you’d like to volunteer for future sessions, contact Adam Bertram (@adbertram) on Twitter.

Once you’re done getting schooled on everything this post has to offer head on over to the powershell.org announcement for links to the other four past and upcoming #PSBlogWeek articles this week!

 

In a previous life, I managed Microsoft’s System Center Configuration Manager (SCCM) product. I was a SCCM ninja. One of the coolest things I got out of that was learning about the CMTrace log utility.  Part of the System Center Configuration Manager Toolkit, CMTrace is a log viewing utility that allows you to watch logs, in real time, as well as point out various potential problems through yellow and red highlighting, a sortable timestamp column and more.

cmtrace

Just look at the beauty of the sortable columns and the red highlighting! At first, you might think that you can view any kind of text log in CMTrace and you’d be right. However, let’s a look at the WindowsUpdate.log file in CMTrace.2015-12-03_18-22-01

Notice all the columns are gone?  CMTrace will still view regular log files but you won’t get some of the features that makes CMTrace great.  You’ll soon find that a text file has to be properly formatted in order to get all of those helpful columns to show up and to properly define which lines should be highlighted yellow vs. red. vs. nothing at all.

In today’s post, I’d like to show you a couple of functions called

Write-Log and Start-Log
 . These functions were specifically built to record your script’s activity to a log file which can then be read in CMtrace. By the end of this post, you will have a function that you can call in your scripts to build log files in a way for CMtrace to read them properly.

Start-Log

To prevent having to specify the same log file path over and over again I chose to create a function called

Start-Log
 . This function is intended to be called at the top of your script.  This function simply creates a text file and (the important part) sets a global variable called
ScriptLogFilePath
 .
[CmdletBinding()]
    param (
        [ValidateScript({ Split-Path $_ -Parent | Test-Path })]
	[string]$FilePath
    )
	
    try
    {
        if (!(Test-Path $FilePath))
	{
	    ## Create the log file
	    New-Item $FilePath -Type File | Out-Null
	}
		
	## Set the global variable to be used as the FilePath for all subsequent Write-Log
	## calls in this session
	$global:ScriptLogFilePath = $FilePath
    }
    catch
    {
        Write-Error $_.Exception.Message
    }

This function is super-simple. However, is required to prevent us from having to pass 

-LogFile
  every, single time we need to call our Write-Log function in our scripts. By simply creating a global variable ahead of time, we can then simply call
Write-Log
  and will know the log file path.

Write-Log

Once you’ve called

Start-Log
  in your script, you are now able to run
Write-Log
  to write log messages to the log file.
Write-Log
  has two parameters;
Message
  and
LogLevel
 .
Message
  is easy. That’s simply what you’d like to write to the log.
LogLevel
  requires some explaining.  In order for CMTrace to highlight lines as red or yellow the line needs to be recorded a certain way. More specifically, it needs to have string like this: 
type="1"
 . This type key can be 1,2 or 3. These indicate levels of severity in your script. For example, if I’d like to log a simple informational message, then that’d be a 1. If I’d like to log a more severe activity then I might use 2 which would get highlighted yellow. Finally, I might choose 3 if I’d like that line highlighted red in CMTrace.
param (
    [Parameter(Mandatory = $true)]
    [string]$Message,
		
    [Parameter()]
    [ValidateSet(1, 2, 3)]
    [int]$LogLevel = 1
)

Notice the

LogLevel
  parameter?  By default, it will set that to a 1 but you are always able to override that if necessary if you’d like to write some more severe activity that happens during your script’s execution.

Next, you need that handy date/time column to show up right. To do this required a specific date/time format that is achieved by this string manipulation wizardry.

$TimeGenerated = "$(Get-Date -Format HH:mm:ss).$((Get-Date).Millisecond)+000"

Next is where I’ll build a log line’s template using all of the appropriate format that the line needs to have to show up correctly in CMtrace.

$Line = '<![LOG[{0}]LOG]!><time="{1}" date="{2}" component="{3}" context="" type="{4}" thread="" file="">'

After you’ve got the template it’s then a matter of building what’s going to go in the

{}
 ‘s. Here, I build an array which I will then pass into the
$Line
  to replace all of our
{}
 ‘s with real information.
$LineFormat = $Message, $TimeGenerated, (Get-Date -Format MM-dd-yyyy), "$($MyInvocation.ScriptName | Split-Path -Leaf):$($MyInvocation.ScriptLineNumber)", $LogLevel

These are in the same order as the

{}
 ‘s above.
{0}
  will get converted to
$Message
 ,
{1}
  will get converted to
$TimeGenerated
 ,
{2}
  will get converted to today’s date and
{4}
  will get converted by
$LogLevel
 .  Notice I skipped
{3}
 ?  This is where I get all ninja on you. CMTrace has a component column that I never used much so I decided to make something out of it. I wanted to see the script’s name and the line number in which
Write-Log
  was called. This string: 
"$($MyInvocation.ScriptName | Split-Path -Leaf):$($MyInvocation.ScriptLineNumber)"
 is what makes that happen.

I then bring these two variables together using PowerShell’s string formatting to build

$Line
 .
$Line = $Line -f $LineFormat

It’s then just a matter of writing

$Line
  to a text file that’s already been defined by
Start-Log
 .
Add-Content -Value $Line -Path $ScriptLogFilePath

How it Works

Let’s say I build a script that looks something like this called LogDemo.ps1:

Start-Log -FilePath C:\MyLog.log
Write-Host "Script log file path is [$ScriptLogFilePath]"
Write-Log -Message 'simple activity'
Write-Log -Message 'warning' -LogLevel 2
Write-Log -Message 'Error' -LogLevel 3

This script creates our log file at

C:\MyLog.log
  and then proceeds to write 3 levels of severity to the log through using the
LogLevel
  parameters I explained above.

When I check out the output of this file with

Get-Content
  it looks pretty ugly.
<![LOG[simple activity]LOG]!><time="18:56:26.307+000" date="12-03-2015" component="LogDemo.ps1:3" context="" type="1" thread="" file="">
<![LOG[warning]LOG]!><time="18:56:26.307+000" date="12-03-2015" component="LogDemo.ps1:4" context="" type="2" thread="" file="">
<![LOG[Error]LOG]!><time="18:56:26.307+000" date="12-03-2015" component="LogDemo.ps1:5" context="" type="3" thread="" file="">

However, let’s break this open in CMTrace and see what it looks like.

2015-12-03_18-58-10

Isn’t that beautiful?

Even if you’re not an SCCM admin I highly recommend using CMtrace for all your log viewing needs. Once you’ve got the log files in the appropriate format (and you now have no excuse not to) simply open them up in CMtrace and observe the beauty of all that is CMtrace!

The post Building Logs for CMTrace with PowerShell appeared first on Adam, the Automator.


Viewing all articles
Browse latest Browse all 19

Trending Articles