Каковы лучшие практики для управления идентификатором события? - PullRequest
16 голосов
/ 28 октября 2009

Я пытаюсь понять, как управлять идентификаторами событий. До этого момента я помещал каждый идентификатор события в каждый метод вручную, причем каждый шаг в методе был пронумерован последовательно. Это не позволяет мне эффективно фильтровать события в журнале событий. Чтобы использовать фильтр в журнале событий, кажется, что каждое зарегистрированное событие должно иметь свой собственный уникальный идентификатор.

Я мог бы хранить их все в таблице с описанием, связанным с ними, но затем, когда мой код выполняется, я записываю "магические" бессмысленные коды событий.

Я выполнил поиск в Google, но, похоже, затрудняюсь найти правильные ключевые слова, с помощью которых можно добраться до сути этой проблемы.

Заранее спасибо

Ответы [ 3 ]

10 голосов
/ 29 октября 2009

Как и предложение Бена, вероятно, стоит использовать уровень косвенности - но вместо использования int для кода, я бы использовал фактическое перечисление, например, для Бена:

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
}

Или в качестве альтернативы (и более объектно-ориентированным способом) использовать шаблон «smart enum»):

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
    }
}

Затем вы можете позвонить:

LogEvent.BuildingCommandObject.Log("stuff");

Немного поработав, вы сможете быть в состоянии раскрыть это безопасным способом с различными событиями журнала, имеющими другой интерфейс, чтобы сделать его безопасным (во время компиляции) с точки зрения количества параметров каждого надо. На самом деле, я уверен, что вы могли бы сделать это, используя интерфейсы и закрытый вложенный класс, но сейчас 4 часа утра, и я слишком устал, чтобы написать это atm:)

7 голосов
/ 28 октября 2009

Первая мысль - и я еще не совсем продумал это, но это кажется разумной возможностью:

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()
    {
    }
}

После этого вы можете иметь класс менеджера событий, который упаковывает ваш список событий, предоставляя метод, который запрашивает список в соответствии с передаваемым параметром, например:

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);
    }
}

Это позволяет упростить управление определениями событий, которыми можно управлять независимо для каждого 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.")
)

И вы можете получить доступ к событиям, используя назначенный вами значимый идентификатор:

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

или

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

Это, вероятно, упростит ваше управление событиями, вы больше не будете называть свои события магическими числами, просто управлять всеми своими событиями в одном месте - классом EventManager, и вы все равно сможете фильтровать свой журнал событий по волшебным номерам требует от вас фильтрации.

0 голосов
/ 09 апреля 2015

Я знаю, что это старый вопрос, но, возможно, вы искали способ сделать что-то подобное, где вы используете собственные идентификаторы событий для различных целей и называете их в соответствующих местах в вашем коде:

public class ErrorLog
{
    //Notifications
    public const int NOTIFY_ALPHA = 2000;
    public const int NOTIFY_BETA = 2001;
    public const int NOTIFY_GAMMA = 2002;

    public static string[] errMessage = 
        {"Critical Error.",           //2000
         "File not found.",          //2001
         "Unknown Event Action Encountered - "     //2002
        };

    public static string GetErrMsg(int errNum)
    {
        return (errMessage[errNum-2000]);
    }

    private static bool ErrorRoutine(int eventLogId)
    {
        try
        {
            string eventAppName = "My Application";
            string eventLogName = "My Apps Events";
            string msgStr = GetErrMsg(eventLogId);  // gets the message associated with the ID from the constant you passed in

            if (!EventLog.SourceExists(eventAppName))
                EventLog.CreateEventSource(eventAppName, eventLogName);

            EventLog.WriteEntry(eventAppName, msgStr, EventLogEntryType.Error, eventLogId);

            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }
}

И тогда вы бы назвали этот класс следующим образом, когда бросили свое исключение:

ErrorLog.ErrorRoutine(ErrorLog.NOTIFY_ALPHA);

Что касается передового опыта, я бы сказал, что было бы хорошо, чтобы вся обработка ошибок была в своем собственном классе, если она будет такой же пользовательской (или более того, например, при связывании предупреждений и информации EventLogEntryTypes или дополнительной информации, кроме консервированные сообщения дают), чем этот. Имея индивидуальные идентификаторы, вы можете просматривать их сообщения, как это, и облегчит вашу жизнь, пытаясь разобраться, какое сообщение вызывать, когда и где.

...