Add DB Connection and Logging

* Utilize LogRus
* Create a DB connection using PGX.
* Create an internal boot package for starting the application.
This commit is contained in:
Abdul Rabbani 2022-04-20 15:44:15 -04:00
parent d0d4f2498e
commit 827475f029
13 changed files with 143 additions and 27 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
ipld-ethcl-indexer
ipld-ethcl-indexer.log

View File

@ -7,7 +7,10 @@ package cmd
import (
"fmt"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/vulcanize/ipld-ethcl-indexer/internal/boot"
)
// headCmd represents the head command
@ -17,9 +20,17 @@ var headCmd = &cobra.Command{
Long: `Capture only the blocks and state at head.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("head called")
startHeadTracking()
},
}
func startHeadTracking() {
_, err := boot.BootApplication(dbAddress, dbPort, dbName, dbUsername, dbPassword, dbDriver)
if err != nil {
log.Fatal("Unable to Start application with error: ", err)
}
}
func init() {
captureCmd.AddCommand(headCmd)

View File

@ -8,18 +8,22 @@ import (
"fmt"
"os"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var (
cfgFile string
dbUserName string
dbPassword string
dbAddress string
dbPort uint16
lhAddress string
lhPort uint16
cfgFile string
dbUsername string
dbPassword string
dbName string
dbAddress string
dbDriver string
dbPort int
lhAddress string
lhPort uint16
logWithCommand log.Entry
)
// rootCmd represents the base command when called without any subcommands
@ -28,6 +32,7 @@ var rootCmd = &cobra.Command{
Short: "This application will keep track of all BeaconState's and SginedBeaconBlock's on the Beacon Chain.",
Long: `This is an application that will capture the BeaconState's and SginedBeaconBlock's on the Beacon Chain.
It can either do this will keeping track of head, or backfilling historic data.`,
PersistentPreRun: initFuncs,
// Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) {},
@ -42,6 +47,43 @@ func Execute() {
}
}
// Prerun for Cobra
func initFuncs(cmd *cobra.Command, args []string) {
viper.BindEnv("log.file", "LOGRUS_FILE")
logfile := viper.GetString("log.file")
if logfile != "" {
file, err := os.OpenFile(logfile,
os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err == nil {
log.Infof("Directing output to %s", logfile)
log.SetOutput(file)
} else {
log.SetOutput(os.Stdout)
log.Info("Failed to log to file, using default stdout")
}
} else {
log.SetOutput(os.Stdout)
}
if err := logLevel(); err != nil {
log.Fatal("Could not set log level: ", err)
}
}
// Set the log level for the application
func logLevel() error {
viper.BindEnv("log.level", "LOGRUS_LEVEL")
lvl, err := log.ParseLevel(viper.GetString("log.level"))
if err != nil {
return err
}
log.SetLevel(lvl)
if lvl > log.InfoLevel {
log.SetReportCaller(true)
}
log.Info("Log level set to ", lvl.String())
return nil
}
func init() {
cobra.OnInitialize(initConfig)
@ -51,18 +93,24 @@ func init() {
// Optional Flags
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.ipld-ethcl-indexer.yaml)")
rootCmd.PersistentFlags().String("log-level", log.InfoLevel.String(), "log level (trace, debug, info, warn, error, fatal, panic)")
rootCmd.PersistentFlags().String("log-file", "ipld-ethcl-indexer.log", "file path for logging")
// Required Flags
//// DB Specific
rootCmd.PersistentFlags().StringVarP(&dbUserName, "db.username", "u", "", "Database username (required)")
rootCmd.PersistentFlags().StringVarP(&dbPassword, "db.password", "p", "", "Database Password (required)")
rootCmd.PersistentFlags().StringVarP(&dbAddress, "db.address", "a", "", "Port to connect to DB(required)")
rootCmd.PersistentFlags().Uint16VarP(&dbPort, "db.port", "o", 0, "Port to connect to DB(required)")
rootCmd.PersistentFlags().StringVarP(&dbUsername, "db.username", "", "", "Database username (required)")
rootCmd.PersistentFlags().StringVarP(&dbPassword, "db.password", "", "", "Database Password (required)")
rootCmd.PersistentFlags().StringVarP(&dbAddress, "db.address", "", "", "Port to connect to DB(required)")
rootCmd.PersistentFlags().StringVarP(&dbName, "db.name", "n", "", "Database name connect to DB(required)")
rootCmd.PersistentFlags().StringVarP(&dbDriver, "db.driver", "", "", "Database Driver to connect to DB(required)")
rootCmd.PersistentFlags().IntVarP(&dbPort, "db.port", "", 0, "Port to connect to DB(required)")
rootCmd.MarkPersistentFlagRequired("db.username")
rootCmd.MarkPersistentFlagRequired("db.password")
rootCmd.MarkPersistentFlagRequired("db.address")
rootCmd.MarkPersistentFlagRequired("db.port")
rootCmd.MarkPersistentFlagRequired("db.name")
rootCmd.MarkPersistentFlagRequired("db.driver")
//// Lighthouse Specific
rootCmd.PersistentFlags().StringVarP(&lhAddress, "lh.address", "l", "", "Address to connect to lighthouse node (required if username is set)")
@ -71,11 +119,17 @@ func init() {
rootCmd.MarkPersistentFlagRequired("lh.port")
// Bind Flags with Viper
// Optional
viper.BindPFlag("log.level", rootCmd.PersistentFlags().Lookup("log-level"))
viper.BindPFlag("log.file", rootCmd.PersistentFlags().Lookup("log-file"))
//// DB Flags
viper.BindPFlag("db.username", rootCmd.PersistentFlags().Lookup("db.username"))
viper.BindPFlag("db.password", rootCmd.PersistentFlags().Lookup("db.password"))
viper.BindPFlag("db.address", rootCmd.PersistentFlags().Lookup("db.address"))
viper.BindPFlag("db.port", rootCmd.PersistentFlags().Lookup("db.port"))
viper.BindPFlag("db.name", rootCmd.PersistentFlags().Lookup("db.name"))
viper.BindPFlag("db.driver", rootCmd.PersistentFlags().Lookup("db.driver"))
// LH specific
viper.BindPFlag("lh.address", rootCmd.PersistentFlags().Lookup("lh.address"))

23
internal/boot/boot.go Normal file
View File

@ -0,0 +1,23 @@
package boot
import (
log "github.com/sirupsen/logrus"
"github.com/vulcanize/ipld-ethcl-indexer/pkg/database/sql/postgres"
)
func setUpLightHouse() {
}
// This function will perform some boot operations.
// 1. Setup a logger
// 2. Connect to the database.
// 3. Connect to to the lighthouse client.
func BootApplication(dbHostname string, dbPort int, dbName string, dbUsername string, dbPassword string, driverName string) (*postgres.DB, error) {
log.Debug("Setting up DB connection")
DB, err := SetupDb(dbHostname, dbPort, dbName, dbUsername, dbPassword, driverName)
if err != nil {
return nil, err
}
return DB, nil
}

View File

@ -0,0 +1,29 @@
// This file will allow users to setup a new DB based on the user provided inputs.
package boot
import (
log "github.com/sirupsen/logrus"
"github.com/vulcanize/ipld-ethcl-indexer/pkg/database/sql/postgres"
)
func SetupDb(dbHostname string, dbPort int, dbName string, dbUsername string, dbPassword string, driverName string) (*postgres.DB, error) {
log.Debug("Resolving Driver Type")
DbDriver, err := postgres.ResolveDriverType(driverName)
if err != nil {
log.Fatal("Can't Connect to DB")
}
log.Info("Using Driver:", DbDriver)
postgresConfig := postgres.Config{
Hostname: dbHostname,
Port: dbPort,
DatabaseName: dbName,
Username: dbUsername,
Password: dbPassword,
Driver: DbDriver,
}
DB, err := postgres.NewPostgresDB(postgresConfig)
return DB, err
}

3
internal/boot/startup.md Normal file
View File

@ -0,0 +1,3 @@
# Overview
This small package will group all the functions needed to start the application. The functions listed here can be utilized regardless of whether the application is meant to track `head` or for `historic` processing.

View File

@ -53,10 +53,6 @@ type Config struct {
MaxConnLifetime time.Duration
ConnTimeout time.Duration
// node info params
ID string
ClientName string
// driver type
Driver DriverType
}

View File

@ -4,7 +4,8 @@ import (
"context"
"fmt"
"github.com/vulcanize/ipld-ethcl-indexer/pkg/dbtools/sql"
log "github.com/sirupsen/logrus"
"github.com/vulcanize/ipld-ethcl-indexer/pkg/database/sql"
)
var _ sql.Database = &DB{}
@ -14,15 +15,10 @@ var _ sql.Database = &DB{}
// This will make sure that if you want a driver, it conforms to the interface.
// NewPostgresDB returns a postgres.DB using the provided Config and driver type.
func NewPostgresDB(c Config, driverName string) (*DB, error) {
func NewPostgresDB(c Config) (*DB, error) {
var driver *pgxDriver
driverType, err := ResolveDriverType(driverName)
if err != nil {
return nil, err
}
driver, err = createDriver(c, driverType)
driver, err := createDriver(c)
if err != nil {
return nil, err
@ -31,15 +27,18 @@ func NewPostgresDB(c Config, driverName string) (*DB, error) {
return &DB{driver}, nil
}
func createDriver(c Config, driverType DriverType) (*pgxDriver, error) {
switch driverType {
func createDriver(c Config) (*pgxDriver, error) {
switch c.Driver {
case PGX:
log.Debug("Creating New Driver")
driver, err := newPGXDriver(context.Background(), c)
if err != nil {
return nil, fmt.Errorf("Error Creating Driver, err: %e", err)
}
log.Info("Successfully created a driver for PGX")
return driver, nil
default:
log.Fatal("Couldnt find a driver to create for: ", c.Driver)
return nil, fmt.Errorf("Can't find a driver to create")
}

View File

@ -8,7 +8,7 @@ import (
"github.com/jackc/pgconn"
"github.com/jackc/pgx/v4"
"github.com/jackc/pgx/v4/pgxpool"
"github.com/vulcanize/ipld-ethcl-indexer/pkg/dbtools/sql"
"github.com/vulcanize/ipld-ethcl-indexer/pkg/database/sql"
)
// pgxDriver driver, implements sql.Driver

View File

@ -7,7 +7,7 @@ import (
"testing"
"github.com/jackc/pgx/v4/pgxpool"
"github.com/vulcanize/ipld-ethcl-indexer/pkg/dbtools/sql"
"github.com/vulcanize/ipld-ethcl-indexer/pkg/database/sql"
"github.com/vulcanize/ipld-ethcl-indexer/pkg/testhelpers"
)