【问题标题】:How to trace a panic in a go routine when the panic causes the context to be done当恐慌导致上下文完成时如何在 go 例程中跟踪恐慌
【发布时间】:2022-01-25 03:46:45
【问题描述】:

我有一个在入站请求进入时创建的 goroutine,这是使用 Opentelemetry 进行跟踪:

        qsSpan.AddEvent("does this print? yes it does")
        go func(natsContext context.Context, nr *NewRequest) {
            defer func() {
                if panicked := recover(); panicked != nil {
                    err = fmt.Errorf("this doesn't print")
                    qsSpan.RecordError(err) // IF PANIC, HOW DO I USE qsSPAN HERE??
                    qsSpan.SetStatus(codes.Error, err.Error())
                }
            }()
            natsContext = callDatabase(natsContext, *nr) // HERE IS WHERE PANIC ORIGINATES
            defer wg.Done()
            defer func() { responseChannel <- *msg }()
            defer natsContext.Done()
            defer qsSpan.End()
        }(natsContext, nr)

我想在 qsSpan 出现恐慌时记录一个错误,但我不能,因为上下文消失了

我正在通过以下方式强制调用数据库发生恐慌:

func callDatabase(ctx context.Context, request NewRequest) context.Context {
    var callDatabaseSpan trace.Span
    ctx, callDatabaseSpan = otel.Tracer("").Start(ctx, "callDatabase")
    defer callDatabaseSpan.End()

    minTime := 2.0
    maxTime := 3.0

    time.Sleep(time.Second * (time.Duration(minTime + rand.Float64()*(maxTime-minTime)))) // simulate db doing something
    callDatabaseSpan.AddEvent(fmt.Sprintf("refreshCount: %d %s %s %s\n", request.RefreshCount, request.DbQueryToRun, request.Requestid, time.Now().String()[:24]))

    panicVar := []string{"a", "b"}

    _ = panicVar[2] // FORCE PANIC HERE

    return ctx
}

我认为问题与我的上下文在 calldatabase 引起恐慌时被终止有关,因此跟踪丢失了。但是我想使用请求进来时创建的跨度,并将恐慌记录为错误,而不是为恐慌初始化一个新的跨度

编辑:

我不想这样做(可行),我想使用 qSpan:

        qsSpan.AddEvent("does this print? yes it does")
        go func(natsContext context.Context, nr *NewRequest) {
            defer func() {
                if panicked := recover(); panicked != nil {
                    ctxPanic := context.Background()
                    var pSpan trace.Span
                    ctxPanic, pSpan = otel.Tracer("").Start(ctxPanic, "panic") // INITIALISING NEW SPAN FOR PANIC WORKS, BUT I WANT TO USE qsSPAN TO TRACE PANIC ORIGIN
                    err := fmt.Errorf("calling calldatabase caused panic")
                    pSpan.RecordError(err)
                    pSpan.SetStatus(codes.Error, err.Error())
                    pSpan.End()
                    ctxPanic.Done()
                }
            }()
            natsContext = callDatabase(natsContext, *nr)
            defer wg.Done()
            defer func() { responseChannel <- *msg }()
            defer natsContext.Done()
            defer qsSpan.End()
        }(natsContext, nr)

【问题讨论】:

  • 您可以尝试将 qsSpan 作为参数传递给 go 例程吗?
  • @SDJ 谢谢,这给了我解决这个问题的想法。我需要为内部例程创建一个跨度,用于恐慌,但不是在函数内从恐慌中恢复
  • 我很高兴它有帮助:)

标签: go concurrency trace goroutine opentracing


【解决方案1】:

感谢@SDJ 为我提供解决此问题的建议

我需要在处理数据库调用 (calldatabase) 的例程中创建一个跨度,然后使用它来记录错误/恐慌。因此,在入站请求例程和处理请求的例程内部之间创建一个中间跨度

        go func(natsContext context.Context, nr *NewRequest) {
            var hsSpan trace.Span
            natsContext, hsSpan = otel.Tracer("").Start(natsContext, "handlerequest") // CREATE THE SPAN HERE
            defer func() {
                if panicked := recover(); panicked != nil {
                    err := fmt.Errorf("calling calldatabase caused panic") // RECORD PANIC USING SPAN CREATED IN THIS ROUTINE
                    hsSpan.RecordError(err)
                    hsSpan.SetStatus(codes.Error, err.Error())
                    response = err.Error()
                    msg.Respond([]byte(response))
                } else {
                  func() { responseChannel <- *msg }() // IF NO PANIC SIGNAL THAT callDatabase DONE WHEN ROUTINE FINISHES
                }
            }()
            natsContext = callDatabase(natsContext, *nr) // CONTEXT PASSED AND RETURNED TO CONTINUE TRACING callDatabase FUNCTION
            defer wg.Done()
            defer natsContext.Done()
            defer hsSpan.End()
        }(natsContext, nr)

所以现在我有一个来自请求的跟踪,来自处理请求,并在出现恐慌时链接到那些,这样我就可以识别引发恐慌的请求的来源

【讨论】:

    猜你喜欢
    • 2018-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-21
    相关资源
    最近更新 更多