pgx
pgx copied to clipboard
pgxpool: acquire wait time stats
Is your feature request related to a problem? Please describe. I'd like to better understand the impact of a fully utilized connection pool. That is the case when there is no idle connections and app tries to acquire one.
There is Stat.EmptyAcquireCount, which is a good start, but it doesn't give full picture. I'd like to be able to get a histogram of times app waited for connection
Describe the solution you'd like
Histogram could be taken if there were OnAcquireStart and OnAcquireComplete, which are called as the very first and very last operation in Pool.Acquire. Alternatively pgxpool could expose histogram in the Stat.
Describe alternatives you've considered
Creting own wrapper around Pool.Acquire func, but this requires changing all call-sites in the app.
Additional context Add any other context or screenshots about the feature request here.
Histogram could be taken if there were OnAcquireStart and OnAcquireComplete, which are called as the very first and very last operation in Pool.Acquire. Alternatively pgxpool could expose histogram in the Stat.
If this is to be done, at least some of the change should be done in the puddle library. Getting the time is cheap, but not free, and it is already done internally in the puddle acquire logic. It might make sense to add a field to puddle.Resource for acquire duration (maybe other fields to like whether a new resource was created, whether it blocked, etc.).
Then the changes in pgxpool would be smaller as well.
What we do is a bit hacky but essentially:
cfg.BeforeAcquire = func(ctx context.Context, c *pgx.Conn) bool {
t, ok := ctx.Value(contextKeyAcquired).(*time.Time)
if ok {
*t = time.Now()
}
return true
}
...
var acquired time.Time
ctx = context.WithValue(ctx, contextKeyAcquired, &acquired)
now := time.Now()
pool.Exec(ctx, ...)
waiting := acquired.Sub(now)
So even with both the above PRs, we would still not be able to get a histogram of how much time it took to acquire the connection, right?
I am not very well versed with pgx code base, but can we leverage acquire tracer to do this?
if p.acquireTracer != nil {
ctx = p.acquireTracer.TraceAcquireStart(ctx, p, TraceAcquireStartData{})
defer func() {
var conn *pgx.Conn
if c != nil {
conn = c.Conn()
}
p.acquireTracer.TraceAcquireEnd(ctx, p, TraceAcquireEndData{Conn: conn, Err: err})
}()
}
It seems like passing the start time in context in TraceAcquireStart and reading in TraceAcquireEnd and registering in a histogram would work?
+1 I need this feature