Log4Net - 添加时间并记录日期时间

发布于 2024-10-31 10:23:56 字数 348 浏览 0 评论 0原文

我开发了一个 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

关于如何实现此目的有什么想法吗?

I developed a asp.net website where I log error information using log4net with format:

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

It logs datetime by current machine's datetime.
For example:

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

But I want to convert datetime to another region or add additional time with it. For example I want to add 3 hours with previous example and want output as:

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

Any idea on how to achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

回忆追雨的时光 2024-11-07 10:23:56

这可能无法回答您的问题,因为我不确定您到底想要实现什么目标。也许如果您可以提供更多详细信息来说明为什么要这样做,您可能会得到更好的答案。

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

您可以尝试 log4net 的 utctime PatternLayout,如 此处

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

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

您可以使用 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 时间转换为任意时区。

This might not answer your question, because I'm not sure exactly what you are trying to achieve. Maybe if you could provide more details on exactly why you want to do this, you might get a better answer.

If you are trying to correlate multiple log files (or other sources) that have been generated in different regions, it might help...

You could try log4net's utctime PatternLayout as described here.

This will get your log times in universal time, which might be easier for you to correlate. If you have control over the sources of timestampes (like your asp.net website), then by normalizing them to universal time, they should be easier to compare.

If you really do want to change the time to a different region or add/substract an arbitrary time span from the timestamp as it is logged, you might have to write your own custom PatternLayout or PatternLayoutConverter. That might be a little bit tricky as I think that neither the log4net DatePatternConverter nor the UtcDatePatternConverter is available for customization (i.e. they are declared internal so you can't subclass them and add your behavior).

You could write your own from scratch, using log4net's implementation from the log4net code repository, but that seems like a lot of trouble to me.

One more note, maybe it would be useful to log time again in a separate column using one of these Custom Date format specifiers: z, zz, zzz, K.

UPDATE:
See this answer for another idea that might help. The question asks for a way to capture username with log4net. Ultimately, the best solution for him was to write a very small class that will return the information the he needs (username). An instance of the class can be stored in the MDC (or GlobalDiagnosticContext) and referenced in the configuration. When log4net gets the value from the MDC (i.e. the object), it calls ToString and logs the result. This approach is a lot easier, if somewhat less flexible, than writing a whole new PatternLayoutConverter.

Towards the bottom of the answer is some sample code like this:

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 "";   
  } 
}

You would store the object in the MDC/GlobalDiagnosticContext.Properties like this:

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

You could probably write something similar to return a different time. You could use this time instead of the log4net-provided time, or you could make this "custom" time an additional column. Your "custom time" object might look like this:

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

Then you could reference it like this:

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

I'm not sure if you can apply formats to items from the MDC/GlobalDiagnosticContext.Properties (I think you can) or not, but you could try it and see.

You could always use a hardcoded format or add a format property to the object like this:

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);
  } 
}

You might take a look at this article for how to convert a UTC time to an arbitrary time zone.

梦幻的味道 2024-11-07 10:23:56

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

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>

If you need just "shift" date to your timezone, you can write your own ForwardingAppender, which will change DateTime of logged event:

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);
        }
    }
}

And in .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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文