ipld-eth-server/vendor/gopkg.in/DataDog/dd-trace-go.v1/contrib/database/sql/driver.go
2018-09-11 16:30:29 -05:00

83 lines
2.0 KiB
Go

package sql
import (
"context"
"database/sql"
"database/sql/driver"
"fmt"
"gopkg.in/DataDog/dd-trace-go.v1/contrib/database/sql/internal"
"gopkg.in/DataDog/dd-trace-go.v1/ddtrace"
"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
}
func (tp *traceParams) newChildSpanFromContext(ctx context.Context, resource string, query string) ddtrace.Span {
name := fmt.Sprintf("%s.query", tp.driverName)
span, _ := tracer.StartSpanFromContext(ctx, name,
tracer.SpanType(ext.SpanTypeSQL),
tracer.ServiceName(tp.config.serviceName),
)
if query != "" {
resource = query
}
span.SetTag(ext.ResourceName, resource)
for k, v := range tp.meta {
span.SetTag(k, v)
}
return span
}
// 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
}