我正在研究为Service Fabric Stateless API实现日志记录的最佳方法,但对于似乎比较简单的要求,各种不同的解决方案使他们有些不知所措。
我已经使用WebHostBuilder().ConfigureLogging
实现了日志记录,并已将跟踪消息成功记录到Debug窗口中,并且通过Serilog.Extensions.Logging.File
我也设法将此日志转储到文件中,所有这些都通过一个#if DEBUG
指令,对此我感到很满意。
然后,我需要配置将其部署到Azure内的群集时发生的情况,这就是我不知所措的时候!!
我认为我可以用与ServiceEventSource
相同的方式注册AddDebug
类型记录器,但这并不是那么简单。
因此,我设法使用ServiceEventSource.Current.Message
使日志显示在诊断窗口中,但是这些日志未集成在ASP.NET日志框架中:/
我的不断调查使我了解到,尽管很多很多文章对最新框架的详细程度和适用性有所不同,但Service Fabric日志应该针对Application Insights。
我目前的想法是,我需要删除ASP.NET日志记录并实现诸如EventFlow
之类的东西,以允许生成跟踪消息,并随后通过管道将其传递到Application Insights以供日后查询。我的想法正确吗?
或者我当前正在切线走吗?
答案 0 :(得分:1)
更新15/05/2019
将其部署到Azure Service Fabric之后,没有填充日志文件,这似乎是Serilog.Sinks.AzureBlobStorage
NUGET程序包与我的项目所针对的.NET Core版本2.2.0之间的不兼容。
我已在GitHub页面上发布了票证并等待响应,在短期内您可以下载源代码并将项目迁移到Microsoft.NETCore.App
2.2.0项目中,并直接引用此项目,并且一切运行正常
原始答案
我似乎做了很多,回答了我自己的问题,但是又来了。我花了一两天的时间才能深入浅出,所以我想我可以与社区分享我的发现和解决方案,以防将来可能对其他人有所帮助和/或可能有人需要补充甚至矛盾。我,欢迎任何输入。
我的开发环境如下:-
Microsoft Visual Studio 15.9.11
Windows 10 Professional
SDK:Microsoft.NETCore.App 2.2.0
我创建了一个新的Service Fabric无状态服务,该服务的目的是为Angular 7前端Web应用程序提供RESTful终结点。
我的要求是在开发环境中通过“调试”窗口提供日志记录信息,并在我的应用程序托管在Azure上的Service Fabric群集中的同时提供类似的日志记录信息。
NUGET软件包安装
Microsoft.Extensions.Logging (2.2.0)
Serilog.AspNetCore (2.1.1)
Serilog.Enrichers.Environment (2.1.3)
Serilog.Settings.Configuration (3.0.1)
Serilog.Sinks.Debug (1.0.1)
Serilog.Sinks.AzureBlobStorage (1.3.0)
控制开发和生产环境
我使用DEBUG
预处理程序指令控制开发和生产环境,以包含appsettings.json
或appsettings.Development.json
文件。
我的appSettings.Development.json文件是这样的:-
{
"AppSettings": {
// My app settings not applicable to this
},
"Serilog": {
"Using": [ "Serilog.Sinks.Debug" ],
"MinimumLevel": {
"Default": "Verbose",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "Debug",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {MachineName} {Level:u3}] {Message:lj}{NewLine}{Exception}"
}
}
],
"Enrich": ["WithMachineName"]
}
}
我的appSettings.json文件是这样的:-
{
"AppSettings": {
// My app settings not applicable to this
},
"Serilog": {
"Using": [ "Serilog.Sinks.AzureBlobStorage" ],
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning"
}
},
"WriteTo": [
{
"Name": "AzureBlobStorage",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {MachineName} {Level:u3}] {Message:lj}{NewLine}{Exception}",
"connectionString": "[Connection String]",
"storageContainerName": "app",
"storageFileName": "{yyyy}-{MM}-{dd}.log"
}
}
],
"Enrich": [ "WithMachineName" ]
}
}
从上述设置文件中可以看到,在开发过程中,我将输出到“调试”窗口,并且在部署到Azure中的Service Fabric群集时,我选择了输出到Azure Blob存储。
要实现Serilog日志记录,请简单阅读下面的我的Stateless Service类实现,其中显示了如何根据环境切换两个不同的appSettings.json文件,以及如何通过使用来将Serilog记录器插入到依赖项注入系统中UseSerilog
扩展方法。
using System.Collections.Generic;
using System.Fabric;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.ServiceFabric.Services.Communication.AspNetCore;
using Microsoft.ServiceFabric.Services.Communication.Runtime;
using Microsoft.ServiceFabric.Services.Runtime;
using Serilog;
namespace Caboodal.Manatee.ServiceFabric.Api.Identity
{
internal sealed class Identity : StatelessService
{
public Identity(StatelessServiceContext context)
: base(context)
{
}
private string AppSettingsFilename
{
get
{
#if DEBUG
return "appsettings.Development.json";
#else
return "appsettings.json";
#endif
}
}
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
var appSettings = GetAppSettings();
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(appSettings)
.CreateLogger();
return new[]
{
new ServiceInstanceListener(
serviceContext =>
new KestrelCommunicationListener(
serviceContext,
"ServiceEndpoint",
(url, listener) =>
{
ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");
return new WebHostBuilder()
.UseKestrel()
.ConfigureAppConfiguration(
(builderContext, config) =>
{
config.AddJsonFile(AppSettingsFilename, false, true);
})
.ConfigureServices(
services => services
.AddSingleton(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseSerilog()
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build();
}))
};
}
private IConfigurationRoot GetAppSettings()
{
return new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(AppSettingsFilename)
.Build();
}
}
}
在控制器中使用记录器
由于ILogger实例被配置为依赖注入实例,因此可以像其他任何依赖一样,在Controller类中轻松访问它。
[Authorize]
[ApiController]
[Route("[controller]")]
public class UserController : ApiController
{
private readonly IUserService _userService;
private readonly ILogger<UserController> _logger;
public UserController(IUserService userService, ILogger<UserController> logger)
{
_userService = userService;
_logger = logger;
}
[AllowAnonymous]
[HttpPost("authenticate")]
public IActionResult Authenticate([FromBody] DtoAuthenticateRequest request)
{
// Adding log entries
_logger.Log(LogLevel.Debug, "Here is a log entry");
// Some code in here
return Ok(response);
}
}
我对ServiceEventSource.cs
类感到非常困惑,但是由于使用了Serilog,我现在忽略了项目模板的这一方面。
如果您希望将日志输出给其他数据使用者或简单地以其他格式输出,则只需查看Serilog网站here以获得可用的接收器的完整列表,其中Application Insights就是其中之一。