getsentry / sentry

Developer-first error tracking and performance monitoring
https://sentry.io
Other
38.95k stars 4.18k forks source link

SentrySdk.CaptureException() will break my traceId search #74850

Closed drew-fc closed 2 months ago

drew-fc commented 3 months ago

Environment

SaaS (https://sentry.io/)

What are you trying to accomplish?

hi, I am using the C# SDK in an Azure Functions Isolated Worker app. I have some very simple middleware for logging exceptions. It has been working fine, but recently I wanted to enhance it with additional information, like saving the HTTP body of the request to the logs, so I learned about Scopes.

How are you getting stuck?

I updated my code to use Scopes and also to use the CaptureException() function. However, when I start using this new code, I no longer can search using my TraceID (Which I was generating with a GUID at the start). For whatever reason, it stops logging my message after I call CaptureException()?

I tried updating it to use the transaction.TraceID from Sentry instead, but the issue is still there. Here is my code


    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
        var transaction = SentrySdk.StartTransaction("FunctionExecution", "http.server");
        SentrySdk.ConfigureScope(scope => scope.Transaction = transaction);

        string traceId = transaction.TraceId.ToString(); //Guid.NewGuid().ToString();

        context.Items["TraceId"] = traceId;

        string requestBody = string.Empty;
        string queryString = string.Empty;

        try
        {
            // Capture the request body for logging later
            var httpRequestData = await context.GetHttpRequestDataAsync();
            if (httpRequestData != null)
            {
                using (var reader = new StreamReader(httpRequestData.Body, leaveOpen: true))
                {
                    requestBody = await reader.ReadToEndAsync();
                    httpRequestData.Body.Position = 0; // Reset the stream position for further processing
                }
                queryString = httpRequestData.Url.Query;
            }

            await next(context);

            // Finish the transaction successfully
            transaction.Finish();
        }
        //see https://blog.stephencleary.com/2020/06/a-new-pattern-for-exception-logging.html
        catch (ApiErrorException apiException)
        {
          //  LogException(apiException, traceId, requestBody, queryString, "ApiErrorException");
            LogException(apiException, transaction, requestBody, queryString, "ApiErrorException");

            // _logger.LogError(apiException, $"ApiException thrown {apiException.ErrorCode}, TraceId = {traceId}");
            await SendApiErrorResponse(context, traceId, apiException);
        }
        catch (AggregateException ex)
        {
            LogException(ex, transaction, requestBody,queryString, "AggregateException");
            //  _logger.LogError(ex, $"TraceId = {traceId} Unhandled AggregateException in Middleware {ex.Message}");//_logger.LogError(ex, $"TraceId = {traceId} Unhandled AggregateException in Middleware");
            await Send500ErrorResponse(context, traceId);
        }
        catch (ApplicationException ae)
        {
            LogException(ae, transaction, requestBody, queryString, "ApplicationException");
            await Send500ErrorResponse(context, traceId);
        }
        catch (Exception ex)
        {
            LogException(ex, transaction, requestBody,queryString, "Unexpected/Unhandled generic Exception");
            await Send500ErrorResponse(context,traceId);
        }
    }

    private void LogException(Exception ex, ITransactionTracer transaction, string requestBody, string queryString, string exceptionType)
    {
        //using (SentrySdk.PushScope())
        //{
            SentrySdk.ConfigureScope(scope =>
            {
                scope.SetExtra("TraceId", transaction.TraceId.ToString());
                scope.SetExtra("RequestBody", requestBody);
                scope.SetExtra("QueryString", queryString);
                scope.SetTag("ExceptionType", exceptionType);
            });

           // SentrySdk.CaptureException(ex);
        //}

        _logger.LogError(ex, $"TraceId = {transaction.TraceId} {exceptionType} in Middleware: {ex.Message}");

        // Mark the transaction as failed
        transaction.Status = SpanStatus.InternalError;
        transaction.Finish();
    }

also, here's a screenshot of the logs, you can see my TraceId isnt actually using the TraceId from Sentry?

Image

Where in the product are you?

Issues

Link

No response

DSN

No response

Version

No response

getsantry[bot] commented 3 months ago

Assigning to @getsentry/support for routing ⏲️

getsantry[bot] commented 2 months ago

Routing to @getsentry/product-owners-issues for triage ⏲️

armenzg commented 2 months ago

Hi @drew-fc This may be a better topic for the Sentry Discord server since you are doing something custom.

Nevertheless, I have noticed at least one thing:

scope.SetExtra("TraceId", transaction.TraceId.ToString()); context.Items["TraceId"] = traceId;

and later on you do this one more time:

scope.SetExtra("TraceId", transaction.TraceId.ToString());

This may be the source of discrepancy between the two different trace ID values you see.