-2

I am writing a program to read a log file. each entry starts with a time-stamp, except when there is an error, which in this case, I would have multiple lines for the error message and without time-stamp.

The file looks like this:

20190207 14:23:10.123 info Read input
20190207 14:23:11.001 info connecting to database
20190207 14:23:17.101 error truncating the table customer. Error code XXXX
the file was blocked.

I would like to store every entry with its time-stamp, event type, and message in a table that has three columns, one column for the time-stamp (datetime) and another column for the events (info/warning/error), and a column for the text (data type text).

How do I iterate through the file and read all the entries including the error message which sometimes be in multiple lines?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
  • 4
    Could you show your code, please? – Fatikhan Gasimov Feb 11 '19 at 14:48
  • Could you describe the trouble you're having with your current approach? It should be relatively easy to tell if a line is a continuation of a previous line's error (i.e. It won't begin with a predictable timestamp - presumably). – Broots Waymb Feb 11 '19 at 14:51
  • How do you tell the difference between the events and the text? – Chris Feb 11 '19 at 14:53
  • the second column is the event (info, warning, error). in case of it is an error, it usually have multiple line, I would like to to store those multiple lines in one message with the event error and time stamp – user2274800 Feb 11 '19 at 15:09
  • the code is too long to fit in the comment – user2274800 Feb 11 '19 at 15:11

1 Answers1

0

What you can do is to use Regex to try to match each line of the log. If you have match then you create entry otherwise you append the line to the existing entry. I will provide the code to try to explain approach...

//strings for simplification, in your code you should use DateTime and parse properly
public class Entry
{
    public string Timestamp { get; set; }
    public string Type { get; set; }
    public string Description { get; set; }
}

Then you could define regular expression to capture log line. I did this using groups so it is easier to extract data from it. Notice that you should add all types you expect, I just use info|error|warning.

//you should define all types you expect in log, I just put info and error
string LogLineRegex = @"(?<date>\d{4}\d{2}\d{2} \d{2}:\d{2}:\d{2}.\d{3}) (?<type>info|error|warning) (?<text>.*)";

And then read each line of the log:

  • match - create new entry
  • not match - append the line to the rolling entry, assumption is that you have an error

Log parsing example

Entry rollingEntry = null;

foreach (var line in log)
{
    var match = Regex.Match(line, LogLineRegex);

    if (match.Success)
    {
        if (rollingEntry != null) { entries.Add(rollingEntry); }

        rollingEntry = new Entry{ 
            Timestamp = match.Groups["date"].ToString(),
            Type = match.Groups["type"].ToString(),
            Description = match.Groups["text"].ToString() };
    }
    else
    {
        if (rollingEntry != null) { rollingEntry.Description += $"{Environment.NewLine}{line}"; }
    }
}
Johnny
  • 8,939
  • 2
  • 28
  • 33