如何实现调试时将Cosmos DB客户端API请求日志输出至ILogger
Cosmos DB 调试日志与LINQ语句获取方案
1. API请求日志输出到ILogger实现
使用Cosmos DB .NET SDK V3及以上版本自带的自定义请求管道功能,无需依赖已过时的Codeplex ETL工具,即可将全量API请求日志写入ILogger,实现步骤如下:
- 实现自定义请求处理器,继承
RequestHandler,注入ILogger实例,在请求执行前后记录所需信息:
public class CosmosLoggingHandler : RequestHandler { private readonly ILogger<CosmosLoggingHandler> _logger; public CosmosLoggingHandler(ILogger<CosmosLoggingHandler> logger) { _logger = logger; } public override async Task<ResponseMessage> SendAsync(RequestMessage request, CancellationToken cancellationToken) { // 记录请求基础信息 _logger.LogInformation("Cosmos DB请求发起:[{Method}] {RequestUri}", request.Method.Method, request.RequestUri); var startTime = Stopwatch.GetTimestamp(); var response = await base.SendAsync(request, cancellationToken); var elapsedMs = Stopwatch.GetElapsedTime(startTime).TotalMilliseconds; // 记录返回结果与资源消耗 _logger.LogInformation("Cosmos DB请求完成:[{Method}] {RequestUri} | 状态码:{StatusCode} | 耗时:{ElapsedMs}ms | RU消耗:{RU}", request.Method.Method, request.RequestUri, (int)response.StatusCode, elapsedMs, response.Headers.RequestCharge); // 错误场景额外记录详情 if (!response.IsSuccessStatusCode) { string errorContent = await response.Content.ReadAsStringAsync(cancellationToken); _logger.LogError("Cosmos DB请求失败:{ErrorContent}", errorContent); } return response; } }
- 注册自定义处理器到Cosmos客户端,以ASP.NET Core依赖注入场景为例:
builder.Services.AddSingleton(s => { var logger = s.GetRequiredService<ILogger<CosmosLoggingHandler>>(); var clientOptions = new CosmosClientOptions { CustomHandlers = { new CosmosLoggingHandler(logger) } // 其他原有配置保持不变 }; return new CosmosClient("你的Cosmos DB连接字符串", clientOptions); });
2. 获取LINQ操作生成的实际查询语句
Cosmos DB .NET SDK为IQueryable提供了内置扩展方法,无需额外工具即可直接导出LINQ对应的原生SQL查询语句,示例如下:
// 构建LINQ查询 var container = cosmosClient.GetDatabase("数据库名").GetContainer("容器名"); IQueryable<YourModel> linqQuery = container.GetItemLinqQueryable<YourModel>() .Where(item => item.Category == "分类A" && item.Price > 100) .OrderByDescending(item => item.CreateTime); // 转换为查询定义获取原生SQL QueryDefinition queryDefinition = linqQuery.ToQueryDefinition(); // 获取实际生成的SQL语句 string generatedSql = queryDefinition.QueryText; // 获取参数化查询的参数值 IReadOnlyList<(string Name, object Value)> parameters = queryDefinition.Parameters;
该方法同样适用于带分页、投影、分组的LINQ查询,生成的SQL与实际执行的语句完全一致;生产环境日志输出时注意脱敏,避免把敏感参数值明文打印。
内容的提问来源于stack exchange,提问作者Ramon de Klein
相关产品推荐
相关产品推荐

