【问题标题】: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.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 就是其中之一。

【讨论】:

  • 在开发我的 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
相关资源
最近更新 更多