mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
Add dev sql interceptor for logging of queries (#3815)
* Add dev sql interceptor for logging of queries * Remove extra spaces and tabs from queries * Make regex global
This commit is contained in:
parent
85487eb5b2
commit
81672ee50e
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"database/sql/driver"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@ -47,6 +48,7 @@ import (
|
||||
"github.com/go-kit/kit/log/level"
|
||||
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
|
||||
"github.com/kolide/kit/version"
|
||||
"github.com/ngrok/sqlmw"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/spf13/cobra"
|
||||
@ -154,11 +156,17 @@ the way that the Fleet server works.
|
||||
var carveStore fleet.CarveStore
|
||||
mailService := mail.NewService()
|
||||
|
||||
var replicaOpt mysql.DBOption
|
||||
opts := []mysql.DBOption{mysql.Logger(logger)}
|
||||
if config.MysqlReadReplica.Address != "" {
|
||||
replicaOpt = mysql.Replica(&config.MysqlReadReplica)
|
||||
opts = append(opts, mysql.Replica(&config.MysqlReadReplica))
|
||||
}
|
||||
ds, err = mysql.New(config.Mysql, clock.C, mysql.Logger(logger), replicaOpt)
|
||||
if dev && os.Getenv("FLEET_ENABLE_DEV_SQL_INTERCEPTOR") != "" {
|
||||
opts = append(opts, mysql.WithInterceptor(&devSQLInterceptor{
|
||||
logger: kitlog.With(logger, "component", "sql-interceptor"),
|
||||
}))
|
||||
}
|
||||
|
||||
ds, err = mysql.New(config.Mysql, clock.C, opts...)
|
||||
if err != nil {
|
||||
initFatal(err, "initializing datastore")
|
||||
}
|
||||
@ -839,3 +847,51 @@ func getTLSConfig(profile string) *tls.Config {
|
||||
|
||||
return &cfg
|
||||
}
|
||||
|
||||
// devSQLInterceptor is a sql interceptor to be used for development purposes.
|
||||
type devSQLInterceptor struct {
|
||||
sqlmw.NullInterceptor
|
||||
|
||||
logger kitlog.Logger
|
||||
}
|
||||
|
||||
func (in *devSQLInterceptor) StmtQueryContext(ctx context.Context, stmt driver.StmtQueryContext, query string, args []driver.NamedValue) (driver.Rows, error) {
|
||||
start := time.Now()
|
||||
rows, err := stmt.QueryContext(ctx, args)
|
||||
in.logQuery(start, query, args, err)
|
||||
return rows, err
|
||||
}
|
||||
|
||||
func (in *devSQLInterceptor) StmtExecContext(ctx context.Context, stmt driver.StmtExecContext, query string, args []driver.NamedValue) (driver.Result, error) {
|
||||
start := time.Now()
|
||||
result, err := stmt.ExecContext(ctx, args)
|
||||
in.logQuery(start, query, args, err)
|
||||
return result, err
|
||||
}
|
||||
|
||||
var spaceRegex = regexp.MustCompile(`\s+`)
|
||||
|
||||
func (in *devSQLInterceptor) logQuery(start time.Time, query string, args []driver.NamedValue, err error) {
|
||||
logLevel := level.Debug
|
||||
if err != nil {
|
||||
logLevel = level.Error
|
||||
}
|
||||
query = strings.TrimSpace(spaceRegex.ReplaceAllString(query, " "))
|
||||
logLevel(in.logger).Log("duration", time.Since(start), "query", query, "args", argsToString(args), "err", err)
|
||||
}
|
||||
|
||||
func argsToString(args []driver.NamedValue) string {
|
||||
var allArgs strings.Builder
|
||||
allArgs.WriteString("{")
|
||||
for i, arg := range args {
|
||||
if i > 0 {
|
||||
allArgs.WriteString(", ")
|
||||
}
|
||||
if arg.Name != "" {
|
||||
allArgs.WriteString(fmt.Sprintf("%s=", arg.Name))
|
||||
}
|
||||
allArgs.WriteString(fmt.Sprintf("%v", arg.Value))
|
||||
}
|
||||
allArgs.WriteString("}")
|
||||
return allArgs.String()
|
||||
}
|
||||
|
3
go.mod
3
go.mod
@ -25,7 +25,7 @@ require (
|
||||
github.com/facebookincubator/nvdtools v0.1.4
|
||||
github.com/fatih/color v1.12.0
|
||||
github.com/fleetdm/goose v0.0.0-20210209032905-c3c01484bacb
|
||||
github.com/getsentry/sentry-go v0.12.0 // indirect
|
||||
github.com/getsentry/sentry-go v0.12.0
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/go-kit/kit v0.9.0
|
||||
github.com/go-sql-driver/mysql v1.6.0
|
||||
@ -54,6 +54,7 @@ require (
|
||||
github.com/mitchellh/go-ps v1.0.0
|
||||
github.com/mitchellh/gon v0.2.3
|
||||
github.com/mna/redisc v1.3.2
|
||||
github.com/ngrok/sqlmw v0.0.0-20211220175533-9d16fdc47b31
|
||||
github.com/oklog/run v1.1.0
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/open-policy-agent/opa v0.24.0
|
||||
|
8
go.sum
8
go.sum
@ -383,6 +383,7 @@ github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwv
|
||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
|
||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
|
||||
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||
@ -741,7 +742,6 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
|
||||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
@ -753,7 +753,6 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
@ -815,6 +814,8 @@ github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5Vgl
|
||||
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
|
||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/ngrok/sqlmw v0.0.0-20211220175533-9d16fdc47b31 h1:FFHgfAIoAXCCL4xBoAugZVpekfGmZ/fBBueneUKBv7I=
|
||||
github.com/ngrok/sqlmw v0.0.0-20211220175533-9d16fdc47b31/go.mod h1:E26fwEtRNigBfFfHDWsklmo0T7Ixbg0XXgck+Hq4O9k=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
@ -849,6 +850,7 @@ github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrap
|
||||
github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
|
||||
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/peterh/liner v0.0.0-20170211195444-bf27d3ba8e1d/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
||||
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
|
||||
github.com/pkg/errors v0.0.0-20181023235946-059132a15dd0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@ -1049,7 +1051,6 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
|
||||
github.com/zclconf/go-cty v1.1.0 h1:uJwc9HiBOCpoKIObTQaLR+tsEXx1HBHnOsOOpcdhZgw=
|
||||
github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
|
||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||
github.com/zwass/kit v0.0.0-20210625184505-ec5b5c5cce9c h1:TWQ2UvXPkhPxI2KmApKBOCaV6yD2N4mlvqFQ/DlPtpQ=
|
||||
github.com/zwass/kit v0.0.0-20210625184505-ec5b5c5cce9c/go.mod h1:OYYulo9tUqRadRLwB0+LE914sa1ui2yL7OrcU3Q/1XY=
|
||||
@ -1205,7 +1206,6 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211007125505-59d4e928ea9d h1:QWMn1lFvU/nZ58ssWqiFJMd3DKIII8NYc4sn708XgKs=
|
||||
golang.org/x/net v0.0.0-20211007125505-59d4e928ea9d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211008194852-3b03d305991f h1:1scJEYZBaF48BaG6tYbtxmLcXqwYGSfGcMoStTqkkIw=
|
||||
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
|
@ -3,6 +3,7 @@ package mysql
|
||||
import (
|
||||
"github.com/fleetdm/fleet/v4/server/config"
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/ngrok/sqlmw"
|
||||
)
|
||||
|
||||
const defaultMaxAttempts int = 15
|
||||
@ -15,9 +16,10 @@ type dbOptions struct {
|
||||
maxAttempts int
|
||||
logger log.Logger
|
||||
replicaConfig *config.MysqlConfig
|
||||
interceptor sqlmw.Interceptor
|
||||
}
|
||||
|
||||
// Logger adds a logger to the datastore
|
||||
// Logger adds a logger to the datastore.
|
||||
func Logger(l log.Logger) DBOption {
|
||||
return func(o *dbOptions) error {
|
||||
o.logger = l
|
||||
@ -25,6 +27,14 @@ func Logger(l log.Logger) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
// WithInterceptor adds the sql interceptor to the datastore.
|
||||
func WithInterceptor(i sqlmw.Interceptor) DBOption {
|
||||
return func(o *dbOptions) error {
|
||||
o.interceptor = i
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Replica sets the configuration of the read replica for the datastore.
|
||||
func Replica(conf *config.MysqlConfig) DBOption {
|
||||
return func(o *dbOptions) error {
|
||||
|
@ -28,6 +28,7 @@ import (
|
||||
"github.com/go-kit/kit/log/level"
|
||||
"github.com/go-sql-driver/mysql"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/ngrok/sqlmw"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -249,8 +250,14 @@ func (d *Datastore) writeChanLoop() {
|
||||
}
|
||||
|
||||
func newDB(conf *config.MysqlConfig, opts *dbOptions) (*sqlx.DB, error) {
|
||||
driverName := "mysql"
|
||||
if opts.interceptor != nil {
|
||||
driverName = "mysql-mw"
|
||||
sql.Register(driverName, sqlmw.Driver(mysql.MySQLDriver{}, opts.interceptor))
|
||||
}
|
||||
|
||||
dsn := generateMysqlConnectionString(*conf)
|
||||
db, err := sqlx.Open("mysql", dsn)
|
||||
db, err := sqlx.Open(driverName, dsn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user