@@ -12,6 +12,8 @@ import (
1212 "errors"
1313 "fmt"
1414 "runtime"
15+ "runtime/pprof"
16+ "runtime/trace"
1517 "strconv"
1618 "sync"
1719 "time"
@@ -37,11 +39,12 @@ func New(ctx context.Context, p *pgxpool.Pool) (*Locker, error) {
3739 panic (fmt .Sprintf ("%s:%d: db lock pool not closed" , file , line ))
3840 })
3941 go l .run (ctx )
40- go l .ping ()
42+ go l .ping (ctx )
4143
4244 // Wait until a connection is established or the passed context times out.
4345 ready := make (chan struct {})
4446 go func () {
47+ pprof .SetGoroutineLabels (pprof .WithLabels (ctx , pprof .Labels (tracelabel , `ready` )))
4548 l .rc .L .Lock ()
4649 defer l .rc .L .Unlock ()
4750 for l .conn == nil && l .gen != - 1 {
8992
9093// Run pulls a connection out of the pool and runs the reconnect loop.
9194func (l * Locker ) run (ctx context.Context ) {
95+ ctx = pprof .WithLabels (ctx , pprof .Labels (tracelabel , `run` ))
96+ pprof .SetGoroutineLabels (ctx )
9297 ctx = zlog .ContextWithValues (ctx , "component" , "internal/ctxlock/Locker.run" )
9398 for {
9499 tctx , done := context .WithTimeout (ctx , 5 * time .Second )
@@ -165,7 +170,8 @@ func (l *Locker) reconnect(ctx context.Context) func(*pgxpool.Conn) error {
165170}
166171
167172// Ping wakes up the reconnect loop periodically.
168- func (l * Locker ) ping () {
173+ func (l * Locker ) ping (ctx context.Context ) {
174+ pprof .SetGoroutineLabels (pprof .WithLabels (ctx , pprof .Labels (tracelabel , `ping` )))
169175 t := time .NewTicker (5 * time .Second )
170176 defer t .Stop ()
171177 leave := false
@@ -189,12 +195,13 @@ for tests. Currently, the logs always happen and throw off benchmarks.
189195
190196// TryLock attempts to lock on the provided key.
191197//
192- // If unsuccessful, an already-cancelled Context will be returned.
198+ // If unsuccessful, an already-canceled Context will be returned.
193199//
194200// If successful, the returned Context will be parented to the passed-in Context
195201// and also to the underlying connection used for the lock.
196202func (l * Locker ) TryLock (parent context.Context , key string ) (context.Context , context.CancelFunc ) {
197203 // zlog.Debug(parent).Str("key", key).Msg("trying lock")
204+ defer trace .StartRegion (parent , pkgname + ".TryLock" ).End ()
198205 child , done := context .WithCancel (parent )
199206 w , err := l .try (parent , key , done )
200207 switch {
@@ -218,9 +225,10 @@ func (l *Locker) TryLock(parent context.Context, key string) (context.Context, c
218225}
219226
220227// Lock attempts to obtain the named lock until it succeeds or the passed
221- // Context is cancelled .
228+ // Context is canceled .
222229func (l * Locker ) Lock (parent context.Context , key string ) (context.Context , context.CancelFunc ) {
223230 // zlog.Debug(parent).Str("key", key).Msg("locking")
231+ defer trace .StartRegion (parent , pkgname + ".Lock" ).End ()
224232 child , done := context .WithCancel (parent )
225233 for wait := time .Duration (500 * time .Millisecond ); ; backoff (& wait ) {
226234 w , err := l .try (parent , key , done )
@@ -271,6 +279,9 @@ func backoff(w *time.Duration) {
271279func (l * Locker ) try (ctx context.Context , key string , cf context.CancelFunc ) (* watcher , error ) {
272280 const query = `SELECT lock FROM pg_try_advisory_lock($1) lock WHERE lock = true;`
273281 kb := keyify (key )
282+ // Ideally we'd set a profiling label for the key, but labels are not
283+ // recorded for user profiles.
284+ trace .Logf (ctx , pkgname + ".try" , "trying lock for %q (%016x)" , key , kb )
274285 l .rc .L .Lock ()
275286 defer l .rc .L .Unlock ()
276287 var err error
@@ -297,7 +308,7 @@ func (l *Locker) try(ctx context.Context, key string, cf context.CancelFunc) (*w
297308 }
298309 l .cur [key ] = struct {}{}
299310 w := newWatcher (l .unlock (ctx , key , kb , l .gen , cf ))
300- go w .Watch (l .gone )
311+ go w .Watch (ctx , l .gone )
301312 return w , nil
302313}
303314
0 commit comments