mchkorg
asked on
Get-EventLog : how to sort and group by date (not date AND TIME)
Hello,
(I'm quite new to powershell scripting)
I'd like to improve this little script to group my Get-EventLog entries by date (descending) and eventid.
When I say "Date", I mean YYYY/mm/dd, not TimeGenerated because grouping this way is useless (you don't have much entries generated the very same second :)
=> Right now, I have too many repeated lines, which is why I'd like to group
Notice I'm working in a french environment. I don't know if there is a relationship, but my dates are written like "dd/mm/yyyy" and I guess that's why a "sort-object...-descending ..." sorts in a strange way :)
(I'm quite new to powershell scripting)
I'd like to improve this little script to group my Get-EventLog entries by date (descending) and eventid.
When I say "Date", I mean YYYY/mm/dd, not TimeGenerated because grouping this way is useless (you don't have much entries generated the very same second :)
=> Right now, I have too many repeated lines, which is why I'd like to group
Notice I'm working in a french environment. I don't know if there is a relationship, but my dates are written like "dd/mm/yyyy" and I guess that's why a "sort-object...-descending
#later : $machines=@("127.0.0.1","another_host")
$machines=@("127.0.0.1")
$format=@{Expression={$_.TimeGenerated};Label="Date";width=21},`
@{Expression={$_.EventID};Label="EventID";width=7},`
@{Expression={$_.Source};Label="Index";width=25},`
@{Expression={$_.Message};Label="Message"}
foreach ($machine in $machines) {
echo "***************************************************************"
echo $machine
$logs=[System.Diagnostics.EventLog]::GetEventLogs($machine)
Foreach ($log in $logs) {
$entrees=$log.entries | Where-Object {$_.entryType -match "Error"} | Select-Object -Last 20 | Format-Table -wrap $format
if ($entrees.count -gt 0) {
echo $log.LogDisplayName
echo "------------------------------------------------------------------------------"
echo $entrees
}
}
}
Brandon's inactive at the moment otherwise you'd have got a response from him by now.
I did have a play with your code earlier and I can't reproduce an inability to sort by date (also using dd/mm/yyyy). May I ask where in your code you added Sort-Object? Before or after your custom formatting?
Chris
ASKER
Format-Table was the last one - I don't remember exactly what I tried :)
With the code provided in my message, everything's sorted, you're right.
My problem is when I tried to group by eventid+ date, I think I tried to substring the date or something, I don't exactly remember. In that case, 4/04/2009 is after 20/04/2009
==> Anyway, as I don't remeber exactly the tests I've done, let's focus on the goal, which is to group by (date,eventid) and not (TimeGenerated,eventid) because TimeGenerated is a "full" timestamp. I just want %Y/%m/%d :)
Thank you
With the code provided in my message, everything's sorted, you're right.
My problem is when I tried to group by eventid+ date, I think I tried to substring the date or something, I don't exactly remember. In that case, 4/04/2009 is after 20/04/2009
==> Anyway, as I don't remeber exactly the tests I've done, let's focus on the goal, which is to group by (date,eventid) and not (TimeGenerated,eventid) because TimeGenerated is a "full" timestamp. I just want %Y/%m/%d :)
Thank you
No worries, so you'd like to strip the time from TimeGenerated, leaving only the date?
/me goes to play
Chris
ASKER
yes, and be able to group by 2 "columns", this_date + eventID
/me goes home soon
/me goes home soon
This is a spot of sample code then, I think / hope it does what you're after here. It'll need the custom table formatting re-doing since I've changed some of the fields here.
Chris
# For testing, grab all errors from the Application log
$Entrees = ([System.Diagnostics.EventLog]::GetEventLogs("127.0.0.1") | ?{ $_.LogDisplayName -eq "Application" }).Entries | ?{ $_.EntryType -eq "Error" }
# Return an Object containing a reformatted date. Then pass it into Sort-Object
# First sort by date in descending order, then by EventID in ascending order.
$Entrees | Select-Object @{n='Date';e={ (Get-Date($_.TimeGenerated)).ToShortDateString() }}, `
EventID, Source, Message | Sort-Object @{e='Date';Descending=$True}, @{e='EventID';Ascending=$True}
ASKER
Hi, thank you for this code aggregation and the operation regarding the date :) but:
- everything is sorted by day THEN month THEN year, see:
30/10/2008
29/10/2008
28/10/2008
27/10/2008
27/04/2009 <== yes, 27 comes before 28, but 2009 comes after 2008 :)
26/10/2008
26/09/2008
Maybe because of a french environment (DD/MM/YYYY, not YYYY-DD-MM)
Can we revert the date format or force it to be written like YYYY-MM-DD (then string comparison will work)
- I tried to group the data by (date,eventid) - even if the date-sort is bad now.
I just added " | group-object Date,EventID" to your 2nd command group, here's what I get:
Count Name Group
----- ---- -----
1 30/10/2008, 15 {15}
1 30/10/2008, 1054 {1054}
6 30/10/2008, 8005 {8005, 8005, 8005, 8005...}
1 30/10/2008, 8006 {8006}
1 29/10/2008, 15 {15}
3 28/10/2008, 15 {15, 15, 15}
3 27/10/2008, 15 {15, 15, 15}
2 27/04/2009, 1 {1, 1}
==> Ok, this time I see only one (date,eventID) per line, but I lost my category and message explanation
- About the reformatting, I'll play with it after, ok.
any idea for these 2 bugs ?
Thank you
- everything is sorted by day THEN month THEN year, see:
30/10/2008
29/10/2008
28/10/2008
27/10/2008
27/04/2009 <== yes, 27 comes before 28, but 2009 comes after 2008 :)
26/10/2008
26/09/2008
Maybe because of a french environment (DD/MM/YYYY, not YYYY-DD-MM)
Can we revert the date format or force it to be written like YYYY-MM-DD (then string comparison will work)
- I tried to group the data by (date,eventid) - even if the date-sort is bad now.
I just added " | group-object Date,EventID" to your 2nd command group, here's what I get:
Count Name Group
----- ---- -----
1 30/10/2008, 15 {15}
1 30/10/2008, 1054 {1054}
6 30/10/2008, 8005 {8005, 8005, 8005, 8005...}
1 30/10/2008, 8006 {8006}
1 29/10/2008, 15 {15}
3 28/10/2008, 15 {15, 15, 15}
3 27/10/2008, 15 {15, 15, 15}
2 27/04/2009, 1 {1, 1}
==> Ok, this time I see only one (date,eventID) per line, but I lost my category and message explanation
- About the reformatting, I'll play with it after, ok.
any idea for these 2 bugs ?
Thank you
Yeah, I do, give me a moment to have a play :)
Chris
Okay, date first.
PowerShell is happy with localising the date format, so it's not a problem with English / French date formats vs US date formats. But...
My code converted it to a string, only way to entirely drop the time part. Unfortunately my test set was way too small to notice that string sorting was no help here.
So this modification takes us back to date formatting. We have to put up with the "00:00:00" at least until after the list is fully sorted.
Just need a moment to play with the other half of your question.
Chris
# Return an Object containing a reformatted date. Then pass it into Sort-Object
# First sort by date in descending order, then by EventID in ascending order.
$Entrees | Select-Object @{n='Date';e={ (Get-Date($_.TimeGenerated)).Date }}, `
EventID, Source, Message | Sort-Object @{e='Date';Descending=$True}, @{e='EventID';Ascending=$True}
For the second, I take it the output from this one isn't helpful?
$Entrees | Group-Object Date, EventID, Source, Message
It's not the nicest format, might be better off building your own object for that one (unless you happen to find a better CmdLet to use).
Chris
If you want to try a custom object, this truncates the list and adds a count to each identical entry.
Note that the message also has to be unique. Not sure whether that's something you want or not.
Chris
$Temp = @()
ForEach ($Object in ($Entrees | Select-Object -Property Date, EventID, Source, Message -Unique)) {
$Temp += $Object | Select-Object *, `
@{n='Count';e={ $Entries = $Entrees | ?{ $_.EventID -eq $Object.EventID -And $_.Date -eq $Object.Date }; `
If ($Entries.Count) { $Entries.Count } Else { 1 } } }
}
$Entrees = $Temp
ASKER
Mmm, yes it does the trick.
I don't care about the 5th column named "Group" - what's this by the way ? it seems to be all the eventIDs (the same each time) repeated "Count" times, quite useless. I'm might be able to skip this with a correct Reformatting stuff.
I tried to merge this with your previous modification with the Date, it seems alright - with reformatting, I'll be able to truncate the Time I guess
Then I need to apply this all to every Log, not only Application.
Thank you, I'm just finishing this when I have a moment (maybe not today) - just to be sure there's no hidden exception somewhere :) then I'll get back to you.
Thank you!
I don't care about the 5th column named "Group" - what's this by the way ? it seems to be all the eventIDs (the same each time) repeated "Count" times, quite useless. I'm might be able to skip this with a correct Reformatting stuff.
I tried to merge this with your previous modification with the Date, it seems alright - with reformatting, I'll be able to truncate the Time I guess
Then I need to apply this all to every Log, not only Application.
Thank you, I'm just finishing this when I have a moment (maybe not today) - just to be sure there's no hidden exception somewhere :) then I'll get back to you.
Thank you!
ASKER
mmm, are you sure I didn't loose the "message" explanation?
It's maybe just a formatting problem, again. Because right now it looks like this:
Count Name Group
----- ---- -----
2 27/04/2009 00:00:00, 1... {1, 1}
2 27/04/2009 00:00:00, 1... {1030, 1030}
2 27/04/2009 00:00:00, 1... {1058, 1058}
1 27/04/2009 00:00:00, 8... {8006}
3 23/04/2009 00:00:00, 1... {1030, 1030, 1030}
2 23/04/2009 00:00:00, 1... {1058, 1058}
1 22/04/2009 00:00:00, 1... {1000}
==> The 3rd column is the concatenation of every grouped field
It's maybe just a formatting problem, again. Because right now it looks like this:
Count Name Group
----- ---- -----
2 27/04/2009 00:00:00, 1... {1, 1}
2 27/04/2009 00:00:00, 1... {1030, 1030}
2 27/04/2009 00:00:00, 1... {1058, 1058}
1 27/04/2009 00:00:00, 8... {8006}
3 23/04/2009 00:00:00, 1... {1030, 1030, 1030}
2 23/04/2009 00:00:00, 1... {1058, 1058}
1 22/04/2009 00:00:00, 1... {1000}
==> The 3rd column is the concatenation of every grouped field
The Name column is a concatenation as well, it's messy. I like the custom object better :)
Chris
ASKER
Ok so let me just a moment to merge this all :)
Thank you, again
Thank you, again
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Creating an Object sounds good.
But the Date is empty is this created Object, even if all sort/group activities seem OK.
I tried to play with TimeGenerated insted and thus got back to the beginning :) grouped by date+time :(
Sorry I'm too new to powershell scripting :)
Look at this code, sorry I've merged this all in several loops
But the Date is empty is this created Object, even if all sort/group activities seem OK.
I tried to play with TimeGenerated insted and thus got back to the beginning :) grouped by date+time :(
Sorry I'm too new to powershell scripting :)
Look at this code, sorry I've merged this all in several loops
#longer list in the future
$machines=@("127.0.0.1")
foreach ($machine in $machines) {
$logs=[System.Diagnostics.EventLog]::GetEventLogs($machine)
Foreach ($log in $logs) {
$entrees = $log.entries | ?{ $_.EntryType -eq "Error"} | Select-Object -Last 20
if ($entrees.count -gt 0) {
echo $machine $log.LogDisplayName
echo "-----------------------------------"
$Temp = @()
ForEach ($Object in ($Entrees | Select-Object -Property Date, EventID, Source, Message -Unique)) {
$Temp += $Object | Select-Object *, `
@{n='Count';e={ $Entries = $Entrees | ?{ $_.EventID -eq $Object.EventID -And $_.Date -eq ($Object.Date) }; `
If ($Entries.Count) { $Entries.Count } Else { 1 } } }
}
$entrees = $Temp
echo $entrees
}
}
}
ASKER
oops, I posted it a bit late....
ASKER
Simply perfect! Thank you!
Glad it helped out :)
Chris
ASKER
That would be strange to have, let say, an powershell expert, not registering the powershell zone...
I'll check tomorrow
If there are some other zones, regarding "microsoft script language", that might help
But to my mind, with these 3 zones, we should be in the right places.
anyway, thank you