3

我开发了一个 asp.net 网站,在其中使用 log4net 记录错误信息,格式如下:

"%-5p %d - %m%n"

它按当前机器的日期时间记录日期时间。例如:

FATAL 2011-04-10 01:08:11,759 - message

但我想将日期时间转换为另一个区域或添加额外的时间。例如,我想在前面的示例中添加 3 小时,并希望输出为:

FATAL 2011-04-10 **04**:08:11,759 - message

关于如何实现这一目标的任何想法?

4

2 回答 2

5

这可能无法回答您的问题,因为我不确定您要达到的目标。也许如果你能提供更多关于你为什么要这样做的详细信息,你可能会得到一个更好的答案。

如果您尝试关联在不同区域生成的多个日志文件(或其他来源),它可能会有所帮助...

您可以按照此处所述尝试 log4net 的utctimePatternLayout 。

这将使您的日志时间采用通用时间,这可能更容易让您关联起来。如果您可以控制时间戳的来源(例如您的 asp.net 网站),那么通过将它们标准化为通用时间,它们应该更容易比较。

如果您确实想将时间更改为不同的区域或在记录的时间戳中添加/减去任意时间跨度,您可能必须编写自己的自定义 PatternLayout 或 PatternLayoutConverter。这可能有点棘手,因为我认为 log4net DatePatternConverter 和 UtcDatePatternConverter 都不能用于自定义(即它们已被声明internal,因此您不能对它们进行子类化并添加您的行为)。

您可以使用 log4net代码存储库中的 log4net 实现从头开始编写自己的代码,但这对我来说似乎很麻烦。

还有一点需要注意的是,使用以下自定义日期格式说明符之一在单独的列中再次记录时间可能会很有用:z、zz、zzzK

更新: 请参阅此答案以获取可能有帮助的另一个想法。该问题要求一种使用 log4net 捕获用户名的方法。最终,对他来说最好的解决方案是编写一个非常小的类来返回他需要的信息(用户名)。类的实例可以存储在 MDC(或 GlobalDiagnosticContext)中并在配置中引用。当 log4net 从 MDC(即对象)获取值时,它会调用 ToString 并记录结果。这种方法比编写一个全新的 PatternLayoutConverter 要容易得多,但灵活性稍差一些。

在答案的底部是一些示例代码,如下所示:

public class HttpContextUserNameProvider 
{   
  public override string ToString()   
  {     
    HttpContext context = HttpContext.Current;       
    if (context != null && 
        context.User != null && 
        context.User.Identity.IsAuthenticated)
    {
      return context.Identity.Name;     
    }     
    return "";   
  } 
}

您可以像这样将对象存储在 MDC/GlobalDiagnosticContext.Properties 中:

MDC.Set("user", new HttpContextUserNameProvider()); 

你可能会写一些类似的东西来返回不同的时间。您可以使用此时间而不是 log4net 提供的时间,或者您可以将此“自定义”时间作为附加列。您的“自定义时间”对象可能如下所示:

public class MyLocalTimeProvider 
{   
  public override string ToString()   
  {     
    DateTime myLocalTime = GetUtcTimeInMyTimeZone(DateTime.UtcNow);
    return myLocalTime;
  } 
}

然后你可以像这样引用它:

MDC.Set("myLocalTime", new MyLocalTimeProvider()); 

我不确定您是否可以将格式应用于 MDC/GlobalDiagnosticContext.Properties 中的项目(我认为可以),但您可以尝试一下。

您始终可以使用硬编码格式或向对象添加格式属性,如下所示:

public class MyLocalTimeProvider 
{   
  public MyLocalTimeProvider(string format)
  {
    Format = format;
  }

  public MyLocalTimeProvider()
    : this ("G")
  {
  }

  public string Format { get; set; }
  public override string ToString()   
  {     
    DateTime myLocalTime = GetUtcTimeInMyTimeZone(DateTime.UtcNow);
    return myLocalTime.ToString(Format);
  } 
}

您可以查看这篇文章,了解如何将 UTC 时间转换为任意时区。

于 2011-04-11T18:53:13.340 回答
0

如果您只需要将日期“转移”到您的时区,您可以编写自己的 ForwardingAppender,这将更改记录事件的 DateTime:

namespace Olekstra
{
    using System;

    using log4net.Appender;
    using log4net.Core;

    public class TimeShiftForwardingAppender : ForwardingAppender
    {
        private TimeSpan shift;

        private TimeSpan targetOffset;

        public TimeShiftForwardingAppender()
        {
            TargetOffset = TimeZoneInfo.Local.BaseUtcOffset;
        }

        public TimeSpan TargetOffset
        {
            get
            {
                return targetOffset;
            }

            set
            {
                targetOffset = value;
                shift = targetOffset.Subtract(TimeZoneInfo.Local.BaseUtcOffset);
            }
        }

        protected override void Append(LoggingEvent loggingEvent)
        {
            var eventData = loggingEvent.GetLoggingEventData();
            eventData.TimeStamp = eventData.TimeStamp.Add(shift);
            base.Append(new LoggingEvent(eventData));
        }

        protected override void Append(LoggingEvent[] loggingEvents)
        {
            for (var i = 0; i < loggingEvents.Length; i++)
            {
                var eventData = loggingEvents[i].GetLoggingEventData();
                eventData.TimeStamp = eventData.TimeStamp.Add(shift);
                loggingEvents[i] = new LoggingEvent(eventData);
            }
            base.Append(loggingEvents);
        }
    }
}

在 .config 中

<log4net>
  <appender name="FileAppender" type="log4net.Appender.RollingFileAppender">
       <!-- Your real appender here -->
  </appender>
  <appender name="TimeShiftAppender" type="Olekstra.TimeShiftForwardingAppender">
    <targetOffset>06:00:00</targetOffset> <!-- your desired (local) UTC offset value -->
    <appender-ref ref="FileAppender" /> <!-- real appender(s) -->
  </appender>
  <root>
    <level value="DEBUG" />
    <appender-ref ref="TimeShiftAppender" />
  </root>
</log4net>
于 2014-03-21T07:56:40.857 回答