Skip to content

Commit

Permalink
feat: use passed receiver value, log in json
Browse files Browse the repository at this point in the history
  • Loading branch information
tyzbit committed May 3, 2022
1 parent c3af914 commit cefff51
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 34 deletions.
9 changes: 6 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ type Watcher struct {
CancelSignals map[string]chan bool
DB *gorm.DB
LogConfig logger.Interface
// Config is embedded into Watcher at the top level, except
// it needs to be explicitly called when using pointers.
Config
}

Expand Down Expand Up @@ -59,7 +61,7 @@ var (
)

func init() {
InitLogging()
watcher.InitLogging()

// Set defaults and throw errors if necessary values aren't set
watcher.FillDefaults()
Expand All @@ -83,8 +85,9 @@ func main() {
ExplorerURL: watcher.BTCAPIEndpoint,
}

StartWatches()
r := gin.Default()
watcher.StartWatches()
r := gin.New()
r.Use(gin.LoggerWithFormatter(GinJSONFormatter))
InitFrontend(r)
InitBackend(r)

Expand Down
89 changes: 58 additions & 31 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,27 @@ import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/fs"
"net/http"
"os"
"path/filepath"
"strings"
"sync"
"text/template"
"time"

"github.com/gin-gonic/gin"
cfg "github.com/golobby/config/v3"
"github.com/golobby/config/v3/pkg/feeder"
log "github.com/sirupsen/logrus"
"gorm.io/gorm/logger"
)

const (
TimeFormatter string = time.RFC3339
)

// Info is an interface for AddressInfo and PubkeyInfo
type Info interface {
GetIdentifier() string
Expand All @@ -34,100 +41,120 @@ func (w Watcher) UpdateInfo(i Info) {
}

// InitLogging sets up logging
func InitLogging() {
func (w *Watcher) InitLogging() {
// Read from .env and override from the local environment
dotEnvFeeder := feeder.DotEnv{Path: ".env"}
envFeeder := feeder.Env{}

_ = cfg.New().AddFeeder(dotEnvFeeder).AddStruct(&watcher).Feed()
_ = cfg.New().AddFeeder(envFeeder).AddStruct(&watcher).Feed()
// We need to use w.Config because we're using pointers
_ = cfg.New().AddFeeder(dotEnvFeeder).AddStruct(&w.Config).Feed()
_ = cfg.New().AddFeeder(envFeeder).AddStruct(&w.Config).Feed()

// Info level by default
LogLevelSelection := log.InfoLevel
switch {
case strings.EqualFold(watcher.LogLevel, "trace"):
case strings.EqualFold(w.LogLevel, "trace"):
LogLevelSelection = log.TraceLevel
log.SetReportCaller(true)
case strings.EqualFold(watcher.LogLevel, "debug"):
case strings.EqualFold(w.LogLevel, "debug"):
LogLevelSelection = log.DebugLevel
log.SetReportCaller(true)
case strings.EqualFold(watcher.LogLevel, "info"):
case strings.EqualFold(w.LogLevel, "info"):
LogLevelSelection = log.InfoLevel
case strings.EqualFold(watcher.LogLevel, "warn"):
case strings.EqualFold(w.LogLevel, "warn"):
LogLevelSelection = log.WarnLevel
case strings.EqualFold(watcher.LogLevel, "error"):
case strings.EqualFold(w.LogLevel, "error"):
LogLevelSelection = log.ErrorLevel
}
log.SetLevel(LogLevelSelection)
log.SetFormatter(&log.JSONFormatter{})

if log.GetLevel() > log.DebugLevel {
watcher.LogConfig = logger.Default.LogMode(logger.Info)
w.LogConfig = logger.Default.LogMode(logger.Info)
}
}

func GinJSONFormatter(param gin.LogFormatterParams) string {
jsonFormat := `{"level":"%s","time":"%s","clientip":"%s","method":"%s","uri":"%s","status":%3d,"latency":"%v","message":"%s","host":"%s","useragent":"%s","proto","%s","error_msg":"%s","size":%d}` + "\n"
return fmt.Sprintf(jsonFormat,
watcher.LogLevel,
param.TimeStamp.Format(TimeFormatter),
param.ClientIP,
param.Method,
param.Request.RequestURI,
param.StatusCode,
param.Latency,
fmt.Sprintf("%s %s %s", param.Method, param.Request.URL, param.Request.Proto),
param.Request.Host,
param.Request.UserAgent(),
param.Request.Proto,
param.ErrorMessage,
param.BodySize,
)
}

// FillDefaults sets a Watcher to default
// values defined in the constants
func (w Watcher) FillDefaults() {
func (w *Watcher) FillDefaults() {
// Set unitialized values to preset defaults
if w.BTCAPIEndpoint == "" {
watcher.BTCAPIEndpoint = DefaultApi
w.BTCAPIEndpoint = DefaultApi
}
if w.SleepInterval == 0 {
watcher.SleepInterval = DefaultSleepInterval
w.SleepInterval = DefaultSleepInterval
}
if w.Lookahead == 0 {
watcher.Lookahead = DefaultLookahead
w.Lookahead = DefaultLookahead
}
if w.PageSize == 0 {
watcher.PageSize = DefaultPageSize
w.PageSize = DefaultPageSize
}
if w.DBPath == "" {
watcher.DBPath = DefaultDBPath
w.DBPath = DefaultDBPath
}
if w.Port == "" {
watcher.Port = "80"
w.Port = "80"
}
if w.Currency == "" {
watcher.Currency = CurrencyUSD
w.Currency = CurrencyUSD
}

// Set up DB path
// Create the folder path if it doesn't exist
if _, err := os.Stat(watcher.DBPath); errors.Is(err, fs.ErrNotExist) {
dirPath := filepath.Dir(watcher.DBPath)
if _, err := os.Stat(w.DBPath); errors.Is(err, fs.ErrNotExist) {
dirPath := filepath.Dir(w.DBPath)
if err := os.MkdirAll(dirPath, 0660); err != nil {
log.Warn("unable to make directory path ", dirPath, " err: ", err)
watcher.DBPath = "./local.db"
w.DBPath = "./local.db"
}
}
}

// StartWatches starts goroutines for watching all of the known
// addresses in the database.
func StartWatches() {
watcher.CancelWaitGroup = &sync.WaitGroup{}
func (w *Watcher) StartWatches() {
w.CancelWaitGroup = &sync.WaitGroup{}
// Check balance of each address
addresses := []AddressInfo{}
watcher.DB.Model(&AddressInfo{}).Scan(&addresses)
watcher.CancelSignals = map[string]chan bool{}
w.DB.Model(&AddressInfo{}).Scan(&addresses)
w.CancelSignals = map[string]chan bool{}
for _, address := range addresses {
// This channel is used to send a signal to stop watching the address
cancel := make(chan bool, 1)
watcher.CancelWaitGroup.Add(1)
watcher.AddCancelSignal(address.Address, cancel)
go watcher.WatchAddress(cancel, address.Address)
w.CancelWaitGroup.Add(1)
w.AddCancelSignal(address.Address, cancel)
go w.WatchAddress(cancel, address.Address)
}

// Check balance of each key of each pubkey
pubkeys := []PubkeyInfo{}
watcher.DB.Model(&PubkeyInfo{}).Scan(&pubkeys)
w.DB.Model(&PubkeyInfo{}).Scan(&pubkeys)
for _, pubkey := range pubkeys {
// This channel is used to send a signal to stop watching the pubkey
cancel := make(chan bool, 1)
watcher.CancelWaitGroup.Add(1)
watcher.AddCancelSignal(pubkey.Pubkey, cancel)
go watcher.WatchPubkey(cancel, pubkey.Pubkey)
w.CancelWaitGroup.Add(1)
w.AddCancelSignal(pubkey.Pubkey, cancel)
go w.WatchPubkey(cancel, pubkey.Pubkey)
}
log.Infof("watching %d addresses and %d pubkeys", len(addresses), len(pubkeys))
}
Expand Down

0 comments on commit cefff51

Please sign in to comment.