@@ -30,6 +30,7 @@ import (
3030 "github.com/cockroachdb/cockroach/pkg/util/metamorphic"
3131 "github.com/cockroachdb/cockroach/pkg/util/timeutil"
3232 "github.com/cockroachdb/cockroach/pkg/util/tracing"
33+ "github.com/cockroachdb/crlib/crtime"
3334 "github.com/cockroachdb/errors"
3435)
3536
@@ -329,7 +330,7 @@ func (g *routineGenerator) startInternal(ctx context.Context, txn *kv.Txn) (err
329330 rrw := NewRowResultWriter (& g .rch )
330331 var cursorHelper * plpgsqlCursorHelper
331332 err = g .expr .ForEachPlan (ctx , ef , rrw , g .args ,
332- func (plan tree.RoutinePlan , stmt tree.RoutineBodyStmt , isFinalPlan bool ) error {
333+ func (plan tree.RoutinePlan , stmt tree.RoutineBodyStmt , latencyRecorder * tree. RoutineStatementLatencyRecorder , isFinalPlan bool ) error {
333334 stmtIdx ++
334335 opName := "routine-stmt-" + g .expr .Name + "-" + strconv .Itoa (stmtIdx )
335336 ctx , sp := tracing .ChildSpan (ctx , opName )
@@ -372,26 +373,30 @@ func (g *routineGenerator) startInternal(ctx context.Context, txn *kv.Txn) (err
372373
373374 // Run the plan.
374375 params := runParams {ctx , g .p .ExtendedEvalContext (), g .p }
375- var builder sqlstats.RecordedStatementStatsBuilder [sqlstats. StatementLatencyRecorder , topLevelQueryStats , PlanInfo ]
376+ var builder sqlstats.RecordedStatementStatsBuilder [* tree. RoutineStatementLatencyRecorder , topLevelQueryStats , PlanInfo ]
376377 if stmt .FingerprintId != 0 {
377- builder = sqlstats .NewRecordedStatementStatsBuilder [sqlstats. StatementLatencyRecorder , topLevelQueryStats , PlanInfo ](
378+ builder = sqlstats .NewRecordedStatementStatsBuilder [* tree. RoutineStatementLatencyRecorder , topLevelQueryStats , PlanInfo ](
378379 appstatspb .StmtFingerprintID (stmt .FingerprintId ),
379380 g .p .extendedEvalCtx .SessionID ,
380381 stmt .DbName ,
381382 stmt .FingerprintStr ,
382383 stmt .SummaryStr ,
383384 clusterunique.ID {},
384- stmt .StmtType , stmt . AppName ,
385- PlanInfo {
385+ stmt .StmtType ,
386+ stmt . AppName , PlanInfo {
386387 planFlags : g .p .curPlan .flags , // TODO: Is this right?
387388 planGist : explain.PlanGist {},
388389 })
389390 defer func () {
390- g .p .ExtendedEvalContext ().sqlStatsIngester .RecordStatement (builder .Build ())
391+ latencyRecorder .RecordPhase (tree .RoutineStatementEnd , crtime .NowMono ())
392+ // TODO: only record if statement stats recording is enabled. We can also avoid building the
393+ // tree.RoutineBodyStmt struct passed into this function if stats recording is disabled.
394+ g .p .ExtendedEvalContext ().sqlStatsIngester .RecordStatement (builder .LatencyRecorder (latencyRecorder ).Build ())
391395 }()
392396 }
397+ latencyRecorder .RecordPhase (tree .RoutineStatementStartExec , crtime .NowMono ())
393398 queryStats , err := runPlanInsidePlan (ctx , params , plan .(* planComponents ), w , g , stmt .StmtString )
394-
399+ latencyRecorder . RecordPhase ( tree . RoutineStatementEndExec , crtime . NowMono ())
395400 if err != nil {
396401 builder = builder .StatementError (err )
397402 return err
0 commit comments