这可能是不可能的,但我想知道是否有办法让它发挥作用。
我有一个大型的ASP.NET MVC43应用程序,它已经使用了日志语句。
现在我们需要包含一个"公司名称"每个日志条目中的Session对象的值。是否可以将log4net配置为读取会话数据并将其包含在日志条目中?或者某种方式迫使它......?
感谢任何想法。
[编辑] 这个问题有很多帮助:How can I include SessionID in log files using log4net in ASP.NET?
我最终将此作为我的解决方案:
在Global.asax.cs中:
// After the session is acquired, push the organization code into log4net's thread context, in case it has to log anything.
protected void Application_PostAcquireRequestState(object sender, EventArgs e)
{
if (Context.Handler is IRequiresSessionState && Session != null && Session[Constants.EMPLOYEE_DETAILS] != null)
log4net.ThreadContext.Properties["Company"] = ((EmployeeDetails)Session[Constants.EMPLOYEE_DETAILS]).Company;
}
在log4net配置中:
<parameter>
<parameterName value="@Company"/>
<dbType value="String"/>
<size value="10"/>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{Company}" />
</layout>
</parameter>
效果很好 - 我现在在日志输出中得到一个公司名称。感谢大家的帮助。
答案 0 :(得分:2)
使用自定义布局转换器
public class CompanyLayoutConverter : PatternLayoutConverter
{
protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
{
var httpContext = HttpContext.Current;
if (httpContext == null)
return;
writer.Write(httpContext.Session["Company Name"]);
}
}
将此转换器添加到appender布局,公司名称将显示在输出中(只需在conversionPattern值使用%company
):
<appender name="RollingLogFileAppender"
type="log4net.Appender.RollingFileAppender">
<threshold value="All" />
<file value="C:\LogFile" />
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="'.'yyyyMMdd'.log.txt'" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<converter>
<name value="company"/>
<type value="Foo.Bar.CompanyLayoutConverter"/>
</converter>
<conversionPattern value="%date %-5level %logger - %company %message%newline" />
</layout>
</appender>
答案 1 :(得分:1)
有关如何实现此目的的一些想法,请参阅此答案。
你应该能够在不实现自己的Appender的情况下完成它。
以下是从PatternLayoutConverter
中提取参数化值的自定义HttpContext.Current.Session
的示例。 (我不记得是否在我作为链接答案的一部分发布时进行了测试,但它应该是关闭的):
namespace Log4NetTest
{
class HttpContextSessionPatternConverter : PatternLayoutConverter
{
protected override void Convert(System.IO.TextWriter writer, LoggingEvent loggingEvent)
{
//Use the value in Option as a key into HttpContext.Current.Session
string setting = "";
HttpContext context = HttpContext.Current;
if (context != null)
{
object sessionItem;
sessionItem = context.Session[Option];
if (sessionItem != null)
{
setting = sessionItem.ToString();
}
writer.Write(setting);
}
}
}
}
另一个更简单的想法是做这样的事情......创建一个对象,它将检索你想要的Session参数并将该对象放在MDC中,然后在你的布局中引用MDC。当log4net从MDC访问对象时,它将调用其ToString方法来获取要写入日志的值。
public class HttpContextSessionParametreProvider
{
private string _name;
private string _notSet;
public HttpContextSessionParameterProvider(string name)
{
_name = name;
_notSet = string.Format("{0} not set", _name);
}
public override string ToString()
{
HttpContext context = HttpContext.Current;
if (context != null && context.Session != null)
{
object item = context.Session[_name];
if (item != null)
{
return item.ToString();
}
}
return _notSet;
}
}
在程序的入口点附近使用它:
MDC.Set("CompanyName", new HttpContextSessionParametreProvider("Company Name"));
(我没有关于如何配置log4net以从MDC中提取参数的示例,但是应该不难找到一个参数。)
编辑:
你可以像这样配置你的PatternLayout:
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%thread]|[%property{CompanyName}]|%message%newline"/>
</layout>
现在,假设HttpContext.Session["Company Name"]
设置为某个内容,无论何时记录消息,该值都将写入日志。
答案 2 :(得分:0)
我认为你可以使用上下文和模式布局来做到这一点:
http://logging.apache.org/log4net/release/manual/contexts.html
http://logging.apache.org/log4net/release/sdk/log4net.Layout.PatternLayout.html
虽然文档没有多大帮助。