2012-11-12 3 views
3

Nlog를 사용하여 텍스트 파일에 일부 로깅을 작성하고 있습니다. 일부 nlog.config : 로그 파일에nlog가 현재 날짜를 읽을 수 없습니다.

<target name="file" xsi:type="File" fileName="${basedir}/MBWRunner_log.txt" 
      layout="${date} (${level}): ${message} 
Exception: ${exception:format=Method, ToString}"/> 

라인은 다음과 같이 :

0001-01-01 0시 0분 0초 (트레이스) : MBWRunner 당신으로

시작 날짜와 시간은 모두 0입니다. 나는 {longdate}와 {date : format = yyyyMMddHHmmss}를 같은 결과로 테스트했습니다.

응용 프로그램은 상승 된 명령 줄에서 실행되는 콘솔 응용 프로그램입니다.

실마리가 있습니까?

[편집] 나는이 결과를 조직 내의 2 대의 기계에서 테스트했다. 도와주세요! 사용

코드 :

static Logger _logger = LogManager.GetCurrentClassLogger(); 

public static void Log(string message, LogLevel priority) 
    { 
     LogEventInfo eventinfo = new LogEventInfo(); ; 
     eventinfo.Message = message; 
     eventinfo.Level = priority; 
     Log(eventinfo); 
    } 

static void Log(LogEventInfo logentry) 
{  
    _logger.Log(logentry); 
} 
+0

Log 메서드와 LogEventInfo 클래스를 사용하여 메시지를 작성할 수 있습니까? – wageoghe

+0

@wageoghe 나는 그렇게 기대한다. 그러나 나는 atm과 코드를 갖고 있지 않다. 내가 살펴 보자 마자 바로 업데이 트됩니다 – edosoft

+0

LogEventInfo에 대한 기본 생성자를 사용하는 것이 문제라고 생각합니다. 내 대답에 대한 자세한 내용을 추가했습니다. – wageoghe

답변

5

업데이트 :이 문제가 LogEventInfo의 기본 생성자의 사용이라고 생각 @edosoft

. 여기

https://github.com/NLog/NLog/blob/master/src/NLog/LogEventInfo.cs

기본 생성자를 사용하면 .TimeStamp 필드를 채울하지 않는 것을 볼 수 있습니다, 그래서 필드가 아마 내가 가정 날짜 시간에 대한 기본 값으로 기본 설정됩니다 LogEventInfo의 소스를 보면 DateTime.MinValue입니다. 다른 생성자 중 하나 또는 Create 메서드 중 하나를 사용해야합니다. 당신은 단지 메시지와 레벨 필드를 설정하고 있기 때문에, 나도 제안 :

var logEvent = new LogEventInfo(priority, "", message); //Second param is logger name. 

또는 (here에서) DateLayoutRenderer에 대한 NLog 소스에서

var logEvent = LogEventInfo.Create(priority, "", message); 

우리가 날짜 값이 취득하는 것을 볼 수 있습니다 로깅 스트림의 일부는 다음과 같이 계산으로 작성 :

protected override void Append(StringBuilder builder, LogEventInfo logEvent) 
    { 
     var ts = logEvent.TimeStamp; 
     if (this.UniversalTime) 
     { 
      ts = ts.ToUniversalTime(); 
     } 

     builder.Append(ts.ToString(this.Format, this.Culture)); 
    } 

여기에서 일어나고있는 것은 DateLayoutRenderer이 getti 때문이다 LogEventInfo 개체의 TimeStamp 값 (NLog는 Logger.Trace, Logger.Debug, Logger.Info 등의 메서드를 사용할 때마다이 중 하나를 만듭니다. 직접 LogEventInfo 개체를 만들고 Logger.Log 메서드를 사용하여 로그에 기록 할 수도 있습니다. LogEventInfo 객체가 생성 될 때 기본적으로

가, 그 TimeStamp 필드 (LogEventInfohere의 소스에서) 다음과 같이 설정 (CurrentTimeGetter.Now의 사용에주의) :

public LogEventInfo(LogLevel level, string loggerName, IFormatProvider formatProvider, [Localizable(false)] string message, object[] parameters, Exception exception) 
    { 
     this.TimeStamp = CurrentTimeGetter.Now; 
     this.Level = level; 
     this.LoggerName = loggerName; 
     this.Message = message; 
     this.Parameters = parameters; 
     this.FormatProvider = formatProvider; 
     this.Exception = exception; 
     this.SequenceID = Interlocked.Increment(ref globalSequenceId); 

     if (NeedToPreformatMessage(parameters)) 
     { 
      this.CalcFormattedMessage(); 
     } 
    } 

TimeStamp 필드가 설정되어 LogEventInfo 생성자는 TimeSource.Current.Now 속성을 사용하며 그 구현은 here으로 볼 수 있습니다.

(UPDATE은 - 어떤 시점에서 NLog 본질적) CurrentTimeGetter와 동일 여러 향미를 갖는 TimeSource 오브젝트 (중 하나 CachedTimeSource를 갖는 더 일반적인 접근법을 사용 CurrentTimeGetter 변경).

링크를 탐색의 문제를 저장하려면, 여기 CachedTimeSource의 소스입니다 :

public abstract class CachedTimeSource : TimeSource 
{ 
    private int lastTicks = -1; 
    private DateTime lastTime = DateTime.MinValue; 

    /// <summary> 
    /// Gets raw uncached time from derived time source. 
    /// </summary> 
    protected abstract DateTime FreshTime { get; } 

    /// <summary> 
    /// Gets current time cached for one system tick (15.6 milliseconds). 
    /// </summary> 
    public override DateTime Time 
    { 
     get 
     { 
      int tickCount = Environment.TickCount; 
      if (tickCount == lastTicks) 
       return lastTime; 
      else 
      { 
       DateTime time = FreshTime; 
       lastTicks = tickCount; 
       lastTime = time; 
       return time; 
      } 
     } 
    } 
} 
이 클래스의 목적은 상대적으로 비용이 많이 드는 작업에 대한 액세스를 제한하기 위해 상대적으로 저렴한 작업 ( Environment.Ticks)를 사용하는 것입니다

(DateTime.Now). Ticks 값이 통화 간 (기록 된 메시지에서 다음 메시지로) 변경되지 않으면 DateTime.Now의 값은 이번에 검색 한 DateTime.Now의 값과 같으므로 이번에는 마지막으로 검색된 값.

이 코드를 모두 사용하면 (대부분의 사람들에게 날짜/시간 로깅이 작동하는 것처럼 보임) 문제의 한 가지 가능한 설명은 Logger.Log 메서드를 사용하여 메시지를 로깅하고 LogEventInfo 개체를 직접. 기본적으로 LogEventInfo 개체를 새로 추가 한 경우 TimeStamp 속성의 자동 설정이 정상적으로 작동합니다. 적절한 경우 Environment.Ticks, DateTime.Now 및 마지막 DateTime.Now 값을 재사용하는 논리에만 종속됩니다. 개체를 만든 다음 TimeStamp 속성을 DateTime.MinValue으로 설정할 수 있습니까? 기록되는 날짜가 DateTime.MinValue이기 때문에 묻습니다.

내가 생각할 수있는 유일한 설명은 Environment.Ticks이 어떤 이유로 -1을 반환하는 경우입니다. 그렇다면 CurrentTimeGetter은 항상 lastDateTime 전용 멤버 변수의 초기 값을 반환합니다. Environment.Ticks이 -1을 반환하는 시나리오를 상상할 수 없습니다.

+0

좋은 답변입니다! 아쉽게도 내 코드를 확인하십시오 – edosoft

+0

감사합니다. 코드를 업데이트하고 다시 테스트 하겠지만, Nlog 소스를 보면 네 말이 맞아 보인다. – edosoft

관련 문제