Skip to content

Some errors not captured if out of performance units #3283

@bruno-garcia

Description

@bruno-garcia

A customer on ASP.NET Core said that when they are out of performance quota, some errors are not captured.

Looking at an event, it's going through this middleware:
image

That's here:

await _next(context).ConfigureAwait(false);

Since we only capture the exception further down, I wonder if we're possibly throwing an exception somewhere here:

// The Transaction name was altered during the pipeline execution,
// That could be done by user interference or by some Event Capture
// That triggers ScopeExtensions.Populate.
if (transaction.Name != initialName)
{
_options.LogDebug(
"transaction name set from '{0}' to '{1}' during request pipeline execution.",
initialName,
transaction.Name);
}
// try to get the transaction name.
else if (context.TryGetTransactionName() is { } transactionName &&
!string.IsNullOrEmpty(transactionName))
{
_options.LogDebug(
"Changed transaction '{0}', name set to '{1}' after request pipeline executed.",
transaction.SpanId,
transactionName);
transaction.Name = transactionName;
}
transaction.SetExtra(OtelSemanticConventions.AttributeHttpResponseStatusCode, context.Response.StatusCode);
var status = SpanStatusConverter.FromHttpStatusCode(context.Response.StatusCode);
// If no Name was found for Transaction, then we don't have the route.
if (transaction.Name == string.Empty)
{
var method = context.Request.Method.ToUpperInvariant();
// If we've set a TransactionNameProvider, use that here
var customTransactionName = context.TryGetCustomTransactionName();
if (!string.IsNullOrEmpty(customTransactionName))
{
transaction.Name = $"{method} {customTransactionName}";
((TransactionTracer)transaction).NameSource = TransactionNameSource.Custom;
}
else
{
// Finally, fallback to using the URL path.
// e.g. "GET /pets/1"
var path = context.Request.Path;
transaction.Name = $"{method} {path}";
((TransactionTracer)transaction).NameSource = TransactionNameSource.Url;
}
}
if (exception is null)
{
transaction.Finish(status);
}
// Status code not yet changed to 500 but an exception does exist
// so lets avoid passing the misleading 200 down and close only with
// the exception instance that will be inferred as errored.
else if (status == SpanStatus.Ok)
{
transaction.Finish(exception);
}
else
{
transaction.Finish(exception, status);
}

And not reaching this:

if (exception is not null)
{
ExceptionDispatchInfo.Capture(exception).Throw();
}

Otherwise I'm not sure why such error would not be captured unless they are not capturing transactions (or are out of quota).

The exceptions are captured by SentryMiddleware.UnhandledException so I might be looking at it wrong as SentryMiddleware was hidden:

image

await next(context).ConfigureAwait(false);

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status

    Done

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions