mayuki / Rin

Request/response Inspector middleware for ASP.NET Core
MIT License
651 stars 24 forks source link

TimelineScope is already prepared in current execution. #79

Open JanEggers opened 2 months ago

JanEggers commented 2 months ago

my app was running fine but after some time I get this:

TimelineScope is already prepared in current execution. System.InvalidOperationException: TimelineScope is already prepared in current execution. at Rin.Core.Record.TimelineScope.Prepare()

this is the code:

while (!cancellationToken.IsCancellationRequested)
{
    HttpRequestRecord? record = default;
    try
    {
        duration.Restart();

        var timelineRoot = TimelineScope.Prepare();

        record = await PreprocessAsync(timelineRoot);

        using var scope = _serviceScopeFactory.CreateScope();

       // do the work 
    }
    catch (Exception ex)
    {
        if (record != null)
        {
            record.Exception = new ExceptionData(ex);
            record.ResponseStatusCode = 500;
        }
    }
    finally
    {
        try
        {
            if (record != null)
            {
                record.Transferring = TimelineScope.Create("Transferring", TimelineEventCategory.AspNetCoreCommon);
                record.TransferringCompletedAt = DateTime.Now;
                record.Transferring?.Complete();

                record.Timeline.Complete();

                if (_options.CurrentValue.EnableRin)
                {
                    await _eventBus.PostAsync(new RequestEventMessage(EventSourceName, record, RequestEvent.CompleteRequest));
                }
            }
        }
        catch (Exception)
        {
            // ignored
        }

        await _timer.WaitForNextTickAsync(cancellationToken);
    }

I could wrap the prepare call to handle the exception but id prefere to first check if the is a scope and only if there is none create one to avoid throwing the exception in the first place but right now the current scope is internal so im missing an api to do the check

JanEggers commented 2 months ago

here is my current workaround

public ITimelineScope Prepare()
    {
        try
        {
            return TimelineScope.Prepare();
        }
        catch (Exception)
        {
            return TimelineScope.Create("root");
        }
    }