From 51bc7cb3a090d4878587eed07a1d9a87a3dada38 Mon Sep 17 00:00:00 2001 From: Melora Hugues Date: Sat, 4 Feb 2023 18:14:23 +0100 Subject: [PATCH] Use logrus to handle logs This commit adds the logrus module, and improves logs handling for the entire program. Error logs are better displayed, and the log level can be set from the configuration file. --- README.md | 5 ++++- tracker/bot/bot.go | 17 +++++++++++++++++ tracker/config/config.go | 24 ++++++++++++++++++++++++ tracker/go.mod | 1 + tracker/go.sum | 15 +++++++++++++++ tracker/logger/logger.go | 10 ++++++++++ tracker/main.go | 26 ++++++++++++++++---------- 7 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 tracker/logger/logger.go diff --git a/README.md b/README.md index 02fe11c..d14e9f3 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,10 @@ For now, the program is configured through a JSON configuration file. Here is a "token": "", "channel_id": 9999999 }, - "polling_frequency": 5 + "polling_frequency": 5, + "log": { + "level": "info" + } } ``` diff --git a/tracker/bot/bot.go b/tracker/bot/bot.go index d7a58ba..4cb3d9c 100644 --- a/tracker/bot/bot.go +++ b/tracker/bot/bot.go @@ -8,9 +8,11 @@ import ( "git.faercol.me/faercol/public-ip-tracker/tracker/config" "git.faercol.me/faercol/public-ip-tracker/tracker/ip" + "git.faercol.me/faercol/public-ip-tracker/tracker/logger" "github.com/ahugues/go-telegram-api/bot" "github.com/ahugues/go-telegram-api/notifier" "github.com/ahugues/go-telegram-api/structs" + "github.com/sirupsen/logrus" ) type Notifier struct { @@ -26,21 +28,26 @@ type Notifier struct { errChan chan error changesChan chan net.IP exitChan chan struct{} + logger logrus.Logger } func (n *Notifier) SendInitMessage() error { + n.logger.Debug("Getting current public IP") publicIP, err := n.ipGetter.GetCurrentPublicIP(n.ctx) if err != nil { return fmt.Errorf("failed to get current public IP: %w", err) } + n.logger.Debugf("Current public IP is %s", publicIP.String()) n.currentIP = publicIP currentTime := n.timeGetter() + n.logger.Debug("Sending init message to Telegram") initMsg := fmt.Sprintf("Public IP tracker initialized at %v, public IP is %s", currentTime, publicIP) if err := n.tgBot.SendMessage(n.ctx, n.tgChatID, initMsg); err != nil { return fmt.Errorf("failed to send initialization message: %w", err) } + n.logger.Debug("Message sent") return nil } @@ -61,6 +68,7 @@ func (n *Notifier) sendCurrentIP() error { } func (n *Notifier) watchTG() { + n.logger.Debug("Subscribing to messages notificator") id, updateChan := n.tgWatcher.Subscribe([]structs.UpdateType{structs.UpdateMessage}) go n.tgWatcher.Run(n.ctx) @@ -81,21 +89,29 @@ func (n *Notifier) watchTG() { func (n *Notifier) Run() { go n.watchTG() + n.logger.Infof("Start watching for public IP changes, polling frequency is %v", n.frequency) for { select { case <-time.After(n.frequency): + n.logger.Debug("Checking if current IP has changed") newIP, err := n.ipGetter.GetCurrentPublicIP(n.ctx) if err != nil { n.errChan <- fmt.Errorf("failed to update public IP: %w", err) continue } + n.logger.Debugf("Got new public IP %s", newIP.String()) if !newIP.Equal(n.currentIP) { + n.logger.Debug("New public IP is different from previous IP") + n.logger.Warnf("Public IP has changed from %s to %s", n.currentIP.String(), newIP.String()) n.currentIP = newIP if err := n.sendUpdatedIPMsg(); err != nil { n.errChan <- err } + } else { + n.logger.Debug("Public IP has not changed") } case <-n.ctx.Done(): + n.logger.Info("Stopping notification daemon") n.exitChan <- struct{}{} return } @@ -125,5 +141,6 @@ func New(ctx context.Context, config *config.Config) *Notifier { exitChan: make(chan struct{}, 1), frequency: config.PollingFrequency, tgWatcher: notifier.New(config.Telegram.Token), + logger: logger.L, } } diff --git a/tracker/config/config.go b/tracker/config/config.go index 1e38ca1..827c003 100644 --- a/tracker/config/config.go +++ b/tracker/config/config.go @@ -5,6 +5,8 @@ import ( "fmt" "os" "time" + + "github.com/sirupsen/logrus" ) type TelegramConfig struct { @@ -12,14 +14,33 @@ type TelegramConfig struct { Token string `json:"token"` } +type LogConfig struct { + Level logrus.Level +} + +type jsonLogConfig struct { + Level string `json:"level"` +} + type Config struct { Telegram *TelegramConfig PollingFrequency time.Duration + Log *LogConfig } type jsonConfig struct { Telegram *TelegramConfig `json:"telegram"` PollingFrequency int64 `json:"polling_frequency"` + Log *jsonLogConfig `json:"log"` +} + +func parseLevel(lvlStr string) logrus.Level { + for _, lvl := range logrus.AllLevels { + if lvl.String() == lvlStr { + return lvl + } + } + return logrus.InfoLevel } func New(filepath string) (*Config, error) { @@ -34,5 +55,8 @@ func New(filepath string) (*Config, error) { return &Config{ Telegram: jsonConf.Telegram, PollingFrequency: time.Duration(jsonConf.PollingFrequency) * time.Second, + Log: &LogConfig{ + Level: parseLevel(jsonConf.Log.Level), + }, }, nil } diff --git a/tracker/go.mod b/tracker/go.mod index ba2e733..5f6a200 100644 --- a/tracker/go.mod +++ b/tracker/go.mod @@ -5,4 +5,5 @@ go 1.16 require ( github.com/ahugues/go-telegram-api v0.1.0 github.com/google/uuid v1.3.0 + github.com/sirupsen/logrus v1.9.0 ) diff --git a/tracker/go.sum b/tracker/go.sum index ec5b682..486d07f 100644 --- a/tracker/go.sum +++ b/tracker/go.sum @@ -1,7 +1,17 @@ github.com/ahugues/go-telegram-api v0.1.0 h1:CGJG0WR282O0hAO9JH2RutPj+Vn+Q+zbjdSHjuvN5yY= github.com/ahugues/go-telegram-api v0.1.0/go.mod h1:8I/JWxd9GYM7dHOgGmkRI3Ei1u+nGvzeR2knIMmFw7E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -16,6 +26,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -26,3 +38,6 @@ golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tracker/logger/logger.go b/tracker/logger/logger.go new file mode 100644 index 0000000..1db7579 --- /dev/null +++ b/tracker/logger/logger.go @@ -0,0 +1,10 @@ +package logger + +import "github.com/sirupsen/logrus" + +var L logrus.Logger + +func Init(level logrus.Level) { + L = *logrus.New() + L.SetLevel(level) +} diff --git a/tracker/main.go b/tracker/main.go index d5db008..2b88227 100644 --- a/tracker/main.go +++ b/tracker/main.go @@ -3,12 +3,12 @@ package main import ( "context" "flag" - "fmt" "os" "os/signal" "git.faercol.me/faercol/public-ip-tracker/tracker/bot" "git.faercol.me/faercol/public-ip-tracker/tracker/config" + "git.faercol.me/faercol/public-ip-tracker/tracker/logger" ) type cliArgs struct { @@ -26,45 +26,51 @@ func parseArgs() *cliArgs { } func main() { - fmt.Println("Parsing arguments") args := parseArgs() mainCtx, cancel := context.WithCancel(context.Background()) - fmt.Println("Parsing config") conf, err := config.New(args.configPath) if err != nil { panic(err) } - fmt.Println("Initializing bot") + logger.Init(conf.Log.Level) + logger.L.Infof("Intialized logger with level %v", conf.Log.Level) + + logger.L.Debug("Initializing notification bot") notifBot := bot.New(mainCtx, conf) + + logger.L.Debug("Sending initialization message to Telegram") if err := notifBot.SendInitMessage(); err != nil { - panic(err) + logger.L.Fatalf("Failed to send an initialization message: %s", err.Error()) } - fmt.Println("Starting monitoring") + logger.L.Debug("Starting IP monitoring") go notifBot.Run() c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) + logger.L.Info("Public IP monitoring service is operational") + outerloop: for { select { case <-c: - fmt.Println("received cancel") + logger.L.Info("Stopping IP monitoring service") cancel() break outerloop case err := <-notifBot.ErrChan(): - fmt.Printf("Unexpected error %s", err.Error()) + logger.L.Error(err.Error()) case <-notifBot.Exit(): - fmt.Println("Unexpected exit") + logger.L.Fatal("Unexpected exit from the monitoring bot") } } + logger.L.Debug("Waiting for all services to shut down") <-notifBot.Exit() - fmt.Println("OK") + logger.L.Info("Public IP monitoring service successfully stopped") os.Exit(0) }