Source File
driver.go
Belonging Package
contrib.go.opencensus.io/integrations/ocsql
package ocsql
import (
)
type conn interface {
driver.Pinger
driver.Execer
driver.ExecerContext
driver.Queryer
driver.QueryerContext
driver.Conn
driver.ConnPrepareContext
driver.ConnBeginTx
}
var (
regMu sync.Mutex
attrMissingContext = trace.StringAttribute("ocsql.warning", "missing upstream context")
attrDeprecated = trace.StringAttribute("ocsql.warning", "database driver uses deprecated features")
_ driver.Driver = &ocDriver{}
_ conn = &ocConn{}
_ driver.Result = &ocResult{}
_ driver.Stmt = &ocStmt{}
_ driver.StmtExecContext = &ocStmt{}
_ driver.StmtQueryContext = &ocStmt{}
_ driver.Rows = &ocRows{}
_ driver.RowsNextResultSet = &ocRows{}
_ driver.RowsColumnTypeDatabaseTypeName = &ocRows{}
_ driver.RowsColumnTypeLength = &ocRows{}
_ driver.RowsColumnTypeNullable = &ocRows{}
_ driver.RowsColumnTypePrecisionScale = &ocRows{}
)
func ( driver.Driver, ...TraceOption) driver.Driver {
:= TraceOptions{}
for , := range {
(&)
}
if .QueryParams && !.Query {
.QueryParams = false
}
return wrapDriver(, )
}
func ( driver.Conn, ...TraceOption) driver.Conn {
:= TraceOptions{}
for , := range {
(&)
}
return wrapConn(, )
}
type ocConn struct {
parent driver.Conn
options TraceOptions
}
func ( ocConn) ( context.Context) ( error) {
defer recordCallStats(, "go.sql.ping")()
if .options.Ping && (.options.AllowRoot || trace.FromContext() != nil) {
var *trace.Span
, = trace.StartSpan(, "sql:ping", trace.WithSpanKind(trace.SpanKindClient))
if len(.options.DefaultAttributes) > 0 {
.AddAttributes(.options.DefaultAttributes...)
}
defer func() {
if != nil {
.SetStatus(trace.Status{
Code: trace.StatusCodeUnavailable,
Message: .Error(),
})
} else {
.SetStatus(trace.Status{Code: trace.StatusCodeOK})
}
.End()
}()
}
if , := .parent.(driver.Pinger); {
= .Ping()
}
return
}
func ( ocConn) ( string, []driver.Value) ( driver.Result, error) {
defer recordCallStats(context.Background(), "go.sql.exec")()
if , := .parent.(driver.Execer); {
if !.options.AllowRoot {
return .Exec(, )
}
, := trace.StartSpan(context.Background(), "sql:exec", trace.WithSpanKind(trace.SpanKindClient))
:= make([]trace.Attribute, 0, len(.options.DefaultAttributes)+2)
= append(, .options.DefaultAttributes...)
= append(
,
attrDeprecated,
trace.StringAttribute(
"ocsql.deprecated", "driver does not support ExecerContext",
),
)
if .options.Query {
= append(, trace.StringAttribute("sql.query", ))
if .options.QueryParams {
= append(, paramsAttr()...)
}
}
.AddAttributes(...)
defer func() {
setSpanStatus(, )
.End()
}()
if , = .Exec(, ); != nil {
return nil,
}
return ocResult{parent: , ctx: , options: .options}, nil
}
return nil, driver.ErrSkip
}
func ( ocConn) ( context.Context, string, []driver.NamedValue) ( driver.Result, error) {
defer recordCallStats(, "go.sql.exec")()
if , := .parent.(driver.ExecerContext); {
:= trace.FromContext()
if !.options.AllowRoot && == nil {
return .ExecContext(, , )
}
var *trace.Span
if == nil {
, = trace.StartSpan(, "sql:exec", trace.WithSpanKind(trace.SpanKindClient))
} else {
_, = trace.StartSpan(, "sql:exec", trace.WithSpanKind(trace.SpanKindClient))
}
:= append([]trace.Attribute(nil), .options.DefaultAttributes...)
if .options.Query {
= append(, trace.StringAttribute("sql.query", ))
if .options.QueryParams {
= append(, namedParamsAttr()...)
}
}
.AddAttributes(...)
defer func() {
setSpanStatus(, )
.End()
}()
if , = .ExecContext(, , ); != nil {
return nil,
}
return ocResult{parent: , ctx: , options: .options}, nil
}
return nil, driver.ErrSkip
}
func ( ocConn) ( string, []driver.Value) ( driver.Rows, error) {
defer recordCallStats(context.Background(), "go.sql.query")()
if , := .parent.(driver.Queryer); {
if !.options.AllowRoot {
return .Query(, )
}
, := trace.StartSpan(context.Background(), "sql:query", trace.WithSpanKind(trace.SpanKindClient))
:= make([]trace.Attribute, 0, len(.options.DefaultAttributes)+2)
= append(, .options.DefaultAttributes...)
= append(
,
attrDeprecated,
trace.StringAttribute(
"ocsql.deprecated", "driver does not support QueryerContext",
),
)
if .options.Query {
= append(, trace.StringAttribute("sql.query", ))
if .options.QueryParams {
= append(, paramsAttr()...)
}
}
.AddAttributes(...)
defer func() {
setSpanStatus(, )
.End()
}()
, = .Query(, )
if != nil {
return nil,
}
return wrapRows(, , .options), nil
}
return nil, driver.ErrSkip
}
func ( ocConn) ( context.Context, string, []driver.NamedValue) ( driver.Rows, error) {
defer recordCallStats(, "go.sql.query")()
if , := .parent.(driver.QueryerContext); {
:= trace.FromContext()
if !.options.AllowRoot && == nil {
return .QueryContext(, , )
}
var *trace.Span
if == nil {
, = trace.StartSpan(, "sql:query", trace.WithSpanKind(trace.SpanKindClient))
} else {
_, = trace.StartSpan(, "sql:query", trace.WithSpanKind(trace.SpanKindClient))
}
:= append([]trace.Attribute(nil), .options.DefaultAttributes...)
if .options.Query {
= append(, trace.StringAttribute("sql.query", ))
if .options.QueryParams {
= append(, namedParamsAttr()...)
}
}
.AddAttributes(...)
defer func() {
setSpanStatus(, )
.End()
}()
, = .QueryContext(, , )
if != nil {
return nil,
}
return wrapRows(, , .options), nil
}
return nil, driver.ErrSkip
}
func ( ocConn) ( string) ( driver.Stmt, error) {
defer recordCallStats(context.Background(), "go.sql.prepare")()
if .options.AllowRoot {
, := trace.StartSpan(context.Background(), "sql:prepare", trace.WithSpanKind(trace.SpanKindClient))
:= make([]trace.Attribute, 0, len(.options.DefaultAttributes)+1)
= append(, .options.DefaultAttributes...)
= append(, attrMissingContext)
if .options.Query {
= append(, trace.StringAttribute("sql.query", ))
}
.AddAttributes(...)
defer func() {
setSpanStatus(, )
.End()
}()
}
, = .parent.Prepare()
if != nil {
return nil,
}
= wrapStmt(, , .options)
return
}
func ( *ocConn) () error {
return .parent.Close()
}
func ( *ocConn) () (driver.Tx, error) {
return .BeginTx(context.TODO(), driver.TxOptions{})
}
func ( *ocConn) ( context.Context, string) ( driver.Stmt, error) {
defer recordCallStats(, "go.sql.prepare")()
var *trace.Span
:= append([]trace.Attribute(nil), .options.DefaultAttributes...)
if .options.AllowRoot || trace.FromContext() != nil {
, = trace.StartSpan(, "sql:prepare", trace.WithSpanKind(trace.SpanKindClient))
if .options.Query {
= append(, trace.StringAttribute("sql.query", ))
}
defer func() {
setSpanStatus(, )
.End()
}()
}
if , := .parent.(driver.ConnPrepareContext); {
, = .PrepareContext(, )
} else {
if != nil {
= append(, attrMissingContext)
}
, = .parent.Prepare()
}
.AddAttributes(...)
if != nil {
return nil,
}
= wrapStmt(, , .options)
return
}
func ( *ocConn) ( context.Context, driver.TxOptions) ( driver.Tx, error) {
defer recordCallStats(, "go.sql.begin")()
if !.options.AllowRoot && trace.FromContext() == nil {
if , := .parent.(driver.ConnBeginTx); {
return .BeginTx(, )
}
return .parent.Begin()
}
var *trace.Span
:= append([]trace.Attribute(nil), .options.DefaultAttributes...)
if == nil || == context.TODO() {
= context.Background()
_, = trace.StartSpan(, "sql:begin_transaction", trace.WithSpanKind(trace.SpanKindClient))
= append(, attrMissingContext)
} else {
_, = trace.StartSpan(, "sql:begin_transaction", trace.WithSpanKind(trace.SpanKindClient))
}
defer func() {
if len() > 0 {
.AddAttributes(...)
}
.End()
}()
if , := .parent.(driver.ConnBeginTx); {
, = .BeginTx(, )
setSpanStatus(, )
if != nil {
return nil,
}
return ocTx{parent: , ctx: , options: .options}, nil
}
= append(
,
attrDeprecated,
trace.StringAttribute(
"ocsql.deprecated", "driver does not support ConnBeginTx",
),
)
, = .parent.Begin()
setSpanStatus(, )
if != nil {
return nil,
}
return ocTx{parent: , ctx: , options: .options}, nil
}
type ocResult struct {
parent driver.Result
ctx context.Context
options TraceOptions
}
func ( ocResult) () ( int64, error) {
if .options.LastInsertID {
, := trace.StartSpan(.ctx, "sql:last_insert_id", trace.WithSpanKind(trace.SpanKindClient))
if len(.options.DefaultAttributes) > 0 {
.AddAttributes(.options.DefaultAttributes...)
}
defer func() {
setSpanStatus(, )
.End()
}()
}
, = .parent.LastInsertId()
return
}
func ( ocResult) () ( int64, error) {
if .options.RowsAffected {
, := trace.StartSpan(.ctx, "sql:rows_affected", trace.WithSpanKind(trace.SpanKindClient))
if len(.options.DefaultAttributes) > 0 {
.AddAttributes(.options.DefaultAttributes...)
}
defer func() {
setSpanStatus(, )
.End()
}()
}
, = .parent.RowsAffected()
return
}
type ocStmt struct {
parent driver.Stmt
query string
options TraceOptions
}
func ( ocStmt) ( []driver.Value) ( driver.Result, error) {
defer recordCallStats(context.Background(), "go.sql.stmt.exec")()
if !.options.AllowRoot {
return .parent.Exec()
}
, := trace.StartSpan(context.Background(), "sql:exec", trace.WithSpanKind(trace.SpanKindClient))
:= make([]trace.Attribute, 0, len(.options.DefaultAttributes)+2)
= append(, .options.DefaultAttributes...)
= append(
,
attrDeprecated,
trace.StringAttribute(
"ocsql.deprecated", "driver does not support StmtExecContext",
),
)
if .options.Query {
= append(, trace.StringAttribute("sql.query", .query))
if .options.QueryParams {
= append(, paramsAttr()...)
}
}
.AddAttributes(...)
defer func() {
setSpanStatus(, )
.End()
}()
, = .parent.Exec()
if != nil {
return nil,
}
, = ocResult{parent: , ctx: , options: .options}, nil
return
}
func ( ocStmt) () error {
return .parent.Close()
}
func ( ocStmt) () int {
return .parent.NumInput()
}
func ( ocStmt) ( []driver.Value) ( driver.Rows, error) {
defer recordCallStats(context.Background(), "go.sql.stmt.query")()
if !.options.AllowRoot {
return .parent.Query()
}
, := trace.StartSpan(context.Background(), "sql:query", trace.WithSpanKind(trace.SpanKindClient))
:= make([]trace.Attribute, 0, len(.options.DefaultAttributes)+2)
= append(, .options.DefaultAttributes...)
= append(
,
attrDeprecated,
trace.StringAttribute(
"ocsql.deprecated", "driver does not support StmtQueryContext",
),
)
if .options.Query {
= append(, trace.StringAttribute("sql.query", .query))
if .options.QueryParams {
= append(, paramsAttr()...)
}
}
.AddAttributes(...)
defer func() {
setSpanStatus(, )
.End()
}()
, = .parent.Query()
if != nil {
return nil,
}
, = wrapRows(, , .options), nil
return
}
func ( ocStmt) ( context.Context, []driver.NamedValue) ( driver.Result, error) {
defer recordCallStats(, "go.sql.stmt.exec")()
:= trace.FromContext()
return .parent.(driver.StmtExecContext).ExecContext(, )
}
var *trace.Span
if == nil {
, = trace.StartSpan(, "sql:exec", trace.WithSpanKind(trace.SpanKindClient))
} else {
_, = trace.StartSpan(, "sql:exec", trace.WithSpanKind(trace.SpanKindClient))
}
:= append([]trace.Attribute(nil), .options.DefaultAttributes...)
if .options.Query {
= append(, trace.StringAttribute("sql.query", .query))
if .options.QueryParams {
= append(, namedParamsAttr()...)
}
}
.AddAttributes(...)
defer func() {
setSpanStatus(, )
.End()
}()
:= .parent.(driver.StmtExecContext)
, = .ExecContext(, )
if != nil {
return nil,
}
, = ocResult{parent: , ctx: , options: .options}, nil
return
}
func ( ocStmt) ( context.Context, []driver.NamedValue) ( driver.Rows, error) {
defer recordCallStats(, "go.sql.stmt.query")()
:= trace.FromContext()
return .parent.(driver.StmtQueryContext).QueryContext(, )
}
var *trace.Span
if == nil {
, = trace.StartSpan(, "sql:query", trace.WithSpanKind(trace.SpanKindClient))
} else {
_, = trace.StartSpan(, "sql:query", trace.WithSpanKind(trace.SpanKindClient))
}
:= append([]trace.Attribute(nil), .options.DefaultAttributes...)
if .options.Query {
= append(, trace.StringAttribute("sql.query", .query))
if .options.QueryParams {
= append(, namedParamsAttr()...)
}
}
.AddAttributes(...)
defer func() {
setSpanStatus(, )
.End()
}()
:= .parent.(driver.StmtQueryContext)
, = .QueryContext(, )
if != nil {
return nil,
}
, = wrapRows(, , .options), nil
return
}
type withRowsColumnTypeScanType interface {
ColumnTypeScanType(index int) reflect.Type
}
func ( ocRows) () bool {
if , := .parent.(driver.RowsNextResultSet); {
return .HasNextResultSet()
}
return false
}
func ( ocRows) () error {
if , := .parent.(driver.RowsNextResultSet); {
return .NextResultSet()
}
return io.EOF
}
func ( ocRows) ( int) string {
if , := .parent.(driver.RowsColumnTypeDatabaseTypeName); {
return .ColumnTypeDatabaseTypeName()
}
return ""
}
func ( ocRows) ( int) ( int64, bool) {
if , := .parent.(driver.RowsColumnTypeLength); {
return .ColumnTypeLength()
}
return 0, false
}
func ( ocRows) ( int) (, bool) {
if , := .parent.(driver.RowsColumnTypeNullable); {
return .ColumnTypeNullable()
}
return false, false
}
func ( ocRows) ( int) (, int64, bool) {
if , := .parent.(driver.RowsColumnTypePrecisionScale); {
return .ColumnTypePrecisionScale()
}
return 0, 0, false
}
func ( ocRows) () []string {
return .parent.Columns()
}
func ( ocRows) () ( error) {
if .options.RowsClose {
, := trace.StartSpan(.ctx, "sql:rows_close", trace.WithSpanKind(trace.SpanKindClient))
if len(.options.DefaultAttributes) > 0 {
.AddAttributes(.options.DefaultAttributes...)
}
defer func() {
setSpanStatus(, )
.End()
}()
}
= .parent.Close()
return
}
func ( ocRows) ( []driver.Value) ( error) {
if .options.RowsNext {
, := trace.StartSpan(.ctx, "sql:rows_next", trace.WithSpanKind(trace.SpanKindClient))
if len(.options.DefaultAttributes) > 0 {
.AddAttributes(.options.DefaultAttributes...)
}
defer func() {
setSpanStatus(, nil)
} else {
setSpanStatus(, )
}
.End()
}()
}
= .parent.Next()
return
}
func ( context.Context, driver.Rows, TraceOptions) driver.Rows {
var (
, = .(driver.RowsColumnTypeScanType)
)
:= ocRows{
parent: ,
ctx: ,
options: ,
}
if {
return struct {
ocRows
withRowsColumnTypeScanType
}{, }
}
return
}
type ocTx struct {
parent driver.Tx
ctx context.Context
options TraceOptions
}
func ( ocTx) () ( error) {
defer recordCallStats(context.Background(), "go.sql.commit")()
, := trace.StartSpan(.ctx, "sql:commit", trace.WithSpanKind(trace.SpanKindClient))
if len(.options.DefaultAttributes) > 0 {
.AddAttributes(.options.DefaultAttributes...)
}
defer func() {
setSpanStatus(, )
.End()
}()
= .parent.Commit()
return
}
func ( ocTx) () ( error) {
defer recordCallStats(context.Background(), "go.sql.rollback")()
, := trace.StartSpan(.ctx, "sql:rollback", trace.WithSpanKind(trace.SpanKindClient))
if len(.options.DefaultAttributes) > 0 {
.AddAttributes(.options.DefaultAttributes...)
}
defer func() {
setSpanStatus(, )
.End()
}()
= .parent.Rollback()
return
}
func ( []driver.Value) []trace.Attribute {
:= make([]trace.Attribute, 0, len())
for , := range {
:= "sql.arg" + strconv.Itoa()
= append(, argToAttr(, ))
}
return
}
func ( []driver.NamedValue) []trace.Attribute {
:= make([]trace.Attribute, 0, len())
for , := range {
var string
if .Name != "" {
= .Name
} else {
= "sql.arg." + strconv.Itoa(.Ordinal)
}
= append(, argToAttr(, .Value))
}
return
}
func ( string, interface{}) trace.Attribute {
switch v := .(type) {
case nil:
return trace.StringAttribute(, "")
case int64:
return trace.Int64Attribute(, )
case float64:
return trace.StringAttribute(, fmt.Sprintf("%f", ))
case bool:
return trace.BoolAttribute(, )
case []byte:
if len() > 256 {
= [0:256]
}
return trace.StringAttribute(, fmt.Sprintf("%s", ))
default:
:= fmt.Sprintf("%v", )
if len() > 256 {
= [0:256]
}
return trace.StringAttribute(, )
}
}
func ( *trace.Span, error) {
var trace.Status
switch {
case nil:
.Code = trace.StatusCodeOK
.SetStatus()
return
case context.Canceled:
.Code = trace.StatusCodeCancelled
case context.DeadlineExceeded:
.Code = trace.StatusCodeDeadlineExceeded
case sql.ErrNoRows:
.Code = trace.StatusCodeNotFound
case sql.ErrTxDone, errConnDone:
.Code = trace.StatusCodeFailedPrecondition
default:
.Code = trace.StatusCodeUnknown
}
.Message = .Error()
.SetStatus()
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |