簡體   English   中英

Microsoft Service Fabric 和日志記錄

[英]Microsoft Service Fabric and logging

我正在研究為我的 Service Fabric 無狀態 API 實現日志記錄的最佳方法,並且對於看似相對簡單的需求的各種不同解決方案感到有些不知所措。

我已經使用WebHostBuilder().ConfigureLogging實現了日志記錄並成功地將我的跟蹤消息記錄到調試窗口並通過Serilog.Extensions.Logging.File我還設法將此日志轉儲到一個文件中,這一切都通過#if DEBUG控制#if DEBUG指令和我很滿意。

然后我需要配置部署到 Azure 中的集群時會發生什么,這讓我不知所措!!!

我認為我可以像使用AddDebug一樣注冊ServiceEventSource類型記錄器,但它並不是那么簡單。

因此,我設法使用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 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 日志記錄,請簡單查看下面我的無狀態服務類實現,它顯示了如何根據環境切換兩個不同的 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 實例被配置為一個依賴注入的實例,它可以像任何其他依賴一樣在你的控制器類中簡單地訪問,例如

    [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 就是其中之一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM