diff --git a/README.md b/README.md index 5d45cf9..a8a5f15 100644 --- a/README.md +++ b/README.md @@ -744,7 +744,7 @@ func main() { ### ORM Integration `go-sdk` comes with an integration with the popular -[gorm](https://github.com/jinzhu/gorm) as an object-relational mapper (ORM). +[gorm](https://gorm.io/gorm) as an object-relational mapper (ORM). Using the configuration details, namely the [data source name](https://en.wikipedia.org/wiki/Data_source_name) (DSN) as their product, gorm is able to open a connection and give the `go-sdk` users a preconfigured @@ -773,7 +773,7 @@ words the `NewConnection` function, so they remain opaque for the user. #### Usage of ORM Invoking the constructor for a database connection, `go-sdk` returns a -[Gorm-powered](https://github.com/jinzhu/gorm) database connection. It can be +[Gorm-powered](https://gorm.io/gorm) database connection. It can be used right away to query the database: ```go @@ -783,7 +783,7 @@ import ( "fmt" sdkdb "github.com/scribd/go-sdk/pkg/database" - "github.com/jinzhu/gorm" + "gorm.io/gorm" ) type User struct { @@ -1041,7 +1041,7 @@ if err != nil { `DatabaseLogging` for both HTTP and gRPC servers. The `Database` middleware which instruments the -[Gorm-powered](https://github.com/jinzhu/gorm) database connection. It utilizes +[Gorm-powered](https://gorm.io/gorm) database connection. It utilizes Gorm-specific callbacks that report spans and traces to Datadog. The instrumented Gorm database connection is injected in the request `Context` and it is always scoped within the request. @@ -1051,8 +1051,11 @@ The `DatabaseLogging` middleware checks for a logger injected in the request which in turn uses the logger to produce database query logs. A nice side-effect of this approach is that, if the logger is tagged with a `request_id`, there's a logs correlation between the HTTP requests and the -database queries. Also, if the logger is tagged with `treace_id` we can easily -correlate logs with traces and see corresponding database queries. +database queries. Also, if the logger is tagged with `trace_id` we can easily +correlate logs with traces and see corresponding database queries. Keep in mind +that ORM logging happens at the same level as the base logger. The additional +database fields ('duration', 'affected_rows' and 'sql') are available +only when using the `trace` levels. #### HTTP server middleware example diff --git a/go.mod b/go.mod index 08bf6af..cc30933 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/scribd/go-sdk go 1.19 require ( + github.com/DATA-DOG/go-sqlmock v1.5.0 github.com/DATA-DOG/go-txdb v0.1.3 github.com/DataDog/datadog-go v4.8.2+incompatible github.com/aws/aws-sdk-go v1.34.28 @@ -10,9 +11,7 @@ require ( github.com/google/go-cmp v0.5.7 github.com/google/uuid v1.3.0 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 - github.com/jinzhu/gorm v1.9.11 github.com/magefile/mage v1.13.0 - github.com/mattn/go-sqlite3 v1.14.14 github.com/rs/cors v1.7.0 github.com/sirupsen/logrus v1.7.0 github.com/spf13/viper v1.10.1 @@ -22,6 +21,9 @@ require ( google.golang.org/protobuf v1.28.0 gopkg.in/DataDog/dd-trace-go.v1 v1.47.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 + gorm.io/driver/mysql v1.4.6 + gorm.io/driver/sqlite v1.4.4 + gorm.io/gorm v1.24.5 ) require ( @@ -37,18 +39,20 @@ require ( github.com/dgraph-io/ristretto v0.1.0 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect - github.com/go-sql-driver/mysql v1.6.0 // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/gorilla/mux v1.7.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/klauspost/compress v1.15.2 // indirect github.com/magiconair/properties v1.8.5 // indirect github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-sqlite3 v1.14.15 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/pelletier/go-toml v1.9.4 // indirect github.com/philhofer/fwd v1.1.1 // indirect diff --git a/go.sum b/go.sum index 2da4821..49e5630 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,12 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DATA-DOG/go-txdb v0.1.3 h1:R4v6OuOcy2O147e2zHxU0B4NDtF+INb5R9q/CV7AEMg= github.com/DATA-DOG/go-txdb v0.1.3/go.mod h1:DhAhxMXZpUJVGnT+p9IbzJoRKvlArO2pkHjnGX7o0n0= github.com/DataDog/datadog-agent/pkg/obfuscate v0.0.0-20211129110424-6491aa3bf583 h1:3nVO1nQyh64IUY6BPZUpMYMZ738Pu+LsMt3E0eqqIYw= @@ -28,18 +29,12 @@ github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6 github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/aws/aws-sdk-go v1.34.28 h1:sscPpn/Ns3i0F4HPEWAVcwdIRaZZCuL7llJ2/60yPIk= github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -65,8 +60,6 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= -github.com/denisenkom/go-mssqldb v0.11.0 h1:9rHa233rhdOyrz2GcP9NM+gi2psgJZ4GWDpL/7ND8HI= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI= github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= @@ -75,9 +68,6 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -86,8 +76,6 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= -github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= @@ -105,27 +93,19 @@ github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/ 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-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -141,10 +121,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -158,18 +136,13 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.1 h1:Dw4jY2nghMMRsh1ol8dv1axHkDwMQK2DHerMNJsIpJU= github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -177,7 +150,6 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmo github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -189,12 +161,11 @@ github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/ github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= -github.com/jinzhu/gorm v1.9.11 h1:gaHGvE+UnWGlbWG4Y3FUwY1EcZ5n6S9WtqBA/uySMLE= -github.com/jinzhu/gorm v1.9.11/go.mod h1:bu/pK8szGZ2puuErfU0RwyeNdsf3e6nCX/noXaVxkfw= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.3 h1:PlHq1bSCSZL9K0wUhbm2pGLoTWs2GwVhsP6emvGV/ZI= +github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -203,24 +174,19 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.15.2 h1:3WH+AG7s2+T8o3nrM/8u2rdqUEcQhmga7smjrT41nAw= github.com/klauspost/compress v1.15.2/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -229,7 +195,6 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= -github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/magefile/mage v1.13.0 h1:XtLJl8bcCM7EFoO8FyH8XK3t7G5hQAeK+i4tq+veT9M= github.com/magefile/mage v1.13.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= @@ -246,11 +211,9 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw= -github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= +github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -262,7 +225,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= 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= @@ -270,45 +232,32 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE= github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= 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.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052 h1:Qp27Idfgi6ACvFQat5+VJvlYToylpM/hcyLBI3WaKPA= github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052/go.mod h1:uvX/8buq8uVeiZiFht+0lqSLBHF+uGV8BrTv8W/SIwk= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= @@ -322,7 +271,6 @@ github.com/secure-systems-lab/go-securesystemslib v0.4.0 h1:b23VGrQhTA8cN2CbBw7/ github.com/secure-systems-lab/go-securesystemslib v0.4.0/go.mod h1:FGBZgq2tXWICsxWQW1msNf49F0Pf2Op5Htayx335Qbs= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -347,7 +295,6 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -391,17 +338,14 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE= go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA= go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 h1:FyBZqvoA/jbNzuAWLQE2kG820zMAkcilx6BMjGbL/E4= go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -415,16 +359,13 @@ golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -447,20 +388,15 @@ golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -496,7 +432,6 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -504,17 +439,14 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M= golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -527,18 +459,14 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa h1:I0YcKz0I7OAhddo7ya8kMnvprhcWM045PmkBdMO9zN0= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -564,9 +492,7 @@ google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscL google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/DataDog/dd-trace-go.v1 v1.47.0 h1:w3mHEgOR1o52mkyCbkTM+El8DG732+Fnug4FAGhIpsk= gopkg.in/DataDog/dd-trace-go.v1 v1.47.0/go.mod h1:aHb6c4hPRANXnB64LDAKyfWotKgfRjlHv23MnahM8AI= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -579,7 +505,6 @@ gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3M gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -591,10 +516,16 @@ gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.4.6 h1:5zS3vIKcyb46byXZNcYxaT9EWNIhXzu0gPuvvVrwZ8s= +gorm.io/driver/mysql v1.4.6/go.mod h1:SxzItlnT1cb6e1e4ZRpgJN2VYtcqJgqnHxWr4wsP8oc= +gorm.io/driver/sqlite v1.4.4 h1:gIufGoR0dQzjkyqDyYSCvsYR6fba1Gw5YKDqKeChxFc= +gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI= +gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= +gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= +gorm.io/gorm v1.24.5 h1:g6OPREKqqlWq4kh/3MCQbZKImeB9e6Xgc4zD+JgNZGE= +gorm.io/gorm v1.24.5/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= inet.af/netaddr v0.0.0-20220617031823-097006376321 h1:B4dC8ySKTQXasnjDTMsoCMf1sQG4WsMej0WXaHxunmU= inet.af/netaddr v0.0.0-20220617031823-097006376321/go.mod h1:OIezDfdzOgFhuw4HuWapWq2e9l0H9tK4F1j+ETRtF3k= diff --git a/pkg/context/database/context.go b/pkg/context/database/context.go index 30c467c..5cf1394 100644 --- a/pkg/context/database/context.go +++ b/pkg/context/database/context.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/jinzhu/gorm" + "gorm.io/gorm" ) type ctxDatabaseMarker struct{} diff --git a/pkg/database/gorm.go b/pkg/database/gorm.go index 77711da..383bb45 100644 --- a/pkg/database/gorm.go +++ b/pkg/database/gorm.go @@ -1,31 +1,50 @@ package database import ( - "github.com/DATA-DOG/go-txdb" - "github.com/jinzhu/gorm" + "strconv" + "time" - // Imports required gorm MySQL dialect. - _ "github.com/jinzhu/gorm/dialects/mysql" + "github.com/DATA-DOG/go-txdb" + "gorm.io/driver/mysql" + "gorm.io/gorm" ) +const testEnv = "test" + // NewConnection returns a new Gorm database connection. func NewConnection(config *Config, environment string) (*gorm.DB, error) { - var db *gorm.DB - var err error - connectionDetails := NewConnectionDetails(config) - switch environment { - case "test": - txdb.Register("txdb", connectionDetails.Dialect, connectionDetails.String()) - db, err = gorm.Open(connectionDetails.Dialect, "txdb", "tx_1") - default: - db, err = gorm.Open(connectionDetails.Dialect, connectionDetails.String()) + connectionString := connectionDetails.String() + driverName := connectionDetails.Dialect + + // Register the test driver and mock driver name and connection string in test environment. + if environment == testEnv { + // Using time.Now() as a unique identifier for the test database so that we can call NewConnection() + // multiple times without getting an error. + testDriverName := strconv.Itoa(int(time.Now().UnixNano())) + + txdb.Register(testDriverName, connectionDetails.Dialect, connectionString) + driverName = testDriverName + connectionString = testDriverName } - if err == nil { - db.DB().SetMaxIdleConns(connectionDetails.Pool) + dialector := mysql.New(mysql.Config{ + DSN: connectionString, + DriverName: driverName, + }) + + db, err := gorm.Open(dialector) + if err != nil { + return nil, err } - return db, err + sqlDB, err := db.DB() + if err != nil { + return nil, err + } + + sqlDB.SetMaxIdleConns(config.Pool) + + return db, nil } diff --git a/pkg/instrumentation/database.go b/pkg/instrumentation/database.go index 0b614ba..19922c2 100644 --- a/pkg/instrumentation/database.go +++ b/pkg/instrumentation/database.go @@ -5,9 +5,9 @@ import ( "fmt" "strings" - "github.com/jinzhu/gorm" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/ext" ddtrace "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" + "gorm.io/gorm" ) const ( @@ -34,7 +34,7 @@ func InstrumentDatabase(db *gorm.DB, appName string) { registerCallbacks(db, "query", callbacks) registerCallbacks(db, "update", callbacks) registerCallbacks(db, "delete", callbacks) - registerCallbacks(db, "row_query", callbacks) + registerCallbacks(db, "row", callbacks) } type callbacks struct { @@ -47,18 +47,18 @@ func newCallbacks(appName string) *callbacks { } } -func (c *callbacks) beforeCreate(scope *gorm.Scope) { c.before(scope, "INSERT", c.serviceName) } -func (c *callbacks) afterCreate(scope *gorm.Scope) { c.after(scope) } -func (c *callbacks) beforeQuery(scope *gorm.Scope) { c.before(scope, "SELECT", c.serviceName) } -func (c *callbacks) afterQuery(scope *gorm.Scope) { c.after(scope) } -func (c *callbacks) beforeUpdate(scope *gorm.Scope) { c.before(scope, "UPDATE", c.serviceName) } -func (c *callbacks) afterUpdate(scope *gorm.Scope) { c.after(scope) } -func (c *callbacks) beforeDelete(scope *gorm.Scope) { c.before(scope, "DELETE", c.serviceName) } -func (c *callbacks) afterDelete(scope *gorm.Scope) { c.after(scope) } -func (c *callbacks) beforeRowQuery(scope *gorm.Scope) { c.before(scope, "", c.serviceName) } -func (c *callbacks) afterRowQuery(scope *gorm.Scope) { c.after(scope) } -func (c *callbacks) before(scope *gorm.Scope, operationName string, serviceName string) { - val, ok := scope.Get(ParentSpanGormKey) +func (c *callbacks) beforeCreate(db *gorm.DB) { c.before(db, "INSERT", c.serviceName) } +func (c *callbacks) afterCreate(db *gorm.DB) { c.after(db) } +func (c *callbacks) beforeQuery(db *gorm.DB) { c.before(db, "SELECT", c.serviceName) } +func (c *callbacks) afterQuery(db *gorm.DB) { c.after(db) } +func (c *callbacks) beforeUpdate(db *gorm.DB) { c.before(db, "UPDATE", c.serviceName) } +func (c *callbacks) afterUpdate(db *gorm.DB) { c.after(db) } +func (c *callbacks) beforeDelete(db *gorm.DB) { c.before(db, "DELETE", c.serviceName) } +func (c *callbacks) afterDelete(db *gorm.DB) { c.after(db) } +func (c *callbacks) beforeRow(db *gorm.DB) { c.before(db, "", c.serviceName) } +func (c *callbacks) afterRow(db *gorm.DB) { c.after(db) } +func (c *callbacks) before(db *gorm.DB, operationName string, serviceName string) { + val, ok := db.Get(ParentSpanGormKey) if !ok { return } @@ -70,46 +70,79 @@ func (c *callbacks) before(scope *gorm.Scope, operationName string, serviceName ddtrace.ServiceName(serviceName), } if operationName == "" { - operationName = strings.Split(scope.SQL, " ")[0] + operationName = strings.Split(db.Statement.SQL.String(), " ")[0] } sp := ddtrace.StartSpan(operationName, spanOpts...) - scope.Set(SpanGormKey, sp) + db.Set(SpanGormKey, sp) } -func (c *callbacks) after(scope *gorm.Scope) { - val, ok := scope.Get(SpanGormKey) +func (c *callbacks) after(db *gorm.DB) { + val, ok := db.Get(SpanGormKey) if !ok { return } + sp := val.(ddtrace.Span) - sp.SetTag(ext.ResourceName, strings.ToUpper(scope.SQL)) - sp.SetTag("db.table", scope.TableName()) - sp.SetTag("db.query", strings.ToUpper(scope.SQL)) - sp.SetTag("db.err", scope.HasError()) - sp.SetTag("db.count", scope.DB().RowsAffected) + sp.SetTag(ext.ResourceName, strings.ToUpper(db.Statement.SQL.String())) + sp.SetTag("db.table", db.Statement.Table) + sp.SetTag("db.query", strings.ToUpper(db.Statement.SQL.String())) + sp.SetTag("db.err", db.Error) + sp.SetTag("db.count", db.RowsAffected) sp.Finish() } func registerCallbacks(db *gorm.DB, name string, c *callbacks) { + var err error + beforeName := fmt.Sprintf("tracing:%v_before", name) afterName := fmt.Sprintf("tracing:%v_after", name) gormCallbackName := fmt.Sprintf("gorm:%v", name) // gorm does some magic, if you pass CallbackProcessor here - nothing works switch name { case "create": - db.Callback().Create().Before(gormCallbackName).Register(beforeName, c.beforeCreate) - db.Callback().Create().After(gormCallbackName).Register(afterName, c.afterCreate) + err = db.Callback().Create().Before(gormCallbackName).Register(beforeName, c.beforeCreate) + if err != nil { + return + } + err = db.Callback().Create().After(gormCallbackName).Register(afterName, c.afterCreate) + if err != nil { + return + } case "query": - db.Callback().Query().Before(gormCallbackName).Register(beforeName, c.beforeQuery) - db.Callback().Query().After(gormCallbackName).Register(afterName, c.afterQuery) + err = db.Callback().Query().Before(gormCallbackName).Register(beforeName, c.beforeQuery) + if err != nil { + return + } + err = db.Callback().Query().After(gormCallbackName).Register(afterName, c.afterQuery) + if err != nil { + return + } case "update": - db.Callback().Update().Before(gormCallbackName).Register(beforeName, c.beforeUpdate) - db.Callback().Update().After(gormCallbackName).Register(afterName, c.afterUpdate) + err = db.Callback().Update().Before(gormCallbackName).Register(beforeName, c.beforeUpdate) + if err != nil { + return + } + err = db.Callback().Update().After(gormCallbackName).Register(afterName, c.afterUpdate) + if err != nil { + return + } case "delete": - db.Callback().Delete().Before(gormCallbackName).Register(beforeName, c.beforeDelete) - db.Callback().Delete().After(gormCallbackName).Register(afterName, c.afterDelete) - case "row_query": - db.Callback().RowQuery().Before(gormCallbackName).Register(beforeName, c.beforeRowQuery) - db.Callback().RowQuery().After(gormCallbackName).Register(afterName, c.afterRowQuery) + err = db.Callback().Delete().Before(gormCallbackName).Register(beforeName, c.beforeDelete) + if err != nil { + return + } + err = db.Callback().Delete().After(gormCallbackName).Register(afterName, c.afterDelete) + if err != nil { + return + } + case "row": + err = db.Callback().Row().Before(gormCallbackName).Register(beforeName, c.beforeRow) + if err != nil { + return + } + err = db.Callback().Row().After(gormCallbackName).Register(afterName, c.afterRow) + if err != nil { + return + } } } diff --git a/pkg/instrumentation/database_test.go b/pkg/instrumentation/database_test.go index 66703df..8d7ce54 100644 --- a/pkg/instrumentation/database_test.go +++ b/pkg/instrumentation/database_test.go @@ -2,14 +2,13 @@ package instrumentation import ( "context" - "os" "path" "testing" "github.com/google/go-cmp/cmp" - "github.com/jinzhu/gorm" - _ "github.com/mattn/go-sqlite3" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/mocktracer" + "gorm.io/driver/sqlite" + "gorm.io/gorm" ) type TestRecord struct { @@ -22,52 +21,64 @@ func TestInstrumentDatabase(t *testing.T) { name string tags map[string]interface{} }{ + { + name: "SELECT", + tags: map[string]interface{}{ + "db.count": int64(-1), + "db.err": nil, + "db.table": "", + "service.name": "test_app_name-mysql", + "span.type": "sql", + "db.query": `SELECT COUNT(*) FROM SQLITE_MASTER WHERE TYPE='TABLE' AND NAME=?`, + "resource.name": `SELECT COUNT(*) FROM SQLITE_MASTER WHERE TYPE='TABLE' AND NAME=?`, + }, + }, { name: "INSERT", tags: map[string]interface{}{ "db.count": int64(1), - "db.err": false, + "db.err": nil, "db.table": "test_records", "service.name": "test_app_name-mysql", "span.type": "sql", - "db.query": `INSERT INTO "TEST_RECORDS" ("ID","NAME") VALUES (?,?)`, - "resource.name": `INSERT INTO "TEST_RECORDS" ("ID","NAME") VALUES (?,?)`, + "db.query": "INSERT INTO `TEST_RECORDS` (`NAME`,`ID`) VALUES (?,?) RETURNING `ID`", + "resource.name": "INSERT INTO `TEST_RECORDS` (`NAME`,`ID`) VALUES (?,?) RETURNING `ID`", }, }, { name: "UPDATE", tags: map[string]interface{}{ "db.count": int64(1), - "db.err": false, + "db.err": nil, "db.table": "test_records", "service.name": "test_app_name-mysql", "span.type": "sql", - "db.query": `UPDATE "TEST_RECORDS" SET "NAME" = ? WHERE "TEST_RECORDS"."ID" = ?`, - "resource.name": `UPDATE "TEST_RECORDS" SET "NAME" = ? WHERE "TEST_RECORDS"."ID" = ?`, + "db.query": "UPDATE `TEST_RECORDS` SET `ID`=?,`NAME`=? WHERE `ID` = ? RETURNING `ID`", + "resource.name": "UPDATE `TEST_RECORDS` SET `ID`=?,`NAME`=? WHERE `ID` = ? RETURNING `ID`", }, }, { name: "SELECT", tags: map[string]interface{}{ "db.count": int64(1), - "db.err": false, + "db.err": nil, "db.table": "test_records", "service.name": "test_app_name-mysql", "span.type": "sql", - "db.query": `SELECT * FROM "TEST_RECORDS" ORDER BY "TEST_RECORDS"."ID" ASC LIMIT 1`, - "resource.name": `SELECT * FROM "TEST_RECORDS" ORDER BY "TEST_RECORDS"."ID" ASC LIMIT 1`, + "db.query": "SELECT * FROM `TEST_RECORDS` WHERE `ID` = ? ORDER BY `TEST_RECORDS`.`ID` LIMIT 1", + "resource.name": "SELECT * FROM `TEST_RECORDS` WHERE `ID` = ? ORDER BY `TEST_RECORDS`.`ID` LIMIT 1", }, }, { name: "DELETE", tags: map[string]interface{}{ "db.count": int64(1), - "db.err": false, + "db.err": nil, "db.table": "test_records", "service.name": "test_app_name-mysql", "span.type": "sql", - "db.query": `DELETE FROM "TEST_RECORDS" WHERE "TEST_RECORDS"."ID" = ?`, - "resource.name": `DELETE FROM "TEST_RECORDS" WHERE "TEST_RECORDS"."ID" = ?`, + "db.query": "DELETE FROM `TEST_RECORDS` WHERE `ID` = ? AND `TEST_RECORDS`.`ID` = ? RETURNING `ID`", + "resource.name": "DELETE FROM `TEST_RECORDS` WHERE `ID` = ? AND `TEST_RECORDS`.`ID` = ? RETURNING `ID`", }, }, } @@ -76,13 +87,10 @@ func TestInstrumentDatabase(t *testing.T) { defer mt.Stop() dbFile := path.Join(t.TempDir(), "test_db") - defer os.Remove(dbFile) - - db, err := gorm.Open("sqlite3", dbFile) + db, err := gorm.Open(sqlite.Open(dbFile)) if err != nil { t.Fatalf("Failed to open DB: %s", err) } - defer db.Close() InstrumentDatabase(db, "test_app_name") db = TraceDatabase(context.Background(), db) @@ -93,19 +101,21 @@ func TestInstrumentDatabase(t *testing.T) { readRecord = &TestRecord{} ) - errors := db.Begin(). - CreateTable(TestRecord{}). - Create(testRecord). - Save(updatedRecord). - First(readRecord). - Delete(testRecord). - Commit().GetErrors() - for _, err := range errors { - t.Fatalf("Errors: %v", err) + if err = db.AutoMigrate(TestRecord{}); err != nil { + t.Fatalf("Failed to migrate DB: %s", err) + } + + err = db.Begin().Create(&testRecord). + Save(&updatedRecord). + First(&readRecord). + Delete(&testRecord). + Commit().Error + if err != nil { + t.Fatalf("Failed to commit changes on test record: %s", err) } spans := mt.FinishedSpans() - if len(spans) != 4 { + if len(spans) != 5 { t.Fatalf("Unexpected number of spans: %d", len(spans)) } diff --git a/pkg/interceptors/database.go b/pkg/interceptors/database.go index 2c8dc03..51ca31a 100644 --- a/pkg/interceptors/database.go +++ b/pkg/interceptors/database.go @@ -4,8 +4,8 @@ import ( "context" grpcmiddleware "github.com/grpc-ecosystem/go-grpc-middleware" - "github.com/jinzhu/gorm" "google.golang.org/grpc" + "gorm.io/gorm" sdkcontext "github.com/scribd/go-sdk/pkg/context/database" sdkinstrumentation "github.com/scribd/go-sdk/pkg/instrumentation" diff --git a/pkg/interceptors/database_logging.go b/pkg/interceptors/database_logging.go index 0a0195e..1827339 100644 --- a/pkg/interceptors/database_logging.go +++ b/pkg/interceptors/database_logging.go @@ -5,6 +5,7 @@ import ( grpcmiddleware "github.com/grpc-ecosystem/go-grpc-middleware" "google.golang.org/grpc" + "gorm.io/gorm" sdkdatabasecontext "github.com/scribd/go-sdk/pkg/context/database" sdkloggercontext "github.com/scribd/go-sdk/pkg/context/logger" @@ -19,10 +20,10 @@ func DatabaseLoggingUnaryServerInterceptor() grpc.UnaryServerInterceptor { return func( ctx context.Context, req interface{}, - info *grpc.UnaryServerInfo, + _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler, ) (interface{}, error) { - d, err := sdkdatabasecontext.Extract(ctx) + db, err := sdkdatabasecontext.Extract(ctx) if err != nil { return nil, err } @@ -32,11 +33,12 @@ func DatabaseLoggingUnaryServerInterceptor() grpc.UnaryServerInterceptor { return nil, err } - newDb := d.New() - newDb.LogMode(true) - newDb.SetLogger(sdklogger.NewGormLogger(l)) + newDB := db.Session(&gorm.Session{ + Logger: sdklogger.NewGormLogger(l), + NewDB: true, + }) - newCtx := sdkdatabasecontext.ToContext(ctx, newDb) + newCtx := sdkdatabasecontext.ToContext(ctx, newDB) return handler(newCtx, req) } @@ -50,10 +52,10 @@ func DatabaseLoggingStreamServerInterceptor() grpc.StreamServerInterceptor { return func( srv interface{}, stream grpc.ServerStream, - info *grpc.StreamServerInfo, + _ *grpc.StreamServerInfo, handler grpc.StreamHandler, ) error { - d, err := sdkdatabasecontext.Extract(stream.Context()) + db, err := sdkdatabasecontext.Extract(stream.Context()) if err != nil { return err } @@ -63,11 +65,12 @@ func DatabaseLoggingStreamServerInterceptor() grpc.StreamServerInterceptor { return err } - newDb := d.New() - newDb.LogMode(true) - newDb.SetLogger(sdklogger.NewGormLogger(l)) + newDB := db.Session(&gorm.Session{ + Logger: sdklogger.NewGormLogger(l), + NewDB: true, + }) - newCtx := sdkdatabasecontext.ToContext(stream.Context(), newDb) + newCtx := sdkdatabasecontext.ToContext(stream.Context(), newDB) wrapped := grpcmiddleware.WrapServerStream(stream) wrapped.WrappedContext = newCtx diff --git a/pkg/interceptors/database_logging_test.go b/pkg/interceptors/database_logging_test.go index 645541b..00113d2 100644 --- a/pkg/interceptors/database_logging_test.go +++ b/pkg/interceptors/database_logging_test.go @@ -7,24 +7,20 @@ import ( "io" golog "log" "net" - "os" "path" "testing" - "github.com/jinzhu/gorm" - "google.golang.org/grpc/credentials/insecure" - - "github.com/scribd/go-sdk/pkg/testing/testproto" - - _ "github.com/mattn/go-sqlite3" - - sdktesting "github.com/scribd/go-sdk/pkg/testing" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/test/bufconn" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/mocktracer" + "gorm.io/driver/sqlite" + "gorm.io/gorm" + + sdktesting "github.com/scribd/go-sdk/pkg/testing" + "github.com/scribd/go-sdk/pkg/testing/testproto" ) type TestRecord struct { @@ -36,38 +32,37 @@ func TestDatabaseLoggingUnaryServerInterceptor(t *testing.T) { mt := mocktracer.Start() defer mt.Stop() - dbFile := path.Join(t.TempDir(), "test_db") - defer os.Remove(dbFile) + tempDBPath := path.Join(t.TempDir(), "test_db") - db, err := gorm.Open("sqlite3", dbFile) + db, err := gorm.Open(sqlite.Open(tempDBPath)) if err != nil { t.Fatalf("Failed to open DB: %s", err) } - defer db.Close() - var ( - testRecordOne = TestRecord{ID: 1, Name: "test_name"} - testRecordTwo = TestRecord{ID: 2, Name: "new_test_name"} - ) + testRecordOne := TestRecord{ID: 1, Name: "test_name"} + testRecordTwo := TestRecord{ID: 2, Name: "new_test_name"} - errors := db.Begin(). - CreateTable(TestRecord{}). - Create(testRecordOne). - Create(testRecordTwo). - Commit().GetErrors() + if err = db.AutoMigrate(TestRecord{}); err != nil { + t.Fatalf("Failed to migrate DB: %s", err) + } - for _, err := range errors { - t.Fatalf("Errors: %v", err) + err = db.Begin(). + Create(&testRecordOne). + Create(&testRecordTwo). + Commit().Error + if err != nil { + t.Fatalf("Failed to create record: %s", err) } var buffer bytes.Buffer - l, err := getLogger("debug", &buffer) + l, err := getLogger("trace", &buffer) require.Nil(t, err) lis := bufconn.Listen(bufSize) s := grpc.NewServer([]grpc.ServerOption{ grpc.ChainUnaryInterceptor( + RequestIDUnaryServerInterceptor(), TracingUnaryServerInterceptor("test"), LoggerUnaryServerInterceptor(l), DatabaseUnaryServerInterceptor(db), @@ -112,38 +107,36 @@ func TestDatabaseLoggingStreamServerInterceptors(t *testing.T) { mt := mocktracer.Start() defer mt.Stop() - dbFile := path.Join(t.TempDir(), "test_db") - defer os.Remove(dbFile) - - db, err := gorm.Open("sqlite3", dbFile) + tempDBPath := path.Join(t.TempDir(), "test_db") + db, err := gorm.Open(sqlite.Open(tempDBPath)) if err != nil { t.Fatalf("Failed to open DB: %s", err) } - defer db.Close() - var ( - testRecordOne = TestRecord{ID: 1, Name: "test_name"} - testRecordTwo = TestRecord{ID: 2, Name: "new_test_name"} - ) + testRecordOne := TestRecord{ID: 1, Name: "test_name"} + testRecordTwo := TestRecord{ID: 2, Name: "new_test_name"} - errors := db.Begin(). - CreateTable(TestRecord{}). - Create(testRecordOne). - Create(testRecordTwo). - Commit().GetErrors() + if err = db.AutoMigrate(TestRecord{}); err != nil { + t.Fatalf("Failed to migrate DB: %s", err) + } - for _, err := range errors { - t.Fatalf("Errors: %v", err) + err = db.Begin(). + Create(&testRecordOne). + Create(&testRecordTwo). + Commit().Error + if err != nil { + t.Fatalf("Failed to create record: %s", err) } var buffer bytes.Buffer - l, err := getLogger("debug", &buffer) + l, err := getLogger("trace", &buffer) require.Nil(t, err) lis := bufconn.Listen(bufSize) s := grpc.NewServer([]grpc.ServerOption{ grpc.ChainStreamInterceptor( + RequestIDStreamServerInterceptor(), TracingStreamServerInterceptor("test"), LoggerStreamServerInterceptor(l), DatabaseStreamServerInterceptor(db), @@ -199,10 +192,11 @@ func TestDatabaseLoggingStreamServerInterceptors(t *testing.T) { func checkGormLoggerFields(t *testing.T, fields map[string]interface{}) { assert.NotEmpty(t, fields["sql"]) - var sql = (fields["sql"]).(map[string]interface{}) + dbFields, ok := (fields["sql"]).(map[string]interface{}) + assert.True(t, ok, "%s not found in log fields", "trace") + assert.NotEmpty(t, dbFields) - assert.NotEmpty(t, sql["duration"]) - assert.NotEmpty(t, sql["affected_rows"]) - assert.NotEmpty(t, sql["file_location"]) - assert.NotNil(t, sql["values"]) + assert.Contains(t, dbFields, "duration") + assert.Contains(t, dbFields, "affected_rows") + assert.Contains(t, dbFields, "sql") } diff --git a/pkg/logger/gorm.go b/pkg/logger/gorm.go index 9af6cf7..76f2c2f 100644 --- a/pkg/logger/gorm.go +++ b/pkg/logger/gorm.go @@ -1,95 +1,64 @@ package logger import ( - "database/sql/driver" + "context" "fmt" - "reflect" - "strings" "time" - "unicode" + + "gorm.io/gorm/logger" +) + +const ( + gormLoggerTraceFieldKey = "sql" + gormLoggerMsg = "gorm DB Logger" ) func NewGormLogger(l Logger) gormLogger { - return gormLogger{ - logger: l, - } + return gormLogger{l} } type gormLogger struct { logger Logger } -// Print formats & prints the log -func (gl gormLogger) Print(values ...interface{}) { - if values[0] == "sql" { - location := values[1].(string) - duration := values[2].(time.Duration) - sql := values[3].(string) - formattedValues := formatValues(values[4].([]interface{})) - affectedRows := values[5].(int64) +func (g gormLogger) LogMode(logger.LogLevel) logger.Interface { + // we ignore changes to the log level. + // making changes to logger level causes a change to the root logger. + return g +} - logger := gl.logger.WithFields(Fields{ - "sql": Fields{ - "duration": duration, - "affected_rows": affectedRows, - "file_location": location, - "values": formattedValues, - }, - }) +func (g gormLogger) Info(ctx context.Context, msg string, args ...interface{}) { + g.logger.Infof(msg, args...) +} - logger.Debugf(sql) - } else { - gl.logger.Tracef("%v", values[2:]...) - } +func (g gormLogger) Warn(ctx context.Context, msg string, args ...interface{}) { + g.logger.Warnf(msg, args...) } -// Code blatantly stolen and modified for our needs from Gorm: -// https://github.com/jinzhu/gorm/blob/2a3ab99/logger.go#L30-L109 -func formatValues(values []interface{}) string { - var formattedValues []string - for _, value := range values { - indirectValue := reflect.Indirect(reflect.ValueOf(value)) - if indirectValue.IsValid() { - value = indirectValue.Interface() - if t, ok := value.(time.Time); ok { - if t.IsZero() { - formattedValues = append(formattedValues, fmt.Sprintf("'%v'", "0000-00-00 00:00:00")) - } else { - formattedValues = append(formattedValues, fmt.Sprintf("'%v'", t.Format("2006-01-02 15:04:05"))) - } - } else if b, ok := value.([]byte); ok { - if str := string(b); isPrintable(str) { - formattedValues = append(formattedValues, fmt.Sprintf("'%v'", str)) - } else { - formattedValues = append(formattedValues, "''") - } - } else if r, ok := value.(driver.Valuer); ok { - if value, err := r.Value(); err == nil && value != nil { - formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value)) - } else { - formattedValues = append(formattedValues, "NULL") - } - } else { - switch value.(type) { - case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, bool: - formattedValues = append(formattedValues, fmt.Sprintf("%v", value)) - default: - formattedValues = append(formattedValues, fmt.Sprintf("'%v'", value)) - } - } - } else { - formattedValues = append(formattedValues, "NULL") - } +func (g gormLogger) Error(ctx context.Context, msg string, args ...interface{}) { + g.logger.WithError(fmt.Errorf(msg, args...)).Errorf(gormLoggerMsg) +} + +func (g gormLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) { + sql, rows := fc() + + l := g.logger.WithFields(Fields{ + gormLoggerTraceFieldKey: Fields{ + "duration": time.Since(begin), + "affected_rows": rows, + "sql": sql, + }, + }) + + if err != nil { + l.WithError(err).Tracef(gormLoggerMsg) + + return } - return strings.Join(formattedValues, " ") + l.Tracef(gormLoggerMsg) } -func isPrintable(s string) bool { - for _, r := range s { - if !unicode.IsPrint(r) { - return false - } - } - return true +func (g gormLogger) ParamsFilter(ctx context.Context, sql string, params ...interface{}) (string, []interface{}) { + return sql, nil } diff --git a/pkg/logger/gorm_test.go b/pkg/logger/gorm_test.go index 395ced3..22abcf9 100644 --- a/pkg/logger/gorm_test.go +++ b/pkg/logger/gorm_test.go @@ -3,25 +3,36 @@ package logger import ( "bytes" "encoding/json" + "errors" "testing" - "time" + "github.com/DATA-DOG/go-sqlmock" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gorm.io/driver/mysql" + "gorm.io/gorm" ) func TestNewGormLogger(t *testing.T) { + sampleQuery := "SELECT id FROM users" + + testDBErrorMsg := "test error" + testDBError := errors.New(testDBErrorMsg) + + var expectedEffectedRows int64 = 1 + var expectedLastInsertID int64 = 1 + // expectedEffectedRowsString := strconv.Itoa(int(expectedEffectedRows)) + tests := []struct { - name string - input []interface{} - cfg Config - isEmpty bool - expected map[string]interface{} + name string + isLogged bool + resultError bool + cfg Config }{ { - name: "Empty on fatal log level", - input: []interface{}{"sql", "test/test", time.Second, "select * from test;", []interface{}{}, int64(10)}, - isEmpty: true, + name: "Empty on fatal log level with error", + isLogged: false, + resultError: true, cfg: Config{ ConsoleEnabled: true, ConsoleJSONFormat: true, @@ -29,63 +40,69 @@ func TestNewGormLogger(t *testing.T) { }, }, { - name: "Empty on error log level", - input: []interface{}{"sql", "test/test", time.Second, "select * from test;", []interface{}{}, int64(10)}, - isEmpty: true, + name: "Empty on fatal log level with error", + isLogged: false, + resultError: true, cfg: Config{ ConsoleEnabled: true, ConsoleJSONFormat: true, - ConsoleLevel: "error", + ConsoleLevel: "fatal", }, }, { - name: "Empty on warning log level", - input: []interface{}{"sql", "test/test", time.Second, "select * from test;", []interface{}{}, int64(10)}, - isEmpty: true, + name: "Empty on error log level without error", + isLogged: false, + resultError: false, cfg: Config{ ConsoleEnabled: true, ConsoleJSONFormat: true, - ConsoleLevel: "warning", + ConsoleLevel: "error", }, }, { - name: "Empty on info log level", - input: []interface{}{"sql", "test/test", time.Second, "select * from test;", []interface{}{}, int64(10)}, - isEmpty: true, + name: "Empty on error log level with error", + isLogged: false, + resultError: true, cfg: Config{ ConsoleEnabled: true, ConsoleJSONFormat: true, - ConsoleLevel: "info", + ConsoleLevel: "error", }, }, { - name: "Print database log", - input: []interface{}{"sql", "test/test", time.Second, "select * from test;", []interface{}{}, int64(10)}, + name: "Empty on debug log level without error", + isLogged: false, + resultError: false, cfg: Config{ ConsoleEnabled: true, ConsoleJSONFormat: true, ConsoleLevel: "debug", }, - expected: map[string]interface{}{ - "duration": float64(time.Second), - "affected_rows": float64(10), - "file_location": "test/test", - "values": "", - }, }, { - name: "Empty on non sql input in debug mode", - input: []interface{}{"test string", "test/test", time.Second, "select * from test;", []interface{}{}, int64(10)}, + name: "Empty on debug log level with error", + isLogged: false, + resultError: true, cfg: Config{ ConsoleEnabled: true, ConsoleJSONFormat: true, ConsoleLevel: "debug", }, - isEmpty: true, }, { - name: "Print log in trace mode on non sql input", - input: []interface{}{"test string", "test/test", time.Second, "select * from test;", []interface{}{}, int64(10)}, + name: "Print on trace log level without error", + isLogged: true, + resultError: false, + cfg: Config{ + ConsoleEnabled: true, + ConsoleJSONFormat: true, + ConsoleLevel: "trace", + }, + }, + { + name: "Print on trace log level with error", + isLogged: true, + resultError: true, cfg: Config{ ConsoleEnabled: true, ConsoleJSONFormat: true, @@ -96,28 +113,73 @@ func TestNewGormLogger(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - var fields Fields var buffer bytes.Buffer b := NewBuilder(&tt.cfg) l, err := b.BuildTestLogger(&buffer) require.Nil(t, err) - gl := NewGormLogger(l) - gl.Print(tt.input...) + gormDB, mock := mockGormConnectionWithLogger(t, l) + ee := mock.ExpectExec(sampleQuery) - if tt.isEmpty { - assert.Empty(t, buffer.Bytes()) + if tt.resultError { + ee.WillReturnError(testDBError) } else { - err = json.Unmarshal(buffer.Bytes(), &fields) + ee.WillReturnResult(sqlmock.NewResult(expectedLastInsertID, expectedEffectedRows)) + } + + gormDB.Exec(sampleQuery) + + if tt.isLogged { + var fields map[string]interface{} + err := json.Unmarshal(buffer.Bytes(), &fields) assert.Nil(t, err) - if tt.expected != nil { - assert.Equal(t, tt.expected, fields["sql"]) + assert.Contains(t, buffer.String(), "level") + + assert.Contains(t, buffer.String(), "message") + assert.Equal(t, fields["message"], gormLoggerMsg) + + assert.Contains(t, buffer.String(), "sql") + assert.Contains(t, fields["sql"], "sql") + assert.Contains(t, fields["sql"], "duration") + assert.Contains(t, fields["sql"], "affected_rows") + + if tt.resultError { + assert.Equal(t, fields["level"], "trace") + assert.Contains(t, buffer.String(), "error") + assert.Equal(t, fields["error"], testDBErrorMsg) } else { - assert.NotEmpty(t, fields["message"]) + assert.Equal(t, fields["level"], "trace") } + } else { + assert.Empty(t, buffer.Bytes()) + } + + if err := mock.ExpectationsWereMet(); err != nil { + t.Errorf("there were unfulfilled expectations: %s", err) } }) + + } +} + +func mockGormConnectionWithLogger(t *testing.T, l Logger) (*gorm.DB, sqlmock.Sqlmock) { + db, mock, err := sqlmock.New() + if err != nil { + t.Error(err) + } + + mockedDB, err := gorm.Open( + mysql.New(mysql.Config{ + Conn: db, + SkipInitializeWithVersion: true, + }), + &gorm.Config{Logger: NewGormLogger(l)}, + ) + if err != nil { + t.Error(err) } + + return mockedDB, mock } diff --git a/pkg/middleware/database.go b/pkg/middleware/database.go index f1e28fd..1449a07 100644 --- a/pkg/middleware/database.go +++ b/pkg/middleware/database.go @@ -6,7 +6,7 @@ import ( sdkdatabasecontext "github.com/scribd/go-sdk/pkg/context/database" sdkinstrumentation "github.com/scribd/go-sdk/pkg/instrumentation" - "github.com/jinzhu/gorm" + "gorm.io/gorm" ) // DatabaseMiddleware wraps an instantiated *gorm.DB that will be diff --git a/pkg/middleware/database_logging.go b/pkg/middleware/database_logging.go index 3380b6c..8f35b27 100644 --- a/pkg/middleware/database_logging.go +++ b/pkg/middleware/database_logging.go @@ -3,6 +3,8 @@ package middleware import ( "net/http" + "gorm.io/gorm" + sdkdatabasecontext "github.com/scribd/go-sdk/pkg/context/database" sdkloggercontext "github.com/scribd/go-sdk/pkg/context/logger" sdklogger "github.com/scribd/go-sdk/pkg/logger" @@ -25,7 +27,7 @@ func NewDatabaseLoggingMiddleware() DatabaseLoggingMiddleware { // meta-information using the logger. func (dlm DatabaseLoggingMiddleware) Handler(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - d, err := sdkdatabasecontext.Extract(r.Context()) + db, err := sdkdatabasecontext.Extract(r.Context()) if err != nil { http.Error(w, "Unable to get DB connection", http.StatusInternalServerError) return @@ -37,11 +39,12 @@ func (dlm DatabaseLoggingMiddleware) Handler(next http.Handler) http.Handler { return } - newDb := d.New() - newDb.LogMode(true) - newDb.SetLogger(sdklogger.NewGormLogger(l)) + newDB := db.Session(&gorm.Session{ + Logger: sdklogger.NewGormLogger(l), + NewDB: true, + }) - ctx := sdkdatabasecontext.ToContext(r.Context(), newDb) + ctx := sdkdatabasecontext.ToContext(r.Context(), newDB) next.ServeHTTP(w, r.WithContext(ctx)) }) } diff --git a/pkg/middleware/database_logging_test.go b/pkg/middleware/database_logging_test.go index f9987ba..e3659d8 100644 --- a/pkg/middleware/database_logging_test.go +++ b/pkg/middleware/database_logging_test.go @@ -5,17 +5,16 @@ import ( "encoding/json" "net/http" "net/http/httptest" - "os" "path" "sync" "testing" - "github.com/jinzhu/gorm" - _ "github.com/mattn/go-sqlite3" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" http2 "gopkg.in/DataDog/dd-trace-go.v1/contrib/net/http" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/mocktracer" + "gorm.io/driver/sqlite" + "gorm.io/gorm" sdkdatabasecontext "github.com/scribd/go-sdk/pkg/context/database" sdklogger "github.com/scribd/go-sdk/pkg/logger" @@ -31,7 +30,8 @@ func testingDbHandler(t *testing.T) http.Handler { db, err := sdkdatabasecontext.Extract(req.Context()) require.Nil(t, err) - _, err = db.First(&TestRecord{}).Rows() + db.Exec("insert asd") + err = db.First(&TestRecord{}).Error require.Nil(t, err) w.WriteHeader(http.StatusOK) @@ -45,27 +45,23 @@ func TestNewDatabaseLoggingMiddleware(t *testing.T) { defer mt.Stop() dbFile := path.Join(t.TempDir(), "test_db") - defer os.Remove(dbFile) - - db, err := gorm.Open("sqlite3", dbFile) + db, err := gorm.Open(sqlite.Open(dbFile)) if err != nil { t.Fatalf("Failed to open DB: %s", err) } - defer db.Close() - var ( - testRecord = TestRecord{ID: 1, Name: "test_name"} - updatedRecord = TestRecord{ID: 1, Name: "new_test_name"} - ) + testRecord := TestRecord{ID: 1, Name: "test_name"} + updatedRecord := TestRecord{ID: 1, Name: "new_test_name"} - errors := db.Begin(). - CreateTable(TestRecord{}). - Create(testRecord). - Save(updatedRecord). - Commit().GetErrors() + if err = db.AutoMigrate(&TestRecord{}); err != nil { + t.Fatalf("Failed to migrate DB: %s", err) + } - for _, err := range errors { - t.Fatalf("Errors: %v", err) + if err = db.Begin(). + Create(&testRecord). + Save(&updatedRecord). + Commit().Error; err != nil { + t.Fatalf("Failed to create and update record: %s", err) } handler := testingDbHandler(t) @@ -74,7 +70,7 @@ func TestNewDatabaseLoggingMiddleware(t *testing.T) { config := &sdklogger.Config{ ConsoleEnabled: true, ConsoleJSONFormat: true, - ConsoleLevel: "debug", + ConsoleLevel: "trace", FileEnabled: false, } @@ -90,6 +86,8 @@ func TestNewDatabaseLoggingMiddleware(t *testing.T) { loggingMiddleware := NewLoggingMiddleware(l) loggingHandler := loggingMiddleware.Handler(databaseHandler) + testHandler := NewRequestIDMiddleware().Handler(loggingHandler) + var wg sync.WaitGroup // test concurrent calls to the handler @@ -103,7 +101,7 @@ func TestNewDatabaseLoggingMiddleware(t *testing.T) { req, reqErr := http.NewRequest("GET", "http://example.com", nil) require.Nil(t, reqErr) - http2.WrapHandler(loggingHandler, "test", "test").ServeHTTP(recorder, req) + http2.WrapHandler(testHandler, "test", "test").ServeHTTP(recorder, req) }() } @@ -115,11 +113,11 @@ func TestNewDatabaseLoggingMiddleware(t *testing.T) { err = dec.Decode(&fields) require.Nil(t, err) - var sql = (fields["sql"]).(map[string]interface{}) - assert.NotEmpty(t, sql) + dbFields, ok := (fields["sql"]).(map[string]interface{}) + assert.True(t, ok, "%s not found in log fields", "trace") + assert.NotEmpty(t, dbFields) - assert.NotEmpty(t, sql["duration"]) - assert.NotEmpty(t, sql["affected_rows"]) - assert.NotEmpty(t, sql["file_location"]) - assert.NotNil(t, sql["values"]) + assert.Contains(t, dbFields, "duration") + assert.Contains(t, dbFields, "affected_rows") + assert.Contains(t, dbFields, "sql") } diff --git a/pkg/testing/testservice.go b/pkg/testing/testservice.go index 2d06192..dc383a0 100644 --- a/pkg/testing/testservice.go +++ b/pkg/testing/testservice.go @@ -3,7 +3,7 @@ package testing import ( "context" - "github.com/jinzhu/gorm" + "gorm.io/gorm" sdkdatabasecontext "github.com/scribd/go-sdk/pkg/context/database" "github.com/scribd/go-sdk/pkg/testing/testproto"