2009-10-28 5 views
15

イベントIDの管理方法を理解しようとしています。ここまでは、メソッドの各ステップを順番に番号付けして、各メソッドの各イベントIDを手動で入力していました。これにより、イベントログのイベントを効果的にフィルタリングすることはできません。イベントログにフィルタを使用するには、ログに記録された各イベントに固有のIDが必要です。イベントID管理のベストプラクティスは何ですか?

私はテーブルにそれらをリンクされた説明とともに格納することができましたが、私のコードが実行されると、意味のないイベントコードが記録されます。

私はGoogleの検索を行いましたが、この問題の最下部に到達するために使用する正しいキーワードが失われているようです。

事前

+0

イベントログに記録する際にイベントIDを使用しませんでした。私はちょうどその時点で何が起こっていたかについての十分な情報を入れて彼女にリッピングさせてください... – Will

+0

@ウィル - 関連するアイテムを見つけようとしているときに、どのようにイベントログをフィルタリングしますか?たとえば、現在冗長にログを記録しているコンポーネントがありますが、特定のイベントの後ろにいる場合は、そのイベントIDでフィルタリングする唯一の方法です。 – BobTheBuilder

+0

@ウィル - ここでのアイデアは、特定のイベントの出現頻度を項目別に掘り下げて関連するものを見つけることなく評価することです。 – BobTheBuilder

答えて

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

を、あなたは、もはやあなたを呼び出していないしていますイベントをマジックナンバーで簡単に管理することができます。これは、EventManagerクラスの1つのイベントですべてのイベントを簡単に管理でき、フィルタリングする必要があるマジックナンバーでイベントログをフィルタリングできます。ベンの提案のように

+0

"そして、あなたは" - 何を渡す? "という意味の識別子を使ってイベントにアクセスすることができます。 – BobTheBuilder

+0

ImmutableDictionaryを使用するために_eventListをリファクタリングします。これにより、遅いLINQクエリを使用する必要がなくなります。それは遅くは見えないかもしれませんが、計算上の複雑さはO(n)ですが、ImmutableDictionaryはO(1)の読み取りアクセスを保証します。さらに、イベントを削除するためのユースケースはありません。イベントの削除を許可すると、キーのない孤立したイベントログレコードが作成されます。 AddRangeを呼び出さないでください。辞書を渡すだけです。さらに、Formatterは文字列ではなくファーストクラス汎用Formatter (文字列形式)でなければならないので、どのような引数型をフォーマッタに渡すのかを消費者に明確にする必要があります。 –

10

は、それが間接のレベルを使用して、おそらく価値がある - が、代わりにコードの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を書くにはあまりにも疲れています:)

0

私はこれは古い質問ですが、

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

そして、あなたはときには、このようにこのクラスを呼びたい:あなたは、さまざまな目的のためにカスタムイベントIDを使用して、このような何かを、行うには、あなたのコードでの適切な場所にそれらを呼び出すための方法を探してあなたはあなたの例外を投げた:

ErrorLog.ErrorRoutine(ErrorLog.NOTIFY_ALPHA); 

ベストプラクティスは、 uldは、それがカスタムである場合(あるいは、警告や情報EventLogEntryTypesや缶詰メッセージよりも多くの情報を結びつける場合など)、それ自身のクラスですべてのエラー処理を行うことは良いことだと言います。個々のIDを持つことで、このようなメッセージを参照すると、いつ、どこで、どこで、どのメッセージを呼び出すかを整理しようとするときの人生が楽になります。

関連する問題