什么是事件ID管理的最佳实践?

Bob*_*der 16 .net c# events trace event-log

我正在试图弄清楚如何管理我的事件ID.到目前为止,我已经手动将每个事件id放在每个方法中,并按顺序编号的方法中的每个步骤.这不允许我有效地过滤事件日志中的事件.为了在事件日志中使用过滤器,似乎每个记录的事件都必须具有自己的唯一ID.

我可以将它们全部存储在一个表中,并将描述链接到它们,但随后我的代码执行,我正在记录"魔术"毫无意义的事件代码.

我进行了谷歌搜索,但我似乎对用于解决此问题的正确关键字感到茫然.

提前致谢

Jon*_*eet 10

像Ben的建议一样,它可能值得使用一个间接级别 - 但不是使用int代码,我会使用实际的枚举,所以Ben的例子:

public enum EventId
{
    [Format("Building command object from {0}.")]
    BuildingCommandObject = 1,
    [Format("Command object build successfully.")]
    CommandObjectBuilt = 2,
    [Format("Connecting to {0}.")]
    ConnectingToDatabase = 3,
    [Format("Executing command against database {0}.")]
    ExecutingCommand = 4,
    [Format("Command executed successfully.")]
    CommandExecuted = 5,
    [Format("Disconnecting from {0}.")]
    DisconnectingFromDatabase = 6,
    [Format("Connection terminated")]
    Disconnected = 7
}
Run Code Online (Sandbox Code Playgroud)

或者(以更面向对象的方式)使用"智能枚举"模式):

public class LogEvent
{
    public static readonly LogEvent BuildingCommandObject = new LogEvent(1,
         "Building command object from {0}");
    // etc

    private readonly int id;
    private readonly string format;

    // Add the description if you want
    private LogEvent(int id, string format)
    {
        this.id = id;
        this.format = format;
    }

    public void Log(params object[] data)
    {
        string message = string.Format(format, data);
        // Do the logging here
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以打电话:

LogEvent.BuildingCommandObject.Log("stuff");
Run Code Online (Sandbox Code Playgroud)

通过一些工作,您可以以安全的方式公开它,使用具有不同接口的不同日志事件,以便在每个参数的数量方面使其安全(在编译时).事实上,我确信你可以使用接口和私有嵌套类来做到这一点,但是凌晨4点,我太累了,不能写出来atm :)


Ben*_*ter 7

首先想到 - 我还没有完全想到这一点,但这似乎是一个合理的可能性:

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()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以拥有一个事件管理器类,它包装您的事件列表,提供根据您传递的参数查询列表的方法 - 例如:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这样可以简化事件定义的管理,可以为每个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.")
)
Run Code Online (Sandbox Code Playgroud)

您可以使用您指定的有意义的标识符访问事件:

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

要么

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

这可能会简化您的事件管理,您不再通过幻数来调用您的事件,在一个地方管理您的所有事件很简单 - 您的EventManager类,您仍然可以通过它需要的神奇数字过滤您的事件日志过滤.