2010-10-14 45 views
5

Ứng dụng My (local, windows/mono) ghi lại các sự kiện quan trọng vào một tệp văn bản. Trong trường hợp xảy ra sự cố đột ngột/lỗi/lối ra cưỡng bức, không có dữ liệu nào được giữ nguyên (không thể thực hiện được). Do đó, tôi hiện đang sử dụng phương pháp chắp thêm tập tin văn bản đơn giản:Cách tiếp cận tốt nhất để đăng nhập là gì?

Public Shared Sub LogAppEvent(ByVal EventData As String) 
    Dim Config As ConfigHandler = ConfigHandler.GetSingleton() 
    Dim AppLog As New IO.StreamWriter(Config.GetUserFilesRootDir() & ConfigOptions.AppLogName, True) 
    AppLog.WriteLine(String.Format("[{0}] {1}", Date.Now.ToString(), EventData)) 
    AppLog.Close() 
End Sub 

Đây là các sự kiện phụ tối ưu nhưng rất hiếm. Bạn có đề xuất và chuyển sang lớp đăng nhập System.Diagnostics không?

Hoặc có thể bạn sẽ đề xuất giải pháp khác?

Trả lời

14

Nếu phương pháp tiếp cận siêu cơ bản như thế này đủ chức năng cho nhu cầu của bạn, bạn có thể gắn bó với nó. Tuy nhiên, bạn có thể tự hỏi mình một vài câu hỏi để đảm bảo:

  • Có thể cho các sự kiện được ghi đồng thời bởi nhiều chuỗi không? Hàm này không phải là luồng an toàn

  • Thông báo lỗi có cần thiết không?

  • Có rủi ro về tệp nhật ký phát triển mà không có giới hạn không cắt tỉa tự động không?

  • Bạn có được hưởng lợi từ việc ghi nhật ký rộng hơn để bạn có thêm thông tin về các sự kiện dẫn đến lỗi không?

  • Bạn có được hưởng lợi từ chi tiết hơn về các lỗi (stack trace, chi tiết ngoại lệ, vv)

  • Liệu chạy chương trình của bạn trên nhiều máy tính? Nếu có, nhật ký sẽ như thế nào với bạn?

  • Có bất kỳ nhu cầu/giá trị nào trong các công cụ để giúp phân tích tệp nhật ký (đơn lẻ hoặc tìm mẫu như lỗi phổ biến trên nhiều tệp nhật ký) không?

Nếu bạn quyết định rằng bạn có yêu cầu khác, có một số khuôn khổ khai thác gỗ miễn phí như NLog or log4net có thể giúp ghi lại các bản ghi chi tiết hơn, và có một số sản phẩm thương mại như GIBRALTARSmartInspect sẵn có thể giúp với quản lý và phân tích nhật ký.

+1

+1 cho điểm an toàn của luồng, mặc dù chỉ có chủ đề chính đẩy các sự kiện nhật ký. Cảm ơn câu trả lời toàn diện của bạn. –

2

Nloglog4Net là các lựa chọn phổ biến để đăng nhập các dự án .net.

+0

Cả hai đều là những đề xuất tuyệt vời. Tôi yêu cấu hình của họ. –

+0

quy tắc log4Net !!! – user279521

1

Có, bạn có thể xem xét System.Diagnostics. Miễn là bạn không viết một số lượng lớn các sự kiện, lợi thế cho Nhật ký Sự kiện Windows là quản trị viên có một nơi để tìm kiếm tất cả các sự kiện từ tất cả các ứng dụng.

Dưới đây là một số mã VB.NET có thể giúp bạn, bạn nên quyết định đi tuyến đường này:

Imports System.Diagnostics 

Public Function WriteToEventLog(ByVal Entry As String, _ 
    Optional ByVal AppName As String = "VB.NET Application", _ 
    Optional ByVal EventType As _ 
    EventLogEntryType = EventLogEntryType.Information, _ 
    Optional ByVal LogName As String = "Application") As Boolean 

'************************************************************* 
'PURPOSE: Write Entry to Event Log using VB.NET 
'PARAMETERS: Entry - Value to Write 
'   AppName - Name of Client Application. Needed 
'    because before writing to event log, you must 
'    have a named EventLog source. 
'   EventType - Entry Type, from EventLogEntryType 
'    Structure e.g., EventLogEntryType.Warning, 
'    EventLogEntryType.Error 
'   LogName: Name of Log (System, Application; 
'    Security is read-only) If you 
'    specify a non-existent log, the log will be 
'    created 

'RETURNS: True if successful, false if not 

'EXAMPLES: 
'1. Simple Example, Accepting All Defaults 
' WriteToEventLog "Hello Event Log" 

'2. Specify EventSource, EventType, and LogName 
' WriteToEventLog("Danger, Danger, Danger", "MyVbApp", _ 
'      EventLogEntryType.Warning, "System") 
' 
'NOTE:  EventSources are tightly tied to their log. 
'   So don't use the same source name for different 
'   logs, and vice versa 
     '****************************************************** 

     Dim objEventLog As New EventLog() 

     Try 
      'Register the App as an Event Source 
      If Not objEventLog.SourceExists(AppName) Then 

       objEventLog.CreateEventSource(AppName, LogName) 
      End If 

      objEventLog.Source = AppName 

      'WriteEntry is overloaded; this is one 
      'of 10 ways to call it 
      objEventLog.WriteEntry(Entry, EventType) 
      Return True 
     Catch Ex As Exception 
      Return False 

     End Try 

    End Function 
+0

Cảm ơn sự trợ giúp chi tiết này. Tôi sẽ xem xét tính năng này trong ứng dụng của mình. –

+0

System.Diagnostics có thể ghi vào những nơi khác ngoài nhật ký sự kiện. –

13

Như đã đề cập trước đó, NLog và log4net đều khuôn khổ khai thác gỗ tốt. Như Jeff đã đề cập ở trên, System.Diagnostics cũng là một lựa chọn hợp lý (cho nhiều hơn là chỉ đăng nhập vào EventLog). Đang cố gắng thêm một số giá trị vào câu trả lời của tôi, thay vì chỉ vẹt những gì đã được nói, bạn có thể tăng cường ghi nhật ký System.Diagnostics của mình bằng cách sử dụng TraceSources và bằng cách sử dụng miễn phí Ukadc.Diagnostics library from codeplex.

Với TraceSources bạn có thể tạo "trình ghi nhật ký có tên", tương tự như cách bạn có thể thực hiện trong NLog và log4net. Các TraceSources này có thể được cấu hình để đăng nhập ở các mức nhất định (thay đổi theo TraceSource) và chúng có thể được gửi đến các đích khác nhau (TraceListeners). Tất cả TraceSources có thể đăng nhập vào cùng một người nghe hoặc một số có thể đăng nhập vào một số người nghe trong khi những người khác đăng nhập vào người nghe khác. Bất kỳ TraceSource nào cũng có thể được gửi tới nhiều TraceListeners. Đây là cách bạn sẽ sử dụng TraceSources trong mã (giả sử rằng TraceSource "abc" đã được cấu hình trong tệp app.config để ghi nhật ký "Thông tin" và các thông điệp ưu tiên cao hơn và đã được cấu hình để đăng nhập vào tệp "nhật ký." txt ").

public class MyClass 
{ 
    static TraceSource ts = new TraceSource("abc"); //Common idiom for NLog and log4net, not sure if as common for TraceSource 

    public void Func1(int x) 
    { 
    ts.Information("Entering Func1"); 
    ts.Verbose("x = {0}", x); //Won't log if "abc" is configured to log Info and HIGHER messgaes 
    ts.Information("Exiting Func1"); 
    } 
} 

Một lợi ích lớn của Ukadc.Diagnostics, hơn TraceSources "đồng bằng", là bạn có thể cấu hình định dạng đầu ra NLog/log4net phong cách để bạn có thể có quyền kiểm soát nhiều hơn nữa so với những gì các lĩnh vực hiển thị trong sản lượng khai thác gỗ của bạn và những gì định dạng.

Ba điều đó là khá hữu ích từ NLog/log4net mà không có sẵn trong System.Diagnostics là:

  1. Khả năng tự động đăng nhập thông tin trang web gọi (phương pháp/chức năng)

  2. đăng nhập bổ sung context (GDC - thuộc tính ghi log toàn cục, MDC - các thuộc tính ghi luồng trong NLl/log4net). System.Diagnostics không có Trace.CorrelationManager.LogicalOperationStack, tương tự như NDC.

  3. Bộ ghi nhật ký Hierarichal.

Trình ghi nhật ký Hierarichical có nghĩa là bạn có thể định cấu hình trình ghi "tổ tiên" và bất kỳ nhật ký "hậu duệ" nào sẽ kế thừa các cài đặt đó. Ví dụ: giả sử rằng bạn có một lớp có tên loại đầy đủ (không gian tên) đủ điều kiện là Namespace1.Namespace2.Class. Với NLog/log4net bạn có thể cấu hình thông tin đăng nhập (level, destination) cho "Namespace1" và nếu bạn yêu cầu logger dựa trên tên đầy đủ của bất kỳ kiểu nào trong Namespace1, nó sẽ kế thừa các thiết lập của Namespace1. Bạn có thể đạt được một cái gì đó tương tự như thế này bằng cách sử dụng TraceSources bằng cách xem cách Castle implemented their TraceSource-based logging trừu tượng. Đặc biệt, hãy xem hàm Khởi tạo. Nó khá dễ dàng để làm việc (trong trình bao bọc mỏng của bạn xung quanh TraceSource) và, như một lợi ích phụ, làm cho cấu hình của TraceSources của bạn dễ dàng hơn một chút vì bạn không phải cấu hình từng TraceSource riêng lẻ. Lưu ý rằng bạn có thể dễ dàng thêm khả năng có cấu hình "root" bằng cách định cấu hình TraceSource được gọi là "" và thêm một số mã trong lược đồ Castle để mặc định thành cấu hình "" nếu không tìm thấy tổ tiên thực sự. Ví dụ, bạn có thể cấu hình "*" để đăng nhập, nói Verbose, và sau đó cấu hình cụ thể một số TraceSources nhất định (hoặc theo lớp hoặc theo không gian tên) để tắt hoặc ở một mức độ khác. Nếu không có logger hierarichal, để làm điều tương tự với TraceSources sẽ yêu cầu bạn phải cấu hình mỗi TraceSource duy nhất để đăng nhập vào "Verbose" mà bạn muốn tiết lộ.

Trong khi tôi nói nhiều về logger cho các lớp và không gian tên, NLog, log4net và TraceSources cũng cho phép bạn định nghĩa tên logger của bạn thành chuỗi tùy ý. Như vậy, bạn lạnh xác định một hệ thống phân cấp logger theo khu vực chức năng chứ không phải bởi không gian tên/lớp:

Database 
Database.Connect 
Database.Query 
Database.Update 
Database.SQL 
Amazon 
Amazon.Books 
Amazon.Books.Fiction 
Amazon.Books.Nonfiction 
Amazon.Electronics 
Amazon.Electronics.Video 
Amazon.Electronics.Music 
Amazon.Electronics.Computer 

Vì vậy, bạn có thể bật "Amazon" khai thác gỗ và tất cả các bản ghi Amazon thứ (mà không cần phải cấu hình một cách rõ ràng và mỗi "con" TraceSource) và cơ sở dữ liệu công cụ sẽ không. Hoặc, bạn có thể biến Amazon trên và Amazon.Electronics tắt và chỉ Amazon.Books (và trẻ em) sẽ đăng nhập.

Cuối cùng, nếu bạn thực hiện với NLog hoặc log4net, điều đáng nói là NLog vừa mới phát hành một bản phát hành mới, NLog 2.0, (trong bản beta).

+0

Cảm ơn câu trả lời kỹ lưỡng của bạn =) Tuy nhiên, kích thước ứng dụng của tôi gần như sẽ được nhân với 5 nếu tôi bắt đầu sử dụng NLog :) Đó là một ứng dụng rất nhẹ, vì vậy nó không thực sự cần * * ghi nhật ký nâng cao. Tuy nhiên, cảm ơn câu trả lời tuyệt vời của bạn, mà tôi sẽ sử dụng cho một dự án khác. –

+1

Câu trả lời hay. Rất kỹ lưỡng, và có một ví dụ mã. Bravo! Thông tin này chỉ là những gì tôi đang tìm kiếm. –

0

Tôi sử dụng biến công cộng và hẹn giờ thêm dòng mới vào tệp txt.

Ví dụ:

Public Class Form1 

    Public WriteToLog = "" 

    Dim LogFilePath As String = My.Application.Info.DirectoryPath & "\applog.txt" 

.... 

    Public Function Log_to_txt(ByVal text As String) 

     Dim CurDate As String 
     CurDate = Format(Now, "General Date") 

     WriteToLog = WriteToLog & "[" & CurDate & "] " & text & vbCrLf 

     Return True 

    End Function 

... 

Log_to_txt("Application started...") 

... 

    Private Sub WriteToLogTimer_Tick(sender As Object, e As EventArgs) Handles WriteToLogTimer.Tick 

     Dim CatchLog As String = WriteToLog 

     WriteToLog = "" 

     Try 

      My.Computer.FileSystem.WriteAllText(LogFilePath, CatchLog, True) 

     Catch ex As IOException 

     End Try 

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