Skip to content

Commit 47a2e39

Browse files
committed
feat: Replacing custom database ddtrace with dd-trace-go library
1 parent ae2e612 commit 47a2e39

File tree

4 files changed

+71
-287
lines changed

4 files changed

+71
-287
lines changed

go.sum

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/E
151151
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
152152
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
153153
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
154+
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
155+
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
156+
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
157+
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
154158
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
155159
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
156160
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -195,6 +199,12 @@ github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/
195199
github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk=
196200
github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
197201
github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
202+
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
203+
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
204+
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
205+
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
206+
github.com/jackc/pgx/v5 v5.4.2 h1:u1gmGDwbdRUZiwisBm/Ky2M14uQyUP65bG8+20nnyrg=
207+
github.com/jackc/pgx/v5 v5.4.2/go.mod h1:q6iHT8uDNXWiFNOlRqJzBTaSH3+2xCXkokxHZC5qWFY=
198208
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
199209
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
200210
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
@@ -250,6 +260,8 @@ github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxU
250260
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
251261
github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
252262
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
263+
github.com/microsoft/go-mssqldb v0.21.0 h1:p2rpHIL7TlSv1QrbXJUAcbyRKnIT0C9rRkH2E4OjLn8=
264+
github.com/microsoft/go-mssqldb v0.21.0/go.mod h1:+4wZTUnz/SV6nffv+RRRB/ss8jPng5Sho2SmM1l2ts4=
253265
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
254266
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
255267
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
@@ -510,8 +522,12 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
510522
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
511523
gorm.io/driver/mysql v1.4.6 h1:5zS3vIKcyb46byXZNcYxaT9EWNIhXzu0gPuvvVrwZ8s=
512524
gorm.io/driver/mysql v1.4.6/go.mod h1:SxzItlnT1cb6e1e4ZRpgJN2VYtcqJgqnHxWr4wsP8oc=
525+
gorm.io/driver/postgres v1.4.6 h1:1FPESNXqIKG5JmraaH2bfCVlMQ7paLoCreFxDtqzwdc=
526+
gorm.io/driver/postgres v1.4.6/go.mod h1:UJChCNLFKeBqQRE+HrkFUbKbq9idPXmTOk2u4Wok8S4=
513527
gorm.io/driver/sqlite v1.4.4 h1:gIufGoR0dQzjkyqDyYSCvsYR6fba1Gw5YKDqKeChxFc=
514528
gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
529+
gorm.io/driver/sqlserver v1.4.2 h1:nMtEeKqv2R/vv9FoHUFWfXfP6SskAgRar0TPlZV1stk=
530+
gorm.io/driver/sqlserver v1.4.2/go.mod h1:XHwBuB4Tlh7DqO0x7Ema8dmyWsQW7wi38VQOAFkrbXY=
515531
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
516532
gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
517533
gorm.io/gorm v1.25.3 h1:zi4rHZj1anhZS2EuEODMhDisGy+Daq9jtPrNGgbQYD8=

pkg/database/gorm.go

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,36 @@
11
package database
22

33
import (
4+
"fmt"
45
"strconv"
56
"time"
67

78
"github.com/DATA-DOG/go-txdb"
9+
gormtrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/gorm.io/gorm.v1"
810
"gorm.io/driver/mysql"
911
"gorm.io/gorm"
1012
)
1113

1214
const testEnv = "test"
1315

14-
// NewConnection returns a new Gorm database connection.
15-
func NewConnection(config *Config, environment string) (*gorm.DB, error) {
16+
// NewConnection returns a new instrumented Gorm database connection.
17+
func NewConnection(config *Config, environment, appName string) (*gorm.DB, error) {
18+
serviceName := fmt.Sprintf("%s-mysql", appName)
19+
dialector := getDialectorFromConfig(config, environment)
20+
21+
db, err := gormtrace.Open(dialector, nil, gormtrace.WithServiceName(serviceName))
22+
if err != nil {
23+
return nil, err
24+
}
25+
26+
if err := databasePoolSettings(db, config); err != nil {
27+
return nil, err
28+
}
29+
30+
return db, nil
31+
}
32+
33+
func getDialectorFromConfig(config *Config, environment string) gorm.Dialector {
1634
connectionDetails := NewConnectionDetails(config)
1735

1836
connectionString := connectionDetails.String()
@@ -29,25 +47,22 @@ func NewConnection(config *Config, environment string) (*gorm.DB, error) {
2947
connectionString = testDriverName
3048
}
3149

32-
dialector := mysql.New(mysql.Config{
50+
return mysql.New(mysql.Config{
3351
DSN: connectionString,
3452
DriverName: driverName,
3553
})
54+
}
3655

37-
db, err := gorm.Open(dialector)
38-
if err != nil {
39-
return nil, err
40-
}
41-
42-
sqlDB, err := db.DB()
56+
func databasePoolSettings(gormDB *gorm.DB, config *Config) error {
57+
db, err := gormDB.DB()
4358
if err != nil {
44-
return nil, err
59+
return err
4560
}
4661

47-
sqlDB.SetMaxIdleConns(config.Pool)
48-
sqlDB.SetMaxOpenConns(config.MaxOpenConnections)
49-
sqlDB.SetConnMaxIdleTime(config.ConnectionMaxIdleTime)
50-
sqlDB.SetConnMaxLifetime(config.ConnectionMaxLifetime)
62+
db.SetMaxIdleConns(config.Pool)
63+
db.SetMaxOpenConns(config.MaxOpenConnections)
64+
db.SetConnMaxIdleTime(config.ConnectionMaxIdleTime)
65+
db.SetConnMaxLifetime(config.ConnectionMaxLifetime)
5166

52-
return db, nil
67+
return nil
5368
}

pkg/instrumentation/database.go

Lines changed: 5 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -2,159 +2,18 @@ package instrumentation
22

33
import (
44
"context"
5-
"fmt"
6-
"strings"
75

8-
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
9-
ddtrace "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
6+
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
107
"gorm.io/gorm"
118
)
129

13-
type spanContextKey string
14-
15-
var (
16-
// ParentSpanGormKey is the name of the parent span key
17-
parentSpanGormKey = spanContextKey("trancingParentSpan")
18-
// SpanGormKey is the name of the span key
19-
spanGormKey = spanContextKey("tracingSpan")
20-
)
21-
22-
// TraceDatabase sets span to gorm settings, returns cloned DB
10+
// TraceDatabase fetches the span from the context and injects it to a new
11+
// database session's statement context.
2312
func TraceDatabase(ctx context.Context, db *gorm.DB) *gorm.DB {
2413
if ctx == nil {
2514
return db
2615
}
2716

28-
parentSpan, _ := ddtrace.SpanFromContext(ctx)
29-
30-
return db.Session(&gorm.Session{
31-
Context: context.WithValue(db.Statement.Context, parentSpanGormKey, parentSpan),
32-
})
33-
}
34-
35-
// InstrumentDatabase adds callbacks for tracing, call TraceDatabase to make it work
36-
func InstrumentDatabase(db *gorm.DB, appName string) {
37-
callbacks := newCallbacks(appName)
38-
39-
registerCallbacks(db, "create", callbacks)
40-
registerCallbacks(db, "query", callbacks)
41-
registerCallbacks(db, "update", callbacks)
42-
registerCallbacks(db, "delete", callbacks)
43-
registerCallbacks(db, "row", callbacks)
44-
}
45-
46-
type callbacks struct {
47-
serviceName string
48-
}
49-
50-
func newCallbacks(appName string) *callbacks {
51-
return &callbacks{
52-
serviceName: fmt.Sprintf("%s-%s", appName, "mysql"),
53-
}
54-
}
55-
56-
func (c *callbacks) beforeCreate(db *gorm.DB) { c.before(db, "INSERT", c.serviceName) }
57-
func (c *callbacks) afterCreate(db *gorm.DB) { c.after(db) }
58-
func (c *callbacks) beforeQuery(db *gorm.DB) { c.before(db, "SELECT", c.serviceName) }
59-
func (c *callbacks) afterQuery(db *gorm.DB) { c.after(db) }
60-
func (c *callbacks) beforeUpdate(db *gorm.DB) { c.before(db, "UPDATE", c.serviceName) }
61-
func (c *callbacks) afterUpdate(db *gorm.DB) { c.after(db) }
62-
func (c *callbacks) beforeDelete(db *gorm.DB) { c.before(db, "DELETE", c.serviceName) }
63-
func (c *callbacks) afterDelete(db *gorm.DB) { c.after(db) }
64-
func (c *callbacks) beforeRow(db *gorm.DB) { c.before(db, "", c.serviceName) }
65-
func (c *callbacks) afterRow(db *gorm.DB) { c.after(db) }
66-
func (c *callbacks) before(db *gorm.DB, operationName string, serviceName string) {
67-
if db.Statement == nil || db.Statement.Context == nil {
68-
return
69-
}
70-
71-
parentSpan, ok := db.Statement.Context.Value(parentSpanGormKey).(ddtrace.Span)
72-
if !ok {
73-
return
74-
}
75-
76-
spanOpts := []ddtrace.StartSpanOption{
77-
ddtrace.ChildOf(parentSpan.Context()),
78-
ddtrace.SpanType(ext.SpanTypeSQL),
79-
ddtrace.ServiceName(serviceName),
80-
}
81-
if operationName == "" {
82-
operationName = strings.Split(db.Statement.SQL.String(), " ")[0]
83-
}
84-
sp := ddtrace.StartSpan(operationName, spanOpts...)
85-
db.Statement.Context = context.WithValue(db.Statement.Context, spanGormKey, sp)
86-
}
87-
88-
func (c *callbacks) after(db *gorm.DB) {
89-
if db.Statement == nil || db.Statement.Context == nil {
90-
return
91-
}
92-
93-
sp, ok := db.Statement.Context.Value(spanGormKey).(ddtrace.Span)
94-
if !ok {
95-
return
96-
}
97-
98-
sp.SetTag(ext.ResourceName, strings.ToUpper(db.Statement.SQL.String()))
99-
sp.SetTag("db.table", db.Statement.Table)
100-
sp.SetTag("db.query", strings.ToUpper(db.Statement.SQL.String()))
101-
sp.SetTag("db.err", db.Error)
102-
sp.SetTag("db.count", db.RowsAffected)
103-
sp.Finish()
104-
}
105-
106-
func registerCallbacks(db *gorm.DB, name string, c *callbacks) {
107-
var err error
108-
109-
beforeName := fmt.Sprintf("tracing:%v_before", name)
110-
afterName := fmt.Sprintf("tracing:%v_after", name)
111-
gormCallbackName := fmt.Sprintf("gorm:%v", name)
112-
// gorm does some magic, if you pass CallbackProcessor here - nothing works
113-
switch name {
114-
case "create":
115-
err = db.Callback().Create().Before(gormCallbackName).Register(beforeName, c.beforeCreate)
116-
if err != nil {
117-
return
118-
}
119-
err = db.Callback().Create().After(gormCallbackName).Register(afterName, c.afterCreate)
120-
if err != nil {
121-
return
122-
}
123-
case "query":
124-
err = db.Callback().Query().Before(gormCallbackName).Register(beforeName, c.beforeQuery)
125-
if err != nil {
126-
return
127-
}
128-
err = db.Callback().Query().After(gormCallbackName).Register(afterName, c.afterQuery)
129-
if err != nil {
130-
return
131-
}
132-
case "update":
133-
err = db.Callback().Update().Before(gormCallbackName).Register(beforeName, c.beforeUpdate)
134-
if err != nil {
135-
return
136-
}
137-
err = db.Callback().Update().After(gormCallbackName).Register(afterName, c.afterUpdate)
138-
if err != nil {
139-
return
140-
}
141-
case "delete":
142-
err = db.Callback().Delete().Before(gormCallbackName).Register(beforeName, c.beforeDelete)
143-
if err != nil {
144-
return
145-
}
146-
err = db.Callback().Delete().After(gormCallbackName).Register(afterName, c.afterDelete)
147-
if err != nil {
148-
return
149-
}
150-
case "row":
151-
err = db.Callback().Row().Before(gormCallbackName).Register(beforeName, c.beforeRow)
152-
if err != nil {
153-
return
154-
}
155-
err = db.Callback().Row().After(gormCallbackName).Register(afterName, c.afterRow)
156-
if err != nil {
157-
return
158-
}
159-
}
17+
parentSpan, _ := tracer.SpanFromContext(ctx)
18+
return db.WithContext(tracer.ContextWithSpan(ctx, parentSpan))
16019
}

0 commit comments

Comments
 (0)