1

I am trying to extract error lines from a log file which are defined by two things. The log file line looks like this:

2018-05-22 06:25:35.309 +0200 (Production,S8320,DKMdczmpOXVJtYCSosPS6SfK8kGTSN1E,WwObvwqUw-0AAEnc-XsAAAPR) catalina-exec-12 : ERROR com.tableausoftware.api.webclient.remoting.RemoteCallHandler - Exception raised by call target: User 2027 does not have permissions to view comments for view 13086. (errorCode=1)
com.tableausoftware.domain.exceptions.PermissionDeniedException: User 2027 does not have permissions to view comments for view 13086. (errorCode=1)

The error is described in two lines, so I need to filter the error and the current hour and then copy it into a file. This code does does copy all the errors, but not only from the current hour.

$hodina = (Get-Date -UFormat "%H").ToString()
$hodina = " " + $hodina +":"
$err = ": ERROR"
$errors = Select-String -Path "D:\..\file.log" -Pattern $hodina, $err -Context 0, 1
echo ($errors).Line >> Errors_file.txt

So I was wondering, how to put multiple variables into -Pattern, or if there is another solution to this problem.

dkrizka
  • 13
  • 5
  • Does `... blabla ...` follow any pattern or are we to assume it could be anything? Are the date fields fixed width? e.i. using leading zeros and such- always 29 characters? We need to filter the dates either before `select-string` or with – Matt May 22 '18 at 13:09
  • 1
    You might want to consider parsing out the date/time into a datetime object, and then test to see whether the log entry falls into the period of interest. – Jeff Zeitlin May 22 '18 at 13:09
  • In other words, there is no way, I get bad lines with the filters i used, so they are fine, but I am open for new ones. – dkrizka May 22 '18 at 13:28

1 Answers1

0

Here is how to get all of the matching lines:

Get-Content "file.log" | 
    Select-String -Pattern "^(?:(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})).* : ERROR (?:(.*))$" |
        ForEach-Object {
            [PsCustomObject]@{
                TimeStamp=(Get-Date $_.Matches.Groups[1].Value)
                LineNumber=$_.LineNumber
                Error=$_.Matches.Groups[2].Value
            }
        }

This will give you output like this:

TimeStamp           LineNumber Error                                                                                                                                              
---------           ---------- -----                                                                                                                                              
22/05/2018 06:25:35          1 com.tableausoftware.api.webclient.remoting.RemoteCallHandler - Exception raised...
22/05/2018 06:25:35          4 com.tableausoftware.api.webclient.remoting.RemoteCallHandler - Exception raised...
22/05/2018 06:25:35          8 com.tableausoftware.api.webclient.remoting.RemoteCallHandler - Exception raised...
22/05/2018 06:25:35         10 com.tableausoftware.api.webclient.remoting.RemoteCallHandler - Exception raised...

If you only want the items where the hour of the timestamp matches the current hour, modify the code like this:

Get-Content "file.log" | 
    Select-String -Pattern "^(?:(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})).* : ERROR (?:(.*))$" |
        ForEach-Object {
            [PsCustomObject]@{
                TimeStamp=(Get-Date $_.Matches.Groups[1].Value)
                LineNumber=$_.LineNumber
                Error=$_.Matches.Groups[2].Value
            }
        } | Where-Object {$_.TimeStamp.Hour -eq (Get-Date).Hour}

You can then send the output to file, or better (if you plan to manipulate them later in PowerShell), CSV (Export-Csv) or CliXml (Export-CliXml)

boxdog
  • 7,894
  • 2
  • 18
  • 27
  • Thanks, this is something I was looking for, but I couldn't quite get the PsCustomObject to work. – dkrizka May 22 '18 at 13:53
  • The second line is missing (`-context 0,1`) Add `Context=$_.Context.PostContext[0]` to your `[PSCustomObject]` –  May 22 '18 at 14:06