2009-10-28 40 views
15

Tôi đang cố gắng tìm ra cách quản lý id sự kiện của mình. Tính đến thời điểm này, tôi đã đặt từng id sự kiện trong từng phương thức theo cách thủ công với từng bước trong một phương pháp được đánh số liên tục. Điều này không cho phép tôi lọc hiệu quả các sự kiện trong nhật ký sự kiện. Để sử dụng bộ lọc trong nhật ký sự kiện, có vẻ như mọi sự kiện đã ghi phải có id duy nhất của riêng nó.Thực tiễn tốt nhất cho quản lý id sự kiện là gì?

Tôi có thể lưu trữ tất cả trong bảng có mô tả được liên kết với chúng, nhưng khi mã của tôi thực thi, tôi đang ghi nhật ký sự kiện vô nghĩa "ma thuật".

Tôi đã thực hiện tìm kiếm trên Google, nhưng có vẻ như tôi đang thua lỗ về từ khóa chính xác để sử dụng để đi đến cuối vấn đề này.

Cảm ơn trước

+0

Không bao giờ sử dụng id sự kiện khi đăng nhập vào nhật ký sự kiện. Tôi chỉ cần đặt đủ thông tin về những gì đã xảy ra tại thời điểm đó và để cô ấy rip ... – Will

+0

@Will - Vậy làm thế nào để bạn lọc nhật ký sự kiện của mình khi bạn đang cố gắng tìm các mục có liên quan? Ví dụ, nếu tôi có một thành phần hiện đang ghi nhật ký một cách chi tiết nhưng sau một sự kiện cụ thể - cách duy nhất tôi có thể lọc trên đó là lọc trên id sự kiện. – BobTheBuilder

+0

@Will - ý tưởng ở đây là để đánh giá tần suất xuất hiện của một sự kiện cụ thể mà không phải đào qua mục nhật ký theo mục để tìm các mục có liên quan. – BobTheBuilder

Trả lời

7

suy nghĩ đầu tiên - và tôi đã không hoàn toàn nghĩ này thông qua, nhưng nó có vẻ như một khả năng hợp lý:

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

Sau đó bạn có thể có một lớp quản lý sự kiện mà kết thúc tốt đẹp danh sách các sự kiện cung cấp một phương pháp mà truy vấn danh sách theo tham số bạn vượt qua - ví dụ:

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

này cho phép quản lý đơn giản của ev ent định nghĩa có thể được quản lý độc lập cho mỗi 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.") 
) 

Và bạn có thể truy cập vào các sự kiện bằng cách sử dụng định danh có ý nghĩa bạn đã gán:

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

hoặc

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

này có lẽ sẽ đơn giản hóa quản lý sự kiện của bạn, bạn không còn kêu gọi của bạn các sự kiện bằng số ảo, thật đơn giản để quản lý tất cả các sự kiện của bạn ở một nơi - lớp EventManager của bạn và bạn vẫn có thể lọc nhật ký sự kiện của mình theo số ma thuật mà nó yêu cầu bạn lọc theo.

+0

"Và bạn có thể truy cập các sự kiện bằng cách sử dụng một số nhận dạng có ý nghĩa trong khi vẫn truyền" - truyền cái gì? – BobTheBuilder

+0

Tôi sẽ refactor _eventList để sử dụng ImmutableDictionary. Điều này sẽ loại bỏ sự cần thiết phải sử dụng một truy vấn LINQ chậm. Nó có thể không có vẻ chậm, nhưng độ phức tạp tính toán của nó là O (n), trong khi ImmutableDictionary đảm bảo truy cập đọc O (1). Hơn nữa, tôi không thấy trường hợp sử dụng để xóa sự kiện. Cho phép xóa các sự kiện sẽ tạo các bản ghi sự kiện mồ côi mồ côi mà không có khóa. Đừng gọi AddRange; chỉ cần vượt qua trong từ điển. Hơn nữa, Formatter phải là một Formatter chung loại đầu tiên (định dạng chuỗi) chứ không phải là một chuỗi, do đó, nó rõ ràng cho người tiêu dùng loại đối số nào để truyền vào trình định dạng. –

10

Giống như gợi ý của Ben, nó có thể là giá trị sử dụng một mức gián tiếp - nhưng thay vì sử dụng một int cho mã này, tôi muốn sử dụng một enum thực tế, ví dụ như vậy 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 
} 

Hoặc cách khác (và trong một thời trang hướng đối tượng trở lên) sử dụng "enum thông minh" mẫu):

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

sau đó, bạn có thể gọi:

LogEvent.BuildingCommandObject.Log("stuff"); 

Với một chút công việc, có thể có thể hiển thị điều này một cách an toàn với các sự kiện nhật ký khác nhau có giao diện khác nhau để làm cho nó an toàn (tại thời gian biên dịch) về số lượng tham số.Trong thực tế, tôi chắc chắn bạn có thể làm điều đó bằng cách sử dụng giao diện và một lớp lồng nhau tư nhân, nhưng đó là 4 giờ sáng và tôi quá mệt mỏi để viết nó ra atm :)

0

Tôi biết đây là một câu hỏi cũ, nhưng có lẽ bạn đã tìm kiếm một cách để làm một cái gì đó như thế này, nơi bạn sử dụng Event ID tùy chỉnh cho các mục đích khác nhau, và gọi cho họ ở những nơi thích hợp của họ trong mã của bạn:

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

và sau đó bạn muốn gọi lớp này như thế này, khi bạn đã ném ngoại lệ của mình:

ErrorLog.ErrorRoutine(ErrorLog.NOTIFY_ALPHA); 

Theo như thực tiễn tốt nhất, tôi sẽ uld nói rằng tốt là có tất cả các lỗi xử lý trong lớp riêng của nó nếu nó sẽ được tùy chỉnh (hoặc nhiều hơn như vậy, chẳng hạn như khi buộc trong cảnh báo và thông tin EventLogEntryTypes hoặc thông tin bổ sung hơn các tin nhắn đóng hộp cung cấp) hơn này. Có ID cá nhân, bạn có thể tra cứu thông điệp của họ như thế này sẽ làm cho cuộc sống của bạn dễ dàng hơn khi cố gắng sắp xếp thông điệp để gọi, khi nào và ở đâu.

Các vấn đề liên quan