杭州电子商务研究院

为 GraphQL.NET 服务器配置适用于 .NET 的 Azure Application Insights SDK

2020-10-19 08:00飞浪

介绍

GraphQL 正成为一项越来越重要的技术。许多大公司(例如 GitHub、Coursea,当然还有 Facebook(GraphQL 的创建者))都采用了它。但是,由于 GraphQL 的设计与传输无关,因此它不依赖 HTTP 状态代码将错误传达给客户端。这意味着您需要更新监视和日志记录代码以适应 GraphQL。在本指南中,您将学习如何使用 Azure Application Insights 配置GraphQL.NET 服务器以正确报告错误代码和失败的请求。

Application Insights 数据模型

Application Insights 提供与编程语言无关的数据模型,用于存储和发送来自应用程序的遥测数据。了解数据模型的基础知识对于正确将故障传达给 Azure 门户中的 Application Insights UI 非常重要。

对于 GraphQL 服务器,有三种重要的遥测类型:

  • 请求遥测:传入 GraphQL 服务器的请求。这可能是 GraphQL 查询、变更或订阅。
  • 异常遥测:发生的可能导致请求失败的错误
  • 依赖项遥测:您的服务器可能依赖于第三方系统,例如其他 REST API 或数据库。依赖项遥测可以记录这些依赖项是成功还是失败以及执行所需的时间等信息。

上述遥测可以分组为一个操作。对于 GraphQL 服务器,此操作将在客户端发出变更、查询或订阅请求时开始。因此,操作的根源将是请求遥测,其中可能包含嵌套遥测甚至操作。这种分组使得在请求中查找相关日志并了解故障(例如超时)变得容易。

使用请求遥测记录 GraphQL 操作

如果您在 ASP.NET Core 服务器中使用 GraphQL.NET,则Microsoft.ApplicationInsights.AspetNetCore中打包的默认中间件不足以正确报告失败的 GraphQL 操作。此外,此中间件是基于端点的。这意味着您的所有请求都将分组到/graphql下,这使得了解 GraphQL 服务器的使用模式变得更加困难。

解决此问题的一种简单方法是将GraphQL.Server.Internal.DefaultGraphQLExecuter<TSchema>子类化,并将 GraphQL 查询和ExecutionResult映射到 Application Insights 数据模型。以下代码片段演示了如何执行此操作。

      public class GraphQLExecutorWithDiagnostics<TSchema> : DefaultGraphQLExecuter<TSchema>
        where TSchema : GraphQL.Types.ISchema
    {
        private readonly TelemetryClient _telemetryClient;

        public GraphQLExecutorWithDiagnostics(
            TSchema schema,
            IDocumentExecuter documentExecuter,
            IOptions<GraphQLOptions> options,
            IEnumerable<IDocumentExecutionListener> listeners,
            IEnumerable<IValidationRule> validationRules,
            TelemetryClient telemetryClient)
            : base(schema, documentExecuter, options, listeners, validationRules)
        {
            _telemetryClient = telemetryClient;
        }

        public override async Task<ExecutionResult> ExecuteAsync(
            string operationName,
            string query,
            Inputs variables,
            IDictionary<string, object> context,
            CancellationToken cancellationToken = default)
        {
            using var operationHolder = _telemetryClient.StartOperation<RequestTelemetry>("GRAPHQL " + operationName);
            var telemetry = operationHolder.Telemetry;
            telemetry.Context.Operation.Name = operationHolder.Telemetry.Name;
            telemetry.Properties["Type"] = "GRAPHQL";

            var result = await base.ExecuteAsync(operationName, query, variables, context, cancellationToken);

            if (result.Errors?.Any() ?? false)
            {
                telemetry.Success = false;
                telemetry.ResponseCode = result.Errors.First().Code ?? "Faulted";
            }

            if (result.Extensions?.ContainsKey("tracing") == true)
            {
                foreach (var perf in result.Perf)
                {
                    if (perf.Subject is string perfMetricSubject)
                    {
                        operationHolder.Telemetry.Metrics[perfMetricSubject] = perf.Duration;
                    }
                }
            }

            return result;
        }
    }
    

您已创建GraphQLExecutorWithDiagnostics<TSchema>类来创建请求遥测。此类具有以下职责:

  • 如果执行结果有错误,则将请求遥测更新为success = false 。
  • 记录从客户端发送的操作名称。这对于区分 GraphQL 查询的类型很有用。在 Azure 门户中的 Application Insights UI 中,您将能够按操作名称进行筛选、分组和排序。
  • 如果 GraphQL 操作失败,则在请求遥测中设置响应代码。通常这是服务器的 HTTP 状态代码。但是,对于 GraphQL,您需要手动将其设置为 GraphQL 错误。
  • operationHolder自动创建一个秒表来测量您的请求执行所需的时间。

向请求遥测添加自定义维度

到目前为止,您已记录了有关 GraphQL 操作的一些基本详细信息,例如操作是否成功以及是否存在任何错误状态。您可以通过添加自定义维度并记录整个 GraphQL 查询文本和错误消息详细信息来扩展此功能。

为此,通过添加以下内容更新您之前创建的GraphQLExecutor :

      if (result.Errors?.Any() ?? false)
{
    telemetry.Success = false;
    telemetry.ResponseCode = result.Errors.First().Code ?? "Faulted";
    telemetry.Properties["GraphQLQuery"] = result.Query;
    Telemetry.Properties["GraphErrorData"] = JsonSerializer.Serialize(result.Errors.First().Data);
    

注意:自定义尺寸有大小限制,因此如果太大,可能会被 Application Insights SDK 截断或删除。

注册你的 GraphQLExecutor

最后,要使用增强型GraphQLExecutor ,请在Startup.cs中添加几行来告诉您的 IoC 容器如何构建您的服务。

      services.AddApplicationInsightsTelemetry();
services.AddGraphQL(_ =>
{
    _.ExposeExceptions = false;
})
.AddSystemTextJson(deserializerSettings => { }, serializerSettings => { })
.AddDataLoader();

services.RemoveAll(typeof(IGraphQLExecuter<>));
services.AddTransient(typeof(IGraphQLExecuter<>), typeof(GraphQLExecutorWithDiagnostics<>));
    

您已用自己的GraphQLExecutorWithDiagnostics替换了DefaultGraphQLExecuter。

结论

Application Insights 提供了一组丰富的功能用于监视、诊断和日志记录。为了从这些功能中受益,你需要确保你的应用程序发送有用的遥测数据。通过了解 Application Insights 数据模型的基础知识,你可以更好地观察你的应用程序。

曝光25875浏览1399