3

Nlog を使用して、ログをテキスト ファイルに書き込みます。部分的な nlog.config:

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

ログファイルの行は次のようになります。

0001-01-01 00:00:00 (トレース): 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);
}
4

1 に答える 1

5

アップデート:

@edosoft問題は、LogEventInfoのデフォルトコンストラクターの使用にあると思います。ここでLogEventInfoのソースを見ると

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

デフォルトのコンストラクターを使用してもフィールドにデータが入力されないことがわかります.TimeStamp。そのため、フィールドはおそらくデフォルトでDateTimeのデフォルト値になります。これは私が想定している値ですDateTime.MinValue。他のコンストラクターの1つまたはCreateメソッドの1つを使用する必要があります。メッセージフィールドとレベルフィールドのみを設定しているので、次のいずれかをお勧めします。

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

または

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

DateLayoutRendererここから)のNLogソースから、ロギングストリームの一部として書き込まれる日付値が次のように計算されていることがわかります。

    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取得していることです(NLogは、、、、などのメソッドを使用するたびにこれらの1つを作成します。自分でオブジェクトを作成し、メソッドを使用してログに記録することもできます)。TimeStampLogEventInfoLogger.TraceLogger.DebugLogger.InfoLogEventInfoLogger.Log

デフォルトでは、LogEventInfoオブジェクトが作成されると、そのTimeStampフィールドは次のように設定されます(LogEventInfo ここのソースから)(の使用に注意してください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確認できます。

(更新-ある時点で、NLogは、いくつかのフレーバーを持つオブジェクトをCurrentTimeGetter持つというより一般的なアプローチに変更されました(そのうちの1つは本質的にと同じです))。TimeSourceCachedTimeSourceCurrentTimeGetter

リンクをナビゲートする手間を省くために、ここにソースがあります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の値と同じになります。今回取得されたので、最後の値を使用してください。取得した値。

このすべてのコードが機能している場合(そして、日付/時刻のログが他のほとんどの人にとって明らかに機能している場合)、問題の1つの考えられる説明は、Logger.Logメッセージをログに記録するメソッドを使用していて、LogEventInfoオブジェクトを自分で構築していることです。デフォルトでは、LogEventInfoオブジェクトを新しく作成したばかりの場合、プロパティの自動設定は正常に機能TimeStampするはずです。、、および必要に応じて最後の値を再利用するロジックにEnvironment.Ticksのみ依存します。DateTime.NowDateTime.Now

オブジェクトを作成してからLogEventInfo、そのTimeStampプロパティをに設定している可能性はありDateTime.MinValueますか?ログに記録されている日付はですのでお願いしますDateTime.MinValue

私が考えることができる他の唯一の説明はEnvironment.Ticks、何らかの理由で-1を返す場合です。含まれている場合は、CurrentTimeGetter常にlastDateTimeプライベートメンバー変数の初期値を返します。Environment.Ticks-1が返されるシナリオは想像できません。

于 2012-12-03T20:03:58.847 に答える