Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decouple config loading & log initialization #471

Merged
merged 2 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 6 additions & 23 deletions cmd/vspd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (

"github.com/decred/dcrd/dcrutil/v4"
"github.com/decred/dcrd/hdkeychain/v3"
"github.com/decred/slog"
"github.com/decred/vspd/database"
"github.com/decred/vspd/internal/config"
"github.com/decred/vspd/internal/version"
Expand Down Expand Up @@ -60,9 +59,7 @@ type vspdConfig struct {
HomeDir string `long:"homedir" no-ini:"true" description:"Path to application home directory. Used for storing VSP database and logs."`
ConfigFile string `long:"configfile" no-ini:"true" description:"DEPRECATED: This behavior is no longer available and this option will be removed in a future version of the software."`

logBackend *slog.Backend
logLevel slog.Level

logPath string
dbPath string
network *config.Network
dcrdCert []byte
Expand Down Expand Up @@ -379,18 +376,8 @@ func loadConfig() (*vspdConfig, error) {
return nil, fmt.Errorf("failed to create data directory: %w", err)
}

// Initialize loggers and log rotation.
logDir := filepath.Join(cfg.HomeDir, "logs", cfg.network.Name)
cfg.logBackend, err = newLogBackend(logDir, appName, cfg.MaxLogSize, cfg.LogsToKeep)
if err != nil {
return nil, fmt.Errorf("failed to initialize logger: %w", err)
}

var ok bool
cfg.logLevel, ok = slog.LevelFromString(cfg.LogLevel)
if !ok {
return nil, fmt.Errorf("unknown log level: %s", cfg.LogLevel)
}
// Set the log path.
cfg.logPath = filepath.Join(cfg.HomeDir, "logs", cfg.network.Name)

// Set the database path.
cfg.dbPath = filepath.Join(dataDir, dbFilename)
Expand All @@ -410,12 +397,14 @@ func loadConfig() (*vspdConfig, error) {
}

// Create new database.
err = database.CreateNew(cfg.dbPath, cfg.FeeXPub, cfg.logger(" DB"))
fmt.Printf("Initializing new database at %s\n", cfg.dbPath)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now these won't be in the logs.

err = database.CreateNew(cfg.dbPath, cfg.FeeXPub)
if err != nil {
return nil, fmt.Errorf("error creating db file %s: %w", cfg.dbPath, err)
}

// Exit with success
fmt.Printf("Database initialized\n")
os.Exit(0)
}

Expand All @@ -427,9 +416,3 @@ func loadConfig() (*vspdConfig, error) {

return &cfg, nil
}

func (cfg *vspdConfig) logger(subsystem string) slog.Logger {
log := cfg.logBackend.Logger(subsystem)
log.SetLevel(cfg.logLevel)
return log
}
37 changes: 33 additions & 4 deletions cmd/vspd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"time"

"github.com/decred/dcrd/wire"
"github.com/decred/slog"
"github.com/decred/vspd/database"
"github.com/decred/vspd/internal/config"
"github.com/decred/vspd/internal/signal"
Expand All @@ -33,6 +34,28 @@ func main() {
os.Exit(run())
}

// initLogging uses the provided vspd config to create a logging backend, and
// returns a function which can be used to create ready-to-use subsystem
// loggers.
func initLogging(cfg *vspdConfig) (func(subsystem string) slog.Logger, error) {
backend, err := newLogBackend(cfg.logPath, "vspd", cfg.MaxLogSize, cfg.LogsToKeep)
if err != nil {
return nil, fmt.Errorf("failed to initialize logger: %w", err)
}

var ok bool
level, ok := slog.LevelFromString(cfg.LogLevel)
if !ok {
return nil, fmt.Errorf("unknown log level: %q", cfg.LogLevel)
}

return func(subsystem string) slog.Logger {
log := backend.Logger(subsystem)
log.SetLevel(level)
return log
}, nil
}

// run is the real main function for vspd. It is necessary to work around the
// fact that deferred functions do not run when os.Exit() is called.
func run() int {
Expand All @@ -43,7 +66,13 @@ func run() int {
return 1
}

log := cfg.logger("VSP")
makeLogger, err := initLogging(cfg)
if err != nil {
fmt.Fprintf(os.Stderr, "initLogging error: %v\n", err)
return 1
}

log := makeLogger("VSP")

// Create a context that is canceled when a shutdown request is received
// through an interrupt signal such as SIGINT (Ctrl+C).
Expand Down Expand Up @@ -72,15 +101,15 @@ func run() int {
}

// Open database.
db, err := database.Open(cfg.dbPath, cfg.logger(" DB"), maxVoteChangeRecords)
db, err := database.Open(cfg.dbPath, makeLogger(" DB"), maxVoteChangeRecords)
if err != nil {
log.Errorf("Failed to open database: %v", err)
return 1
}
const writeBackup = true
defer db.Close(writeBackup)

rpcLog := cfg.logger("RPC")
rpcLog := makeLogger("RPC")

// Create a channel to receive blockConnected notifications from dcrd.
blockNotifChan := make(chan *wire.BlockHeader)
Expand Down Expand Up @@ -108,7 +137,7 @@ func run() int {
MaxVoteChangeRecords: maxVoteChangeRecords,
VspdVersion: version.String(),
}
api, err := webapi.New(db, cfg.logger("API"), dcrd, wallets, apiCfg)
api, err := webapi.New(db, makeLogger("API"), dcrd, wallets, apiCfg)
if err != nil {
log.Errorf("Failed to initialize webapi: %v", err)
return 1
Expand Down
9 changes: 1 addition & 8 deletions database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,7 @@ func (vdb *VspDatabase) WriteHotBackupFile() error {
// - the provided extended pubkey (to be used for deriving fee addresses).
// - an ed25519 keypair to sign API responses.
// - a secret key to use for initializing a HTTP cookie store.
func CreateNew(dbFile, feeXPub string, log slog.Logger) error {
log.Infof("Initializing new database at %s", dbFile)
func CreateNew(dbFile, feeXPub string) error {

db, err := bolt.Open(dbFile, 0600, &bolt.Options{Timeout: 1 * time.Second})
if err != nil {
Expand All @@ -115,8 +114,6 @@ func CreateNew(dbFile, feeXPub string, log slog.Logger) error {
return err
}

log.Info("Generating ed25519 signing key")

// Generate ed25519 key
_, signKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
Expand All @@ -128,7 +125,6 @@ func CreateNew(dbFile, feeXPub string, log slog.Logger) error {
}

// Generate a secret key for initializing the cookie store.
log.Info("Generating cookie secret")
secret := make([]byte, 32)
_, err = rand.Read(secret)
if err != nil {
Expand All @@ -139,7 +135,6 @@ func CreateNew(dbFile, feeXPub string, log slog.Logger) error {
return err
}

log.Info("Storing extended public key")
// Store fee xpub
err = vspBkt.Put(feeXPubK, []byte(feeXPub))
if err != nil {
Expand All @@ -165,8 +160,6 @@ func CreateNew(dbFile, feeXPub string, log slog.Logger) error {
return err
}

log.Info("Database initialized")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a log you wouldn't want to lose.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per #465, creating the database will soon be in a new dedicated binary, so this is somewhat temporary/irrelevant.


return nil
}

Expand Down
2 changes: 1 addition & 1 deletion database/database_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func TestDatabase(t *testing.T) {
for testName, test := range tests {

// Create a new blank database for each sub-test.
err := CreateNew(testDb, feeXPub, log)
err := CreateNew(testDb, feeXPub)
if err != nil {
t.Fatalf("error creating test database: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/webapi/setaltsignaddr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func TestMain(m *testing.M) {
os.Remove(testDb)

// Create a new blank database for all tests.
err := database.CreateNew(testDb, feeXPub, log)
err := database.CreateNew(testDb, feeXPub)
if err != nil {
panic(fmt.Errorf("error creating test database: %w", err))
}
Expand Down
Loading