#.net #azure #azure-application-insights #hotchocolate
Вопрос:
Есть ли какой-либо способ интегрировать Azure App Insights с платформой Hotchoclate graphql? В настоящее время существует несколько способов совместного взлома.
Каков наилучший способ получить всю информацию о приложениях с разбивкой по запросам в приложении, как это было бы с помощью REST api
Ответ №1:
В HC вам нужно подключиться к прослушивателю диагностических событий, чтобы получить представление о конвейере, и оттуда вы можете подключаться к различным событиям и регистрировать телеметрию. Главное здесь-убедиться, что вы различаете запрос с именем запроса, чтобы он правильно отображался в app insights, в остальном все будет на конечной точке /graphql
public class AppInsightsDiagnosticEventListener : ExecutionDiagnosticEventListener { private readonly TelemetryClient _telemetryClient; public AppInsightsDiagnosticEventListener(TelemetryClient telemetryClient) =gt; _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(() =gt; OnEndRequest(context, operation)); } private void OnEndRequest(IRequestContext context, IOperationHolderlt;RequestTelemetrygt; operation) { var httpContext = GetHttpContextFrom(context); operation.Telemetry.Success = httpContext.Response.StatusCode is gt;= 200 and lt;= 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, IReadOnlyListlt;IErrorgt; 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) =gt; context.TraceIdentifier; } internal class ScopeWithEndAction : IDisposable { private readonly Action _disposeAction; public ScopeWithEndAction(Action disposeAction) =gt; _disposeAction = disposeAction; public void Dispose() =gt; _disposeAction.Invoke(); }
И в запуске
services.AddApplicationInsightsTelemetry(); services.AddGraphQLServer() .AddDiagnosticEventListenerlt;AppInsightsDiagnosticEventListenergt;((sp) =gt; new AppInsightsDiagnosticEventListener(sp.GetServicelt;TelemetryClientgt;()));