2010-10-31 25 views
8

Tôi có một đối tượng TraceSource mà tôi sử dụng để đăng nhập khởi tạo của một ứng dụng VB.Net. Nó có một vài TraceListeners kèm theo:.Net: Làm thế nào để ngăn chặn tiêu đề TraceSource ("SourceName TraceEventType: Id:")?

  • ConsoleTraceListener
  • TextWriterTraceListener
  • EventLogTraceListener

Đối với hai đầu tiên tôi muốn đầu ra nhập là "thô" - có nghĩa là, mà không tiêu chuẩn tiêu đề:

SourceName TraceEventType: Id :

.210

tôi đã thực hiện một wrapper mà thực hiện điều này khi TraceEventType được thiết lập để Verbose:

If _buffer.EventType = TraceEventType.Verbose Then 
    For Each listener As TraceListener In _traceSource.Listeners 
     listener.Write(_buffer.Text) 
    Next 
Else 
    _traceSource.TraceEvent(_buffer.EventType, id, _buffer.Text) 
End If 

tôi có thể làm điều này cho tất cả các truy tìm, nhưng sau đó tất cả các mục trong EventLog sẽ được liệt kê với Level = Thông tin. Vì vậy, tôi muốn có thể chỉ định mức độ nghiêm trọng của thông điệp theo dõi, nhưng tôi không thể tìm thấy bất kỳ phương pháp nào trên TraceSource hoặc TraceListeners cho phép tôi thực hiện điều này. Theo như tôi có thể nói, TraceListener có các tùy chọn cho văn bản cho nó:

  • Write()
  • WriteLine()
  • TraceData()
  • TraceEvent()
  • TraceTransfer()

3 cuối cùng cho phép cung cấp TraceEventType (nhãn này ghi nhãn các mục nhập EventLog một cách chính xác, nhưng kết quả đầu ra cho bảng điều khiển và tệp nhật ký sau đó bao gồm các tiền tố và kết thúc như thế này (ví dụ):

Bootstrapper Warning: 0 : Failed to validate assembly

Có cách nào để ghi đè lên như thế nào ConsoleTraceListener và định dạng TextWriterTraceListener sản lượng của họ để không bao gồm tiêu đề này, trong khi cùng một lúc có thể gắn thẻ mục với một TraceEventType (cho EventLog)?

Đây là tốt nhất mà tôi đã đưa ra cho đến nay:

For Each listener As TraceListener In _traceSource.Listeners 
    If listener.GetType Is GetType(ConsoleTraceListener) OrElse listener.GetType Is GetType(TextWriterTraceListener) Then 
     listener.Write(_buffer.Text) 
    Else 
     listener.TraceEvent(Nothing, _traceSource.Name, _buffer.EventType, id, _buffer.Text) 
    End If 
Next 

Điều này dường như làm việc, nhưng trong tài liệu trên TraceListener.TraceEvent Method từ Microsoft, nó nói:

Important: This method is not intended to be called directly by application code but by members of the Debug, Trace, and TraceSource classes to write trace data to output.

.. Tôi không chắc đó có phải là điều tốt để làm không?

Edit:

Tôi chỉ nhận ra rằng nếu tôi làm điều gì đó giống như ví dụ cuối cùng của tôi ở đây, tôi không cần TraceSource ở tất cả, vì nó đang được bỏ qua anyway. Nhưng nó cũng có nghĩa là tôi phải thực hiện các cơ chế lọc và chuyển đổi của riêng mình (nhưng đó có thể là một mức giá OK để trả tiền để làm cho nó hoạt động theo cách tôi muốn).

Trả lời

0

Nhìn vào dự án Ukadc.Diagnostics trên codeplex. Nó là một addon để System.Diagnostics cung cấp cho bạn khả năng định dạng đầu ra log/trace của bạn tuy nhiên bạn muốn (tương tự như những gì bạn có thể làm với log4net và NLog). Bạn sử dụng nó thông qua cấu hình, vì vậy mã của bạn sẽ không phụ thuộc trực tiếp vào thư viện. Thư viện đi kèm với các đối tượng có thể định cấu hình để định dạng và TraceListeners tùy chỉnh cần thiết để tận dụng định dạng này. Thư viện cũng giúp bạn dễ dàng viết các thẻ "định dạng" và TraceListener của riêng bạn.

Ví dụ, bạn có thể cấu hình các Ukadc.Diagnostics ConsoleTraceListener sử dụng một cái gì đó tuyên bố định dạng như thế này:

{DateTime} {Source} {EventType} {Message} 

Mỗi thông điệp đăng nhập sẽ gây ra ngày/thời gian, tên nguồn, loại sự kiện, và thông điệp.

Hãy dùng thử, tôi nghĩ bạn sẽ thích nó. Tôi đã sử dụng nó một số bản thân mình (chủ yếu là cho prototyping, không cho một sản phẩm "thực sự" được nêu ra) và đã có thành công tốt đẹp. Lưu ý rằng đối với một số mã thông báo (như DateTime), bạn cũng có thể áp dụng các định dạng chuẩn phù hợp cho loại (ví dụ: đối với DateTime bạn có thể chỉ định định dạng mà ngày/thời gian sẽ được viết).

Trình nghe theo dõi tệp đi kèm với Ukadc.Diagnostics cũng cho phép tên tệp của nó được chỉ định bằng cách sử dụng hệ thống mã thông báo.

+0

Cảm ơn, tôi sẽ xem xét (mặc dù tôi không thích sử dụng phần bổ trợ bên ngoài vì một lý do nào đó). Và bây giờ tôi cũng đã thực hiện hệ thống truy tìm của riêng mình, nơi tôi có thể làm những việc tương tự. Lớp của tôi có chức năng tương tự như TraceSource, nhưng nó có hai bộ sưu tập người nghe.Một hàm hoạt động theo cách tiêu chuẩn, sử dụng TraceEvent() và phương thức kia sử dụng hàm Write() "thô". Mỗi tin nhắn được ghi lại được đẩy tới tất cả người nghe trong cả hai danh mục (tùy thuộc vào một số cờ nhất định, v.v.), vì vậy bạn có thể thêm người nghe yêu cầu gắn thẻ EventType vào một danh sách, và những người có định dạng đồng bộ/tùy chỉnh trong khác. Hoạt động tốt. – d7samurai

+0

Tôi nghĩ thư viện rất tuyệt, nên hãy tiếp tục và thử nó, bạn có thể thích nó. Một cách có thể giúp công việc của bạn là bạn có thể sử dụng cùng một tập các lớp TraceListener, nhưng thay đổi những gì thực sự được viết thông qua cấu hình. Vì vậy, bạn có thể có một định dạng "thô" kết hợp với một số người nghe (Console và TextWriter) và định dạng "sự kiện" được liên kết với những người khác (EventLog). Nếu bạn quyết định vào tuần tới hoặc tháng tiếp theo mà bạn muốn thêm hoặc xóa một số thông tin từ một trong hai định dạng, thì bạn chỉ cần thay đổi định dạng trong app.config. Không có thay đổi mã. Chúc may mắn! – wageoghe

+0

d7samurai, bạn có quen thuộc với NotInventedHere-Antipattern không? –

2

Một dự án tương tự khác có trình lắng nghe có thể chỉnh sửa mà bạn có thể sử dụng là Essential Diagnostics, vốn thực sự được lấy cảm hứng từ Ukadc.Diagnostics.

Bạn đã chỉ ra, tuy nhiên, bạn không muốn phụ thuộc bên ngoài, nhưng bạn vẫn có nhiều lựa chọn mà không cần viết các bộ phận của khung:

(A) Thay vì viết lại TraceSource, phần mở rộng thiết kế trong .NET Framework là viết TraceListener của riêng bạn.

Nếu bạn viết trình theo dõi của riêng mình "ConsoleWithoutPrefixListener" và "FileWithoutPrefixListener", thì bạn có thể ghi đè các phương thức TraceEvent() để chuyển tiếp thư tới TraceWrite() (và thả các tiền tố). Trong thực tế, không có ConsoleTraceListener hoặc TextWriterTraceListener được niêm phong, vì vậy tôi nghĩ rằng bạn có thể kế thừa từ chúng và làm việc này với một dòng ghi đè lên phương thức TraceEvent() (cộng với hàm khởi tạo).

(B) Một giải pháp thay thế khác là để EventLogTraceListener được cấu hình dựa vào nguồn nhưng định cấu hình hai trình nghe khác dưới (chứ không phải nguồn theo dõi).

Hạn chế của việc này là trong mã của bạn, bạn cần phải đăng nhập hai lần mỗi lần, ví dụ:

_traceSource.TraceEvent (_buffer.EventType, id, _buffer.Text) Trace.TraceWrite (_buffer.Text)

Nếu bạn muốn viết một số tin nhắn có tiền tố và một số không có thì bạn sẽ cần hai nguồn theo dõi: một nguồn được định cấu hình với cả ba trình lắng nghe và một chỉ với trình nghe sự kiện.

Sau đó, trong trình bao bọc của bạn hoặc ghi vào nguồn A (tất cả ba) hoặc nguồn B + Dấu vết phương pháp tĩnh.

(C) Cá nhân, hướng dẫn của tôi sẽ không sử dụng truy tìm để ghi vào nhật ký sự kiện - nếu các vấn đề đủ quan trọng để ghi vào nhật ký sự kiện bạn thường không muốn người dùng có thể bật chúng tắt thông qua cấu hình.

Trong trường hợp này trình bao bọc của bạn ghi trực tiếp vào nhật ký sự kiện (EventLog.WriteEntry hoặc bất kỳ thứ gì) và sau đó mã của bạn ghi vào nguồn theo dõi và/hoặc theo dõi phương pháp tĩnh cho tệp và bảng điều khiển.

Lưu ý rằng để ghi vào Nhật ký sự kiện hoạt động chính xác, bạn cần phải đưa vào quyền tài khoản. Để tạo nguồn nhật ký sự kiện, bạn cần phải là chạy với tư cách là quản trị viên. Là nhà phát triển, bạn có thể thường có quyền quản trị viên, vì vậy bạn cần phải kiểm tra chính xác điều này trong ngữ cảnh của người không. Cũng cần lưu ý rằng đây chỉ là tác phẩm đầu tiên cần quyền quản trị và điều này được thực hiện tự động khi bạn viết thư đầu tiên, vì vậy nếu bạn đã thực hiện với tư cách là quản trị viên nhà phát triển, bạn cần tìm một máy sạch để kiểm tra trên. Bởi vì điều này, thông thường bạn cần phải có một EventLogInstaller như là một phần của mã của bạn, được điều hành bởi InstallUtil (hoặc tương đương với MSI hoặc bất cứ điều gì) tạo nguồn nhật ký sự kiện trong khi cài đặt (vì cài đặt được thực hiện bởi một người quản lý). Sau đó, khi chương trình chạy nguồn tồn tại.

Vì vậy, điều này có liên quan gì đến việc ghi vào dấu vết - tốt, nếu điều duy nhất bạn làm là định cấu hình EventLogTraceListener trong cấu hình của bạn thì đối với người dùng bình thường, nó sẽ không hoạt động; nó sẽ thử và ghi các sự kiện vào nguồn (trong thuộc tính initializeData), sau đó sẽ cố gắng tạo nguồn và nếu không chạy như quản trị viên sẽ thất bại.

Nếu bạn thêm trình cài đặt cho nguồn sự kiện thì bạn vẫn gặp sự cố nếu ai đó thay đổi tệp cấu hình.

Vì lý do này, tôi khuyên bạn nên cả EventLogInstaller và EventLog được tạo trực tiếp trong mã, để đảm bảo tên khớp, và không đi qua cơ sở hạ tầng truy tìm.

1

Đây là giải pháp đầy đủ của tôi cho điều này, lấy cảm hứng từ câu trả lời của @Sly.

Để chặn thông tin tiêu đề khi sử dụng phương pháp TraceEvent(), bạn có thể kế thừa từ ConsoleTraceListener hoặc TextWriterTraceListener (hoặc bất kỳ hương vị người nghe nào được yêu cầu) như vậy;

namespace Custom.Lib { 
    public class ConsoleTraceListener : System.Diagnostics.ConsoleTraceListener { 

     // overridding this method here will suppress header information 
     // your TraceEvent() messages will still reach the listener 
     public override void Write(string message) { 
      //base.Write(message); 
     } 

    } 
} 

N.B. Khi cố gắng ghi đè phương thứcTraceEventTôi nhận thấy rằng thông tin tiêu đề chưa được thêm vào chuỗi tin nhắn tại thời điểm này. Thay vào đó, tôi đã chọn tắt tiếng cuộc gọi tớiWrite(string)mà dường như không có bất kỳ hiệu ứng knock-on nào khác nhưng nó cảm thấy một chút 'hackish', nếu có ai đó có 'cách tiếp cận rõ ràng hơn', tôi sẽ mở nó.

Cấu hình để sử dụng trình xử lý khách hàng này sau đó sẽ trông giống như thế này;

<system.diagnostics> 
    <sources> 
     <source name="AppTrace" switchName="sourceSwitch" switchType="System.Diagnostics.SourceSwitch"> 
     <listeners> 
      <add name="consoleListener"/> 
     </listeners> 
     </source> 
    </sources> 
    <switches> 
     <add name="sourceSwitch" value="Information"/> 
    </switches> 
    <sharedListeners> 
     <add name="consoleListener" type="Custom.Lib.ConsoleTraceListener, Custom.Lib" initializeData=""/> 
    </sharedListeners> 
    </system.diagnostics> 
Các vấn đề liên quan