17

イベント ID を管理する方法を理解しようとしています。この時点まで、各メソッドに各イベント ID を手動で入れ、メソッドの各ステップに順番に番号を付けていました。これでは、イベント ログでイベントを効果的にフィルター処理できません。イベント ログでフィルターを使用するには、ログに記録されたすべてのイベントに独自の一意の ID が必要なようです。

説明がリンクされたテーブルにすべてを格納できますが、コードを実行すると、「魔法の」無意味なイベント コードがログに記録されます。

Google 検索を行いましたが、この問題の真相にたどり着くために使用する正しいキーワードについて途方に暮れているようです。

前もって感謝します

4

3 に答える 3

11

ベンの提案のように、おそらく間接的なレベルを使用する価値がありますが、コードに 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
}

または、代わりに (よりオブジェクト指向の方法で) 「スマート列挙型」パターンを使用します):

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に書き出すことができません:)

于 2009-10-29T04:07:12.273 に答える
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()
    {
    }
}

次に、イベントのリストをラップするイベント マネージャー クラスを作成して、渡したパラメーターに従ってリストをクエリするメソッドを提供できます。たとえば、次のようになります。

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

これにより、おそらくイベント管理が簡素化されます。イベントをマジック ナンバーで呼び出す必要はなくなります。すべてのイベントを 1 か所 (EventManager クラス) で簡単に管理でき、必要なマジック ナンバーでイベント ログをフィルター処理することもできます。でフィルタリングします。

于 2009-10-28T18:42:14.667 に答える
0

これは古い質問であることは承知していますが、おそらく、さまざまな目的でカスタム イベント ID を使用し、コード内の適切な場所でそれらを呼び出す、次のような方法を探していたのでしょう。

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 または定型メッセージが提供する追加情報を結び付ける場合など)。 ) これより。このようにメッセージを参照できる個別の ID を持っていると、いつ、どこで、どのメッセージを呼び出すかを整理しようとするときに、作業が楽になります。

于 2015-04-09T02:30:28.013 に答える