2010-11-16 25 views
8

Chỉ gần đây đã vào thử nghiệm với NLog, và nó xảy ra với tôi rằng tôi muốn để có thể thêm thông tin tiêu đề đầu trang một log file như:nLog - Tạo header Mục cho một tập tin log

thực thi tên phiên bản tệp ngày phát hành người dùng Windows ID vv ...

Sau khi một số tìm kiếm tôi đã không thể tìm thấy bất cứ điều gì trong các diễn đàn trực tuyến tài liệu hướng dẫn hoặc mã hiện có mà chỉ loại chức năng. Điều này có thể không? Trước đây tôi đã bao gồm loại thông tin này trong các tệp nhật ký và đã thấy nó hữu ích trên nhiều occs trong quá khứ, khi tìm nguồn cung cấp thông tin về các vấn đề sản xuất tại các trang của khách hàng. Phải thừa nhận rằng, chức năng này được xây dựng tùy chỉnh cho các giải pháp và không dựa trên bất kỳ khung công tác ghi nhật ký .NET hiện hành nào.

Trả lời

4

Tôi không biết cách làm điều đó rất dễ dàng. Có nói rằng, tất cả các ví dụ bạn cung cấp có sẵn (hoặc khá dễ dàng có sẵn với một số mã tùy chỉnh) để được thêm vào mỗi thông điệp tường trình. Tức là, mỗi thông điệp đã đăng nhập có thể được gắn thẻ với tên thực thi, phiên bản tệp, ngày phát hành, id người dùng cửa sổ, v.v. qua Bố cục và Trình sắp xếp Layout.

Điều này rõ ràng không giống như việc tạo tiêu đề ở đầu tệp nhật ký, vì vậy nó có thể không hữu ích cho bạn.

Mặt khác, bạn có thể sử dụng kỹ thuật được đề cập trong câu trả lời của Pat in this post để liên kết nhiều trình kết xuất bố cục với cùng một mục tiêu. Bạn có thể định nghĩa bố cục chứa các trường bạn muốn trong tiêu đề và đặt bộ lọc trong Trình lọc để chỉ áp dụng bố cục cho thông báo đầu tiên của phiên (hoặc bạn có thể sử dụng một số kỹ thuật khác mà nó được thêm vào tệp đầu ra chỉ một lần).

Sử dụng tệp NLog.config của mình, đây là một cách mà bạn có thể đạt được những gì bạn muốn. Lưu ý rằng tôi đã không cố gắng này, vì vậy tôi không biết nếu tập tin cấu hình này là hợp lệ hoặc, nếu có, nếu nó sẽ tạo ra các kết quả mà bạn muốn.

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.mono2.xsd" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     autoReload="true" 
     internalLogLevel="Warn" 
     internalLogFile="nlog log.log" 
     > 
    <variable name="HeaderLayout" value="${processname} ${gdc:item=version} ${gdc:item=releasedate} ${windows-identity}" /> 
    <variable name="NormalLayout" value="${longdate} ${logger} ${level} ${message} /> 

    <targets async="true"> 
     <target name="file" xsi:type="File" fileName="log.log" 
       layout="${NormalLayout}"> 
     </target> 

     <target name="fileHeader" xsi:type="File" fileName="log.log" 
       layout="${HeaderLayout}"> 
     </target>  
    </targets> 

    <rules> 
     <logger name="HeaderLogger" minlevel="Trace" writeTo="fileHeader" final="true" />   
     <logger name="*" minlevel="Trace" writeTo="file" /> 
    </rules> 

</nlog> 

Trong code của bạn, logic khởi động của bạn có thể trông như thế này:

public void Main() 
{ 
    AddHeaderToLogFile(); 
} 

public void AddHeaderToLogFile() 
{ 
    Logger headerlogger = LogManager.GetLogger("HeaderLogger"); 

    //Use GlobalDiagnosticContext in 2.0, GDC in pre-2.0 
    GlobalDiagnosticContext["releasedate"] = GetReleaseDate();  
    GlobalDiagnosticContext["version"] = GetFileVersion();  
    GlobalDiagnosticContext["someotherproperty"] = GetSomeOtherProperty(); 

    headerlogger.Info("message doesn't matter since it is not specified in the layout"); 

    //Log file should now have the header as defined by the HeaderLayout 

    //You could remove the global properties now if you are not going to log them in any 
    //more messages. 
} 

Ý tưởng ở đây là bạn sẽ đặt các phiên bản tập tin, ngày phát hành, vv trong GDC khi chương trình bắt đầu. Đăng nhập một thông điệp bằng trình ghi "HeaderLogger". Thông báo này sẽ được ghi vào tệp nhật ký bằng cách sử dụng "HeaderLayout" vì "HeaderLogger" được liên kết với mục tiêu "fileHeader" được liên kết với "HeaderLayout". Các trường được xác định trong bố cục tiêu đề được ghi vào tệp nhật ký. Thông điệp tường trình tiếp theo, vì chúng sẽ không sử dụng "HeaderLogger", sẽ sử dụng bố cục "root" (*). Họ sẽ đi đến cùng một tệp vì cả mục tiêu "tệp" và "tệpHeader" cuối cùng đều trỏ đến cùng một tên tệp.

Trước khi tôi bắt đầu nhập phản hồi này, tôi không chắc chắn bạn có thể dễ dàng hoàn thành việc thêm tiêu đề vào tệp nhật ký của mình như thế nào. Có đánh máy này, tôi nghĩ rằng nó thực sự có thể khá dễ dàng!

Chúc may mắn!

[EDIT] Một cái gì đó như thế này có thể hoạt động để thay đổi bố cục dựa trên cấp độ. Trong phần đầu tiên, tôi đã xác định một số biến, mỗi biến xác định bố cục. Trong phần tiếp theo, tôi đã xác định một số mục tiêu mà mỗi mục tiêu sử dụng cùng một tệp, nhưng được lọc để chỉ cho phép các thông điệp của một cấp cụ thể được viết. Trong phần cuối cùng, tôi xác định một quy tắc duy nhất sẽ gửi tất cả các thông điệp (do đó có tên "logger") cho tất cả các mục tiêu.Vì mỗi mục tiêu được lọc theo cấp độ, mục tiêu "theo dõi" sẽ chỉ ghi các thông điệp "dấu vết", v.v. Vì vậy, các thông báo "theo dõi" sẽ được viết bằng cách sử dụng bố cục "theo dõi", thông báo "gỡ lỗi" sẽ được ghi bằng cách sử dụng "gỡ lỗi" bố trí, vv Vì tất cả các mục tiêu cuối cùng ghi vào cùng một tệp, tất cả các thư sẽ kết thúc trong cùng một tệp. Tôi đã không thử điều này, nhưng tôi nghĩ rằng nó có thể sẽ làm việc.

<variable name="TraceLayout" value="THIS IS A TRACE: ${longdate} ${level:upperCase=true} ${message}" /> 
<variable name="DebugLayout" value="THIS IS A DEBUG: ${longdate} ${level:upperCase=true} ${message}" /> 
<variable name="InfoLayout" value="THIS IS AN INFO: ${longdate} ${level:upperCase=true} ${message}" /> 


<targets async="true"> 
    <target name="fileAsTrace" xsi:type="FilteringWrapper" condition="level==LogLevel.Trace"> 
     <target xsi:type="File" fileName="log.log" layout="${TraceLayout}" /> 
    </target> 
    <target name="fileAsDebug" xsi:type="FilteringWrapper" condition="level==LogLevel.Debug"> 
     <target xsi:type="File" fileName="log.log" layout="${DebugLayout}" /> 
    </target> 
    <target name="fileAsInfo" xsi:type="FilteringWrapper" condition="level==LogLevel.Info"> 
     <target xsi:type="File" fileName="log.log" layout="${InfoLayout}" /> 
    </target> 
</targets> 

<rules> 
    <logger name="*" minlevel="Trace" writeTo="fileAsTrace, fileAsDebug, fileAsInfo" /> 
</rules> 

(Lưu ý rằng tôi chỉ bao gồm 3 cấp ở đây).

Sau khi hiển thị cách (nếu nó hoạt động, dù sao) để áp dụng bố cục khác nhau dựa trên cấp độ, điều này có vẻ giống như trường hợp sử dụng bất thường. Tôi không nói rằng đó là một ý tưởng tốt hay một ý tưởng tồi, nhưng tôi không thể nói rằng tôi đã thực sự thấy điều này được thực hiện rất nhiều. Tùy thuộc vào chính xác như thế nào bạn muốn đầu ra cuối cùng của bạn để xem xét, những gì tôi đã cho thấy bạn có thể hoặc có thể không phải là cách tốt nhất để đạt được nó. Có lẽ bạn có thể đăng một số ví dụ về cách bạn muốn đầu ra của bạn để xem xét.

Bạn cũng có thể xem xét chấp nhận câu trả lời gốc và sau đó tạo câu hỏi mới về cách bố trí đầu ra cho mỗi cấp để chúng tôi có thể tập trung thảo luận trong câu hỏi đó về vấn đề cấp/bố cục. Đó là vào bạn nếu điều đó có vẻ hữu ích hay không.

này hoạt động:

<variable name="TraceLayout" value="This is a TRACE - ${longdate} | ${logger} | ${level} | ${message}"/> 
    <variable name="DebugLayout" value="This is a DEBUG - ${longdate} | ${logger} | ${level} | ${message}"/> 
    <variable name="InfoLayout" value="This is an INFO - ${longdate} | ${logger} | ${level} | ${message}"/> 
    <variable name="WarnLayout" value="This is a WARN - ${longdate} | ${logger} | ${level} | ${message}"/> 
    <variable name="ErrorLayout" value="This is an ERROR - ${longdate} | ${logger} | ${level} | ${message}"/> 
    <variable name="FatalLayout" value="This is a FATAL - ${longdate} | ${logger} | ${level} | ${message}"/> 
    <targets> 
    <target name="fileAsTrace" xsi:type="FilteringWrapper" condition="level==LogLevel.Trace"> 
     <target xsi:type="File" fileName="xxx.log" layout="${TraceLayout}" /> 
    </target> 
    <target name="fileAsDebug" xsi:type="FilteringWrapper" condition="level==LogLevel.Debug"> 
     <target xsi:type="File" fileName="xxx.log" layout="${DebugLayout}" /> 
    </target> 
    <target name="fileAsInfo" xsi:type="FilteringWrapper" condition="level==LogLevel.Info"> 
     <target xsi:type="File" fileName="xxx.log" layout="${InfoLayout}" /> 
    </target> 
    <target name="fileAsWarn" xsi:type="FilteringWrapper" condition="level==LogLevel.Warn"> 
     <target xsi:type="File" fileName="xxx.log" layout="${WarnLayout}" /> 
    </target> 
    <target name="fileAsError" xsi:type="FilteringWrapper" condition="level==LogLevel.Error"> 
     <target xsi:type="File" fileName="xxx.log" layout="${ErrorLayout}" /> 
    </target> 
    <target name="fileAsFatal" xsi:type="FilteringWrapper" condition="level==LogLevel.Fatal"> 
     <target xsi:type="File" fileName="xxx.log" layout="${FatalLayout}" /> 
    </target> 
    </targets> 


    <rules> 
     <logger name="*" minlevel="Trace" writeTo="fileAsTrace,fileAsDebug,fileAsInfo,fileAsWarn,fileAsError,fileAsFatal" /> 
     <logger name="*" minlevel="Info" writeTo="dbg" /> 
    </rules> 

Tôi đã thiết lập một Giao diện cho mỗi cấp độ khai thác gỗ, thêm một chuỗi chữ vào đầu mô tả mức độ của thông điệp (đây là để chứng minh rằng một định dạng khác nhau được sử dụng cho mỗi cấp độ). Mỗi Layout được kết hợp với một FilteringWrapper để lọc dựa trên mức độ của thông báo và hướng bất kỳ thông điệp nào vượt qua bộ lọc được ghi vào tệp đầu ra. Mỗi FilteringWrapper được gói cùng một tệp đầu ra, vì vậy tất cả các thông điệp tường trình sẽ được ghi vào cùng một tệp.

Đây là một phần của mã mà tôi sử dụng để thử nghiệm:

logger.Trace("Trace msg"); 
    logger.Debug("Debug msg"); 
    logger.Info("Info msg"); 
    logger.Warn("Warn msg"); 
    logger.Error("Error msg"); 
    logger.Fatal("Fatal msg"); 

Và đây là những gì đầu ra trông giống như:

This is a TRACE - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Trace | Trace msg 
This is a DEBUG - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Debug | Debug msg 
This is an INFO - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Info | Info msg 
This is a WARN - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Warn | Warn msg 
This is an ERROR - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Error | Error msg 
This is a FATAL - 2010-11-22 13:20:00.4131 | NLogTest.Form1 | Fatal | Fatal msg 

Rõ ràng vấn đề về thông tin cấu hình trước đây của tôi là không gian giữa các giá trị "writeTo". Tôi đoán NLog rất nhạy cảm với điều này. Tôi đã có một cái gì đó như "writeTo=blah1, blah2, blah3". Khi tôi thay đổi điều đó thành "writeTo=blah1,blah2,blah3" lỗi đã biến mất. Chúc may mắn!

+0

Nhiều cảm ơn salaryoghe, điều đó đã làm việc điều trị. Về cơ bản tôi cần phải có bố trí khác nhau cho các mức độ đăng nhập khác nhau, làm thế nào để bạn thực hiện bố trí có điều kiện ở cấp độ được lựa chọn? –

+0

Bạn muốn bố cục khác nhau trông như thế nào? Bạn có muốn có các trường khác nhau trong bố cục cho các mức ghi khác nhau không? Ở mức nào, bạn có thể sử dụng kỹ thuật mà Pat hiển thị trong liên kết ở trên. Ông định nghĩa một mục tiêu tập tin cho thông điệp khai thác "bình thường" của mình và xác định mục tiêu "trình bao bọc bộ lọc" để sử dụng bố cục khác cho các thư có chứa ngoại lệ. Tôi sẽ cố gắng thêm một ví dụ về thứ gì đó có thể giúp bạn. – wageoghe

+0

Sử dụng kỹ thuật được đề xuất, cho các mục sau: Tôi nhận được lỗi sau trong tệp cấu hình: 'Thuộc tính' writeTo 'không hợp lệ ....' cho –

9

Chỉ tình cờ gặp phải vấn đề này trong khi xem xét sao chép đầu trang/chân trang trong nhật ký một trong những đồng nghiệp của tôi được tạo bằng log4net. Tôi tìm thấy điều này từ một số dự án mã nguồn mở và điều chỉnh nó như là một ví dụ nội bộ. Tôi nghĩ rằng nó nên được đơn giản để sửa đổi cho nhu cầu của bạn.

<target name="logfile2" xsi:type="File" fileName="Logs\NLogDemo2.txt"> 
    <layout xsi:type="LayoutWithHeaderAndFooter"> 
    <header xsi:type="SimpleLayout" text="----------NLog Demo Starting---------&#xD;&#xA;"/> 
    <layout xsi:type="SimpleLayout" text="${longdate}|${level:uppercase=true}|${logger}|${message}" /> 
    <footer xsi:type="SimpleLayout" text="----------NLog Demo Ending-----------&#xD;&#xA;"/> 
    </layout> 
</target> 

Nó mang lại cho tôi ra trông như thế này:

----------NLog Demo Starting--------- 

2013-03-01 16:40:19.5404|INFO|Project.Form1|Sample informational message 
2013-03-01 16:40:19.5714|WARN|Project.Form1|Sample warning message 
2013-03-01 16:40:19.5714|ERROR|Project.Form1|Sample error message 
2013-03-01 16:40:19.5714|FATAL|Project.Form1|Sample fatal error message 
----------NLog Demo Ending----------- 

Tôi không có ý tưởng tại sao điều này dường như không có giấy tờ. Các tài liệu tham khảo duy nhất tôi có thể tìm được ở đây: https://github.com/nlog/NLog/wiki/LayoutWithHeaderAndFooter

-Jody

+0

liên kết bị hỏng? https://github.com/nlog/NLog/wiki/LayoutWithHeaderAndFooter – drzaus

+0

Đã sửa lỗi liên kết. Cảm ơn. – JKoplo

1

Bạn có thể tạo một phần header/footer mỗi "dụ" (ví dụ:Lần đầu tiên ứng dụng và lần cuối cùng các ứng dụng ghi vào bất kỳ tập tin nhất định) sử dụng Layouts như indicated by previous answer:

Xem chi tiết:

+0

Có lẽ chúng ta có thể hợp nhất câu trả lời của bạn với câu trả lời trước, vì bạn chỉ cần thêm các liên kết mới. Cũng có thể trỏ đến https://github.com/NLog/NLog/issues/2119 nơi ai đó yêu cầu có đầu trang & chân trang mỗi khi ứng dụng bắt đầu và dừng. – user276648

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