PowerShell Diversion #2: Discussion

[Follow-up discussion for PowerShell Diversion #2]

There are a number of things we need to look at to make a table with a  built-in chart (as mentioned in the hint file from the original post).  The first is working out how to read events from the event log:

This code will do that for us:

Get-EventLog -LogName System -EntryType Error,Warning |  
     Group-Object Source |   
          Sort-Object Count –Descending | 
               Format-Table Count, Name -Autosize

This is a single line of PowerShell.  I have broken the line at each pipe and indented the next row – I find this makes for neater and easier to read code when you have a long or complex 1-liner.

What is it doing? Well, firstly the Get-EventLog cmdlet gathers the specific event types (“error” and “warning”) from the target log (“system”), which it then sends to be grouped by Group-ObjectGroup-Object produces a group of event entries for each unique source in the  stream sent by Get-EventLog.  It also kindly counts the number of items in each group, which Sort-Object makes use of to sort the groups in order starting with the most populous to the least.  Finally, Format-Table shows the information in a neat table like this:

Count Name                  
----- ----                  
  129 Kerberos              
   57 NETLOGON              
   36 cdrom                 
   29 Schannel              
   26 Microsoft Antimalware 
   25 DCOM                  
   17 Service Control Manager
    7 Disk                  
    2 Virtual Disk Service  
    2 WudfUsbccidDriver     
    2 volsnap               
    2 SCardSvr              
    1 Ntfs                  
    1 EventLog

We’re half-way to our end goal.  This information is useful as is (I think I might have an issue with Kerberos), but just to add that finishing touch of the ‘chart’, we need to tweak the code:

$Evt = Get-EventLog -LogName System `
    -EntryType Error,Warning |
        Group-Object Source |
            Sort-Object Count -Descending

$Scale = 20 / $Evt[0].Count

$Chart = @{Label="Chart";`
           Expression={"X"*(($_.Count) * $Scale)}}

$Evt | Format-Table Count, Name, $Chart -Autosize

Now, what is this doing?  The first line is just the same as before, except we capture the events into a variable instead of displaying them.  Next we calculate a scaling factor using the size of the largest group – here we divide 20 by the group size, so that in the final chart this group will be represented by 20 Xs. 

The interesting stuff takes place on the next line, where we use a hashtable (signified by ‘@{ … }’) to produce the ‘calculated property’ that will be our chart values.  The hashtable comprises of two parts, the ‘label’, which will become the title of the chart column in our final table, and the ‘expression’, which executes some PowerShell code to calculate the values in the rows of that column.  In this instance, we make use of the fact that the multiplication operator has an overload that effectively concatenates an input string with itself the given number of times.  For example, “X” * 5, produces: “XXXXX”.

Finally, we display the events in a table, which gives a result like this:

Count Name                    Chart              
----- ----                    -----              
  129 Kerberos                XXXXXXXXXXXXXXXXXXXX
   57 NETLOGON                XXXXXXXXX          
   36 cdrom                   XXXXXX             
   29 Schannel                XXXX               
   26 Microsoft Antimalware   XXXX               
   25 DCOM                    XXXX               
   17 Service Control Manager XXX                
    7 Disk                    X 

For the optional enhancements (running against multiple computers and grouping by source and Event ID), we need to perform these two simple changes:

To run the script against multiple machines, simply alter the GetEventLog cmdlet to include the –ComputerName parameter, like this: –ComputerName Server1, Server2, Server3, …

To group by source and Event ID, change the Group-Object cmdlet to include both, like this: Group-Object Source, EventID

Comments (1)

  1. xcud says:

    I keep a function in my profile for doing just this (but with an Ansi block characters). Inline bar charts are great; especially when you don't need to spend more than half a second thinking about how you're going to make that call into WPF. Just pipe the data to your chart Cmdlet. Here's a link to a blog I wrote up when I wrote mine (inspired by Chad Miller) awhile back: blog.xcud.com/…/out-ansigraph

Skip to main content