0

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
kiwisan
  • 449
  • 6
  • 16
  • Can you post an example of what you'd like the result to look like, given the posted input data? – mjolinor Sep 29 '14 at 20:33
  • I just edited my question to include this. Thanks. – kiwisan Sep 29 '14 at 20:42
  • You just looking for how long something was down? Like went down at 8/31/2014 05:30:04 AM and came back up at 8/31/2014 05:30:59 AM? That should be doable. – TheMadTechnician Sep 29 '14 at 20:43
  • Yes, I've got that part already, but I'm trying to construct a test so that I never get two consecutive event types. In first array output above, there are two `6005` events in a row (for whatever reason) which messes up the numbers. If two consecutive events are the same (down or up) I want to discard the first and move down the line (to always get exactly one `down` and `up` in the pair). – kiwisan Sep 29 '14 at 20:46
  • I can't make any sense out of the example output. For instance, the input data has an UP event at 8/24/2014 5:31:00 AM, but that timestamp appears as a Downtime event in the example output, and the output shows a Downtime event at 2014-08-17 05:31:02 but there's nothing in the input data with that timestamp. – mjolinor Sep 29 '14 at 20:58
  • The output was just to give a visual example for formatting. I should have made that clear. I will alter the data above to reflect this. There should obviously be exactly one down event, and exactly one up event and that's it. Again, the goal here is to detect when there are two events of the same type (message field) and DISCARD the first of the duplicate types and move down the list until there is exactly one up and one down event in the pair. – kiwisan Sep 29 '14 at 21:01
  • Well I see a few problems, first the events of the same type can be duplicated (for example, unexpected shutdown multiple times in a row.) this will cause several not up responses. Additionally sometimes the results the query come back with are an up/down event that occurred at the exact same second and unfortunately the results doesn't return milliseconds so it is possible for some things to be in the wrong order (service starting before the unexpected shutdown message, causes multiple up's in a row) – Noah Sparks Sep 29 '14 at 21:11

2 Answers2

3

Ok, this should select the last of any Down or Up event before the next of the opposite type (last Down before an Up, and last Up before a Down) which I think is what you wanted. Basically match each time the system goes down, with the time it came back up, using the last uptime/downtime notification if there are multiple in a row. I think your whole 'Discard the first of any sequential duplicate event type' is in error, but this does exactly that.

Event collection duplicated from Noah Sparks with the Select argument trimmed down a bit. Then it goes into a Switch creating a custom object whenever there is a Downtime event, and then setting the uptime for each uptime event, and outputting it whenever the next downtime event happens and starting over again.

$Events = Get-EventLog -LogName system  |      
    Where-Object { $_.eventid -eq 6005 -OR $_.eventID -eq 6006 -OR $_.eventID -eq 6008 } |
        Select timegenerated, eventid | sort-object timegenerated
$record=$null
$Output = Switch($Events){
    {$_.EventID -match "600(6|8)"}{if(![string]::IsNullOrEmpty($Record.up)){$record}
                                   $Record=[pscustomobject][ordered]@{
                                       'Down'=$_.timegenerated
                                       'Up'=$null
                                       'Expected'=If($_.EventID -eq 6006){$true}else{$false}
                                   }}
    {$_.EventID -eq "6005"}{$Record.Up = $_.TimeGenerated}
}
$Output += $record
$Output

Personally I'd go with the first uptime even after a downtime event happens, but that's just me. That would take some different coding. Anyway, the results of that look like this (using my own event log entries):

Down                           Up                                Expected 
----                           --                                -------- 
11/20/2013 8:47:42 AM          11/20/2013 8:49:11 AM                 True 
11/20/2013 3:50:14 PM          12/13/2013 9:14:52 AM                 True 
12/13/2013 9:26:21 AM          12/13/2013 9:27:42 AM                False 
12/13/2013 3:40:07 PM          12/13/2013 3:41:31 PM                 True 
1/9/2014 1:13:31 PM            1/16/2014 12:38:08 PM                 True 
1/16/2014 12:39:21 PM          1/16/2014 12:48:44 PM                 True 

If you'll look at the second listing there, I know my computer was not down from 11/20 to 12/13, but discarding the first of sequential duplicates that is how it comes across. If we didn't do that it would show the system coming back up just one minute after going down, which is much more likely for my computer.

TheMadTechnician
  • 34,906
  • 3
  • 42
  • 56
2

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
Noah Sparks
  • 1,710
  • 13
  • 14
  • That's lovely, but it really isn't what he wanted. – TheMadTechnician Sep 29 '14 at 21:52
  • Well it is according to what he wrote. His example doesn't make any sense since what is crash value supposed to be when the first two columns are already showing down and then up time? It could be reworked without too much trouble to just show down/up time on each row instead I guess. Either way though the data he is querying is pretty much worthless for this purpose and monitoring up time should be done with an application for this purpose instead...nagios has a free version for small usage and there are probably some others out there. – Noah Sparks Sep 29 '14 at 22:32
  • I agree, his sample data was garbage, and made it very difficult to ascertain what exactly he wanted, but the format of what he wanted as output was fairly clear I thought, even if it did not match up with his sample data. Just FYI, a 6005 is Windows coming up, 6006 is a planned shutdown, and a 6008 is an unexpected shutdown, so it makes sense that a 6008 is his crash data. – TheMadTechnician Sep 29 '14 at 22:39
  • Yah I suppose it was, I guess I just choose to go with how I interpreted what he wrote. Oh well at least he has two options. – Noah Sparks Sep 29 '14 at 22:55
  • Yeah, and I'll go so far as to upvote yours as providing what I consider to be more useful information that what I think he asked for. – TheMadTechnician Sep 29 '14 at 23:00
  • Thanks. Got yours as well since it was probably more accurate to what he wanted. The problem I was seeing with the events he queries is 6008 (unexpected) doesn't log an entry until the computer starts back up and also happens to do it at the same time that services are starting back up. So not only is it a bad indicator of when the server went down it also causes problems with the sorting when it starts at the same time as a service which is why he initially got duplicated down or up conditions. Additionally if the server unexpectedly crashes, it will never log a 6006 entry. – Noah Sparks Sep 30 '14 at 11:44