Dnxを使用しているアプリでWindowsのイベントビューアに書き込む方法が必要です。しかし、EventLog
クラスはSystem.Diagnostics
名前空間では使用できないため、行き詰まっています。 EventViewerに書き込む他の方法はありますか?
NuGet
から追加Microsoft.Extensions.Logging.EventLog
Version 2.1.1
CM> Install-Package Microsoft.Extensions.Logging.EventLog -Version 2.1.1
名前空間Microsoft.Extensions.Logging.EventLog
をProgram.cs
ファイルに含める
これで私の問題は解決しました。
2.0で利用可能ですが、互換性パックをインストールする必要があります。 https://github.com/dotnet/corefx/issues/2544
朗報です! EventLogはすでに corefxに移植されています であり、 。NET Core 2.1 で使用できるようになります。
現在、プレビューパッケージSystem.Diagnostics.EventLogを MyGet フィードからダウンロードできます。
.Net Coreでイベントログに書き込むには、最初にNugetパッケージのインストールが必要です
Install-Package Microsoft.Extensions.Logging.EventLog -Version 3.1.2
インストールする正しいバージョンは、実行している.Net Coreのバージョンによって異なることに注意してください。上記のパッケージは.Net Coreでテスト済みです。
次に、EventLogを追加する必要があります。 Programクラスでは、次のようにします。
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.EventLog;
namespace SomeAcme.SomeApi
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddEventLog(new EventLogSettings()
{
**SourceName = "SomeApi",
LogName = "SomeApi",**
Filter = (x, y) => y >= LogLevel.Warning
});
logging.AddConsole();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
また、appsettings.jsonファイルにはセットアップが含まれています。
{
"ConnectionStrings": {
"DefaultConnection": "Server=.\\SQLEXPRESS;Database=SomeApi;Trusted_Connection=True;MultipleActiveResultSets=true"
},
**"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},**
"AllowedHosts": "*"
}
ILoggerインスタンスを注入できます
using SomeAcme.SomeApi.SomeModels;
using SomeAcme.SomeApi.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
namespace SomeAcme.SomeApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class SomeController : ControllerBase
{
private readonly ISomeService _healthUnitService;
private readonly ILogger<SomeController> _logger;
public SomeController(ISomeService someService, ILogger<SomeController> logger)
{
_someService= someService;
_logger = logger;
}
// GET: api/Some
[HttpGet]
public IEnumerable<SomeModel> GetAll()
{
return _someService.GetAll();
}
}
}
より高度な使用法として、.Net CoreのスタートアップクラスのConfigureメソッド内にグローバル例外ハンドラーを追加します。
//Set up a global error handler for handling Unhandled exceptions in the API by logging it and giving a HTTP 500 Error with diagnostic information in Development and Staging
app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
context.Response.StatusCode = 500; // or another Status accordingly to Exception Type
context.Response.ContentType = "application/json";
var status = context.Features.Get<IStatusCodeReExecuteFeature>();
var error = context.Features.Get<IExceptionHandlerFeature>();
if (error != null)
{
var ex = error.Error;
string exTitle = "Http 500 Internal Server Error in SomeAcme.SomeApi occured. The unhandled error is: ";
string exceptionString = !env.IsProduction() ? (new ExceptionModel
{
Message = exTitle + ex.Message,
InnerException = ex?.InnerException?.Message,
StackTrace = ex?.StackTrace,
OccuredAt = DateTime.Now,
QueryStringOfException = status?.OriginalQueryString,
RouteOfException = status?.OriginalPath
}).ToString() : new ExceptionModel()
{
Message = exTitle + ex.Message,
OccuredAt = DateTime.Now
}.ToString();
try
{
_logger.LogError(exceptionString);
}
catch (Exception err)
{
Console.WriteLine(err);
}
await context.Response.WriteAsync(exceptionString, Encoding.UTF8);
}
});
});
そして最後に、例外情報をパックするヘルパーモデル。
using System;
using Newtonsoft.Json;
namespace SomeAcme.SomeApi.Models
{
/// <summary>
/// Exception model for generic useful information to be returned to client caller
/// </summary>
public class ExceptionModel
{
public string Message { get; set; }
public string InnerException { get; set; }
public DateTime OccuredAt { get; set; }
public string StackTrace { get; set; }
public string RouteOfException { get; set; }
public string QueryStringOfException { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
}
ここで注意が必要なのは、Startupクラス内でロガーを取得することです。このためにILoggerFactoryを注入して、次のようにすることができます。
_logger = loggerFactory.CreateLogger<Startup>();
上記のグローバルエラーハンドラーで_loggerが使用されている場合。
イベントログへの書き込み方法の問題に戻り、上記のSomeControllerのソースコードを確認します。ここにILoggerを挿入します。そのインスタンスを使用するだけで、構成されたログに書き込むためのさまざまな方法が提供されます。 Programクラスのイベントログに追加したので、これは自動的に行われます。
上記のコードをテストする前に、次のPowershellスクリプトを管理者として実行して、イベントログソースを取得します。
New-EventLog -LogName SomeApi -SourceName SomeApi
このアプローチで私が気に入っているのは、すべてを正しく実行すると、例外がアプリケーションイベントログ内ではなく、SomeApiソース内にうまく表示されることです(IMHOが乱雑になります)。