SuperLightLogger 1.0.17

dotnet add package SuperLightLogger --version 1.0.17
                    
NuGet\Install-Package SuperLightLogger -Version 1.0.17
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SuperLightLogger" Version="1.0.17" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SuperLightLogger" Version="1.0.17" />
                    
Directory.Packages.props
<PackageReference Include="SuperLightLogger" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SuperLightLogger --version 1.0.17
                    
#r "nuget: SuperLightLogger, 1.0.17"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SuperLightLogger@1.0.17
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SuperLightLogger&version=1.0.17
                    
Install as a Cake Addin
#tool nuget:?package=SuperLightLogger&version=1.0.17
                    
Install as a Cake Tool

SuperLightLogger

log4net や NLog を using を1行書き換えるだけで卒業できる、超軽量な互換シム。

using log4net; を using SuperLightLogger; に置き換えるだけで、 コードベースは一切触らずに C# 標準の Microsoft.Extensions.Logging へ移行できます。


こんな悩み、ありませんか?

  • log4net や NLog で書かれた 長年のコードベース を抱えていて、Microsoft.Extensions.Logging への乗り換えを何年も先送りにしている
  • 「全コードを ILogger<T> に書き換えるなんて、工数もリスクも見合わない」と諦めている
  • ASP.NET Core / Generic Host / OpenTelemetry / Serilog などの モダンなエコシステム を使いたいのに、ロギング基盤だけが足を引っ張っている
  • log4net.config や NLog.config の XML を書くたびに、コードでスッキリ書きたいと思っている
  • 新規プロジェクトでは ILogger<T> を使っているが、旧プロジェクトとAPIが二重化 していて統一したい
  • ネイティブ AOT 対応のアプリを作りたいが、既存のロギングライブラリの AOT 互換性が不安

SuperLightLogger なら、移行が「数分」で終わります

やること 所要時間
NuGet 参照を log4net → SuperLightLogger に差し替え 10秒
プロジェクト全体の using log4net; を一括置換 30秒
Program.cs で LogManager.Configure(...) を1回だけ呼ぶ 1分

それだけで、ログ基盤の中身は丸ごと Microsoft.Extensions.Logging に置き換わります。

既存の log.Info(...) も log.DebugFormat(...) も log.Error(message, ex) も、 コードを1行も書き換えずにそのまま動きます。


乗り換えると何が嬉しいの?

1. C# 標準ロギングのエコシステムに直結

Microsoft.Extensions.Logging 互換になるので、以下のシンクが設定だけで使えるようになります:

  • AddConsole() / AddDebug() / AddEventLog() / AddEventSourceLogger()
  • Serilog (AddSerilog())
  • NLog (Microsoft.Extensions.Logging プロバイダ経由)
  • OpenTelemetry (AddOpenTelemetry())
  • Application Insights (AddApplicationInsights())
  • Datadog / New Relic / Seq / Loki などサードパーティのプロバイダ全般

2. ASP.NET Core / Generic Host / DI とシームレスに統合

DI コンテナで構築済みの ILoggerFactory を、たった1行で LogManager に橋渡しできます:

var app = builder.Build();
app.Services.UseSuperLightLogger();   // これだけ

3. 構造化ログへ「段階的に」移行できる

旧コードと新コードを 同じプロジェクトで共存 できるので、書き換えを一気にやる必要がありません:

// 旧コード(log4net 互換)— そのまま動く
log.InfoFormat("ユーザー{0}がログインしました", userId);

// 新コード(M.E.Logging 式の構造化テンプレート)— 余裕ができた箇所から徐々に
log.InfoStructured("ユーザー {UserId} がログインしました", userId);

{UserId} の値は構造化ログとして扱われ、Seq や Datadog などで検索・集計できます。

4. ネイティブ AOT 対応

net8.0 / net10.0 ターゲットで IsAotCompatible=true を有効化済み。 PublishAot=true でビルドしたアプリにそのまま組み込めます。 同梱の samples/AotSample でネイティブ AOT 発行を検証しています。

5. NLog 互換のファイルターゲットを内蔵

NLog の File Target 相当を 追加依存ゼロ で同梱しています。 パステンプレート (${shortdate} 等)・サイズ/日付ベースのアーカイブ・最大保持数・ ヘッダー/フッター・非同期書込みをすべてサポートし、しかも Native AOT 安全。

LogManager.Configure(builder =>
{
    builder.AddSuperLightFile(opt =>
    {
        opt.FileName = "logs/app_${shortdate}.log";
        opt.ArchiveAboveSize = 1L * 1024 * 1024;   // 1 MB でローテート
        opt.MaxArchiveFiles = 10;                  // 10世代で打ち切り
    });
});

詳細は後述の 内蔵 File Target セクションを参照。

6. 依存もコードも、本当に「Super Light」

  • 依存パッケージは Microsoft 純正の 3つだけ
  • 責務を互換 API と内蔵 File Target に絞った、追跡しやすい実装
  • 内蔵 File Target 以外のシンク (Console / Serilog / Datadog / OpenTelemetry 等) は標準 M.E.L にすべて委譲

インストール

dotnet add package SuperLightLogger

クイックスタート

1. 起動時に1回だけ初期化

using Microsoft.Extensions.Logging;
using SuperLightLogger;

LogManager.Configure(builder =>
{
    builder.AddConsole();
    builder.SetMinimumLevel(LogLevel.Debug);
});

💡 1.0.4+: using Microsoft.Extensions.Logging; を書きたくない場合

既存コードに自作の LogLevel 型 (例: Cube.LogLevel) がある場合、MEL を using すると 名前衝突します。その場合は 文字列ベース API を使えば SuperLightLogger 名前空間だけで 設定完結できます:

using SuperLightLogger;

LogManager.Configure(builder =>
{
    builder.SetMinimumLevel("Debug");           // 文字列オーバーロード
    builder.AddSuperLightFile("logs/app.log");  // ファイル名だけのショートカット
});

2. あとは log4net と全く同じ書き方

using SuperLightLogger;

public class OrderService
{
    private static readonly ILog log = LogManager.GetLogger(typeof(OrderService));

    public void PlaceOrder(int orderId)
    {
        log.Info("注文処理を開始します");
        log.DebugFormat("OrderId={0}", orderId);

        try
        {
            // ...
        }
        catch (Exception ex)
        {
            log.Error("注文処理に失敗しました", ex);
        }
    }
}

log4net からの移行 — Before / After

// ───── Before (log4net) ─────
using log4net;

public class MyService
{
    private static readonly ILog log = LogManager.GetLogger(typeof(MyService));
    // ...
}
// ───── After (SuperLightLogger) ─────
using SuperLightLogger;

public class MyService
{
    private static readonly ILog log = LogManager.GetLogger(typeof(MyService));
    // ↑ 1文字も変わっていない!
}

変更点は using の1行だけ。 クラス本体・ロガー取得・ログ呼び出し、すべて手つかずでOK。

XML 設定ファイル (log4net.config) は不要になります。 代わりに Program.cs で LogManager.Configure(...) を呼んで、コードでロガーを構成してください。


NLog 風の書き方も対応

private static readonly ILog log = LogManager.GetCurrentClassLogger();

AOT環境では非推奨: GetCurrentClassLogger() は内部で StackFrame を使うため、 ネイティブAOT / トリミング時に IL2026 警告が出ます。AOT で使う場合は LogManager.GetLogger<MyClass>() を使ってください(こちらも一行で書けます)。


ASP.NET Core / Generic Host との統合

var builder = WebApplication.CreateBuilder(args);

// 普段通り ILoggerFactory を構成
builder.Logging.AddConsole();
builder.Logging.AddDebug();

var app = builder.Build();

// DI コンテナの ILoggerFactory を SuperLightLogger に橋渡し
app.Services.UseSuperLightLogger();

app.Run();

これで appsettings.json の "Logging" セクションも有効になり、 SuperLightLogger 越しのログ出力が Microsoft 標準のフィルタ・プロバイダ機構に乗ります。


構造化ログへの段階的移行

log4net の InfoFormat("{0}", x) から M.E.Logging 式の名前付きテンプレートへ、 ファイル単位・関数単位で少しずつ 移行できます:

// Step 1: そのまま動かす(log4net式)
log.InfoFormat("注文 {0} がユーザー {1} により完了", orderId, userId);

// Step 2: 構造化ログ化(名前付きプレースホルダー)
log.InfoStructured("注文 {OrderId} がユーザー {UserId} により完了", orderId, userId);

Step 2 にしておくと、Seq / Datadog / Application Insights などで OrderId = 12345 のような構造化クエリができるようになります。


内蔵 File Target

log4net や NLog から移行する際にほぼ必須となる「ローカルファイルへのログ出力」を、 追加 NuGet パッケージなし・Native AOT 安全 で同梱しています。 NLog の File Target をそのまま意識して設計されており、NLog 経験者なら設定の見た目だけで動きが想像できます。

最小構成

using SuperLightLogger;

LogManager.Configure(builder =>
{
    // ファイル名だけ指定するワンライナー (パステンプレート使用可)
    builder.AddSuperLightFile("logs/app_${shortdate}.log");
});

これだけで logs/app_2026-04-15.log が日付ごとに自動生成されます。 出力形式は NLog 互換のレイアウトテンプレートでカスタマイズできます。

細かい設定をしたい場合は Action<FileTargetOptions> オーバーロードを使います:

LogManager.Configure(builder =>
{
    builder.AddSuperLightFile(opt =>
    {
        opt.FileName = "logs/app_${shortdate}.log";
        opt.Layout   = "${longdate} [${level}] ${logger} - ${message}";
    });
});

NLog 相当のフル設定例

LogManager.Configure(builder =>
{
    builder.AddSuperLightFile(opt =>
    {
        // パステンプレート
        opt.FileName = "logs/MyApp_${date:format=yyyyMMdd}.log";

        // 1行のレイアウト (デフォルト値とほぼ同等)
        opt.Layout =
            @"${date:format=yyyy-MM-dd HH\:mm\:ss.ffff} [${level:uppercase=true}] " +
            @"[${threadid}] ${message}${onexception:${newline}${exception:format=tostring}}";

        // アーカイブ (サイズ + 最大保持数)
        opt.ArchiveAboveSize = 1L * 1024 * 1024;            // 1 MB 超過でローテート
        opt.MaxArchiveFiles  = 10;                          // 10世代で打ち切り
        opt.ArchiveNumbering = ArchiveNumbering.Sequence;   // .1.log, .2.log, ...

        // 非同期書込み (バックグラウンドスレッドで吐き出す)
        opt.Async              = true;
        opt.AsyncBufferSize    = 10000;
        opt.AsyncFlushInterval = TimeSpan.FromSeconds(1);

        // 個別ターゲットの最低レベルも文字列で設定可能 (log4net 互換表記)
        opt.MinLevelName = "Trace";
    });

    // ↓ Microsoft.Extensions.Logging の `LogLevel` enum に依存せず
    //   文字列で最小レベルを設定できる (using Microsoft.Extensions.Logging; 不要)。
    //   Cube.LogLevel 等の自作 enum と名前衝突するのを避けたい人向け。
    builder.SetMinimumLevel("Trace");
});

FileName に ${shortdate} / ${date} などの動的トークンを使う場合、自然なパス切替で生じる旧ファイルと、同じ具象パスから作られるサイズ/時間アーカイブには MaxArchiveFiles が別々の保持枠として適用されます。高流量日のサイズローテートが過去日のログを保持枠から押し出すことはありません。

💡 LogLevel 名前衝突を避けたい人へ

既存コードに Cube.LogLevel のような自作 enum がある場合、 using Microsoft.Extensions.Logging; を足すと LogLevel が衝突してしまいます。 SuperLightLogger は MEL を using せずに済む文字列ベースの API を提供しています:

using SuperLightLogger;   // これだけで OK

LogManager.Configure(b =>
{
    b.SetMinimumLevel("Info");              // ← 文字列オーバーロード
    b.AddSuperLightFile("logs/app.log");    // ← ファイル名だけ指定の最短形
});

受理される値 (大文字小文字を区別しません): Trace / Debug / Info (= Information) / Warn (= Warning) / Error / Fatal (= Critical) / None (= Off)

FileTargetOptions.MinLevelName プロパティも同じ文字列を受け付けます。

対応するレイアウトレンダラ

${...} 構文で NLog と同じ感覚で記述できます。すべてコンストラクタ時に コンパイル済みデリゲート配列にパース済みのため、出力時はリフレクションを一切使いません。

レンダラ 説明
${longdate} / ${shortdate} / ${time} 日付/時刻のショートカット
${date:format=yyyy-MM-dd HH\:mm\:ss.ffff} カスタムフォーマット
${level:uppercase=true:padding=-5} レベル (大小文字・パディング指定可)
${logger} / ${message} カテゴリ名 / メッセージ本文
${exception:format=tostring} (他に message, type, stacktrace) 例外情報 (format はいずれか1つ)
${onexception:${newline}${exception}} 例外ありのときだけ出力 (ネスト可)
${threadid} / ${threadname} スレッド情報
${processid} / ${processname} / ${machinename} プロセス/マシン情報
${basedir} / ${tempdir} / ${newline} 環境関連

アーカイブ番号付け方式

ArchiveNumbering 例 用途
Sequence (既定) app.1.log, app.2.log, ... NLog 既定。古い番号を残す
Rolling app.0.log が常に最新 tail コマンドと相性が良い
Date app.20260414.log 1日1ファイル + 日付ベースの保持
DateAndSequence app.20260414.1.log 日付 + 同日内シーケンス

時間ベースのアーカイブ

サイズではなく時間境界 (毎時/毎日/毎週) でローテートしたい場合:

opt.ArchiveEvery = ArchiveEvery.Day;     // 日付が変わった瞬間にアーカイブ
opt.ArchiveAboveSize = 0;                // サイズベースは無効化

ArchiveEvery には Year / Month / Day / Hour / Minute / 各曜日が指定できます。

アーカイブパスのカスタマイズ (ArchiveFileName)

アクティブなログファイルとは 別のディレクトリ や 別の命名規則 でアーカイブしたい場合、 ArchiveFileName にレイアウトトークン込みのテンプレートを指定できます:

opt.FileName        = "logs/app.log";
opt.ArchiveFileName = "logs/archive/app.{#}.${logger}.log";
opt.ArchiveNumbering = ArchiveNumbering.Sequence;
opt.MaxArchiveFiles  = 30;
  • {#} はシーケンス番号 (Sequence / Rolling / DateAndSequence 時)
  • ${logger} / ${level} / ${shortdate} などのレイアウトトークンは 実際のログイベントから描画 されるため、 「エラー発生時だけ ${level}=Error のファイルに退避」といった運用も可能
  • 省略した場合は FileName から自動導出 (app.log → app.1.log)

オーバーヘッド

  • 同期モード (デフォルト): 呼び出し元スレッドでファイル書込みと必要なフラッシュを完了します。
  • 非同期モード (Async=true): 呼び出し側は bounded queue へ追加し、専用スレッドが書き込みます。満杯時に待機するか破棄するかは AsyncDiscardOnFull で選べます。
  • AOT: File Target の通常経路はリフレクションと動的コード生成を使わず、追加依存なしで netstandard2.0 でも動作します。

ネイティブ AOT / トリミング対応

net8.0 / net10.0 ターゲットでは以下を有効化済みです:

  • IsAotCompatible=true
  • IsTrimmable=true
  • EnableTrimAnalyzer=true

dotnet publish -p:PublishAot=true でビルドするアプリに、何の追加設定もなく組み込めます。

// AOT 安全なロガー取得
var log = LogManager.GetLogger<MyClass>();

// または typeof 指定
var log = LogManager.GetLogger(typeof(MyClass));

実際のネイティブ AOT ビルドサンプルは samples/AotSample を参照してください。


障害モード契約 / トラブルシューティング

SuperLightLogger は 「ロガーがアプリを殺さない」 ことを優先し、主な障害をアプリへ 伝播させず、次のように処理します。

障害 挙動 通知経路
ディスクフル / 書込み権限なし 該当ログイベントを破棄し、累計エラー数を加算 Console.Error (writer ごとに初回 1 回)
アーカイブローテーション失敗 (ファイル削除 permission denied 等) その回のアーカイブまたは保持掃除を中止し、書込み処理は継続 Console.Error (writer ごとに初回 1 回)
AsyncFileQueue キュー満杯 (AsyncDiscardOnFull = true 時) 該当ログイベントは無言で drop 通知なし
AsyncFileQueue バックグラウンドワーカーの例外 累計エラー数を加算し、同じワーカーで処理を継続 Console.Error (発生ごと)
LogManager.Configure 未呼び出し NullLoggerFactory にフォールバックして全ログを破棄 Console.Error (未構成状態ごとに初回 1 回)
${longdate} 等の DST 切替時間帯 同じ時間帯が二度現れる / 1 時間スキップ 通知なし (DateTime.Now ベース)

🚨 stderr を収集しない環境では監視を追加

Windows Service や GUI アプリなど標準エラー出力を収集しないホストでは、writer の警告を 確認できません。ホストまたはプロセス管理基盤で stderr を収集するか、直接生成して保持した FileLoggerProvider の GetStatistics() を定期的に取得してください。

統計 意味
WorkerErrorCount 同期 writer、アーカイブ処理、Async worker で発生した累計エラー数
DiscardedLogEventCount AsyncDiscardOnFull=true でキュー満杯により破棄した累計イベント数
QueueDepth Async queue の取得時点での近似深さ (同期モードは -1)

統計はベストエフォートのスナップショットです。writer の反復警告は抑制されるため、 本番では stderr と統計の両方を監視してください。

⏰ DST / UTC ログタイムスタンプの注意

FileLogger.Log および LayoutRenderer の ${longdate} / ${shortdate} / ${time} / ${date} は ローカル時刻 (DateTime.Now) で生成されます。これは log4net / NLog のデフォルト挙動と 合わせるためですが、以下のケースで意図しない挙動になる場合があります:

  • DST 切替時間帯: ArchiveEvery.Hour 等の時間境界アーカイブが、巻き戻り時間帯で 「同じ 1 時間が二度現れる」状態になり、同じ時間帯のログが 2 つのファイルに分裂する可能性
  • マルチリージョン分散システム: US-East と Tokyo のサーバーで ${longdate} の値が 9 時間ずれて記録され、Elastic/Kibana 等で時系列集約しづらくなる

UTC 運用が必要な場合は、現状はワークアラウンドとして FileLogger を fork して DateTime.UtcNow を使う形にする必要があります。${longdate:utc=true} トークンパラメータの ネイティブサポートは将来バージョンで検討予定。

⚠️ ロガー名にユーザー入力を渡さない (パストラバーサル防御)

FileName / ArchiveFileName テンプレートに ${logger} を使う構成 (例: "logs/${logger}.log") では、${logger} 内のパス区切り (/ \ :) と Path.GetInvalidFileNameChars() がライブラリ内部で _ に置換されます。これにより LogManager.GetLogger("../../etc/passwd") のような攻撃で任意パスに書き込まれることを防止 しています。

加えて、. / .. は _ に置換し、Windows の予約デバイス名 (CON / PRN / AUX / NUL / COM1〜COM9 / LPT1〜LPT9) には先頭へ _ を付けます。

ただし、ユーザー入力をそのままロガー名にする実装 (例: HTTP request の request.Path を GetLogger(...) に渡す) は引き続き設計上の anti-pattern です。可能な限り LogManager.GetLogger<T>() または静的な定数文字列でロガー名を指定してください。


レベルマッピング

SuperLightLogger Microsoft.Extensions.Logging log4net NLog
Trace() Trace — Trace
Debug() Debug Debug Debug
Info() Information Info Info
Warn() Warning Warn Warn
Error() Error Error Error
Fatal() Critical Fatal Fatal

log4net の 5レベル、NLog の 6レベル、どちらの感覚でもシームレスに使えます。


対応フレームワーク

ターゲット 対象ランタイム
netstandard2.0 .NET Framework 4.6.1+, .NET Core 2.0+, Mono, Unity
net8.0 .NET 8 LTS
net10.0 .NET 10

レガシーな .NET Framework 4.6.1 のプロジェクトから最新の .NET 10 / AOT アプリまで、 同じ NuGet パッケージひとつ でカバーできます。


なぜ "Super Light" なのか

  • 独自の設定ファイル形式は 持ちません(コードで設定する)
  • 通常のロガー取得と File Target はリフレクションや動的コード生成を使いません(GetCurrentClassLogger() だけは StackFrame を使うため AOT / trimming 時に警告)
  • 巨大な依存ツリーは 持ちません(Microsoft 純正 3パッケージのみ)
  • 内蔵シンクは log4net/NLog からの移行で必須となる File Target だけ に絞り込み(残りは M.E.L プロバイダに委譲)

シムは小さいほど、信頼できる。


変更履歴

版ごとの変更点は CHANGELOG.md を参照してください。


ライセンス

MIT License

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.17 279 9/19/2026
1.0.16 432 8/29/2026
1.0.15 216 8/29/2026
1.0.14 131 8/29/2026
1.0.13 200 8/26/2026
1.0.12 496 8/5/2026
1.0.11 123 8/5/2026
1.0.10 239 7/26/2026
1.0.9 310 6/30/2026
1.0.8 616 6/13/2026
1.0.7 1,190 5/16/2026
1.0.6 769 4/16/2026
1.0.4 137 4/14/2026
1.0.2 142 4/14/2026
1.0.0 129 4/14/2026

1.0.17: 依存パッケージと利用者向け文書を更新 — Microsoft.Extensions.* と Logging.Console を 10.0.12、Microsoft.NET.Test.Sdk を 18.10.1、xunit.v3 を 4.0.1 に更新。README の AOT、性能、障害時挙動、監視方法の説明を実装に合わせて整理。製品コードと公開 API の変更なし。 / 1.0.16: NuGet パッケージ文書を更新 — 動的 FileName の自然なパス切替とサイズ/時間アーカイブが別の保持枠になる契約、および 1.0.15 の変更履歴を同梱 README へ反映。コードと依存パッケージの変更なし。 / 1.0.15: File Target の保持管理を修正 — 動的 FileName とサイズアーカイブの保持枠を分離し、高流量日に過去日のログが削除される問題を修正。Rolling と動的 FileName の併用時にも MaxArchiveFiles を適用。 / 1.0.14: File Target の安全性と監視性を向上 — Sync / Async の内部書込み・アーカイブエラーを GetStatistics で監視可能にした。動的パストークンの Windows 予約名とピリオドセグメントを無害化。ArchiveFileName の保持掃除で無関係な兄弟ファイルを削除しないよう候補判定を強化。 / 1.0.13: File Target の信頼性向上 — AsyncFileQueue の Dispose タイムアウト時に writer / queue の所有権競合を防止。動的 FileName と ArchiveFileName の併用時も MaxArchiveFiles を適用。アーカイブエラー出力を writer lock 外へ移動。Microsoft.Extensions.* を 10.0.11 に更新。 / 1.0.12: サプライチェーン強化 — GitHub Actions の actions/setup-dotnet を v6.0.0 (SHA固定) に更新。コード変更なし。 / 1.0.11: サプライチェーン強化 — GitHub Actions の actions/checkout を v7.0.1 (SHA固定) に更新。Dependabot設定 (.github/dependabot.yml) を新規作成し、github-actions / nuget を weekly スケジュールで監視。コード変更なし。 / 1.0.10: 依存パッケージ更新 — Microsoft.Extensions.* (Logging / Logging.Abstractions / DependencyInjection.Abstractions) を 10.0.10 に更新。開発依存も最新化 (Microsoft.NET.Test.Sdk 18.8.1、AotSample の Microsoft.Extensions.Logging.Console 10.0.10)。コード変更なし。 / 1.0.9: 開発依存パッケージ更新 — Microsoft.NET.Test.Sdk を 18.6.0 から 18.7.0 に更新 (本体の依存は変更なし)。 / 1.0.8: 依存パッケージ更新 — Microsoft.Extensions.* (Logging / Logging.Abstractions / DependencyInjection.Abstractions) を 10.0.9 に更新。開発依存も最新化 (Microsoft.NET.Test.Sdk 18.6.0、AotSample の Microsoft.Extensions.Logging.Console 10.0.9)。FileTargetWriter.TemplateFileNameToGlob の XML doc を「Win32 glob」からクロスプラットフォームな検索パターン (Directory.GetFiles のパターン) 表現に修正 (挙動変更なし)。 / 1.0.7: セキュリティ強化と API surface 整理。GitHub Actions の SHA pin + permissions: contents: read 明示 + publish.yml にバージョン整合性検証 step 追加。公開拡張クラスを SLLog プレフィックス化 (ServiceCollectionExtensions → SLLogServiceCollectionExtensions / FileLoggerExtensions → SLLogFileTargetExtensions、旧クラスは削除)。LogManager に所有モデル分離: Configure(ILoggerFactory, bool ownsFactory) 新オーバーロード + UseSuperLightLogger が DI 所有 factory を保護、Configure 二度呼びのライブラリ所有 factory リーク解決。${logger} パストラバーサル防御 (LayoutRenderer に sanitizeForFilePath モード追加)、LogStructured の FormatException 吸収、ロガー自己診断 Console.Error を lock 外へ。FileTargetStatistics + FileLoggerProvider.GetStatistics() で Day-2 Ops 観測点 (discard 件数 / キュー深さ / worker エラー数) を公開。AotSample の Microsoft.Extensions.Logging.Console を 10.0.6 に統一。ビルド時 PowerShell 実行 (icon 生成) を廃止して任意コード実行サーフェスを縮小。回帰テスト 11 件追加、計 193 件すべて pass。Microsoft.Extensions.* を 10.0.8 に更新。 / 1.0.6: ホットパスのパフォーマンス最適化 — *Format 1/2/3 引数版の object[] 配列アロケーション除去、LayoutRenderer の ${level} 描画をルックアップテーブル化、TemplateFileNameToGlob の連続 * 畳み込みを 1 パス化。Microsoft.Extensions.* を 10.0.6 に更新。 / 1.0.4: LogLevel 名前衝突フリーの文字列ベース API (SLLogBuilderExtensions.SetMinimumLevel(string), FileTargetOptions.MinLevelName, SLLogLevels.Parse) と AddSuperLightFile(string fileName) ショートカットを追加。 / 1.0.2: NLog 互換の内蔵 File Target サブシステムを追加。レイアウトテンプレート、アーカイブ (Sequence/Rolling/Date/DateAndSequence)、非同期書込み。追加 NuGet 依存ゼロ・Native AOT 完全対応。 / 1.0.0: log4net 互換 API シムの初版リリース。