0

Sorry if the Title isn't very clear, I think part of my issue is I can't think of a way to clearly describe what I am trying to achieve, which has not helped me in 'Googling' anything that may be of help.

I am trying to create a generic script / function that I can pass 2 time values, a start time and an end time that will output all log file entries between these 2 time stamps. This will become the core part of a script to extract very small time spans of log file entries from logfiles that often exceed 1GB a day and are very difficult to manipulate in file viewers or editors efficiently and therefore take significant time to extract relevant dta from, for the purpose of providing developers with data to aid investigations into problems.

The log files are of differing formats but most of these follow the general format below:

2418 22:19:58: CTracker::ReadAvlPackets - ENTER ...
b18 22:19:58: SICInterfaceApp::ListenerRead: Qtype < 15> Subtype < 27> #8597208 From <¸i`      > 
b18 22:19:58: CTracker::OnListenerRead - PktPrc: 0x00000001
2418 22:20:00: cAvlComIMobile::GetData  - ErrSev: 0x00000000 
2418 22:20:02: cAvlComIMobile::GetData  - ErrSev: 0x00000000 

I have created a basic function:

function Get-LogExtract ($StartTime){
$Log = "path-to-log-file"
Get-Content $Log | 
ForEach-Object {
    $parts = $_ -split ' '
    if ($parts[1] -eq $StartTime) {
            $_
        }
    }
}

which if I run it using the following command line

Get-LogExtract 22:19:58:

it will output only the logfile lines that have the timestamp of 22:19:58: in the line, which is fine, it was what I initally wanted to achieve, but since this point the requirement has expanded.

What I now want to be able to do is to provide a start time and an end time and have all lines between these output.

I have tried to implement a do while loop to do this but was obvioulsy not getting anywhere as I couldn't achieve the goal I am trying to reach.

So I have a few questions.

    1. is there a better way to tackle what I am trying to achieve?
    2. if not, how can I implement a loop to achieve my goal?

Updated Code:

OK, so here's a code segment tweaked as advised by PSGuy below, which works a treat with logfiles that have a time stamp entry on every line.:

function Get-LogExtract ($StartTime, $EndTime) {
$Log = "path-to-log-file"
Get-Content $Log | 
    ForEach {
    $parts = $_ -split ' '
        if ($parts[1] -ge $StartTime -and $parts[1] -le $EndTime) {
            $_
        }
    }
}
wohlstad
  • 12,661
  • 10
  • 26
  • 39
Andy Carroll
  • 65
  • 1
  • 6

1 Answers1

1

There are a few things you can do here. The first is, if you want a true date-time object, then you can run the following static method of the System.DateTime class:

[DateTime]::Parse($Time) # 22:19:58 == Friday, September 19, 2014 10:19:58 PM

You can also do string comparisons, because any comparison operator against a string will evaluate each character by Char value, so "22:19:59" -gt "22:19:58" is true.

I think that converting to a DateTime format will be easier for you, however, doing a simple string comparison will work. Something like:

If $line[$I] -ge "22:19:59" -and $line[$I] -le "23:59:59" will theoretically work in your proposed script / function. I would also recommend doing a for loop to step through each line of the log file, however, it's not required. I'm not a big fan of the foreach-object cmdlet if I'm not using actual objects in the pipleline, where I can call a static method against the object itself. Here, it's just simple string work, and I would personally use a for loop, but it's all a matter of preference. The for construct would look like this:

$logFile = Get-Content myLogFile.log # or whatever file format, it's an input arg anyway
for ($I = 0; $I -le $logFile.GetUpperBound(""); $I++)
{
    $logFile[$I] # reads the line; you can assign a variable at this point
}

A foreach loop would also work. I personally like using for, but foreach is effectively the same thing. The foreach equivalent is:

foreach ($line in $logFile)
{
    $line # perform whatever split operations you want to perform
}

Please let us know if it works!

PSGuy
  • 653
  • 6
  • 17
  • I have marked the answer above as resolving the initial question. :-) However in trying this solution against a few different log files I have found that there are some log files that do not have a time stamp on each line and this causes problems. Should I ask a seperate question outlining the issues? – Andy Carroll Sep 22 '14 at 14:48
  • I'll see if I can figure out how to send you the code on here real quick. I came up with one method you could go about doing it with – PSGuy Sep 24 '14 at 05:18
  • If you have Dropbox (or similiar file share option), you could always put the code in a txt file on there, possibly in the Public folder, and provide the **Copy Public link...** url here. It's a method I've used previously when a forum doesn't have a direct way to upload code / files. – Andy Carroll Sep 24 '14 at 09:32
  • Here's a link to the more detailed explaination of the issue, for the benefit of anyone who hasn't seen that post - http://stackoverflow.com/questions/25996909/powershell-how-to-handle-non-timestamped-log-file-entries-including-blank-lin – Andy Carroll Sep 24 '14 at 13:23