对于使用 Entity Framework Core 拦截器和 Azure Application Insights (.NET 8 REST API) 的慢速查询,日志记录不起作用

问题描述 投票:0回答:1

我在 .NET 8 REST API 中记录缓慢查询的请求详细信息时遇到问题。我正在利用

Microsoft.EntityFrameworkCore
(v8.0.0) 的拦截器功能来捕获缓慢的查询并尝试将它们记录到 Azure Application Insights。但是,日志没有出现在 Application Insights 中。

详情

  • 框架:.NET 8
  • 数据库:Azure SQL
  • 实体框架核心版本:8.0.0
  • Microsoft.ApplicationInsights.AspNetCore:2.21.0
  • Serilog.Sinks.ApplicationInsights:3.1.0

代码

internal sealed class QueryPerformanceInterceptor(ILogger logger) : DbCommandInterceptor
{
    private readonly ILogger _logger = logger.IsNotNull();
    private const long _slowQueryThreshold = 100; // milliseconds

    public override InterceptionResult<DbDataReader> ReaderExecuting(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult<DbDataReader> result)
    {
        Stopwatch stopwatch = Stopwatch.StartNew();

        var originalResult = base.ReaderExecuting(command, eventData, result);

        stopwatch.Stop();

        if (stopwatch.ElapsedMilliseconds > _slowQueryThreshold)
        {
            LogSlowQuery(command, stopwatch.ElapsedMilliseconds);
        }

        return originalResult;
    }

    public override ValueTask<InterceptionResult<DbDataReader>> ReaderExecutingAsync(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult<DbDataReader> result,
        CancellationToken cancellationToken = default)
    {
        Stopwatch stopwatch = Stopwatch.StartNew();

        var originalResult = base.ReaderExecuting(command, eventData, result);

        stopwatch.Stop();

        if (stopwatch.ElapsedMilliseconds > _slowQueryThreshold)
        {
            LogSlowQuery(command, stopwatch.ElapsedMilliseconds);
        }

        return new ValueTask<InterceptionResult<DbDataReader>>(result);
    }

    /// <summary>
    /// Method to log the slow query
    /// </summary>
    /// <param name="command"></param>
    /// <param name="elapsedMilliseconds"></param>
    private void LogSlowQuery(DbCommand command, long elapsedMilliseconds)
    {
        Console.WriteLine($"Slow Query ({elapsedMilliseconds} ms):  {command.CommandText}");
        _logger.LogInformation($"Slow Query ({elapsedMilliseconds} ms):  {command.CommandText}");
    }
}

参考文章:https://learn.microsoft.com/en-us/ef/core/logging-events-diagnostics/interceptors

我测试了多个 API,并且能够模拟慢速查询场景,并且在调试时能够成功执行方法

LogSlowQuery
,但在 Application Insights 中搜索跟踪时,我无法找到它

什么可能导致慢速查询的日志无法发送到 Application Insights?

将拦截器与 Application Insights 日志记录结合使用是否需要任何特定配置?

任何人都可以通过提供指导来帮助我吗?

c# azure-application-insights .net-8.0 ef-core-8.0
1个回答
0
投票

我能够通过将 Serilog Logger 注入 QueryPerformanceInterceptor 类来解决该问题。

这是最新的代码:

using Microsoft.EntityFrameworkCore.Diagnostics;
using Serilog;
using Shared.Core.GuardClauses;
using System.Data.Common;
using System.Diagnostics;

namespace DemoTest.Infrastructure;

internal sealed class QueryPerformanceInterceptor(ILogger logger) : DbCommandInterceptor
{
    private readonly ILogger _logger = logger.IsNotNull();
    private const long _slowQueryThreshold = 100; // milliseconds

    public override InterceptionResult<DbDataReader> ReaderExecuting(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult<DbDataReader> result)
    {
        Stopwatch stopwatch = Stopwatch.StartNew();

        var originalResult = base.ReaderExecuting(command, eventData, result);

        stopwatch.Stop();
        if (stopwatch.ElapsedMilliseconds > _slowQueryThreshold)
        {
            LogSlowQuery(command, stopwatch.ElapsedMilliseconds);
        }

        return originalResult;
    }


    public override ValueTask<InterceptionResult<DbDataReader>> ReaderExecutingAsync(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult<DbDataReader> result,
        CancellationToken cancellationToken = default)
    {
        Stopwatch stopwatch = Stopwatch.StartNew();

        var originalResult = base.ReaderExecuting(command, eventData, result);

        stopwatch.Stop();
        if (stopwatch.ElapsedMilliseconds > _slowQueryThreshold)
        {

            LogSlowQuery(command, stopwatch.ElapsedMilliseconds);
        }

        return new ValueTask<InterceptionResult<DbDataReader>>(result);
    }

    /// <summary>
    /// Method to log the slow query
    /// </summary>
    /// <param name="command"></param>
    /// <param name="elapsedMilliseconds"></param>
    private void LogSlowQuery(DbCommand command, long elapsedMilliseconds)
    {
        Console.WriteLine($"Slow Query ({elapsedMilliseconds} ms):  {command.CommandText}");
        _logger.Information($"Slow Query ({elapsedMilliseconds} ms):  {command.CommandText}");
    }
}

我验证了上述代码,并且能够找到现在登录到 Application Insights 的痕迹。

© www.soinside.com 2019 - 2024. All rights reserved.