Search code examples
arrayspowershellget-eventlog

Powershell: Split Array to Pairs and Discard if Not Alternating


I've got a Powershell script that uses Get-EventLog to search for events 6005, 6006, and 6008 on remote servers; after a little manipulation, it returns the results in an array.

$eventData += Get-EventLog -computerName $server_name -LogName system `
-After $prevMonthBegin -Before $prevMonthEnd |      
  Where-Object `
  { $_.eventid -eq 6005 -OR $_.eventID -eq 6006 -OR $_.eventID -eq 6008 } | 
  Select timegenerated, eventid, message, index, recordid | sort-object timegenerated

I loop through the results, and assign either down or up to the $eventData.message field and sort it again by timegenerated This returns an array like so (apologies for the formatting):

$eventData | Sort-Object timegenerated | format-table

TimeGenerated EventID Message Index
------------- ------- ------- ----- --------
8/3/2014 5:30:02 AM 6006 down 0
8/3/2014 5:30:47 AM 6005 up 0
8/24/2014 5:31:00 AM 6005 up 0
8/31/2014 2:34:59 AM 6008 down 1
8/31/2014 5:30:04 AM 6006 down 0
8/31/2014 5:30:59 AM 6005 up 0
8/31/2014 5:36:26 AM 6005 up 0

How can I create a new array from these results and arrange the TimeGenerated into up/down pairs? I would prefer to disregard the first event of the array if it is anup (so there's always down then up in the pairs), but I can work around this. It's more important to never have two consecutive down or up events, as in the example output above.

I was thinking of maybe iterating through the events and toggling a temp variable between 1 and 0 (or up and down) but that seems clunky and I just can't make anything work. It shouldn't be this hard, but that's why I'm asking for help. Let me know if providing more code would be useful; there's a quite a bit of it and I didn't want to just dump pages of it.

Here's an example of the format for the array that I would like to have. The method that I'm using pairs these events as 12121212 without looking at what types of events they are. So in the above example, the last event pair would calculate downtime where it did not exist because there were two up (6005) events.

Downtime            Uptime              CrashEvent?
8/3/2014 5:30:02 AM  8/3/2014 5:30:47 AM 0
8/24/2014 5:31:00 AM 8/31/2014 2:34:59 AM 0
8/31/2014 2:34:59 AM 8/31/2014 5:30:04 AM 1
8/31/2014 5:30:59 AM 8/31/2014 5:36:26 AM 0

Solution

  • Here is an answer for how to do it that should skip duplicate entries. However, you will likely want to adjust the events you are querying otherwise you end up with down/up conditions occurring at the same time.

    $Events = Get-EventLog -LogName system  |      
    Where-Object { $_.eventid -eq 6005 -OR $_.eventID -eq 6006 -OR $_.eventID -eq 6008 } |
    Select timegenerated, eventid, message, index, recordid | sort-object timegenerated
    
    
    [array]$FullObj = [pscustomobject] @{
            'Time' = ''
            'Status' = ''
            'Message' = ''
            }
    
    Foreach ($Event in $Events)
    { 
        If ($Event.Message -eq 'The Event log service was started.' -and $fullobj.status[-1] -ne 'UP')
        {
            [array]$FullObj += [pscustomobject] @{
            'Time' = $Event.TimeGenerated
            'Status' = 'UP'
            'Message' = $Event.Message
            }
        }
        Elseif ($fullobj.status[-1] -eq 'UP' -and $fullobj.Message[-1] -notlike "The previous system shutdown*")
        {
            [array]$FullObj += [pscustomobject] @{
            'Time' = $Event.TimeGenerated
            'Status' = 'DOWN'
            'Message' = $Event.Message
            }
        }
    }
    
    $FullObj | select time,status