【问题标题】:Azure Application Insights integration with GraphQL API - HotChocolate FrameworkAzure Application Insights 与 GraphQL API 的集成 - HotChocolate 框架
【发布时间】:2022-01-07 00:54:33
【问题描述】:

有没有办法将 Azure App Insights 与 Hotchoclate graphql 框架集成?目前,有多种方法可以一起破解。

像使用 REST api 一样,将所有内容纳入应用洞察中的查询细分的最佳方式是什么?

【问题讨论】:

    标签: .net azure azure-application-insights hotchocolate


    【解决方案1】:

    在 HC 中,您需要连接到诊断事件侦听器以获取管道的句柄,然后您可以从那里连接到各种事件并记录遥测数据。这里的关键是确保您将查询与查询名称区分开来,以便它在应用洞察力中正确显示,否则一切都将在 /graphql 端点上

    public class AppInsightsDiagnosticEventListener : ExecutionDiagnosticEventListener
    {
        private readonly TelemetryClient _telemetryClient;
    
        public AppInsightsDiagnosticEventListener(TelemetryClient telemetryClient) => _telemetryClient = telemetryClient;
    
        public override IDisposable ExecuteRequest(IRequestContext context)
        {
            var httpContext = GetHttpContextFrom(context);
            if (httpContext == null)
                return EmptyScope;
    
            //During debugging every playground action will come here so we want this while debugging
            #if DEBUG
            if (context.Request.OperationName == "IntrospectionQuery")
                return EmptyScope;
            #endif
    
            //Create a new telemetry request
            var operationPath = $"{context.Request.OperationName ?? "UnknownOperation"} - {context.Request.QueryHash}";
            var requestTelemetry = new RequestTelemetry()
            {
                Name = $"/graphql{operationPath}",
                Url = new Uri(httpContext.Request.GetUri().AbsoluteUri + operationPath),
            };
    
            requestTelemetry.Context.Operation.Name = $"POST /graphql/{operationPath}";
            requestTelemetry.Context.Operation.Id = GetOperationIdFrom(httpContext);
            requestTelemetry.Context.Operation.ParentId = GetOperationIdFrom(httpContext);
            requestTelemetry.Context.User.AuthenticatedUserId = httpContext.User.Identity?.Name ?? "Not authenticated";
    
            if (context.Request.Query != null)
                requestTelemetry.Properties.Add("GraphQL Query", context.Request.Query.ToString());
    
            var operation = _telemetryClient.StartOperation(requestTelemetry);
            return new ScopeWithEndAction(() => OnEndRequest(context, operation));
        }
    
        private void OnEndRequest(IRequestContext context, IOperationHolder<RequestTelemetry> operation)
        {
            var httpContext = GetHttpContextFrom(context);
            operation.Telemetry.Success = httpContext.Response.StatusCode is >= 200 and <= 299;
            operation.Telemetry.ResponseCode = httpContext.Response.StatusCode.ToString();
    
            if (context.Exception != null)
            {
                operation.Telemetry.Success = false;
                operation.Telemetry.ResponseCode = "500";
                _telemetryClient.TrackException(context.Exception);
            }
    
            if (context.ValidationResult?.HasErrors ?? false)
            {
                operation.Telemetry.Success = false;
                operation.Telemetry.ResponseCode = "400";
            }
    
            if (context.Result?.Errors != null)
            {
                foreach (var error in context.Result.Errors)
                {
                    if (error.Exception != null)
                    {
                        operation.Telemetry.Success = false;
                        _telemetryClient.TrackException(error.Exception);
                    }
                }
            }
    
            _telemetryClient.StopOperation(operation);
        }
    
        public override void RequestError(IRequestContext context, Exception exception)
        {
            _telemetryClient.TrackException(exception);
            base.RequestError(context, exception);
        }
    
        public override void ValidationErrors(IRequestContext context, IReadOnlyList<IError> errors)
        {
            foreach (var error in errors)
            {
                _telemetryClient.TrackTrace("GraphQL validation error: " + error.Message, SeverityLevel.Warning);
            }
            base.ValidationErrors(context, errors);
        }
    
        private HttpContext GetHttpContextFrom(IRequestContext context)
        {
            // This method is used to enable start/stop events for query.
            if (!context.ContextData.ContainsKey("HttpContext"))
                return null;
    
            return context.ContextData["HttpContext"] as HttpContext;
        }
    
        private string GetOperationIdFrom(HttpContext context) => context.TraceIdentifier;
    }
    
    internal class ScopeWithEndAction : IDisposable
    {
        private readonly Action _disposeAction;
    
        public ScopeWithEndAction(Action disposeAction) => _disposeAction = disposeAction;
    
        public void Dispose() => _disposeAction.Invoke();
    }
    

    在启动中

    services.AddApplicationInsightsTelemetry();
            services.AddGraphQLServer()
                .AddDiagnosticEventListener<AppInsightsDiagnosticEventListener>((sp) => new AppInsightsDiagnosticEventListener(sp.GetService<TelemetryClient>()));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-23
      • 1970-01-01
      • 1970-01-01
      • 2011-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多