事前準備
Visual Studio Codeおよび.NET SDKをインストールし、Pathが通っていることを確認してください。任意のフォルダで右クリック後、Windowsターミナルを起動して「code .」を入力しVisual Studio Codeを起動します。※ここでは「SerilogSample」フォルダで作業を進めます。
私が簡単にサンプルアプリを作成するために事前に用意してあるリポジトリをダウンロードして使用していただいても構いません(.NET 9.0で作成してあります)。
%Project root(SerilogSample)% > git clone https://github.com/TetsuroTakao/ConsoleAppBase
やっていることは、コンソールアプリ.NETテンプレートを作成して各種パッケージを追加したものです。
%Project root(SerilogSample)% > dotnet new console
%Project root(SerilogSample)% > dornet new gitignore
%Project root(SerilogSample)% > dotnet add package Microsoft.Extensions.Hosting
%Project root(SerilogSample)% > dotnet add package Microsoft.Extensions.Logging
%Project root(SerilogSample)% > dotnet add package Microsoft.Extensions.Logging.Console
%Project root(SerilogSample)% > dotnet add package Serilog
%Project root(SerilogSample)% > dotnet add package Serilog.Extensions.Logging
%Project root(SerilogSample)% > dotnet add package Serilog.Sinks.File
Program.csに以下のコードを付けてあります。Dependency injectionを使用しないロギングのサンプルですのでアプリケーションの起動ログに利用できるようにしてあります。
#region using
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using Serilog;
using Serilog.Sinks.File;
#endregion
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
Log.Logger = new LoggerConfiguration()
.WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
ILoggerFactory factory = LoggerFactory.Create(builder =>
{
builder.AddConsole();
builder.AddSerilog(Log.Logger, dispose: true);
});
Microsoft.Extensions.Logging.ILogger logger = factory.CreateLogger<Program>();
builder.Configuration.Sources.Clear();
IHostEnvironment env = builder.Environment;
builder.Configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddUserSecrets<Program>(optional: true, reloadOnChange: true);
logger.LogInformation("Hello, World!");
using IHost host = builder.Build();
await host.RunAsync();
logsフォルダは.gitignoreで除外してありますので、ダウンロード後プロジェクトルートにlogsフォルダを作成してください。
Serilogは出力のオプション
.NETのロギングは一般的にlog4netやNLogなど、.NET Core および ASP.NET Core でのサードパーティ製のログ記録フレームワークを使うことが多いと思います。Serilogは構造化されたログを出力できるので、そのようなロギングを行いたい場合に使うと有用です。
サンプルのロギングの仕組みとしては、Microsoft.Extensions.Loggingを使ってロギングを行いSerilogを使って出力するという仕組みです。サンプルのコードはこの出力の部分を差し替えられるように作成してあります。
+ <program-name>.csproj
+ <PackageReference Include="NLog" Version="5.5.0" />
+ <PackageReference Include="NLog.Extensions.Logging" Version="5.5.0" />
- <PackageReference Include="Serilog" Version="4.3.0" />
- <PackageReference Include="Serilog.Extensions.Logging" Version="9.0.2" />
- <PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
+ using NLog.Extensions.Logging;
+ using NLog.Targets;
- using Serilog;
- using Serilog.Sinks.File;
ILoggerFactory factory = LoggerFactory.Create(builder =>
{
builder.AddConsole();
+ var nlogConfig = new NLog.Config.LoggingConfiguration();
+ nlogConfig.AddRuleForAllLevels(new FileTarget("logfile") { FileName = $"{env.ContentRootPath}/logs/nlog.txt", Layout = "${longdate}|${level:uppercase=true}|${logger}|${message}" });
+ nlogConfig.AddRuleForAllLevels(new ConsoleTarget("logconsole"));
+ builder.AddNLog(nlogConfig);
- builder.AddSerilog(Log.Logger, dispose: true);
});
- var logger = factory.CreateLogger<Program>();
+ var logger = NLog.LogManager.GetCurrentClassLogger();
builder.Configuration.Sources.Clear();
builder.Configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddUserSecrets<Program>(optional: true, reloadOnChange: true);
- logger.LogInformation("Hello, World!");
+ logger.Info("Hello, NLog!/" + env.EnvironmentName);
Serilogの構造化ログ
ここでは、簡単なサンプルとして.NET Aspireのスターターテンプレートを使って、構造化されたログを書き出してみます。.NET Aspireはコンテナを使った開発を行います(.NET Aspire のセットアップとツール)ので、DockerまたはPodmanをインストールしてください。また、Visual Studio CodeのExtensionとしてC# Dev Kitをインストールしておきます。
サンプルのフォルダとは別のフォルダでVisual Studio Codeを起動し、[統合ターミナル]で以下のコマンドを入力します。%新しいプロジェクトのルートフォルダ% > dotnet new aspire-starter
%新しいプロジェクトのルートフォルダ%\AspireSample.AppHost\appsettings.jsonを追加して以下の内容を書き込みます。以下のpodmanまたはdockerは、OCI(Open Container Initiative)互換コンテナランタイムをインストールした環境にあわせてどちらかを使用してください。.NET Aspireは既定でdockerを使用します。
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Aspire.Hosting.Dcp": "Warning"
}
},
"DOTNET_ASPIRE_CONTAINER_RUNTIME": "podman"
// "DOTNET_ASPIRE_CONTAINER_RUNTIME": "docker"
}
Debugについては、launch.jsonとtasks.jsonを%新しいプロジェクトのルートフォルダ%.vscodeに作成します。
{
"configurations": [
{
"type": "coreclr",
"request": "launch",
"name": "Launch AspireSample.AppHost",
"program": "${workspaceFolder}/AspireSample.AppHost/bin/Debug/net9.0/AspireSample.AppHost.dll",
"args": [],
"cwd": "${workspaceFolder}/AspireSample.AppHost",
"stopAtEntry": false,
"preLaunchTask": "build",
"requireExactSource": false
}
]
}
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"dependsOn": "dotnet build",
"command": "dotnet",
"args": [
"build",
"${workspaceFolder}/AspireSample.AppHost/AspireSample.AppHost.csproj",
"--configuration",
"Debug",
"--no-restore"
],
"type": "process",
}
]
}
tasks.jsonのargsパラメーターについてはオフィシャルブログ「dotnet build」を参照ください。また、launch.jsonのconfigurationsパラメーターについてはオフィシャルブログ「Configuring C# debugging」を参照してください。
デバッグの準備が完了次第、Visual Studio Codeの[アクティビティバー]の[Run and Debug]を選択します。launch.jsonとtasks.jsonを%新しいプロジェクトのルートフォルダ%.vscodeに作成してあっても、buildする前は[Run and Debug]ボタンが表示されます。[Run and Debug]ボタンを選択するとbuildが開始され、Aspireの管理画面のリンクが[統合ターミナル]に表示されます。
Aspireの実行
Webフロント側のエンドポイントを選択してAspireのWebアプリ画面を表示します。
[Weather]メニューを選択して、API経由で値を取得してWeb画面に表示させることで分散ログを出力します。
管理画面に戻って[トレース]を選択すると、WebフロントのプロセスからAPIが呼び出されていることを確認できます。
OpenTelemetryとの併用
このAspireソリューションに対して、SerilogSampleの時と同じようにファイルに出力するケースとOpenTelemetryに出力するサンプルを作成しますので、%新しいプロジェクトのルートフォルダ%\AspireSample.AppHost\で前述のSerilogのNugetパッケージと「dotnet add package Serilog.Sinks.OpenTelemetry」を追加して、%新しいプロジェクトのルートフォルダ%\AspireSample.AppHost\program.csに以下のコードを追加します(OpenTelemetryは%新しいプロジェクトのルートフォルダ%\AspireSample.ServiceDefaults\Extensions.csに定義されています。ConfigureOpenTelemetryで「builder.Logging.AddOpenTelemetry」に追加できますが、ここでは解説の都合上Dependency injectionを使用しないロギングのサンプルを使ってます)。
Dependency injectionを使う場合は、GitHubのソースコードSerilog.Sinks.OpenTelemetryが参考になります。
+ #region using
+ using Microsoft.Extensions.Hosting;
+ using Microsoft.Extensions.Logging;
+ using Microsoft.Extensions.Configuration;
+ using Serilog;
+ using Serilog.Sinks.File;
+ using Serilog.Sinks.OpenTelemetry;
+ #endregion
var builder = DistributedApplication.CreateBuilder(args);
+ Log.Logger = new LoggerConfiguration()
+ .WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day)
+ .WriteTo.OpenTelemetry(endpoint: "http://127.0.0.1:4318",protocol: OtlpProtocol.Grpc)
+ .CreateLogger();
+ ILoggerFactory factory = LoggerFactory.Create(builder =>
+ {
+ builder.AddConsole();
+ builder.AddSerilog(Log.Logger, dispose: true);
+ });
+ Microsoft.Extensions.Logging.ILogger logger = factory.CreateLogger<Program>();
+ logger.LogInformation("Starting Aspire Sample Application build ApiService...");
var apiService = builder.AddProject<Projects.AspireSample_ApiService>("apiservice");
+ logger.LogInformation("Starting Aspire Sample Application build Web...");
builder.AddProject<Projects.AspireSample_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(apiService)
.WaitFor(apiService);
builder.Build().Run();