Skip to content

Commit c40e4f3

Browse files
committed
feat(pgdriver): improve otel instrumentation
1 parent 3d8666a commit c40e4f3

File tree

4 files changed

+80
-52
lines changed

4 files changed

+80
-52
lines changed

driver/pgdriver/driver.go

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import (
1515
"time"
1616

1717
"github.com/uptrace/bun/internal"
18+
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
19+
"go.opentelemetry.io/otel/trace"
1820
)
1921

2022
func init() {
@@ -68,38 +70,38 @@ func (d Driver) Open(name string) (driver.Conn, error) {
6870
//------------------------------------------------------------------------------
6971

7072
type Connector struct {
71-
cfg *Config
73+
conf *Config
7274
}
7375

7476
func NewConnector(opts ...Option) *Connector {
75-
c := &Connector{cfg: newDefaultConfig()}
77+
c := &Connector{conf: newDefaultConfig()}
7678
for _, opt := range opts {
77-
opt(c.cfg)
79+
opt(c.conf)
7880
}
7981
return c
8082
}
8183

8284
var _ driver.Connector = (*Connector)(nil)
8385

8486
func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) {
85-
if err := c.cfg.verify(); err != nil {
87+
if err := c.conf.verify(); err != nil {
8688
return nil, err
8789
}
88-
return newConn(ctx, c.cfg)
90+
return newConn(ctx, c.conf)
8991
}
9092

9193
func (c *Connector) Driver() driver.Driver {
9294
return Driver{connector: c}
9395
}
9496

9597
func (c *Connector) Config() *Config {
96-
return c.cfg
98+
return c.conf
9799
}
98100

99101
//------------------------------------------------------------------------------
100102

101103
type Conn struct {
102-
cfg *Config
104+
conf *Config
103105

104106
netConn net.Conn
105107
rd *reader
@@ -112,20 +114,20 @@ type Conn struct {
112114
closed int32
113115
}
114116

115-
func newConn(ctx context.Context, cfg *Config) (*Conn, error) {
116-
netConn, err := cfg.Dialer(ctx, cfg.Network, cfg.Addr)
117+
func newConn(ctx context.Context, conf *Config) (*Conn, error) {
118+
netConn, err := conf.Dialer(ctx, conf.Network, conf.Addr)
117119
if err != nil {
118120
return nil, err
119121
}
120122

121123
cn := &Conn{
122-
cfg: cfg,
124+
conf: conf,
123125
netConn: netConn,
124126
rd: newReader(netConn),
125127
}
126128

127-
if cfg.TLSConfig != nil {
128-
if err := enableSSL(ctx, cn, cfg.TLSConfig); err != nil {
129+
if conf.TLSConfig != nil {
130+
if err := enableSSL(ctx, cn, conf.TLSConfig); err != nil {
129131
return nil, err
130132
}
131133
}
@@ -134,7 +136,7 @@ func newConn(ctx context.Context, cfg *Config) (*Conn, error) {
134136
return nil, err
135137
}
136138

137-
for k, v := range cfg.ConnParams {
139+
for k, v := range conf.ConnParams {
138140
if v != nil {
139141
_, err = cn.ExecContext(ctx, fmt.Sprintf("SET %s TO $1", k), []driver.NamedValue{
140142
{Value: v},
@@ -150,6 +152,17 @@ func newConn(ctx context.Context, cfg *Config) (*Conn, error) {
150152
return cn, nil
151153
}
152154

155+
func (cn *Conn) Close() error {
156+
if !atomic.CompareAndSwapInt32(&cn.closed, 0, 1) {
157+
return nil
158+
}
159+
return cn.netConn.Close()
160+
}
161+
162+
func (cn *Conn) isClosed() bool {
163+
return atomic.LoadInt32(&cn.closed) == 1
164+
}
165+
153166
func (cn *Conn) reader(ctx context.Context, timeout time.Duration) *reader {
154167
cn.setReadDeadline(ctx, timeout)
155168
return cn.rd
@@ -174,11 +187,16 @@ func (cn *Conn) write(ctx context.Context, wb *writeBuffer) error {
174187
var _ driver.Conn = (*Conn)(nil)
175188

176189
func (cn *Conn) Prepare(query string) (driver.Stmt, error) {
190+
return cn.PrepareContext(context.Background(), query)
191+
}
192+
193+
var _ driver.ConnPrepareContext = (*Conn)(nil)
194+
195+
func (cn *Conn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
177196
if cn.isClosed() {
178197
return nil, driver.ErrBadConn
179198
}
180-
181-
ctx := context.TODO()
199+
cn.trace(ctx)
182200

183201
name := fmt.Sprintf("pgdriver-%d", cn.stmtCount)
184202
cn.stmtCount++
@@ -195,32 +213,29 @@ func (cn *Conn) Prepare(query string) (driver.Stmt, error) {
195213
return newStmt(cn, name, rowDesc), nil
196214
}
197215

198-
func (cn *Conn) Close() error {
199-
if !atomic.CompareAndSwapInt32(&cn.closed, 0, 1) {
200-
return nil
201-
}
202-
return cn.netConn.Close()
203-
}
204-
205-
func (cn *Conn) isClosed() bool {
206-
return atomic.LoadInt32(&cn.closed) == 1
207-
}
208-
209216
func (cn *Conn) Begin() (driver.Tx, error) {
210217
return cn.BeginTx(context.Background(), driver.TxOptions{})
211218
}
212219

213220
var _ driver.ConnBeginTx = (*Conn)(nil)
214221

215222
func (cn *Conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
223+
if cn.isClosed() {
224+
return nil, driver.ErrBadConn
225+
}
226+
cn.trace(ctx)
227+
216228
// No need to check if the conn is closed. ExecContext below handles that.
217229
isolation := sql.IsolationLevel(opts.Isolation)
218230

219231
var command string
220232
switch isolation {
221233
case sql.LevelDefault:
222234
command = "BEGIN"
223-
case sql.LevelReadUncommitted, sql.LevelReadCommitted, sql.LevelRepeatableRead, sql.LevelSerializable:
235+
case sql.LevelReadUncommitted,
236+
sql.LevelReadCommitted,
237+
sql.LevelRepeatableRead,
238+
sql.LevelSerializable:
224239
command = fmt.Sprintf("BEGIN; SET TRANSACTION ISOLATION LEVEL %s", isolation.String())
225240
default:
226241
return nil, fmt.Errorf("pgdriver: unsupported transaction isolation: %s", isolation.String())
@@ -244,6 +259,8 @@ func (cn *Conn) ExecContext(
244259
if cn.isClosed() {
245260
return nil, driver.ErrBadConn
246261
}
262+
cn.trace(ctx)
263+
247264
res, err := cn.exec(ctx, query, args)
248265
if err != nil {
249266
return nil, cn.checkBadConn(err)
@@ -272,6 +289,8 @@ func (cn *Conn) QueryContext(
272289
if cn.isClosed() {
273290
return nil, driver.ErrBadConn
274291
}
292+
cn.trace(ctx)
293+
275294
rows, err := cn.query(ctx, query, args)
276295
if err != nil {
277296
return nil, cn.checkBadConn(err)
@@ -301,14 +320,14 @@ func (cn *Conn) Ping(ctx context.Context) error {
301320

302321
func (cn *Conn) setReadDeadline(ctx context.Context, timeout time.Duration) {
303322
if timeout == -1 {
304-
timeout = cn.cfg.ReadTimeout
323+
timeout = cn.conf.ReadTimeout
305324
}
306325
_ = cn.netConn.SetReadDeadline(cn.deadline(ctx, timeout))
307326
}
308327

309328
func (cn *Conn) setWriteDeadline(ctx context.Context, timeout time.Duration) {
310329
if timeout == -1 {
311-
timeout = cn.cfg.WriteTimeout
330+
timeout = cn.conf.WriteTimeout
312331
}
313332
_ = cn.netConn.SetWriteDeadline(cn.deadline(ctx, timeout))
314333
}
@@ -343,8 +362,8 @@ func (cn *Conn) ResetSession(ctx context.Context) error {
343362
if cn.isClosed() {
344363
return driver.ErrBadConn
345364
}
346-
if cn.cfg.ResetSessionFunc != nil {
347-
return cn.cfg.ResetSessionFunc(ctx, cn)
365+
if cn.conf.ResetSessionFunc != nil {
366+
return cn.conf.ResetSessionFunc(ctx, cn)
348367
}
349368
return nil
350369
}
@@ -360,6 +379,16 @@ func (cn *Conn) checkBadConn(err error) error {
360379

361380
func (cn *Conn) Conn() net.Conn { return cn.netConn }
362381

382+
func (cn *Conn) trace(ctx context.Context) {
383+
if span := trace.SpanFromContext(ctx); span.IsRecording() {
384+
span.SetAttributes(
385+
semconv.DBUserKey.String(cn.conf.User),
386+
semconv.DBNameKey.String(cn.conf.Database),
387+
semconv.ServerAddressKey.String(cn.conf.Addr),
388+
)
389+
}
390+
}
391+
363392
//------------------------------------------------------------------------------
364393

365394
type rows struct {

driver/pgdriver/go.mod

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@ go 1.22.0
55
replace github.com/uptrace/bun => ../..
66

77
require (
8-
github.com/stretchr/testify v1.8.1
8+
github.com/stretchr/testify v1.10.0
99
github.com/uptrace/bun v1.2.8
10+
go.opentelemetry.io/otel v1.34.0
11+
go.opentelemetry.io/otel/trace v1.34.0
1012
mellium.im/sasl v0.3.2
1113
)
1214

1315
require (
1416
github.com/davecgh/go-spew v1.1.1 // indirect
1517
github.com/jinzhu/inflection v1.0.0 // indirect
16-
github.com/kr/text v0.1.0 // indirect
1718
github.com/pmezard/go-difflib v1.0.0 // indirect
1819
github.com/puzpuzpuz/xsync/v3 v3.4.0 // indirect
1920
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect

driver/pgdriver/go.sum

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,36 @@
1-
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
21
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
32
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
4+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
45
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
56
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
6-
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
7-
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
8-
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
7+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
8+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
99
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
1010
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
1111
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1212
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
1313
github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4=
1414
github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
15-
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
16-
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
17-
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
18-
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
19-
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
20-
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
21-
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
15+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
16+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
2217
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
2318
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
2419
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
2520
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
2621
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
2722
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
23+
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
24+
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
25+
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
26+
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
2827
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
2928
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
3029
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
3130
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
3231
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
3332
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
3433
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
35-
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
3634
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
3735
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
3836
mellium.im/sasl v0.3.2 h1:PT6Xp7ccn9XaXAnJ03FcEjmAn7kK1x7aoXV6F+Vmrl0=

driver/pgdriver/proto.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -200,12 +200,12 @@ func writeStartup(ctx context.Context, cn *Conn) error {
200200
wb.StartMessage(0)
201201
wb.WriteInt32(196608)
202202
wb.WriteString("user")
203-
wb.WriteString(cn.cfg.User)
203+
wb.WriteString(cn.conf.User)
204204
wb.WriteString("database")
205-
wb.WriteString(cn.cfg.Database)
206-
if cn.cfg.AppName != "" {
205+
wb.WriteString(cn.conf.Database)
206+
if cn.conf.AppName != "" {
207207
wb.WriteString("application_name")
208-
wb.WriteString(cn.cfg.AppName)
208+
wb.WriteString(cn.conf.AppName)
209209
}
210210
wb.WriteString("")
211211
wb.FinishMessage()
@@ -239,7 +239,7 @@ func auth(ctx context.Context, cn *Conn, rd *reader) error {
239239
}
240240

241241
func authCleartext(ctx context.Context, cn *Conn, rd *reader) error {
242-
if err := writePassword(ctx, cn, cn.cfg.Password); err != nil {
242+
if err := writePassword(ctx, cn, cn.conf.Password); err != nil {
243243
return err
244244
}
245245
return readAuthOK(cn, rd)
@@ -280,7 +280,7 @@ func authMD5(ctx context.Context, cn *Conn, rd *reader) error {
280280
return err
281281
}
282282

283-
secret := "md5" + md5s(md5s(cn.cfg.Password+cn.cfg.User)+string(b))
283+
secret := "md5" + md5s(md5s(cn.conf.Password+cn.conf.User)+string(b))
284284
if err := writePassword(ctx, cn, secret); err != nil {
285285
return err
286286
}
@@ -329,7 +329,7 @@ loop:
329329
}
330330

331331
creds := sasl.Credentials(func() (Username, Password, Identity []byte) {
332-
return []byte(cn.cfg.User), []byte(cn.cfg.Password), nil
332+
return []byte(cn.conf.User), []byte(cn.conf.Password), nil
333333
})
334334
client := sasl.NewClient(saslMech, creds)
335335

0 commit comments

Comments
 (0)