2012-03-14 20 views
9

Tôi đã sử dụng log4net để đăng nhập thông điệp nhật ký của trang web ASP.NET của chúng tôi và gần đây tôi muốn thêm thông tin về trang/trình xử lý nơi xảy ra lỗi. Vì vậy, tôi quyết định thêm dòng sau vào Global.asax:Làm thế nào để đặt thuộc tính ngữ cảnh log4net cụ thể cho một yêu cầu ASP.NET?

void Application_BeginRequest(object sender, EventArgs e) 
{ 
    log4net.ThreadContext.Properties["page"] = HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath; 
} 

và như khôn ngoan tôi đã thêm %property{page} để mô hình chuyển đổi của tôi:

<conversionPattern value="%newline%date %-5level %property{page} - %message%newline%newline%newline" /> 

này làm việc tốt cho các yêu cầu duy nhất. Nhưng sau đó tôi nhận thấy trong các bản ghi của tôi rằng thuộc tính trang có thể thay đổi trong một yêu cầu ASP.NET. Tôi đã đăng nhập vào một trình xử lý ASHX và ở giữa quá trình xử lý, thuộc tính trang sẽ thay đổi thành một giá trị khác trỏ đến trang ASPX. Tôi kết luận rằng có một yêu cầu khác đến với ASP.NET và BeginRequest của nó được thực thi và thuộc tính trang tĩnh trong log4net.ThreadContext được thay đổi thành một giá trị khác.

Bây giờ, tôi muốn duy trì thuộc tính trang cho mỗi yêu cầu, để tôi có thể có đường dẫn của trang thực thi đăng nhập vào nhật ký một cách nhất quán. Tôi đã cố gắng tìm một câu trả lời, nhưng tôi không có gì. Cách được khuyến nghị để giải quyết vấn đề này là gì? Tôi chắc rằng đây là chức năng rất cơ bản của việc ghi nhật ký sự kiện máy chủ web.

Trả lời

20

Kể từ ASP.NET does not guarantee rằng toàn bộ yêu cầu trang sẽ được xử lý trên cùng một chuỗi, tôi muốn nhận câu trả lời từ HttpContext.Current as log4net processes sự kiện ghi nhật ký.

Sau đây GetCurrentPage lớp thi đúng những gì hướng dẫn log4net gọi một "Active Property Value" bằng cách ghi đè phương pháp ToString của nó:

public class GetCurrentPage 
{ 
    public override string ToString() 
    { 
     if (null != HttpContext.Current) 
     { 
      return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath; 
     } 
     return string.Empty; // or "[No Page]" if you prefer 
    } 
} 

Đăng ký lớp này trong Global.asax của Application_Start trong GlobalContext log4net của.

protected void Application_Start(object sender, EventArgs e) 
{ 
    XmlConfigurator.Configure(); 
    GlobalContext.Properties["page"] = new GetCurrentPage(); 
} 

Khi log4net viết các %property{page} một phần của dòng nó sẽ gọi phương thức của lớp ToStringGetCurrentPage của chúng tôi mà sẽ tra cứu giá trị trong yêu cầu hiện tại.

+2

Đây là thiên tài. –

2

Bạn đã thử sử dụng Application_PostAcquireRequestState thay vì Application_BeginRequest như đã nêu trong bài viết này chưa? How can I include SessionID in log files using log4net in ASP.NET?

Chúng tôi chưa bao giờ cảm thấy cần phải thêm trang để khai thác gỗ vì chúng ta tạo logger của chúng tôi trong mỗi lớp với tên phương pháp:

private static new readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

và có một mô hình chuyển đổi như thế này:

<conversionPattern value="%date %P{user} %P{addr} [%property{SessionID}] %level %logger - %message%newline" /> 

Vì vậy, chúng tôi sẽ chỉ thấy tên lớp trong đầu ra nhật ký. Điều này cũng cho phép bạn phân biệt liệu việc ghi nhật ký có xảy ra trong chính tệp lớp trang hay không, so với lớp cơ sở mà nó kế thừa từ đó. Giải pháp của bạn sẽ có lợi thế là hiển thị tên trang ngay cả khi mã đang thực thi trong lớp cơ sở. Tôi nghĩ chúng ta sẽ xem xét thêm {page} vào thiết lập của mình.

+0

Điều thú vị là các công trình này. BeginRequest được thực hiện không đồng bộ, nhưng Application_PostAcquireRequestState được xử lý khi bắt đầu một yêu cầu trang, sau đó tất cả các sự kiện trang khác được kích hoạt đồng bộ và một yêu cầu trang khác phải đợi cho đến khi yêu cầu đầu tiên kết thúc. –

+0

@CraigA Tôi không nghĩ rằng toán tử 'mới' là cần thiết trong dòng mã của bạn 'private static new logonnet log4net.ILog'. Không thể chỉnh sửa và xóa nó, vì SO nói "Chỉnh sửa phải có ít nhất 6 ký tự" :). –

0

Lưu trữ giá trị thuộc tính trong ASP.NET bối cảnh HttpContext.Current.Items.Add("yourProperty", value) Nó sẽ có sẵn từ bố trí log4net:

<layout type="log4net.Layout.PatternLayout"> 
    <conversionPattern value="%aspnet-context{yourProperty}" /> 
</layout> 

Tìm chi tiết hơn here.

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