Журналы дважды регистрируются в аналитике приложений при использовании Serilog в приложении Azure Function .NET 6

У меня есть приложение Azure Function в .NET 6, я использую Microsoft.Extension.Logging для ведения журнала, и все работает отлично.

Теперь у меня появилось новое требование по поддержке структурированного ведения журналов, поэтому я решил использовать Serilog, но после настройки журналы Serilog регистрируются дважды в Application Insights.

Это моя startup.cs конфигурация для Serilog

public override void Configure(IFunctionsHostBuilder builder)
{
    var telemetryConfiguration = TelemetryConfiguration.CreateDefault();
    telemetryConfiguration.ConnectionString = Settings.ApplicationInsightsConnectionString;

    // Create and initialize the dependency tracking module
    var dependencyModule = new DependencyTrackingTelemetryModule();
    dependencyModule.Initialize(telemetryConfiguration);

    // Create the custom telemetry processor
    var telemetryProcessorChainBuilder = telemetryConfiguration.DefaultTelemetrySink.TelemetryProcessorChainBuilder;
    var configuration = builder.Services.BuildServiceProvider().GetService<IConfiguration>();
    telemetryProcessorChainBuilder.Use(next => new CustomTelemetryProcessor(next, configuration));

    // Build the telemetry processor chain
    telemetryProcessorChainBuilder.Build();

    Log.Logger = new LoggerConfiguration()
                             .WriteTo.ApplicationInsights(telemetryConfiguration, TelemetryConverter.Traces)
                           .CreateLogger();

    builder.Services.AddSingleton(telemetryConfiguration);
    builder.Services.AddSingleton(typeof(IAppLogger<>), typeof(AppLogger<>));
  
    // rest of the code...
 }

Если я удалю приведенный ниже код из startup.cs, он не будет записываться дважды, и будут показаны только журналы Serilog, но я не смогу удалить этот код, так как мне также нужен специальный процессор телеметрии.

По сути, когда я регистрирую собственный процессор телеметрии, он также активирует Microsoft Logger, и поэтому я получаю журналы в два раза больше, чем я занижал.

  // Create and initialize the dependency tracking module
  var dependencyModule = new DependencyTrackingTelemetryModule();
  dependencyModule.Initialize(telemetryConfiguration);

  // Create the custom telemetry processor
  var telemetryProcessorChainBuilder = telemetryConfiguration.DefaultTelemetrySink.TelemetryProcessorChainBuilder;
  var configuration = builder.Services.BuildServiceProvider().GetService<IConfiguration>();
  telemetryProcessorChainBuilder.Use(next => new CustomTelemetryProcessor(next, configuration));

  // Build the telemetry processor chain
  telemetryProcessorChainBuilder.Build();

Как я могу зарегистрировать собственный процессор телеметрии в Serilog, не активируя регистратор Microsoft?

Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
Как установить LAMP Stack 1/2 на Azure Linux VM
Как установить LAMP Stack 1/2 на Azure Linux VM
В дополнение к нашему предыдущему сообщению о намерении Azure прекратить поддержку Azure Database для MySQL в качестве единого сервера после 16...
0
0
132
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Журналы Serilog регистрируются дважды в Application Insights.

Код ниже работал у меня и записывал только необходимые журналы, дубликатов не было:

Функция1.cs:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;

namespace FunctionApp16
{
    public class Function1
    {
        private readonly Rith_Logger<Function1> rith_lg;

        public Function1(Rith_Logger<Function1> logger)
        {
            rith_lg = logger;
        }

        [FunctionName("Function1")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req)
        {
            rith_lg.LogInformation("Hello Rithwik Bojja !!!");
            var rith_obj = new { Weight = 60, Height = 170 };
            var rith_e = 24;
            rith_lg.LogInformation("Hello the structered log is {@rith_obj} in {rith_e} age", rith_obj, rith_e);
            return new OkObjectResult("Hello Rithwik Bojja !!!");
        }
    }
}

хост.json:

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "enableLiveMetricsFilters": true,
      "samplingSettings": {
        "isEnabled": false,
        "excludedTypes": "Request"
      }
    },
    "console": {
      "isEnabled": true,
      "logLevel": {
        "default": "Information"
      }
    }
  }
}

Здесь для параметра SampleSettings установлено значение false.

Стартап.cs:

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Serilog;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.DependencyCollector;
using Microsoft.Extensions.Logging;
using Microsoft.ApplicationInsights.Channel;

[assembly: FunctionsStartup(typeof(FunctionApp16.Startup))]

namespace FunctionApp16
{
    internal class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            var rith_tc = TelemetryConfiguration.CreateDefault();
            rith_tc.ConnectionString = "InstrumentationKey=af34a9dc-f1df-4ff8-9ac9-6c1f0401ef4c;IngestionEndpoint=https://eastus-8.in.applicationinsights.azure.com/;LiveEndpoint=https://eastus.livediagnostics.monitor.azure.com/;ApplicationId=ff7a6";
            var rith_dm = new DependencyTrackingTelemetryModule();
            rith_dm.Initialize(rith_tc);
            var rit_tpb = rith_tc.DefaultTelemetrySink.TelemetryProcessorChainBuilder;
            var rih_conf = builder.Services.BuildServiceProvider().GetService<IConfiguration>();
            rit_tpb.Use(next => new CustomTelemetryProcessor(next, rih_conf));
            rit_tpb.Build();
            Log.Logger = new LoggerConfiguration()
                .WriteTo.ApplicationInsights(rith_tc, TelemetryConverter.Traces)
                .CreateLogger();
            builder.Services.AddSingleton(rith_tc);
            builder.Services.AddSingleton(typeof(Rith_Logger<>), typeof(AppLogger<>));
            builder.Services.AddLogging(loggingBuilder =>
            {
                loggingBuilder.AddSerilog(Log.Logger, dispose: true);  
            });
        }
    }
    public class CustomTelemetryProcessor : ITelemetryProcessor
    {
        private ITelemetryProcessor Next { get; set; }
        private readonly IConfiguration rith_conf;
        public CustomTelemetryProcessor(ITelemetryProcessor next, IConfiguration configuration)
        {
            Next = next;
            rith_conf = configuration;
        }
        public void Process(ITelemetry rit)
        {
            Next.Process(rit);
        }
    }
    public interface Rith_Logger<T>
    {
        void LogInformation(string rith_ms, object rith_po, int rith);
        void LogInformation(string rith_ms);
    }
    public class AppLogger<T> : Rith_Logger<T>
    {
        private readonly ILogger<T> rith_lg;

        public AppLogger(ILogger<T> logger)
        {
            rith_lg = logger;
        }
        public void LogInformation(string rith_ms, object rith_po, int rith)
        {
            rith_lg.LogInformation(rith_ms, rith_po, rith);
        }
        public void LogInformation(string rith_ms)
        {
            rith_lg.LogInformation(rith_ms);
        }
    }
}

Выход:

Мои пакеты в csproj:

    <ItemGroup>
        <PackageReference Include = "Microsoft.ApplicationInsights" Version = "2.22.0" />
        <PackageReference Include = "Microsoft.ApplicationInsights.DependencyCollector" Version = "2.22.0" />
        <PackageReference Include = "Microsoft.Azure.Functions.Extensions" Version = "1.1.0" />
        <PackageReference Include = "Microsoft.NET.Sdk.Functions" Version = "4.4.0" />
        <PackageReference Include = "Serilog.Formatting.Compact" Version = "2.0.0" />
        <PackageReference Include = "Serilog.Sinks.ApplicationInsights" Version = "4.0.0" />
        <PackageReference Include = "Serilog.Extensions.Logging" Version = "3.0.2" />
        <PackageReference Include = "Serilog.Sinks.Console" Version = "5.0.1" />
    </ItemGroup>
    

Это сработало, спасибо @RithwikBojja :), похоже, проблема была в настройке host.json, в остальном все было хорошо.

Shri 27.05.2024 07:12

Галд, это сработало @Shri

RithwikBojja 27.05.2024 07:18

Другие вопросы по теме

Функции Azure аварийно завершают работу с ошибкой ModuleNotFoundError при сборке с помощью конвейера Azure DevOps, но работают нормально при развертывании вручную
Приложение функции триггера служебной шины Azure перестает отслеживать свою очередь
Могу ли я добавить новые значения среды в приложение-функцию Azure через конвейер Azure Dev Ops?
Почему моя строка подключения развертывается как пустая через ARM и CICD?
Необходимо отобразить раскрывающийся список в триггере HTTP-функции Azure с почтовым запросом Open API
Ошибка устойчивой функции Azure: ожидается, что параметр context будет иметь тип azure.functions.Context
Невозможно получить доступ к Azure Key Vault из сценария Python через «os.environ["VAULT_URL]" — ошибка ключа: «VAULT_URL»
Как запустить функцию HTTP-триггера с помощью трепетания кнопки?
Фабрика данных Azure находит объект JSON по определенной строке/значению, а затем выбирает другое значение
Как получить HttpResponseData в промежуточном программном обеспечении после выполнения функции Azure?