日志记录和诊断

.NET 上的 gRPC 中的日志记录和诊断

James 牛顿-k

本文介绍如何从 gRPC 应用程序收集诊断信息,以帮助解决问题。 涵盖的主题包括:

  • 日志记录-写入到.net Core 日志记录的结构化日志。 应用程序框架使用 ILogger 来编写日志,并由用户在应用中使用其自己的日志记录。
  • 跟踪-与使用 DiaganosticSourceActivity编写的操作相关的事件。 来自诊断源的跟踪通常用于通过库(如Application InsightsOpenTelemetry)收集应用遥测数据。
  • 指标-以时间间隔表示的数据度量值,例如每秒的请求数。 使用 EventCounter 发出指标,可以使用dotnet命令行工具或Application Insights来观察指标。

日志记录

gRPC services 和 gRPC 客户端使用.Net Core 日志记录编写日志。 当你需要在应用中调试意外行为时,可以开始使用日志。

gRPC services 日志记录

警告

服务器端日志可能包含应用中的敏感信息。 请勿将原始日志从生产应用发布到 GitHub 等公共论坛。

由于 gRPC 服务托管在 ASP.NET Core 上,因此它使用 ASP.NET Core 日志记录系统。 在默认配置中,gRPC 记录的信息非常小,但这可以进行配置。 有关配置 ASP.NET Core 日志记录的详细信息,请参阅有关ASP.NET Core 日志记录的文档。

gRPC 在 Grpc 类别下添加日志。 若要从 gRPC 启用详细日志,请通过将以下项添加到 Logging中的 LogLevel 子节,将 Grpc 前缀配置为appsettings文件中的 Debug 级别:

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information",
      "Grpc": "Debug"
    }
  }
}

你还可以在Startup.cs中对此进行配置 ConfigureLogging

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureLogging(logging =>
        {
            logging.AddFilter("Grpc", LogLevel.Debug);
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

如果不使用基于 JSON 的配置,请在配置系统中设置以下配置值:

  • Logging:LogLevel:Grpc = Debug

查看配置系统的文档以确定如何指定嵌套配置值。 例如,使用环境变量时,将使用两个 _ 字符,而不是 : (例如 Logging__LogLevel__Grpc)。

建议在为应用收集更详细的诊断时使用 Debug 级别。 Trace 级别产生非常低级别的诊断,很少需要诊断应用程序中的问题。

日志记录输出示例

下面是 gRPC 服务 Debug 级别的控制台输出示例:

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 POST https://localhost:5001/Greet.Greeter/SayHello application/grpc
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'gRPC - /Greet.Greeter/SayHello'
dbug: Grpc.AspNetCore.Server.ServerCallHandler[1]
      Reading message.
info: GrpcService.GreeterService[0]
      Hello World
dbug: Grpc.AspNetCore.Server.ServerCallHandler[6]
      Sending message.
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'gRPC - /Greet.Greeter/SayHello'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 1.4113ms 200 application/grpc

访问服务器端日志

访问服务器端日志的方式取决于运行的环境。

作为控制台应用

如果在控制台应用中运行,则默认情况下应启用控制台记录器 gRPC 日志将显示在控制台中。

其他环境

如果将应用部署到另一个环境(例如 Docker、Kubernetes 或 Windows 服务),请参阅 .NET Core 和 ASP.NET Core 中的日志记录,了解有关如何配置适用于环境的日志记录提供程序的详细信息。

gRPC 客户端日志记录

警告

客户端日志可能包含应用中的敏感信息。 请勿将原始日志从生产应用发布到 GitHub 等公共论坛。

若要从 .NET 客户端获取日志,可以在创建客户端通道时设置 GrpcChannelOptions.LoggerFactory 属性。 如果要从 ASP.NET Core 的应用程序调用 gRPC 服务,则可以通过依赖关系注入(DI)来解析记录器工厂:

[ApiController]
[Route("[controller]")]
public class GreetingController : ControllerBase
{
    private ILoggerFactory _loggerFactory;

    public GreetingController(ILoggerFactory loggerFactory)
    {
        _loggerFactory = loggerFactory;
    }

    [HttpGet]
    public async Task<ActionResult<string>> Get(string name)
    {
        var channel = GrpcChannel.ForAddress("https://localhost:5001",
            new GrpcChannelOptions { LoggerFactory = _loggerFactory });
        var client = new Greeter.GreeterClient(channel);

        var reply = await client.SayHelloAsync(new HelloRequest { Name = name });
        return Ok(reply.Message);
    }
}

启用客户端日志记录的另一种方法是使用gRPC 客户端工厂来创建客户端。 向客户端工厂注册并从 DI 解析的 gRPC 客户端将自动使用应用的配置日志记录。

如果你的应用未使用 DI,则可以使用server.loggerfactory创建新的 ILoggerFactory 实例。 若要访问此方法,请向应用程序中添加 ""。

var loggerFactory = LoggerFactory.Create(logging =>
{
    logging.AddConsole();
    logging.SetMinimumLevel(LogLevel.Debug);
});

var channel = GrpcChannel.ForAddress("https://localhost:5001",
    new GrpcChannelOptions { LoggerFactory = loggerFactory });

var client = Greeter.GreeterClient(channel);

gRPC 客户端日志范围

GRPC 客户端向 gRPC 调用期间创建的日志添加日志记录范围 作用域具有与 gRPC 调用相关的元数据:

  • GrpcMethodType -gRPC 方法类型。 可能的值是来自 Grpc.Core.MethodType 枚举的名称,如一元
  • GrpcUri -gRPC 方法的相对 URI,例如/greet。Greeter/SayHellos

日志记录输出示例

下面是 gRPC 客户端 Debug 级别的控制台输出示例:

dbug: Grpc.Net.Client.Internal.GrpcCall[1]
      Starting gRPC call. Method type: 'Unary', URI: 'https://localhost:5001/Greet.Greeter/SayHello'.
dbug: Grpc.Net.Client.Internal.GrpcCall[6]
      Sending message.
dbug: Grpc.Net.Client.Internal.GrpcCall[1]
      Reading message.
dbug: Grpc.Net.Client.Internal.GrpcCall[4]
      Finished gRPC call.

跟踪

gRPC services 和 gRPC 客户端使用DiagnosticSource活动提供有关 gRPC 调用的信息。

  • .NET gRPC 使用活动表示 gRPC 调用。
  • 跟踪事件将写入到 gRPC call 活动开始和结束时的诊断源。
  • 跟踪不会捕获有关消息在 gRPC 流调用的生存期内发送的信息。

gRPC 服务跟踪

gRPC services 在 ASP.NET Core 上托管,它报告有关传入 HTTP 请求的事件。 gRPC 特定的元数据添加到 ASP.NET Core 提供的现有 HTTP 请求诊断。

  • 诊断源名称为 Microsoft.AspNetCore
  • 活动名称为 Microsoft.AspNetCore.Hosting.HttpRequestIn
    • GRPC 调用调用的 gRPC 方法的名称将添加为 grpc.method名称的标记。
    • 完成后,gRPC 调用的状态代码将添加为名称为 grpc.status_code的标记。

gRPC 客户端跟踪

.NET gRPC 客户端使用 HttpClient 进行 gRPC 调用。 尽管 HttpClient 会写入诊断事件,但 .NET gRPC 客户端提供自定义诊断源、活动和事件,以便可以收集有关 gRPC 调用的完整信息。

  • 诊断源名称为 Grpc.Net.Client
  • 活动名称为 Grpc.Net.Client.GrpcOut
    • GRPC 调用调用的 gRPC 方法的名称将添加为 grpc.method名称的标记。
    • 完成后,gRPC 调用的状态代码将添加为名称为 grpc.status_code的标记。

正在收集跟踪

使用 DiagnosticSource 的最简单方法是在应用程序中配置遥测库,如Application InsightsOpenTelemetry 库将处理有关 gRPC 调用的信息,以及其他应用遥测。

可以在托管服务(如 Application Insights)中查看跟踪,也可以选择运行自己的分布式跟踪系统。 OpenTelemetry 支持将跟踪数据导出到JaegerZipkin

DiagnosticSource 可以使用 DiagnosticListener使用代码中的跟踪事件。 有关使用代码侦听诊断源的信息,请参阅DiagnosticSource 用户指南

备注

遥测库不捕获当前特定 Grpc.Net.Client.GrpcOut 遥测。 改善了捕获此跟踪的遥测库的工作正在进行中。

度量值

度量值是一种基于时间间隔的数据度量值,例如每秒的请求数。 使用度量值数据可以在高级别观察应用的状态。 使用 EventCounter发出 .NET gRPC 指标。

gRPC 服务指标

Grpc.AspNetCore.Server 事件源上报告 gRPC 服务器指标。

名称 说明
total-calls 总调用数
current-calls 当前调用
calls-failed 失败的调用总数
calls-deadline-exceeded 超过总调用截止时间
messages-sent 发送的邮件总数
messages-received 收到的消息总数
calls-unimplemented 未实现的总调用数

ASP.NET Core 还在 Microsoft.AspNetCore.Hosting 事件源上提供其自己的度量值。

gRPC 客户端指标

Grpc.Net.Client 事件源上报告 gRPC 客户端指标。

名称 说明
total-calls 总调用数
current-calls 当前调用
calls-failed 失败的调用总数
calls-deadline-exceeded 超过总调用截止时间
messages-sent 发送的邮件总数
messages-received 收到的消息总数

观察指标

dotnet是一种性能监视工具,用于即席运行状况监视和一级性能调查。 使用 Grpc.AspNetCore.ServerGrpc.Net.Client 作为提供程序名称监视 .NET 应用程序。

> dotnet-counters monitor --process-id 1902 Grpc.AspNetCore.Server

Press p to pause, r to resume, q to quit.
    Status: Running
[Grpc.AspNetCore.Server]
    Total Calls                                 300
    Current Calls                               5
    Total Calls Failed                          0
    Total Calls Deadline Exceeded               0
    Total Messages Sent                         295
    Total Messages Received                     300
    Total Calls Unimplemented                   0

观察 gRPC 度量值的另一种方法是使用 Application Insights 的EventCounterCollector 包捕获计数器数据。 设置后,Application Insights 在运行时收集常见的 .NET 计数器。 默认情况下,不收集 gRPC 的计数器,但可以自定义 App Insights 以包括其他计数器

指定 gRPC 计数器,以便在Startup.cs中收集 Application insights:

    using Microsoft.ApplicationInsights.Extensibility.EventCounterCollector;

    public void ConfigureServices(IServiceCollection services)
    {
        //... other code...

        services.ConfigureTelemetryModule<EventCounterCollectionModule>(
            (module, o) =>
            {
                // Configure App Insights to collect gRPC counters gRPC services hosted in an ASP.NET Core app
                module.Counters.Add(new EventCounterCollectionRequest("Grpc.AspNetCore.Server", "current-calls"));
                module.Counters.Add(new EventCounterCollectionRequest("Grpc.AspNetCore.Server", "total-calls"));
                module.Counters.Add(new EventCounterCollectionRequest("Grpc.AspNetCore.Server", "calls-failed"));
            }
        );
    }

其他资源