【问题标题】:Microsoft Service Fabric and loggingMicrosoft Service Fabric 和日志记录
【发布时间】:2019-09-27 11:51:10
【问题描述】:

我正在研究为我的 Service Fabric Stateless API 实现日志记录的最佳方式,但对于看似相对简单的需求,各种不同的解决方案有点不知所措。

我已经使用WebHostBuilder().ConfigureLogging 实现了日志记录,并成功地将我的跟踪消息记录到调试窗口,并通过Serilog.Extensions.Logging.File 我还设法将此日志转储到一个文件中,这一切都通过#if DEBUG 指令进行控制这让我很满意。

然后我需要配置部署到 Azure 中的集群时会发生什么,这就是我不知所措的时候!!!

我以为我可以像注册AddDebug 一样注册ServiceEventSource 类型记录器,但事情并非如此简单。

所以我设法使用ServiceEventSource.Current.Message 让我的日志出现在诊断窗口中,但这些日志并未集成到 ASP.NET 日志框架中:/

我的持续调查使我了解到,Service Fabric 日志记录应该针对 Application Insights,尽管许多文章具有不同程度的详细信息和对最新框架的适用性。

我目前的想法是我需要删除 ASP.NET 日志记录并实现诸如 EventFlow 之类的东西,以允许生成我的跟踪消息并随后通过管道传输到 Application Insights 以便在以后进行审讯,这是我的想法对吗??

或者我目前正在切线?

【问题讨论】:

  • 您需要本地转储吗?鉴于您正在调试,您将可以立即访问代码,您是否也可以将本地数据泵送到 AI 中?
  • 感谢您的回复,我想我有一个使用 Serilog 与 Microsoft.Extensions.Logging 包集成的解决方案。关于现实世界的实现,围绕这个主题的文档很少,我很惊讶。一旦我完成了所有工作,我将记录我的流程和我用来将事情整合在一起的工具,它可能会在未来帮助其他人。
  • docs.microsoft.com/en-us/azure/azure-monitor/app/ilogger您应该能够使用此文档来启用应用程序洞察力以捕获所有基于 ILogger 的日志。

标签: c# logging .net-core azure-service-fabric


【解决方案1】:

2019 年 5 月 15 日更新
将其部署到 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.jsonappsettings.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 就是其中之一。

【讨论】:

  • 在开发我的 SF 解决方案时,我得出了与@Andrew Holloway-Breward 相同的结论。我发现ServiceEventSource 相当混乱。我改用Serilog 记录到文件,没有问题。所以我也可以推荐这种方法。
  • 我正在使用与您的日志类似的日志记录,并且使用 Service Fabric 我无法实现调试详细程度(最多达到信息级别)。在独立的网络应用程序上使用相同的设置,我没有任何问题......
  • 嗨@Marko,我们几个月前放弃了Service Fabric,并将所有内容都移到了Azure Functions中,所以我不再有我的设置,但是对详细程度的控制只是由appSettings中的MinimumLevel设置管理。 json 文件或在每个 Sink 上都有一个 RestrictedToMinimumLevel 设置。如果不了解您的问题是什么,就很难再猜测您的问题可能是什么。您要输出到 AzureBlobStorage 吗?您是否在日志文件中获得任何内容?您是否尝试过使用 Serilog.Debugging.SelfLog.Enable 方法调试 serilog?
  • 不,我正在将 lof 写入文件共享上的文件。单机版网页代码与顺丰服务网页版代码相同,所以设置相同。
猜你喜欢
  • 2023-04-06
  • 2017-12-09
  • 2018-09-07
  • 2016-09-29
  • 2016-06-13
  • 1970-01-01
  • 1970-01-01
  • 2016-12-31
  • 2011-06-17
相关资源
最近更新 更多