diff --git a/promql/engine.go b/promql/engine.go index 3cb1c95683..a6b3cc7234 100644 --- a/promql/engine.go +++ b/promql/engine.go @@ -937,7 +937,7 @@ func (ev *evaluator) error(err error) { } // recover is the handler that turns panics into returns from the top level of evaluation. -func (ev *evaluator) recover(ws *storage.Warnings, errp *error) { +func (ev *evaluator) recover(expr parser.Expr, ws *storage.Warnings, errp *error) { e := recover() if e == nil { return @@ -949,7 +949,7 @@ func (ev *evaluator) recover(ws *storage.Warnings, errp *error) { buf := make([]byte, 64<<10) buf = buf[:runtime.Stack(buf, false)] - level.Error(ev.logger).Log("msg", "runtime panic in parser", "err", e, "stacktrace", string(buf)) + level.Error(ev.logger).Log("msg", "runtime panic in parser", "expr", expr.String(), "err", e, "stacktrace", string(buf)) *errp = fmt.Errorf("unexpected error: %w", err) case errWithWarnings: *errp = err.err @@ -960,7 +960,7 @@ func (ev *evaluator) recover(ws *storage.Warnings, errp *error) { } func (ev *evaluator) Eval(expr parser.Expr) (v parser.Value, ws storage.Warnings, err error) { - defer ev.recover(&ws, &err) + defer ev.recover(expr, &ws, &err) v, ws = ev.eval(expr) return v, ws, nil diff --git a/promql/engine_test.go b/promql/engine_test.go index 201676b433..e71f7a7a99 100644 --- a/promql/engine_test.go +++ b/promql/engine_test.go @@ -1641,17 +1641,27 @@ load 1ms } func TestRecoverEvaluatorRuntime(t *testing.T) { - ev := &evaluator{logger: log.NewNopLogger()} + var output []interface{} + logger := log.Logger(log.LoggerFunc(func(keyvals ...interface{}) error { + output = append(output, keyvals...) + return nil + })) + ev := &evaluator{logger: logger} + + expr, _ := parser.ParseExpr("sum(up)") var err error - defer ev.recover(nil, &err) + + defer func() { + require.EqualError(t, err, "unexpected error: runtime error: index out of range [123] with length 0") + require.Contains(t, output, "sum(up)") + }() + defer ev.recover(expr, nil, &err) // Cause a runtime panic. var a []int //nolint:govet a[123] = 1 - - require.EqualError(t, err, "unexpected error") } func TestRecoverEvaluatorError(t *testing.T) { @@ -1663,7 +1673,7 @@ func TestRecoverEvaluatorError(t *testing.T) { defer func() { require.EqualError(t, err, e.Error()) }() - defer ev.recover(nil, &err) + defer ev.recover(nil, nil, &err) panic(e) } @@ -1683,7 +1693,7 @@ func TestRecoverEvaluatorErrorWithWarnings(t *testing.T) { require.EqualError(t, err, e.Error()) require.Equal(t, warnings, ws, "wrong warning message") }() - defer ev.recover(&ws, &err) + defer ev.recover(nil, &ws, &err) panic(e) }