从 NuGet
添加 Microsoft.Extensions.Logging.EventLog
,版本为 2.1.1
CM> Install-Package Microsoft.Extensions.Logging.EventLog -Version 2.1.1
在Program.cs
文件中包含命名空间Microsoft.Extensions.Logging.EventLog
这解决了我的问题。
在 .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 中,更高级的用法是在 Startup 类的 Configure 方法中添加全局异常处理程序:
更高级的用法,可以在 .Net Core 的 Startup 类的 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源内,而不是应用程序事件日志内(在我看来这样可以减少混乱)。
New-EventLog -LogName SomeApi -Source SomeApi
。 - MadMarcEventLog.WriteEntry
是Diagnostics中的一个静态方法:
System.Diagnostics.EventLog.WriteEntry(source, message, MessageType, EventId);
我已经多年来一直在调用它,而且它运行良好。与其他答案相比只需要一行代码,直接回答了提出的问题。
默认使用应用程序事件日志。使用自定义日志需要更多的工作,包括注册表键权限。
"在使用源写入第一条记录之前,您必须创建和配置事件源。... 如果操作系统尚未刷新其事件源列表,并且您尝试使用新的源写入事件,则写入操作将失败。... 您必须具有计算机上的管理员权限才能创建新的事件源。" 阅读文档:https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.eventlog.writeentry- undefined
project.json
的frameworks
部分,可以查看 https://dev59.com/S10a5IYBdhLWcg3wD1Ae 获取一些选项。 - stephen.vakil