This repository has been archived by the owner on May 27, 2021. It is now read-only.
forked from DataDog/dd-trace-go
/
driver.go
91 lines (82 loc) · 2.39 KB
/
driver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package sql
import (
"context"
"database/sql"
"database/sql/driver"
"fmt"
"time"
"gopkg.in/DataDog/dd-trace-go.v1/contrib/database/sql/internal"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)
var _ driver.Driver = (*tracedDriver)(nil)
// tracedDriver wraps an inner sql driver with tracing. It implements the (database/sql).driver.Driver interface.
type tracedDriver struct {
driver.Driver
driverName string
config *registerConfig
}
// Open returns a tracedConn so that we can pass all the info we get from the DSN
// all along the tracing
func (d *tracedDriver) Open(dsn string) (c driver.Conn, err error) {
var (
meta map[string]string
conn driver.Conn
)
meta, err = internal.ParseDSN(d.driverName, dsn)
if err != nil {
return nil, err
}
conn, err = d.Driver.Open(dsn)
if err != nil {
return nil, err
}
tp := &traceParams{
driverName: d.driverName,
config: d.config,
meta: meta,
}
return &tracedConn{conn, tp}, err
}
// traceParams stores all information relative to the tracing
type traceParams struct {
config *registerConfig
driverName string
resource string
meta map[string]string
}
// tryTrace will create a span using the given arguments, but will act as a no-op when err is driver.ErrSkip.
func (tp *traceParams) tryTrace(ctx context.Context, resource string, query string, startTime time.Time, err error) {
if err == driver.ErrSkip {
// Not a user error: driver is telling sql package that an
// optional interface method is not implemented. There is
// nothing to trace here.
// See: https://github.com/DataDog/dd-trace-go/issues/270
return
}
name := fmt.Sprintf("%s.query", tp.driverName)
span, _ := tracer.StartSpanFromContext(ctx, name,
tracer.SpanType(ext.SpanTypeSQL),
tracer.ServiceName(tp.config.serviceName),
tracer.StartTime(startTime),
)
if query != "" {
resource = query
}
span.SetTag(ext.ResourceName, resource)
for k, v := range tp.meta {
span.SetTag(k, v)
}
span.Finish(tracer.WithError(err))
}
// tracedDriverName returns the name of the traced version for the given driver name.
func tracedDriverName(name string) string { return name + ".traced" }
// driverExists returns true if the given driver name has already been registered.
func driverExists(name string) bool {
for _, v := range sql.Drivers() {
if name == v {
return true
}
}
return false
}