我在 .NET 8 REST API 中记录缓慢查询的请求详细信息时遇到问题。我正在利用
Microsoft.EntityFrameworkCore
(v8.0.0) 的拦截器功能来捕获缓慢的查询并尝试将它们记录到 Azure Application Insights。但是,日志没有出现在 Application Insights 中。
详情
代码
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 日志记录结合使用是否需要任何特定配置?
任何人都可以通过提供指导来帮助我吗?
我能够通过将 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 的痕迹。