Skip to content

Commit

Permalink
chore: renamed trace options to be more intuitive.
Browse files Browse the repository at this point in the history
  • Loading branch information
jcchavezs committed Oct 19, 2018
1 parent c6d4fcf commit fe5f218
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 34 deletions.
60 changes: 56 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,79 @@
# Zipkin instrumentation SQL

A sql wrapper including Zipkin instrumentation
[![Build Status](https://travis-ci.com/jcchavezs/zipkin-instrumentation-sql.svg?branch=master)](https://travis-ci.com/jcchavezs/zipkin-instrumentation-sql)
[![Go Report Card](https://goreportcard.com/badge/github.com/jcchavezs/zipkin-instrumentation-sql)](https://goreportcard.com/report/github.com/jcchavezs/zipkin-instrumentation-sql)
[![GoDoc](https://godoc.org/github.com/jcchavezs/zipkin-instrumentation-sql?status.svg)](https://godoc.org/github.com/jcchavezs/zipkin-instrumentation-sql)
[![Sourcegraph](https://sourcegraph.com/github.com/jcchavezs/zipkin-instrumentation-sql/-/badge.svg)](https://sourcegraph.com/github.com/jcchavezs/zipkin-instrumentation-sql?badge)

A SQL wrapper including Zipkin instrumentation

## Usage

```go
import (
_ "github.com/go-sql-driver/mysql"
zipkinsql "github.com/jcchavezs/zipkin-instrumentation-sql"
zipkin "github.com/openzipkin/zipkin-go"
)

var (
driverName string
err error
db *sql.DB
tracer *zipkin.Tracer
)

// Register our zipkinsql wrapper for the provided MySQL driver.
driverName, err = zipkinsql.Register("mysql", zipkinsql.WithAllTraceOptions())
driverName, err = zipkinsql.Register("mysql", tracer, zipkinsql.WithAllTraceOptions())
if err != nil {
log.Fatalf("unable to register zipkin driver: %v\n", err)
}

// Connect to a MySQL database using the ocsql driver wrapper.
// Connect to a MySQL database using the zipkinsql driver wrapper.
db, err = sql.Open(driverName, "myDSN")
```
```

You can also wrap your own driver with zipkin instrumentation as follows:

```go

import (
mysql "github.com/go-sql-driver/mysql"
"github.com/opencensus-integrations/zipkinsql"
)

var (
driver driver.Driver
err error
db *sql.DB
tracer *zipkin.Tracer
)

// Explicitly wrap the MySQL driver with zipkinsql
driver = zipkinsql.Wrap(&mysql.MySQLDriver{}, tracer)

// Register our zipkinsql wrapper as a database driver
sql.Register("zipkinsql-mysql", driver)

// Connect to a MySQL database using the zipkinsql driver wrapper
db, err = sql.Open("zipkinsql-mysql", "myDSN")
```

## Usage of *Context methods

Instrumentation is possible if the context is being passed downstream in methods.
This is not only for instrumentation purposes but also a [good practice](https://medium.com/@cep21/how-to-correctly-use-context-context-in-go-1-7-8f2c0fafdf39) in go programming. `database/sql` package exposes already a set of methods that receive the context as first paramenter:

- `*DB.Begin` -> `*DB.BeginTx`
- `*DB.Exec` -> `*DB.ExecContext`
- `*DB.Ping` -> `*DB.PingContext`
- `*DB.Prepare` -> `*DB.PrepareContext`
- `*DB.Query` -> `*DB.QueryContext`
- `*DB.QueryRow` -> `*DB.QueryRowContext`
- `*Stmt.Exec` -> `*Stmt.ExecContext`
- `*Stmt.Query` -> `*Stmt.QueryContext`
- `*Stmt.QueryRow` -> `*Stmt.QueryRowContext`
- `*Tx.Exec` -> `*Tx.ExecContext`
- `*Tx.Prepare` -> `*Tx.PrepareContext`
- `*Tx.Query` -> `*Tx.QueryContext`
- `*Tx.QueryRow` -> `*Tx.QueryRowContext`
20 changes: 14 additions & 6 deletions driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ func (c zConn) ExecContext(ctx context.Context, query string, args []driver.Name
span, _ := c.tracer.StartSpanFromContext(ctx, "sql/exec")
defer span.Finish()

if c.options.Query {
if c.options.TagQuery {
span.Tag("sql.query", query)
}

Expand Down Expand Up @@ -209,7 +209,7 @@ func (c zConn) QueryContext(ctx context.Context, query string, args []driver.Nam
span, _ := c.tracer.StartSpanFromContext(ctx, "sql/exec")
defer span.Finish()

if c.options.Query {
if c.options.TagQuery {
span.Tag("sql.query", query)
}

Expand Down Expand Up @@ -293,7 +293,7 @@ type zResult struct {
}

func (r zResult) LastInsertId() (int64, error) {
if !r.options.LastInsertID {
if !r.options.LastInsertIDSpan {
return r.driver.LastInsertId()
}

Expand All @@ -310,7 +310,7 @@ func (r zResult) LastInsertId() (int64, error) {

func (r zResult) RowsAffected() (cnt int64, err error) {
zipkin.SpanFromContext(r.ctx)
if r.options.RowsAffected && zipkin.SpanFromContext(r.ctx) != nil {
if r.options.RowsAffectedSpan && zipkin.SpanFromContext(r.ctx) != nil {
span, _ := r.tracer.StartSpanFromContext(r.ctx, "sql/rows_affected")
setSpanDefaultTags(span, r.options.DefaultTags)
defer func() {
Expand Down Expand Up @@ -359,7 +359,7 @@ func (s zStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (res d
span.Finish()
}()

if s.options.Query {
if s.options.TagQuery {
span.Tag("sql.query", s.query)
}

Expand All @@ -370,6 +370,13 @@ func (s zStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (res d
if err != nil {
return nil, err
}

if s.options.TagAffectedRows {
if affectedRows, err := res.RowsAffected(); err != nil {
span.Tag("sql.affected_rows", fmt.Sprintf("%d", affectedRows))
}
}

res, err = zResult{driver: res, ctx: ctx, options: s.options}, nil
return
}
Expand All @@ -385,7 +392,7 @@ func (s zStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (rows
span.Finish()
}()

if s.options.Query {
if s.options.TagQuery {
span.Tag("sql.query", s.query)
}

Expand All @@ -402,6 +409,7 @@ func (s zStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (rows
if err != nil {
return nil, err
}

rows, err = zRows{driver: rows, ctx: ctx, options: s.options}, nil
return
}
Expand Down
59 changes: 35 additions & 24 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,24 @@ package zipkinsql
type TraceOption func(o *TraceOptions)

// TraceOptions holds configuration of our zipkinsql tracing middleware.
// By default all options are set to false intentionally when creating a wrapped
// driver and provide the most sensible default with both performance and
// security in mind.
// By default all boolean options are set to false intentionally when creating
// a wrapped driver and provide the most sensible default with both performance
// and security in mind.
type TraceOptions struct {
// RowsAffected, if set to true, will enable the creation of spans on
// RowsAffected calls.
RowsAffected bool
// LastInsertIDSpan, if set to true, will enable the creation of spans on
// LastInsertId calls.
LastInsertIDSpan bool

// RowsAffectedSpan, if set to true, will enable the creation of spans on
// RowsAffectedSpan calls.
RowsAffectedSpan bool

// Query, if set to true, will enable recording of sql queries in spans.
// TagQuery, if set to true, will enable recording of sql queries in spans.
// Only allow this if it is safe to have queries recorded with respect to
// security.
Query bool
TagQuery bool

// LastInsertID, if set to true, will enable the creation of spans on
// LastInsertId calls.
LastInsertID bool
TagAffectedRows bool

// DefaultTags will be set to each span as default.
DefaultTags map[string]string
Expand All @@ -34,41 +36,50 @@ func WithAllTraceOptions() TraceOption {

// AllTraceOptions has all tracing options enabled.
var AllTraceOptions = TraceOptions{
RowsAffected: true,
Query: true,
LastInsertID: true,
RowsAffectedSpan: true,
LastInsertIDSpan: true,
TagQuery: true,
TagAffectedRows: true,
}

// WithOptions sets our ocsql tracing middleware options through a single
// WithOptions sets the zipkinsql tracing middleware options through a single
// TraceOptions object.
func WithOptions(options TraceOptions) TraceOption {
return func(o *TraceOptions) {
*o = options
}
}

// WithRowsAffected if set to true, will enable the creation of spans on
// WithRowsAffectedSpan if set to true, will enable the creation of spans on
// RowsAffected calls.
func WithRowsAffected(b bool) TraceOption {
func WithRowsAffectedSpan(b bool) TraceOption {
return func(o *TraceOptions) {
o.RowsAffected = b
o.RowsAffectedSpan = b
}
}

// WithLastInsertID if set to true, will enable the creation of spans on
// WithLastInsertIDSpan if set to true, will enable the creation of spans on
// LastInsertId calls.
func WithLastInsertID(b bool) TraceOption {
func WithLastInsertIDSpan(b bool) TraceOption {
return func(o *TraceOptions) {
o.LastInsertID = b
o.LastInsertIDSpan = b
}
}

// WithQuery if set to true, will enable recording of sql queries in spans.
// WithTagQuery if set to true, will enable recording of SQL queries in spans.
// Only allow this if it is safe to have queries recorded with respect to
// security.
func WithQuery(b bool) TraceOption {
func WithTagQuery(b bool) TraceOption {
return func(o *TraceOptions) {
o.TagQuery = b
}
}

// WithTagAffectedRows if set to true, will enable recording of the affected rows
// number in spans.
func WithTagAffectedRows(b bool) TraceOption {
return func(o *TraceOptions) {
o.Query = b
o.TagAffectedRows = b
}
}

Expand Down

0 comments on commit fe5f218

Please sign in to comment.