Skip to content
A logger for Go SQL database driver without modify existing *sql.DB stdlib usage.
Go
Branch: master
Clone or download
simukti Merge pull request #36 from simukti/dependabot/go_modules/github.com/…
…rs/zerolog-1.18.0

Bump github.com/rs/zerolog from 1.17.2 to 1.18.0
Latest commit af376fd Feb 12, 2020
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
logadapter
.gitignore
.golangci.yml
.travis.yml
LICENSE.txt
README.md
connection.go
connection_test.go minor tweak and change CheckNamedValue log msg Jan 2, 2020
connector.go
connector_test.go
database.go
database_test.go
go.mod
go.sum Bump github.com/rs/zerolog from 1.17.2 to 1.18.0 Feb 11, 2020
logger.go
logger_test.go
options.go
options_test.go
result.go
result_test.go
rows.go
rows_test.go
statement.go log stmt.Close() call Jan 2, 2020
statement_test.go
transaction.go use configurable fieldname Dec 6, 2019
transaction_test.go use uid generator from logger option Dec 14, 2019

README.md

SQLDB-Logger

Build Status Coverage Status Go Report Card GolangCI Status Documentation License

A logger for Go SQL database driver without modify existing *sql.DB stdlib usage.

shameless console output sample Colored console writer output above only for sample/development

FEATURES

  • Leveled and configurable logging.
  • Keep using *sql.DB as is (from existing sql.DB usage perspective).
  • Bring your own logger backend via simple log interface.
  • Trackable log output:
    • Every call has its own unique ID.
    • Prepared statement and execution will have same ID.
    • On execution/result error, it will include query, arguments, params, and related IDs.

INSTALL

go get -u -v github.com/simukti/sqldb-logger

Version pinning using dependency manager such as Mod or Dep is highly recommended.

USAGE

TL;DR VERSION

Replace sql.Open() with sqldblogger.OpenDriver(), both will return *sql.DB.

DETAILED VERSION

Assuming we have existing sql.Open using commonly-used go-sql-driver/mysql driver, and wants to log its *sql.DB interaction using rs/zerolog.

dsn := "username:passwd@tcp(mysqlserver:3306)/dbname?parseTime=true"
db, err := sql.Open("mysql", dsn) // db is *sql.DB

Change it with:

loggerAdapter := zerologadapter.New(zerolog.New(os.Stdout)) // zerolog.New(zerolog.NewConsoleWriter()) // <-- for colored console
dsn := "username:passwd@tcp(mysqlserver:3306)/dbname?parseTime=true"
db := sqldblogger.OpenDriver(dsn, &mysql.MySQLDriver{}, loggerAdapter) // db is still *sql.DB

Without giving 4th argument to OpenDriver, it will use default options.

That's it. Use db object as usual.

DETAILED + OPTIONS VERSION

For full control of log output (field name, time format, etc...), pass variadic sqldblogger.Option as 4th argument as below:

db := sqldblogger.OpenDriver(
    dsn, 
    &mysql.MySQLDriver{}, 
    loggerAdapter,
    // zero or more option
    sqldblogger.WithErrorFieldname("sql_error"), // default: error
    sqldblogger.WithDurationFieldname("query_duration"), // default: duration
    sqldblogger.WithTimeFieldname("log_time"), // default: time
    sqldblogger.WithSQLQueryFieldname("sql_query"), // default: query
    sqldblogger.WithSQLArgsFieldname("sql_args"), // default: args
    sqldblogger.WithMinimumLevel(sqldblogger.LevelInfo), // default: LevelDebug
    sqldblogger.WithLogArguments(false), // default: true
    sqldblogger.WithDurationUnit(sqldblogger.DurationNanosecond), // default: millisecond
    sqldblogger.WithTimeFormat(sqldblogger.TimeFormatRFC3339), // default: unix timestamp
    sqldblogger.WithLogDriverErrorSkip(true), // default: false
    sqldblogger.WithSQLQueryAsMessage(true), // default: false
    sqldblogger.WithUIDGenerator(sqldblogger.UIDGenerator), // default: *defaultUID
    sqldblogger.WithConnectionIDFieldname("con_id"), // default: conn_id
    sqldblogger.WithStatementIDFieldname("stm_id"), // default: stmt_id
    sqldblogger.WithTransactionIDFieldname("trx_id"), // default: tx_id
    sqldblogger.WithWrapResult(false), // default: true
)

Click here for options documentation.

SQL DRIVER INTEGRATION

It is compatible with following public empty struct driver:

MySQL (go-sql-driver/mysql)

db := sqldblogger.OpenDriver(dsn, &mysql.MySQLDriver{}, loggerAdapter /*, ...options */)

PostgreSQL (lib/pq)

db := sqldblogger.OpenDriver(dsn, &pq.Driver{}, loggerAdapter /*, ...options */) 

SQLite3 (mattn/go-sqlite3)

db := sqldblogger.OpenDriver(dsn, &sqlite3.SQLiteDriver{}, loggerAdapter /*, ...options */)

Following drivers maybe compatible:

SQL Server (denisenkom/go-mssqldb)

db := sqldblogger.OpenDriver(dsn, &mssql.Driver{}, loggerAdapter /*, ...options */)

Oracle (mattn/go-oci8)

db := sqldblogger.OpenDriver(dsn, oci8.OCI8Driver, loggerAdapter /*, ...options */)

ANOTHER SQL DRIVER INTEGRATION

Specifically for non-public driver

It is also possible to re-use existing *sql.DB driver:

For example, from:

dsn := "username:passwd@tcp(mysqlserver:3306)/dbname?parseTime=true"
db, err := sql.Open("mysql", dsn) // db is *sql.DB
db.Ping() // to check connectivity

To:

dsn := "username:passwd@tcp(mysqlserver:3306)/dbname?parseTime=true"
db, err := sql.Open("mysql", dsn) // db is *sql.DB
// handle err
loggerAdapter := zerologadapter.New(zerolog.New(os.Stdout)) // zerolog.New(zerolog.NewConsoleWriter()) // <-- for colored console
db = sqldblogger.OpenDriver(dsn, db.Driver(), loggerAdapter/*, using_default_options*/) // db is still *sql.DB
db.Ping() // to check connectivity

LOGGER ADAPTER

sqldb-logger does not include a logger backend, but provide adapters that uses well known JSON structured logger:

Provided adapters does not use given context, you need to copy it and adjust with your needs. (example: add http request id/whatever value from context to query log when you call QueryerContext andExecerContext methods)

For another/custom logger backend, Logger interface is just as simple as following:

type Logger interface {
	Log(ctx context.Context, level Level, msg string, data map[string]interface{})
}

MOTIVATION

I want to:

  • Keep using *sql.DB.
  • Have configurable output field.
  • Leverage structured logging.
  • Re-use pgx log interface.

I haven't found SQL logger with that features, so why not created myself?

REFERENCES

CONTRIBUTE

If you found bug, typo, wrong test, idea, help with existing issue, or anything constructive.

Don't hesitate to create an issue or pull request.

CREDITS

  • pgx for awesome PostgreSQL driver.

LICENSE

MIT

You can’t perform that action at this time.