Azure Application Insights 与 GraphQL 的集成 API - HotChocolate Framework
Azure Application Insights integration with GraphQL API - HotChocolate Framework
有没有办法将 Azure App Insights 与 Hotchoclate graphql 框架集成?目前,有多种方法可以一起破解它。
将所有内容都放入应用洞察中的最佳方法是什么,就像您使用 REST 一样 api
因为我必须为我最近构建的应用程序解决这个问题,所以任何人都在那里苦苦挣扎,回答我自己的问题。
在 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>()));
有没有办法将 Azure App Insights 与 Hotchoclate graphql 框架集成?目前,有多种方法可以一起破解它。
将所有内容都放入应用洞察中的最佳方法是什么,就像您使用 REST 一样 api
因为我必须为我最近构建的应用程序解决这个问题,所以任何人都在那里苦苦挣扎,回答我自己的问题。
在 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>()));