Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
fbufler committed Dec 2, 2023
0 parents commit cc88e02
Show file tree
Hide file tree
Showing 16 changed files with 1,362 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test.log
61 changes: 61 additions & 0 deletions cmd/local/local.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package local

import (
"github.com/fbufler/database-monitor/internal/tester"
"github.com/fbufler/database-monitor/pkg/database"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

type LocalCfg struct {
Databases []database.Config `mapstructure:"databases"`
TestTimeout int `mapstructure:"test_timeout"`
TestInterval int `mapstructure:"test_interval"`
}

func LocalCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "local",
Short: "Run dbm database tester",
RunE: local,
}
cmd.Flags().StringSlice("databases", []string{}, "databases to test")
cmd.Flags().Int("test_timeout", 5, "test timeout in seconds")
viper.BindPFlag("databases", cmd.Flags().Lookup("databases"))
viper.BindPFlag("test_timeout", cmd.Flags().Lookup("test_timeout"))
return cmd
}

func local(cmd *cobra.Command, args []string) error {
log.Info().Msg("Starting local")
ctx := cmd.Context()
LocalCfg := LocalCfg{}
err := viper.Unmarshal(&LocalCfg)
if err != nil {
return err
}
log.Debug().Msgf("LocalCfg: %+v", LocalCfg)
testTimeout := viper.GetInt("test_timeout")
if testTimeout > 0 {
LocalCfg.TestTimeout = testTimeout
}
log.Debug().Msg("Initializing database tester")
tester := tester.NewPostgres(tester.Config{
Databases: LocalCfg.Databases,
TestTimeout: LocalCfg.TestTimeout,
TestInterval: LocalCfg.TestInterval,
})
log.Info().Msg("Starting database tester")
result := tester.Run(ctx)
log.Debug().Msg("Handling results")
for {
select {
case res := <-result:
log.Info().Msgf("Result: %+v", res)
case <-ctx.Done():
log.Info().Msg("Context terminated")
return nil
}
}
}
1 change: 1 addition & 0 deletions cmd/local/local_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package local
107 changes: 107 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package main

import (
"context"
"fmt"
"os"
"os/signal"
"strings"
"syscall"
"time"

"github.com/fbufler/database-monitor/cmd/local"
"github.com/fbufler/database-monitor/cmd/serve"
"github.com/fbufler/database-monitor/cmd/setup"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var rootCmd = &cobra.Command{
Use: "dbm",
Version: "0.0.1",
Short: "dbm is a database monitoring tool",
}

func initFlags() {
rootCmd.PersistentFlags().Bool("debug", false, "sets log level to debug")
rootCmd.PersistentFlags().String("logfile", "", "log file path")
viper.BindPFlag("debug", rootCmd.PersistentFlags().Lookup("debug"))
viper.BindPFlag("logfile", rootCmd.PersistentFlags().Lookup("logfile"))
}

func initViper() {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath("/etc/dbm/")
viper.AddConfigPath("$HOME/.dbm")
viper.AddConfigPath(".")
viper.SetEnvPrefix("DBM")
viper.AutomaticEnv()
err := viper.ReadInConfig()
if err != nil {
fmt.Println("No config file found, using defaults")
}
}

func initLogging() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
zerolog.SetGlobalLevel(zerolog.InfoLevel)
output := zerolog.ConsoleWriter{Out: os.Stdout}
output.FormatLevel = func(i interface{}) string {
return strings.ToUpper(fmt.Sprintf("| %-6s|", i))
}
log.Logger = zerolog.New(output)
debug := viper.GetBool("debug")
file := viper.GetString("logfile")
if debug {
zerolog.SetGlobalLevel(zerolog.DebugLevel)
}
if file != "" {
logFile, err := os.OpenFile(file, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
multi := zerolog.MultiLevelWriter(output, logFile)
log.Logger = zerolog.New(multi).With().Timestamp().Logger()
}
}

func main() {
initViper()
initFlags()
initLogging()
log.Debug().Msg("Starting dbm")
log.Debug().Msg("Setting up root command")
context, cancel := context.WithCancel(context.Background())
rootCmd.SetContext(context)
localCmd := local.LocalCommand()
localCmd.SetContext(context)
rootCmd.AddCommand(localCmd)
setupCmd := setup.SetupCommand()
setupCmd.SetContext(context)
rootCmd.AddCommand(setupCmd)
serveCmd := serve.ServeCommand()
serveCmd.SetContext(context)
rootCmd.AddCommand(serveCmd)
log.Debug().Msg("Executing root command")
sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, os.Interrupt, syscall.SIGTERM)
go func() {
err := rootCmd.Execute()
if err != nil {
log.Error().Err(err).Msg("Root command failed")
sigchan <- syscall.SIGTERM
}
}()
log.Debug().Msg("Waiting for termination signal")
<-sigchan
log.Debug().Msg("Received termination signal")
cancel()
log.Debug().Msg("Waiting for root command termination")
time.Sleep(1 * time.Second)
<-rootCmd.Context().Done()
log.Debug().Msg("Root command terminated")
log.Debug().Msg("Exiting dbm")
}
73 changes: 73 additions & 0 deletions cmd/serve/serve.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package serve

import (
"github.com/fbufler/database-monitor/internal/service"
"github.com/fbufler/database-monitor/internal/tester"
"github.com/fbufler/database-monitor/pkg/database"
"github.com/gorilla/mux"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

type ServeCfg struct {
Databases []database.Config `mapstructure:"databases"`
TestTimeout int `mapstructure:"test_timeout"`
TestInterval int `mapstructure:"test_interval"`
Port int `mapstructure:"port"`
InvalidationTime int `mapstructure:"invalidation_time"`
}

func ServeCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "serve",
Short: "Run dbm database tester service",
RunE: serve,
}
cmd.Flags().StringSlice("databases", []string{}, "databases to test")
cmd.Flags().Int("test_timeout", 5, "test timeout in seconds")
cmd.Flags().Int("test_interval", 5, "test interval in seconds")
cmd.Flags().Int("port", 8080, "service port")
cmd.Flags().Int("invalidation_time", 5, "invalidation time in seconds")
viper.BindPFlag("databases", cmd.Flags().Lookup("databases"))
viper.BindPFlag("test_timeout", cmd.Flags().Lookup("test_timeout"))
viper.BindPFlag("test_interval", cmd.Flags().Lookup("test_interval"))
viper.BindPFlag("port", cmd.Flags().Lookup("port"))
viper.BindPFlag("invalidation_time", cmd.Flags().Lookup("invalidation_time"))
return cmd
}

func serve(cmd *cobra.Command, args []string) error {
log.Info().Msg("Starting local")
ctx := cmd.Context()
serveCfg := ServeCfg{}
err := viper.Unmarshal(&serveCfg)
if err != nil {
return err
}
log.Debug().Msgf("LocalCfg: %+v", serveCfg)
testTimeout := viper.GetInt("test_timeout")
if testTimeout > 0 {
serveCfg.TestTimeout = testTimeout
}
log.Debug().Msg("Initializing database tester")
tester := tester.NewPostgres(tester.Config{
Databases: serveCfg.Databases,
TestTimeout: serveCfg.TestTimeout,
TestInterval: serveCfg.TestInterval,
})
log.Info().Msg("Starting database tester")
result := tester.Run(ctx)
log.Info().Msg("Initializing service")
router := mux.NewRouter()
service := service.New(service.Config{
Port: serveCfg.Port,
InvalidationTime: serveCfg.InvalidationTime,
}, result, router)
log.Info().Msg("Starting service")
go service.Run(ctx)
log.Debug().Msg("Waiting for context termination")
<-ctx.Done()
log.Info().Msg("Context terminated")
return nil
}
46 changes: 46 additions & 0 deletions cmd/setup/setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package setup

import (
"github.com/fbufler/database-monitor/internal/tester"
"github.com/fbufler/database-monitor/pkg/database"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

type LocalCfg struct {
Databases []database.Config `mapstructure:"databases"`
}

func SetupCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "setup",
Short: "Setup dbm database tester",
RunE: setup,
}
cmd.Flags().StringSlice("databases", []string{}, "databases to test")
viper.BindPFlag("databases", cmd.Flags().Lookup("databases"))
return cmd
}

func setup(cmd *cobra.Command, args []string) error {
log.Info().Msg("Starting local")
ctx := cmd.Context()
LocalCfg := LocalCfg{}
err := viper.Unmarshal(&LocalCfg)
if err != nil {
return err
}
log.Debug().Msgf("LocalCfg: %+v", LocalCfg)
log.Debug().Msg("Initializing database tester")
tester := tester.NewPostgres(tester.Config{
Databases: LocalCfg.Databases,
})
log.Info().Msg("Setup tester")
err = tester.Setup(ctx)
if err != nil {
return err
}
log.Info().Msg("Tester setup complete")
return nil
}
17 changes: 17 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
logfile: test.log
debug: true
test_timeout: 5
test_interval: 30
databases:
- host: localhost
port: 5432
username: postgres
password: postgres
database: postgres
connection_timeout: 5
- host: localhost
port: 5433
username: postgres
password: postgres
database: postgres
connection_timeout: 5
38 changes: 38 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module github.com/fbufler/database-monitor

go 1.21.1

require (
github.com/gorilla/mux v1.8.1
github.com/lib/pq v1.10.9
github.com/rs/zerolog v1.31.0
github.com/spf13/cobra v1.8.0
github.com/spf13/viper v1.17.0
github.com/stretchr/testify v1.8.4
)

require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/sagikazarmark/locafero v0.3.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.10.0 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.13.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading

0 comments on commit cc88e02

Please sign in to comment.