From b12e812b36989f1ed526f770ad4887d8b628625b Mon Sep 17 00:00:00 2001 From: Atvaark Date: Thu, 11 May 2017 08:01:12 +0200 Subject: [PATCH] Add database logmode to the config This allows users to change the default logging verbosity (errors) to either *detailed* (prints SQL statements) or *silent*. Also added support for using a custom logger function. - Fixed the gorm unit test that checks the automigrations They will actually fail if any errors were logged now. - Added a postgres unit test Currently disabled because it would need a running local postgres db and a change to the .travis.yml file to work inside the CI build. --- .travis.yml | 4 +-- config/config.go | 23 +++++++++++++++++- db/gorm.go | 30 ++++++++++++++++++++++- db/gorm_test.go | 63 ++++++++++++++++++++++++++++++++++++++++++++++-- main.go | 2 +- 5 files changed, 115 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5b8db6c5..c0a274f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,9 +7,9 @@ before_install: script: # Downloads deps automatically. No need to add manually. - go list -f '{{.Deps}}' | tr "[" " " | tr "]" " " | xargs go list -e -f '{{if not .Standard}}{{.ImportPath}}{{end}}' | grep -v 'github.com/ewhal/nyaa' | xargs go get -v -- go get +- go get - go build -- go vet +- go vet - go test -v ./... before_deploy: - ./package.sh diff --git a/config/config.go b/config/config.go index ae599c23..19b446d9 100644 --- a/config/config.go +++ b/config/config.go @@ -22,6 +22,7 @@ type Config struct { // DBParams will be directly passed to Gorm, and its internal // structure depends on the dialect for each db type DBParams string `json:"db_params"` + DBLogMode string `json:"db_logmode"` // tracker scraper config (required) Scrape ScraperConfig `json:"scraper"` // cache config @@ -32,7 +33,7 @@ type Config struct { I2P *I2PConfig `json:"i2p"` } -var Defaults = Config{"localhost", 9999, "sqlite3", "./nyaa.db?cache_size=50", DefaultScraperConfig, DefaultCacheConfig, DefaultSearchConfig, nil} +var Defaults = Config{"localhost", 9999, "sqlite3", "./nyaa.db?cache_size=50", "default", DefaultScraperConfig, DefaultCacheConfig, DefaultSearchConfig, nil} var allowedDatabaseTypes = map[string]bool{ "sqlite3": true, @@ -41,12 +42,19 @@ var allowedDatabaseTypes = map[string]bool{ "mssql": true, } +var allowedDBLogModes = map[string]bool{ + "default": true, // errors only + "detailed": true, + "silent": true, +} + func New() *Config { var config Config config.Host = Defaults.Host config.Port = Defaults.Port config.DBType = Defaults.DBType config.DBParams = Defaults.DBParams + config.DBLogMode = Defaults.DBLogMode config.Scrape = Defaults.Scrape config.Cache = Defaults.Cache return &config @@ -60,6 +68,7 @@ func (config *Config) BindFlags() func() error { host := flag.String("host", Defaults.Host, "binding address of the server") port := flag.Int("port", Defaults.Port, "port of the server") dbParams := flag.String("dbparams", Defaults.DBParams, "parameters to open the database (see Gorm's doc)") + dbLogMode := flag.String("dblogmode", Defaults.DBLogMode, "database log verbosity (errors only by default)") return func() error { // You can override fields in the config file with flags. @@ -70,6 +79,10 @@ func (config *Config) BindFlags() func() error { if err != nil { return err } + err = config.SetDBLogMode(*dbLogMode) + if err != nil { + return err + } err = config.HandleConfFileFlag(*confFile) return err } @@ -98,6 +111,14 @@ func (config *Config) SetDBType(db_type string) error { return nil } +func (config *Config) SetDBLogMode(db_logmode string) error { + if !allowedDBLogModes[db_logmode] { + return fmt.Errorf("unknown database log mode '%s'", db_logmode) + } + config.DBLogMode = db_logmode + return nil +} + func (config *Config) Read(input io.Reader) error { return json.NewDecoder(input).Decode(config) } diff --git a/db/gorm.go b/db/gorm.go index 77fa33a6..c2e75e60 100644 --- a/db/gorm.go +++ b/db/gorm.go @@ -9,12 +9,20 @@ import ( _ "github.com/jinzhu/gorm/dialects/sqlite" ) +type Logger interface { + Print(v ...interface{}) +} + +// use the default gorm logger that prints to stdout +var DefaultLogger Logger = nil + var ORM *gorm.DB var IsSqlite bool // GormInit init gorm ORM. -func GormInit(conf *config.Config) (*gorm.DB, error) { +func GormInit(conf *config.Config, logger Logger) (*gorm.DB, error) { + db, openErr := gorm.Open(conf.DBType, conf.DBParams) if openErr != nil { log.CheckError(openErr) @@ -35,9 +43,29 @@ func GormInit(conf *config.Config) (*gorm.DB, error) { db.LogMode(true) } + switch conf.DBLogMode { + case "detailed": + db.LogMode(true) + case "silent": + db.LogMode(false) + } + + if logger != nil { + db.SetLogger(logger) + } + db.AutoMigrate(&model.User{}, &model.UserFollows{}, &model.UserUploadsOld{}) + if db.Error != nil { + return db, db.Error + } db.AutoMigrate(&model.Torrent{}, &model.TorrentReport{}) + if db.Error != nil { + return db, db.Error + } db.AutoMigrate(&model.Comment{}, &model.OldComment{}) + if db.Error != nil { + return db, db.Error + } return db, nil } diff --git a/db/gorm_test.go b/db/gorm_test.go index eefc8fbb..ec61824a 100644 --- a/db/gorm_test.go +++ b/db/gorm_test.go @@ -1,22 +1,81 @@ package db import ( + "fmt" "testing" + "github.com/azhao12345/gorm" "github.com/ewhal/nyaa/config" ) -func TestGormInit(t *testing.T) { +type errorLogger struct { + t *testing.T +} + +func (logger *errorLogger) Print(values ...interface{}) { + if len(values) > 1 { + message := gorm.LogFormatter(values...) + level := values[0] + if level == "log" { + logger.t.Error(message...) + } + + fmt.Println(message...) + } +} + +func TestGormInitSqlite(t *testing.T) { conf := config.New() conf.DBType = "sqlite3" conf.DBParams = ":memory:?cache=shared&mode=memory" + conf.DBLogMode = "detailed" - db, err := GormInit(conf) + db, err := GormInit(conf, &errorLogger{t}) if err != nil { t.Errorf("failed to initialize database: %v", err) return } + if db == nil { + return + } + + err = db.Close() + if err != nil { + t.Errorf("failed to close database: %v", err) + } +} + +// This test requires a running postgres instance. To run it in CI build add these settings in the .travis.yml +// services: +// - postgresql +// before_script: +// - psql -c "CREATE DATABASE nyaapantsu;" -U postgres +// - psql -c "CREATE USER nyaapantsu WITH PASSWORD 'nyaapantsu';" -U postgres +// +// Then enable the test by setting this variable to "true" via ldflags: +// go test ./... -v -ldflags="-X github.com/ewhal/nyaa/db.testPostgres=true" +var testPostgres = "false" + +func TestGormInitPostgres(t *testing.T) { + if testPostgres != "true" { + t.Skip("skip", testPostgres) + } + + conf := config.New() + conf.DBType = "postgres" + conf.DBParams = "host=localhost user=nyaapantsu dbname=nyaapantsu sslmode=disable password=nyaapantsu" + conf.DBLogMode = "detailed" + + db, err := GormInit(conf, &errorLogger{t}) + if err != nil { + t.Errorf("failed to initialize database: %v", err) + } + + if db == nil { + return + } + err = db.Close() if err != nil { t.Errorf("failed to close database: %v", err) diff --git a/main.go b/main.go index 07260f53..48368b9e 100644 --- a/main.go +++ b/main.go @@ -118,7 +118,7 @@ func main() { if err != nil { log.CheckError(err) } - db.ORM, err = db.GormInit(conf) + db.ORM, err = db.GormInit(conf, db.DefaultLogger) if err != nil { log.Fatal(err.Error()) }