c# - Microsoft Service Fabric 和日志记录
问题描述
我正在研究为我的 Service Fabric 无状态 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 以供日后询问,我的想法是否正确?
还是我目前正在切线?
解决方案
更新 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
开发工具包: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
orappsettings.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 文件,以及如何通过使用UseSerilog
扩展方法将 Serilog 记录器插入到依赖注入系统中.
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();
}
}
}
在控制器中使用 Logger
因为 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 网站以获取可用接收器的完整列表,Application Insights 就是其中之一。
推荐阅读
- ios - 目标 C 显示最近的问题未定义的符号:_OBJC_CLASS_$_FIRApp
- excel - 如何在excel vba中将范围分配给命名范围?
- java - 普通类和注入类的区别
- python-3.x - 当我尝试在 Google Collab 中克隆 github 存储库时,为什么会收到“错误:命令错误,退出状态为 1”?
- reactjs - 为什么 react-image-magnify 在 swiper js 中不起作用?
- javascript - 多个动态输入 onchange 和 onblur 函数 javascript
- react-hooks - 如何使用 useState 挂钩将多个对象推送到数组中
- vue.js - Axios/Vue/Nuxt - 找出所有 API 调用何时完成
- function - 加入 PySpark 时有 right_anti 吗?
- html - Flask Jinja2 HTML/CSS 可折叠部分按钮彼此相邻而不是下方?