/// <summary> /// Registers a continuation on the task. /// Within the continuation it ends the transaction and captures errors /// </summary> /// <param name="task">Task.</param> /// <param name="transaction">Transaction.</param> private void RegisterContinuation(Task task, ISpan span) { task.ContinueWith((t) => { if (t.IsFaulted) { if (t.Exception != null) { if (t.Exception is AggregateException aggregateException) { ExceptionFilter.Capture( aggregateException.InnerExceptions.Count == 1 ? aggregateException.InnerExceptions[0] : aggregateException.Flatten(), span); } else { ExceptionFilter.Capture(t.Exception, span); } } else { span.CaptureError("Task faulted", "A task faulted", new StackTrace().GetFrames()); } } else if (t.IsCanceled) { if (t.Exception == null) { span.CaptureError("Task canceled", "A task was canceled", new StackTrace().GetFrames()); //TODO: this async stacktrace is hard to use, make it readable! } else { span.CaptureException(t.Exception); } } span.End(); }, System.Threading.CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); }
private static void RegisterError(ISpan span, IApiCallDetails response) { if (response.Success) { return; } var exception = response.OriginalException ?? response.AuditTrail.FirstOrDefault(a => a.Exception != null)?.Exception; var f = PipelineFailure.Unexpected; // report inner exception stack traces for these directly if possible if (exception is ElasticsearchClientException es) { f = es.FailureReason ?? f; exception = es.InnerException ?? es; } if (exception is UnexpectedElasticsearchClientException un) { f = un.FailureReason ?? f; exception = un.InnerException ?? un; } var culprit = "Client Error"; var message = $"{f.GetStringValue()} {exception?.Message}"; var stackFrames = exception == null ? null : new StackTrace(exception, true).GetFrames(); if (stackFrames == null || stackFrames.Length == 0) { stackFrames = new StackTrace(true).GetFrames(); } var causeOnServer = false; if (response.ResponseBodyInBytes != null) { using var memoryStream = new MemoryStream(response.ResponseBodyInBytes); if (ServerError.TryCreate(memoryStream, out var serverError) && serverError != null) { causeOnServer = true; culprit = $"Elasticsearch Server Error: {serverError.Error.Type}"; message = $"The server returned a ({response.HttpStatusCode}) and indicated: " + ( serverError.Error?.CausedBy?.Reason ?? serverError.Error?.CausedBy?.Type ?? serverError.Error?.RootCause.FirstOrDefault()?.Reason ?? serverError.Error?.Reason ?? "Response did not indicate a server error, usually means no json was with an error key was returned."); } } if (exception == null && !causeOnServer) { return; } if (causeOnServer && string.IsNullOrEmpty(message)) { return; } if (causeOnServer) { span.CaptureError(message, culprit, stackFrames); } else { span.CaptureException(exception); } }