Search code examples
powershellpowershell-4.0

parse a log file for errors on a specific date


Thank you for any help in advance! :)

I am a beginner to Powershell. I have the powershell app, not powershell ISE. I need to parse through a log file GENERATED BY MY BACKUPSOLUTION APP INTO A RTF DOCUMENT and look for the word "Errors: " in the last 24-72 hours. I basically have to see when my backup solution for my laptop is failing me.

I have the following so far:

     $daysBack = 3
$refDate  = (Get-Date).AddDays(-$daysBack).Date  # set this to midnight
$log      = Get-Content -Path 'C:\Users\<User>\Documents\TheLog.log'

# find lines that start with what looks like a date and contains 'Errors:'
# capture the date part in backreference $matches[1] to parse into a real datetime object for comparison with $refDate
$errors = @($log | Where-Object { $_ -match '(\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}).*Errors:' } |   
                   Where-Object { [datetime]::ParseExact($matches[1], 'dd/MM/yyyy HH:mm:ss', $null) -ge $refDate }).Count

# if $errors not 0
if ($errors) {
    $count = if ($errors -eq 1) { "was an error" } else { "were $errors errors" }
    "There {0} in your back up solution in the last $daysBack days. Please check your log file." -f $count
}
else {
    "There were no errors in backing up your files in the last $daysBack days."
}

The above code does not find the following error:

18/02/2021 08:57:37 - can not access C:\users\<username>\documents\ The network path was not found.
18/02/2021 08:57:37 - End: Desktop... Copied: 0, Errors: 1                                                              

*Sample lines from my logfile that show a successful copy:

22/02/2021 17:27:33 - Begin: Documents=======================================
22/02/2021 17:27:33 - copied Notes.docx from C:\users\<username>\documents\ to D:\users\<username>\documents\
22/02/2021 17:27:33 - End: Documents...Copied 1

*Sample lines that show an unsuccessful copy from a few days back in the log file:

18/02/2021 08:57:37 - can not access C:\users\<username>\documents\ The network path was not found.

18/02/2021 08:57:37 - End: Documents... copied: 0, Errors: 1

I should also mention there are sometimes when I delete a file from my documents and rather than back it up it deletes from the back up as well. As far as I understand my backup solution is an exact mirror of whatever is in my documents. I think I would like to maybe include something about these deletes in my code too.

MY LOG FILE IS A RTF FORMAT *Sample section of log file that deletes:

22/02/2021 17:27:33 - End: Documents...Copied 1, Deleted: 1

EDITTTTTTTTT I have several errors in this document.

This was my prior code:

My code was very simple:

Get-Content -Path 'C:\Users\<User>\Documents\TheLog.log' -select string "Errors: "

But I wanted something that could filter the errors based on critical errors but have no idea how When I run the above code I get this output:

\par 18/02/2021 08:57:37 - \plain\f0\fs16\cf1 End: Documents... copied: 0, Errors: 1 \plain\f0\fs16\cf1

I want to somehow extract that date from that generated string and compare it to today's date.


Solution

  • From what you show the log file looks like, you can do below to test if there were errors reported in the last three days:

    $daysBack = 3
    $refDate  = (Get-Date).AddDays(-$daysBack).Date  # set this to midnight
    $log      = Get-Content -Path 'C:\Users\<User>\Documents\TheLog.log'
    
    # find lines that start with what looks like a date and contains 'Errors:'
    # capture the date part in backreference $matches[1] to parse into a real datetime object for comparison with $refDate
    $errors = @($log | Where-Object { $_ -match '(\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}).*Errors:' } |   
                       Where-Object { [datetime]::ParseExact($matches[1], 'dd/MM/yyyy HH:mm:ss', $null) -ge $refDate }).Count
    
    # if $errors not 0
    if ($errors) {
        $count = if ($errors -eq 1) { "was an error" } else { "were $errors errors" }
        "There {0} in your back up solution in the last $daysBack days. Please check your log file." -f $count
    }
    else {
        "There were no errors in backing up your files in the last $daysBack days."
    }
    

    I have tested with a file:

    18/02/2021 08:57:37 - can not access C:\users\<username>\documents\ The network path was not found.
    18/02/2021 08:57:37 - End: Documents... copied: 0, Errors: 1
    21/02/2021 08:57:37 - can not access C:\users\<username>\documents\ The network path was not found.
    21/02/2021 08:57:37 - End: Documents... copied: 0, Errors: 1
    22/02/2021 17:27:33 - Begin: Documents=======================================
    22/02/2021 17:27:33 - copied Notes.docx from C:\users\<username>\documents\ to D:\users\<username>\documents\
    22/02/2021 17:27:33 - End: Documents...Copied 1
    22/02/2021 17:27:33 - End: Documents...Copied 1, Deleted: 1
    

    and today is 23/02/2021

    When setting

    $daysBack = 3
    $refDate = (Get-Date).AddDays(-3).Date  # set this to midnight
    

    The output is

    There was an error in your back up solution in the last 3 days. Please check your log file.
    

    When setting to 6 days back:

    $daysBack = 6
    $refDate  = (Get-Date).AddDays(-$daysBack).Date  # set this to midnight
    

    The output is as expected:

    There were 2 errors in your back up solution in the last 6 days. Please check your log file.
    

    Regex details:

    (                Match the regular expression below and capture its match into backreference number 1
       \d            Match a single digit 0..9
          {2}        Exactly 2 times
       /             Match the character “/” literally
       \d            Match a single digit 0..9
          {2}        Exactly 2 times
       /             Match the character “/” literally
       \d            Match a single digit 0..9
          {4}        Exactly 4 times
       \             Match the character “ ” literally
       \d            Match a single digit 0..9
          {2}        Exactly 2 times
       :             Match the character “:” literally
       \d            Match a single digit 0..9
          {2}        Exactly 2 times
       :             Match the character “:” literally
       \d            Match a single digit 0..9
          {2}        Exactly 2 times
    )               
    .                Match any single character that is not a line break character
       *             Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
    Errors:          Match the characters “Errors:” literally