You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add an Helper() function to allow clients of the runtime/trace region API to create helpers but hide them from the stack traces.
The API would be similar to testing.Helper().
Use case
The region API (trace.WithRegion, trace.StartRegion) is quite intrusive: to enhance existing code with regions, one must wrap the existing block in a func(). It is even more verbose if the existing block returned values to use after the block (ex: error).
To limit the verbosity, I used generics to write wrappers around the trace.StartRegion API (see below).
Unfortunately, with Go 1.20 the go tool trace output shows the helper function as the encapsulated code instead of the real user's code. This makes the tracing annotations much less useful.
It would be helpful to have a way to declare a caller of the trace.StartRegion as an helper. The testing package has Helper() which would be a good inspiration (but a different API might be needed as runtime/trace performance is critical).
Example helpers
Example wrappers in user code that would be declared as helpers:
// traceWithRegionErr wraps [trace.WithRegion] to ease handling of failure cases.functraceWithRegionErr(ctx context.Context, regionTypestring, fnfunc() error) error {
defertrace.StartRegion(ctx, regionType).End()
err:=fn()
iferr!=nil {
returnfmt.Errorf("%s: %w", regionType, err)
}
returnnil
}
// traceWithRegion1Err1 wraps [trace.WithRegion] to ease defining a region for a function// with one input parameter and returning a value and an error.functraceWithRegion1Err1[I1any, O1any](ctx context.Context, regionTypestring, fnfunc(I1) (O1, error)) func(I1) (O1, error) {
returnfunc(i1I1) (O1, error) {
defertrace.StartRegion(ctx, regionType).End()
o1, err:=fn(i1)
iferr!=nil {
returno1, fmt.Errorf("%s: %w", regionType, err)
}
returno1, nil
}
}
// traceWithRegionCtx1Err1 wraps [trace.WithRegion] to ease defining a region for a function// with a context, another input parameter and returning a value and an error.functraceWithRegionCtx1Err1[I1any, O1any](ctx context.Context, regionTypestring, fnfunc(context.Context, I1) (O1, error)) func(I1) (O1, error) {
returnfunc(i1I1) (O1, error) {
defertrace.StartRegion(ctx, regionType).End()
o1, err:=fn(ctx, i1)
iferr!=nil {
returno1, fmt.Errorf("%s: %w", regionType, err)
}
returno1, nil
}
}
// traceWithRegionCtx31 wraps [trace.WithRegion] to ease defining a region for a function// with a context, 3 other input parameters and returning one value.functraceWithRegionCtx31[I1any, I2any, I3any, O1any](ctx context.Context, regionTypestring, fnfunc(context.Context, I1, I2, I3) O1) func(I1, I2, I3) O1 {
returnfunc(i1I1, i2I2, i3I3) O1 {
defertrace.StartRegion(ctx, regionType).End()
returnfn(ctx, i1, i2, i3)
}
}
The text was updated successfully, but these errors were encountered:
To keep traceback costs (the dominating cost) low, Helper would probably be implemented as a trace event that marks a function by name, and the filtering could be applied lazily in the trace parser.
But I also wonder if we could just do something to make the runtime/trace region API more ergonomic to begin with. I'm not certain generics are powerful enough to cover every case. One possible approach could be to annotate a function (e.g. //go:traceRegion <regionType>) and have the compiler generate a wrapper (which is a fairly straightforward transformation) assuming the first argument is a context.Context. Though, I'm not sure we'd want to add more special annotations of this form.
Add an
Helper()
function to allow clients of theruntime/trace
region API to create helpers but hide them from the stack traces.The API would be similar to
testing.Helper()
.Use case
The region API (
trace.WithRegion
,trace.StartRegion
) is quite intrusive: to enhance existing code with regions, one must wrap the existing block in afunc()
. It is even more verbose if the existing block returned values to use after the block (ex: error).To limit the verbosity, I used generics to write wrappers around the
trace.StartRegion
API (see below).Unfortunately, with Go 1.20 the
go tool trace
output shows the helper function as the encapsulated code instead of the real user's code. This makes the tracing annotations much less useful.It would be helpful to have a way to declare a caller of the
trace.StartRegion
as an helper. Thetesting
package hasHelper()
which would be a good inspiration (but a different API might be needed asruntime/trace
performance is critical).Example helpers
Example wrappers in user code that would be declared as helpers:
The text was updated successfully, but these errors were encountered: