81 lines
2 KiB
Go
81 lines
2 KiB
Go
package jet
|
|
|
|
import (
|
|
"context"
|
|
"runtime"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// PrintableStatement is a statement which sql query can be logged
|
|
type PrintableStatement interface {
|
|
Sql() (query string, args []interface{})
|
|
DebugSql() (query string)
|
|
}
|
|
|
|
// LoggerFunc is a function user can implement to support automatic statement logging.
|
|
type LoggerFunc func(ctx context.Context, statement PrintableStatement)
|
|
|
|
var logger LoggerFunc
|
|
|
|
// SetLoggerFunc sets automatic statement logging
|
|
func SetLoggerFunc(loggerFunc LoggerFunc) {
|
|
logger = loggerFunc
|
|
}
|
|
|
|
func callLogger(ctx context.Context, statement Statement) {
|
|
if logger != nil {
|
|
logger(ctx, statement)
|
|
}
|
|
}
|
|
|
|
// QueryInfo contains information about executed query
|
|
type QueryInfo struct {
|
|
Statement PrintableStatement
|
|
// Depending on how the statement is executed, RowsProcessed is:
|
|
// - Number of rows returned for Query() and QueryContext() methods
|
|
// - RowsAffected() for Exec() and ExecContext() methods
|
|
// - Always 0 for Rows() method.
|
|
RowsProcessed int64
|
|
Duration time.Duration
|
|
Err error
|
|
}
|
|
|
|
// QueryLoggerFunc is a function user can implement to retrieve more information about statement executed.
|
|
type QueryLoggerFunc func(ctx context.Context, info QueryInfo)
|
|
|
|
var queryLoggerFunc QueryLoggerFunc
|
|
|
|
// SetQueryLogger sets automatic query logging function.
|
|
func SetQueryLogger(loggerFunc QueryLoggerFunc) {
|
|
queryLoggerFunc = loggerFunc
|
|
}
|
|
|
|
func callQueryLoggerFunc(ctx context.Context, info QueryInfo) {
|
|
if queryLoggerFunc != nil {
|
|
queryLoggerFunc(ctx, info)
|
|
}
|
|
}
|
|
|
|
// Caller returns information about statement caller
|
|
func (q QueryInfo) Caller() (file string, line int, function string) {
|
|
skip := 4
|
|
// depending on execution type (Query, QueryContext, Exec, ...) looped once or twice
|
|
for {
|
|
var pc uintptr
|
|
var ok bool
|
|
|
|
pc, file, line, ok = runtime.Caller(skip)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
funcDetails := runtime.FuncForPC(pc)
|
|
if !strings.Contains(funcDetails.Name(), "source.gleipnir.technology/Gleipnir/jet/v2/internal") {
|
|
function = funcDetails.Name()
|
|
return
|
|
}
|
|
|
|
skip++
|
|
}
|
|
}
|