2009-06-04 3 views
4

Я использую журнал событий Windows для записи некоторых событий. Событиям в Журнале событий Windows может быть присвоено несколько свойств. Один из них - EventID.Уникальное событие EventId

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

Я хочу, чтобы система сделала это автоматически. Он будет выбирать eventId, который является «уникальным» для позиции в коде, в котором произошло событие регистрации. Теперь есть только 65536 уникальных идентификаторов событий, поэтому вероятность столкновения может быть довольно редкой, чтобы EventId был полезным способом группировать ошибки.

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

public void TestLog() 
{ 
    LogSomething("Moo"); 
    // Do some stuff and then a 100 lines later.. 
    LogSomething("Moo"); 
} 

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

У кого-нибудь есть идеи?

+0

Просто чтобы быть ясно, вы хотите, два вызова в вашем примере, чтобы иметь разные eventID? –

+0

@Michael Да, они должны иметь разные EventIds, потому что вызовы регистрации происходят на разных строках. Мой вопрос: можно ли это сделать? –

ответ

3

Номер смещения IL доступен без символов отладки. В сочетании с информацией о стеке и хэшем я думаю, что это будет трюк.

Вот статья, которая, в частности, охватывает получение интерлейкин смещения (с целью его регистрации для автономного матча с PDB файлов - другая проблема, но я думаю, что он покажет вам, что вам нужно):

http://timstall.dotnetdevelopersjournal.com/getting_file_and_line_numbers_without_deploying_the_pdb_file.htm

+0

Я не знаю, как я пропустил это, но ура. Это именно то, что я искал. –

-1

Теперь я хочу использовать EventId, чтобы попробовать и связанные с группой ошибки.

У вас есть фильтры в окне просмотра событий, так почему (Go найти? У вас есть 65536 уникальных идентификаторов событий тоже.

Или лучше использовать log4net или что-то ??

только мои идеи ....

+0

Две проблемы с этим. Во-первых, даже если я использовал log4net, который бы не решал мою проблему группировки. Во-вторых, я хочу, чтобы EventId использовался *, потому что * я хочу использовать фильтры. Это очень плохой ответ, поэтому я проголосовал за него. –

+0

ну вы можете написать свой собственный код .... – abmv

0

Спасибо за идею хеширования стек вызовов, я собирался спросить, что тот же самый вопрос о том, как выбрать в EVENTID.

Я рекомендую поместить статическую переменную в LogSomething, что incremen ts каждый раз, когда он вызывается.

1

Создать хэш с помощью ILOffset последнего, но один кадр стека вместо номера строки (т.е. фрейм стека вашего метода TestLog выше).

5

Вот код, который можно использовать для генерации EventID со свойствами, которые я описываю в моем вопросе:

public static int GenerateEventId() 
{ 
    StackTrace trace = new StackTrace(); 

    StringBuilder builder = new StringBuilder(); 
    builder.Append(Environment.StackTrace); 

    foreach (StackFrame frame in trace.GetFrames()) 
    { 
      builder.Append(frame.GetILOffset()); 
      builder.Append(","); 
    } 

    return builder.ToString().GetHashCode() & 0xFFFF; 
} 

frame.GetILOffset() вызов метода дает позицию в этом конкретном кадре в момент выполнение.

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

И, наконец, поскольку существует только 65536 уникальных идентификаторов событий, то я логичен и hashcode против 0xFFFF, чтобы извлечь наименее значимые 16-битные. Это значение становится EventId.

1

* Важно: Это сообщение сосредоточено на решении основной причины того, что, по-вашему, ваша проблема, вместо того, чтобы предоставить решение, которое вы специально попросили. Я понимаю, что эта должность устарела, но было важно внести свой вклад. *

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

  1. Префикс сообщения журнала с именем «имя класса». «Имя функции».
  2. Для получения истинных ошибок выведите захваченное исключение в регистратор событий.
  3. Сосредоточьтесь на том, чтобы иметь четкие сообщения как часть обзора однорангового кода в отличие от идентификаторов событий.
  4. Используйте уникальный идентификатор события для каждой функции, просто перейдите сверху вниз и нажмите клавишу.
  5. , когда становится нецелесообразным кодировать каждую функцию с другим идентификатором события, каждый класс должен просто иметь уникальный (столкновения будут прокляты).
  6. Использование категорий событий, чтобы уменьшить зависимость Идентификатор события при фильтрации журнала

Конечно, это важно, насколько большой ваши приложения и как чувствительные данные. Большинство из нас составляют около 10 тыс. До 500 тыс. Строк кода с минимально-чувствительной информацией. Это может показаться слишком упрощенным, но с точки зрения KISS оно прагматично работает.

Учитывая, что использование абстрактного класса журнала событий для упрощения процесса облегчает его использование, хотя очистка моя неприятна. Например:

MyClass.cs (с использованием оболочки)

class MyClass 
{ 
    // hardcoded, but should be from configuration vars 
    private string AppName = "MyApp"; 
    private string AppVersion = "1.0.0.0"; 
    private string ClassName = "MyClass"; 
    private string LogName = "MyApp Log"; 

    EventLogAdapter oEventLogAdapter; 
    EventLogEntryType oEventLogEntryType; 

    public MyClass(){ 
     this.oEventLogAdapter = new EventLogAdapter(
       this.AppName 
      , this.LogName 
      , this.AppName 
      , this.AppVersion 
      , this.ClassName 
     ); 
    } 

    private bool MyFunction() { 
     bool result = false; 
     this.oEventLogAdapter.SetMethodInformation("MyFunction", 100); 
     try { 
      // do stuff 
      this.oEventLogAdapter.WriteEntry("Something important found out...", EventLogEntryType.Information); 

     } catch (Exception oException) { 
      this.oEventLogAdapter.WriteEntry("Error: " + oException.ToString(), EventLogEntryType.Error); 
     } 
     return result; 
    } 
} 

EventLogAdapter.cs

class EventLogAdapter 
{ 
    //vars 
    private string _EventProgram = ""; 
    private string _EventSource = ""; 
    private string _ProgramName = ""; 
    private string _ProgramVersion = ""; 
    private string _EventClass = ""; 
    private string _EventMethod = ""; 
    private int _EventCode = 1; 
    private bool _Initialized = false; 
    private System.Diagnostics.EventLog oEventLog = new EventLog(); 
    // methods 
    public EventLogAdapter() { } 
    public EventLogAdapter(
      string EventProgram 
     , string EventSource 
     , string ProgramName 
     , string ProgramVersion 
     , string EventClass 
    ) { 
     this.SetEventProgram(EventProgram); 
     this.SetEventSource(EventSource); 
     this.SetProgramName(ProgramName); 
     this.SetProgramVersion(ProgramVersion); 
     this.SetEventClass(EventClass); 
     this.InitializeEventLog(); 
    } 
    public void InitializeEventLog() { 
     try { 
      if(
       !String.IsNullOrEmpty(this._EventSource) 
       && !String.IsNullOrEmpty(this._EventProgram) 
      ){ 
       if (!System.Diagnostics.EventLog.SourceExists(this._EventSource)) { 
        System.Diagnostics.EventLog.CreateEventSource(
         this._EventSource 
         , this._EventProgram 
        ); 
       } 
       this.oEventLog.Source = this._EventSource; 
       this.oEventLog.Log = this._EventProgram; 
       this._Initialized = true; 
      } 
     } catch { } 
    } 
    public void WriteEntry(string Message, System.Diagnostics.EventLogEntryType EventEntryType) { 
     try { 
      string _message = 
       "[" + this._ProgramName + " " + this._ProgramVersion + "]" 
       + "." + this._EventClass + "." + this._EventMethod + "():\n" 
       + Message; 
      this.oEventLog.WriteEntry(
        Message 
       , EventEntryType 
       , this._EventCode 
      ); 
     } catch { } 
    } 
    public void SetMethodInformation(
     string EventMethod 
     ,int EventCode 
    ) { 
     this.SetEventMethod(EventMethod); 
     this.SetEventCode(EventCode); 
    } 
    public string GetEventProgram() { return this._EventProgram; } 
    public string GetEventSource() { return this._EventSource; } 
    public string GetProgramName() { return this._ProgramName; } 
    public string GetProgramVersion() { return this._ProgramVersion; } 
    public string GetEventClass() { return this._EventClass; } 
    public string GetEventMethod() { return this._EventMethod; } 
    public int GetEventCode() { return this._EventCode; } 
    public void SetEventProgram(string EventProgram) { this._EventProgram = EventProgram; } 
    public void SetEventSource(string EventSource) { this._EventSource = EventSource; } 
    public void SetProgramName(string ProgramName) { this._ProgramName = ProgramName; } 
    public void SetProgramVersion(string ProgramVersion) { this._ProgramVersion = ProgramVersion; } 
    public void SetEventClass(string EventClass) { this._EventClass = EventClass; } 
    public void SetEventMethod(string EventMethod) { this._EventMethod = EventMethod; } 
    public void SetEventCode(int EventCode) { this._EventCode = EventCode; } 

} 
Смежные вопросы