Search code examples
c#.neteventstraceevent-log

What are best practices for event id management?


I'm trying to figure out how to manage my event ids. Up to this point I've been putting each event id in each method manually with each step in a method numbered sequentially. This doesn't allow me to effectively filter events in the event log. In order to use the filter in the event log, it seems that every logged event must have its own unique id.

I could store them all in a table with the description linked to them, but then as my code executes, I'm logging "magic" meaningless event codes.

I did a Google search, but I appear to be at a loss as to the correct keywords to use to get to the bottom of this issue.

Thanks in advance


Solution

  • First thought - and I haven't entirely thought this through yet, but it seems like a reasonable possibility:

    public class LogEvent
    {
        /* This is the event code you reference from your code 
         * so you're not working with magic numbers.  It will work
         * much like an enum */
        public string Code; 
    
        /* This is the event id that's published to the event log
         * to allow simple filtering for specific events */
        public int Id; 
    
        /* This is a predefined string format that allows insertion
         * of variables so you can have a descriptive text template. */
        public string DisplayFormat;
    
        /* A constructor to allow you to add items to a collection in
         * a single line of code */
        public LogEvent(int id, string code, string displayFormat)
        {
            Code = code;
            Id = id;
            DisplayFormat = displayFormat;
        }
        public LogEvent(int id, string code)
            : this(id, code, null)
        {
        }
        public LogEvent()
        {
        }
    }
    

    You can then have an event manager class that wraps your list of events providing a method that queries the list according to the parameter you pass - for instance:

    public class EventManager
    {
        private List<LogEvent> _eventList;
        public LogEvent this[string eventCode]
        {
            get
            {
                return _eventList.Where(i => i.Code.Equals(eventCode)).SingleOrDefault();
            }
        }
        public LogEvent this[int id]
        {
            get
            {
                return _eventList.Where(i => i.Id.Equals(id)).SingleOrDefault();
            }
        }
        public void AddRange(params LogEvent[] logEvents)
        {
            Array.ForEach(logEvents, AddEvent);
        }
        public void Add(int id, string code)
        {
            AddEvent(new LogEvent(id, code));
        }
        public void Add(int id, string code, string displayFormat)
        {
            AddEvent(new LogEvent(id, code, displayFormat));
        }
        public void Add(LogEvent logEvent)
        {
            _events.Add(logEvent);
        }
        public void Remove(int id)
        {
            _eventList.Remove(_eventList.Where(i => i.id.Equals(id)).SingleOrDefault());
        }
        public void Remove(string code)
        {
            _eventList.Remove(_eventList.Where(i => i.Code.Equals(code)).SingleOrDefault());
        }
        public void Remove(LogEvent logEvent)
        {
            _eventList.Remove(logEvent);
        }
    }
    

    This allows simplified management of event definitions which can be managed independently for each TraceSource.

    var Events = new EventManager();
    Events.AddRange(
        new LogEvent(1, "BuildingCommandObject", "Building command object from {0}."),
        new LogEvent(2, "CommandObjectBuilt", "Command object built successfully."),
        new LogEvent(3, "ConnectingToDatabase", "Connecting to {0}."),
        new LogEvent(4, "ExecutingCommand", "Executing command against database {0}".),
        new LogEvent(5, "CommandExecuted", "Command executed succesfully."),
        new LogEvent(6, "DisconnectingFromDatabase", "Disconnecting from {0}."),
        new LogEvent(7, "Disconnected", "Connection terminated.")
    )
    

    And you can access the events using the meaningful identifier you assigned:

    var evt = Events["ConnectingToDatabase"];
    TraceSource.TraceEvent(TraceEventType.Information, evt.Id, evt.DisplayFormat, otherParams);
    

    or

    var evt = Events[1024];
    Console.WriteLine("Id: {1}{0}Code: {2}{0}DisplayFormat{3}", 
        Environment.NewLine, evt.Id, evt.Code, evt.DisplayFormat);
    

    This would probably simplify your event management, you're no longer calling your events by magic numbers, it's simple to manage all your events in one place - your EventManager class and you can still filter your event log by the magic numbers it requires you to filter by.