1

I've written a simple event logging system, which I write to with a function similar to:

void IIncidentLogic.ReportIncident(
  string code,
  string noun,
  string hostname,
  DateTimeOffset occurredAt)

Where code is derived from a set of constants such as VOL_SIZE_INCREASE, noun would be the path of the volume, hostname the computer where it occurred, and occurredAt when it was detected.

Since code is a known value, I can automatically set other properties, such as the severity of the event, e.g. is it a warning or an error? I also use code to query a resource dictionary for a friendly error message to display to users. Right now for this example the error message would be A volume has increased in size, with the noun clumsily appended to the error message.

I am looking to improve the readability of the error messages, e.g. in this scenario to be something like The volume system (c:) on computer-name has increased in size from 100GB to 200GB.

I can think of a couple of ways to do this, and am wondering what is the better practice.

I could pre-build the error message, and pass to the logging function, storing in it's own field. However I want to programmaticly force the message to the be the same, no matter where it's generated. A string message parameter is too open.

So I could record a dictionary of properties against the report, e.g. {originalSize: '100GB', newSize: '200GB', volume: 'system (c:)'}. I could still use resource strings to generate the messages, but format them, e.g. The volume {0} on {1} has increased in size from {2} to {3}. This allows for i8ln, which is a likely future requirement. But it has a possibility to break legacy data if any part changes, e.g. an additional property is required.

And I could do both: use the properties and string formatting, and store the generated string at the same time.

I could also go as far as having a class per event type, or code, with different constructor parameters, but this certainly feels like overkill.

Or is there a different established pattern for this kind of logging?

3 Answers 3

2

I feel I can contribute to this given answer.

The concept Phill is describing comes very close to the EventSourcing Pattern. If your systems contains several types of Events, consider such an implementation. The overal flexibility, as mentioned by Phill, will drastically increase since you don't have to know yet what you will do with the data.

1
  • Yes I came across Event Sourcing when digging before posting this question, and thought it was a close fit.
    – mattdwen
    Jul 9, 2015 at 21:30
1

If you want consistency, then using a class for each error condition gives you just that - wherever you want to mention that a volume has grown in size, you create an instance of a VolumeSizeIncreased class, passing whatever values you need into its constructor.

To me, it's the next step after rigidly codifying your errors (your VOL_SIZE_INCREASE value).

VolumeSizeIncreasedMessage vsim 
   = new VolumeSizeIncreasedMessage( "PC123456", "system (C:)", 100, 200, DateTime.Now ) 
Console.WriteLine( vsim.toString() ); 

Are you intended to do anything with these errors afterwards (other than physically reading them)? If so, objects are a far better option, because you can query their properties and take actions based on those (but I'm veering into Exception Handling here).

1
  • A number of the messages are generated as a result of exception handling. Other events are measured over time, e.g. CPU usage is over 75%, where I record a single "incident", but multiple occurrences with the CPU usage every minute, which is then displayed in a graph for the incident window. There would be a notification email sent out which needs the formatted message.
    – mattdwen
    Jul 9, 2015 at 21:27
1

The best logging is just to format it as a readable string and persist that. Possibly including the data as a block of data that is accessible to programs as well.

The reason I say this is that I am continually looking at Windows Event logs, which uses a "we write the data and a link to a resource dll containing format strings" pattern, and invariably the dll is only present on the host computer - not on mine where I analyse the logs. Hence, I can never see the full text of what was written, just the raw data.

Its also very easy and simple to write text, and that is what you will want written when you come to look at the logs later, making it the ideal pattern.

Note also that there is a huge controversy in the linux world at the moment as systemd writes its logs using a binary format, meaning you need a special viewer to read them. People were used to using any old text editor to read and/or parse logs written in text formats. There's a good reason text logs with plain formatted strings have been used for logging.

So think of the end-user of your logs and how they will interact with them, and fit your solution to give them the best experience.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.