我正在尝试使用log4net.LogicalThreadContext在OwinMiddleware中存储一些数据,所以我可以稍后在ApiController中记录它,但它似乎不起作用。存储在log4net.LogicalThreadContext中的数据似乎不能在ApiController中使用。这是我的代码片段:
创建ApiMiddleWare以便将一些日志数据注入LogicalThreadContext.Properties [“logdata”]:
public class ApiMiddleWare : OwinMiddleware
{
public ApiMiddleWare(OwinMiddleware next) : base(next)
{
}
public override async Task Invoke(IOwinContext context)
{
var loggers = new ConcurrentDictionary<string, object>();
if (!loggers.ContainsKey("CorellationId"))
{
var correlationId = new[] {Guid.NewGuid().ToString().Replace("-", "")};
loggers.TryAdd("CorellationId", correlationId[0]);
}
if (context.Request.Path.HasValue)
{
loggers.TryAdd("Route", context.Request.Uri.AbsoluteUri);
}
LogicalThreadContext.Properties["logdata"] = loggers;
await Next.Invoke(context);
}
}
然后ApiMiddleWare将在ServiceHost的Startup.cs中使用,如下所示:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
app.Use<ApiMiddleWare>();
Log.Configure();
}
}
我创建了一个自定义RollingFileAppeanderEx来捕获在中间件中分配的日志数据并将其记录下来:
public class RollingFileAppenderEx: RollingFileAppender
{
protected static readonly JsonSerializerSettings JsonSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DateFormatHandling = DateFormatHandling.IsoDateFormat
};
protected override void Append(LoggingEvent loggingEvent)
{
if (FilterEvent(loggingEvent))
{
var logdata = loggingEvent.GetLoggingEventData();
logdata.Message = GetLogData(loggingEvent);
loggingEvent = new LoggingEvent(loggingEvent.GetType(), loggingEvent.Repository, logdata, loggingEvent.Fix);
base.Append(loggingEvent);
}
}
protected string GetLogData(LoggingEvent logEvent)
{
IDictionary<string, object> logData = new Dictionary<string, object>();
var logD = logEvent.Properties["logdata"] as ConcurrentDictionary<string, object>;
if logD != null)
{
foreach (var log in logD)
{
logData.Add(log.Key, log.Value);
}
}
logData.Add("Message", logObject.Message);
var logString = JsonConvert.SerializeObject(logData, JsonSettings);
return logString;
}
}
从ApiController,调用Info函数到log:
public class TestsController : ApiController
{
private static readonly ILogger Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public string Get(int id)
{
Log.Info("Something");
return id;
}
}
这是我的问题:只有“Something”被写入日志。但是,CorellationId和Route不是。通过代码调试,我发现“logEvent.Properties [”logdata“]作为ConcurrentDictionary”在RollingFileAppenderEx中返回了可以为null的值。所以我有一个理论:似乎TestsController类不在同一个线程中,或者不是来自ApiMiddleWare的子线程。因此,存储在LogicalThreadContext中的数据不会一直传播。
如果有人可以帮助查看是否有办法执行此操作,或者我的代码中可能存在错误。我会很感激。感谢。
答案 0 :(得分:1)
也许您必须致电loggingEvent.GetLoggingEventData()
?
我有:
public abstract class AwsVerboseLogsAppender : AppenderSkeleton
{
// ...
protected override void Append(LoggingEvent loggingEvent)
{
// ...
}
// ...
}
// ...
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log4net.config");
var fileinfo = new FileInfo(path);
XmlConfigurator.Configure(fileinfo);
var log = LogManager.GetLogger(GetType());
LogicalThreadContext.Properties["Test"] = "MyValue";
log.Debug("test");
loggingEvent.Properties
内Append
为空。
但是,如果我拨打loggingEvent.GetLoggingEventData()
,则"Test"
和MyValue
会显示在loggingEvent.Properties
内。所以也许你必须打电话给那个方法。