From 647597ac02da20c48102e0f323d9460aee33d222 Mon Sep 17 00:00:00 2001 From: alankan886 Date: Sun, 25 Apr 2021 18:24:18 -0400 Subject: [PATCH 1/3] Convert from logrus to zerolog --- core/configure.go | 62 +++++++++++----------- core/configure_test.go | 27 +--------- core/matcher.go | 36 ++++++------- core/outputs.go | 8 +-- core/prommetric.go | 6 +-- core/remotes.go | 8 +-- core/rules.go | 22 ++++---- go.mod | 2 +- go.sum | 14 ++++- handlers/script.go | 14 ++--- models/bot.go | 5 +- remote/cli/remote.go | 2 +- remote/discord/helper.go | 10 ++-- remote/discord/remote.go | 34 ++++++------ remote/scheduler/remote.go | 21 ++++---- remote/slack/helper.go | 104 ++++++++++++++++++------------------- remote/slack/remote.go | 38 +++++++------- remote/telegram/remote.go | 6 +-- utils/access_check.go | 20 ++++--- utils/rooms.go | 2 +- 20 files changed, 214 insertions(+), 227 deletions(-) diff --git a/core/configure.go b/core/configure.go index 143d5e13..46835802 100644 --- a/core/configure.go +++ b/core/configure.go @@ -1,9 +1,11 @@ package core import ( + "os" "strings" - log "github.com/sirupsen/logrus" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" "github.com/target/flottbot/models" "github.com/target/flottbot/utils" @@ -14,7 +16,7 @@ var defaultSlackListenerPort = "3000" // Configure searches the config directory for the bot.yml to create a Bot object. // The Bot object will be passed around to make accessible system-specific information. func Configure(bot *models.Bot) { - log.Info("Configuring bot...") + log.Info().Msg("Configuring bot...") initLogger(bot) @@ -22,21 +24,15 @@ func Configure(bot *models.Bot) { configureChatApplication(bot) - bot.Log.Infof("Configured bot '%s'!", bot.Name) + bot.Log.Info().Msgf("Configured bot '%s'!", bot.Name) } // initLogger sets log configuration for the bot func initLogger(b *models.Bot) { - b.Log = *log.New() - - b.Log.SetLevel(log.ErrorLevel) + b.Log = zerolog.New(os.Stdout).Level(zerolog.ErrorLevel) if b.Debug { - b.Log.SetLevel(log.DebugLevel) - } - - if b.LogJSON { - b.Log.Formatter = &log.JSONFormatter{} + b.Log.Level(zerolog.DebugLevel) } } @@ -47,7 +43,7 @@ func configureChatApplication(bot *models.Bot) { // update the bot name token, err := utils.Substitute(bot.Name, map[string]string{}) if err != nil { - bot.Log.Warnf("Could not configure bot Name: %s", err.Error()) + bot.Log.Warn().Msgf("Could not configure bot Name: %s", err) } bot.Name = token @@ -58,12 +54,12 @@ func configureChatApplication(bot *models.Bot) { // Discord bot token token, err := utils.Substitute(bot.DiscordToken, map[string]string{}) if err != nil { - bot.Log.Warnf("Could not set Discord Token: %s", err.Error()) + bot.Log.Warn().Msgf("Could not set Discord Token: %s", err) bot.RunChat = false } if token == "" { - bot.Log.Warnf("Discord Token is empty: '%s'", token) + bot.Log.Warn().Msgf("Discord Token is empty: '%s'", token) bot.RunChat = false } @@ -73,12 +69,12 @@ func configureChatApplication(bot *models.Bot) { // See https://support.discordapp.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID- serverID, err := utils.Substitute(bot.DiscordServerID, map[string]string{}) if err != nil { - bot.Log.Warnf("Could not set Discord Server ID: %s", err.Error()) + bot.Log.Warn().Msgf("Could not set Discord Server ID: %s", err) bot.RunChat = false } if serverID == "" { - bot.Log.Warnf("Discord Server ID is empty: '%s'", serverID) + bot.Log.Warn().Msgf("Discord Server ID is empty: '%s'", serverID) bot.RunChat = false } @@ -90,19 +86,19 @@ func configureChatApplication(bot *models.Bot) { case "telegram": token, err := utils.Substitute(bot.TelegramToken, map[string]string{}) if err != nil { - bot.Log.Warnf("Could not set telegram Token: %s", err.Error()) + bot.Log.Warn().Msgf("Could not set telegram Token: %s", err) bot.RunChat = false } if token == "" { - bot.Log.Warnf("telegram Token is empty: '%s'", token) + bot.Log.Warn().Msgf("telegram Token is empty: '%s'", token) bot.RunChat = false } bot.TelegramToken = token default: - bot.Log.Errorf("Chat application '%s' is not supported", bot.ChatApplication) + bot.Log.Error().Msgf("Chat application '%s' is not supported", bot.ChatApplication) bot.RunChat = false } } @@ -112,12 +108,12 @@ func configureSlackBot(bot *models.Bot) { // Slack bot token token, err := utils.Substitute(bot.SlackToken, map[string]string{}) if err != nil { - bot.Log.Warnf("Could not set Slack Token: %s", err.Error()) + bot.Log.Warn().Msgf("Could not set Slack Token: %s", err) bot.RunChat = false } if token == "" { - bot.Log.Warnf("Slack Token is empty: %s", token) + bot.Log.Warn().Msgf("Slack Token is empty: %s", token) bot.RunChat = false } @@ -126,8 +122,8 @@ func configureSlackBot(bot *models.Bot) { // Slack signing secret signingSecret, err := utils.Substitute(bot.SlackSigningSecret, map[string]string{}) if err != nil { - bot.Log.Warnf("Could not set Slack Signing Secret: %s", err.Error()) - bot.Log.Warn("Defaulting to use Slack RTM") + bot.Log.Warn().Msgf("Could not set Slack Signing Secret: %s", err) + bot.Log.Warn().Msg("Defaulting to use Slack RTM") signingSecret = "" } @@ -137,8 +133,8 @@ func configureSlackBot(bot *models.Bot) { // Get Slack Events path eCallbackPath, err := utils.Substitute(bot.SlackEventsCallbackPath, map[string]string{}) if err != nil { - bot.Log.Errorf("Could not set Slack Events API callback path: %s", err.Error()) - bot.Log.Warn("Defaulting to use Slack RTM") + bot.Log.Error().Msgf("Could not set Slack Events API callback path: %s", err) + bot.Log.Warn().Msg("Defaulting to use Slack RTM") bot.SlackSigningSecret = "" } @@ -147,12 +143,12 @@ func configureSlackBot(bot *models.Bot) { // Get Slack Interactive Components path iCallbackPath, err := utils.Substitute(bot.SlackInteractionsCallbackPath, map[string]string{}) if err != nil { - bot.Log.Errorf("Could not set Slack Interactive Components callback path: %s", err.Error()) + bot.Log.Error().Msgf("Could not set Slack Interactive Components callback path: %s", err) bot.InteractiveComponents = false } if iCallbackPath == "" { - bot.Log.Warnf("Slack Interactive Components callback path is empty: %s", iCallbackPath) + bot.Log.Warn().Msgf("Slack Interactive Components callback path is empty: %s", iCallbackPath) bot.InteractiveComponents = false } @@ -161,15 +157,15 @@ func configureSlackBot(bot *models.Bot) { // Get Slack HTTP listener port lPort, err := utils.Substitute(bot.SlackListenerPort, map[string]string{}) if err != nil { - bot.Log.Errorf("Could not set Slack listener por: %s", err.Error()) + bot.Log.Error().Msgf("Could not set Slack listener port: %s", err) bot.SlackListenerPort = "" } // set slack http listener port from config file or default lPortEnvWasUnset := strings.Contains(lPort, "${") // e.g. slack_listener_port: ${PORT} if lPort == "" || lPortEnvWasUnset { - bot.Log.Warnf("Slack listener port is empty: %s", lPort) - bot.Log.WithField("defaultSlackListenerPort", defaultSlackListenerPort).Info("Using default slack listener port.") + bot.Log.Warn().Msgf("Slack listener port is empty: %s", lPort) + bot.Log.Info().Str("defaultSlackListenerPort", defaultSlackListenerPort).Msg("Using default slack listener port.") lPort = defaultSlackListenerPort } @@ -186,18 +182,18 @@ func validateRemoteSetup(bot *models.Bot) { } if !bot.CLI && bot.ChatApplication == "" { - bot.Log.Fatalf("No chat_application specified and cli mode is not enabled. Exiting...") + bot.Log.Fatal().Msgf("No chat_application specified and cli mode is not enabled. Exiting...") } if bot.Scheduler { bot.RunScheduler = true if bot.CLI && bot.ChatApplication == "" { - bot.Log.Warn("Scheduler does not support scheduled outputs to CLI mode") + bot.Log.Warn().Msg("Scheduler does not support scheduled outputs to CLI mode") bot.RunScheduler = false } if bot.ChatApplication == "" { - bot.Log.Warn("Scheduler did not find any configured chat applications. Scheduler is closing") + bot.Log.Warn().Msg("Scheduler did not find any configured chat applications. Scheduler is closing") bot.RunScheduler = false } } diff --git a/core/configure_test.go b/core/configure_test.go index d7170582..8c83d47e 100644 --- a/core/configure_test.go +++ b/core/configure_test.go @@ -2,10 +2,8 @@ package core import ( "os" - "reflect" "testing" - "github.com/sirupsen/logrus" "github.com/target/flottbot/models" ) @@ -31,32 +29,11 @@ func TestInitLogger(t *testing.T) { } t.Run(tt.name, func(t *testing.T) { initLogger(tt.args.bot) - if tt.want != tt.args.bot.Log.Level.String() { - t.Errorf("initLogger() wanted level set at %s, but got %s", tt.want, tt.args.bot.Log.Level.String()) + if tt.want != tt.args.bot.Log.GetLevel().String() { + t.Errorf("initLogger() wanted level set at %s, but got %s", tt.want, tt.args.bot.Log.GetLevel().String()) } }) } - - // Test setting the JSON formatter - jsonTests := []struct { - name string - args args - want bool - }{ - {"JSON logging set", args{testBot}, true}, - {"JSON logging not set", args{testBot}, false}, - } - for _, tt := range jsonTests { - testBot.LogJSON = tt.want - t.Run(tt.name, func(t *testing.T) { - initLogger(tt.args.bot) - equals := reflect.DeepEqual(tt.args.bot.Log.Formatter, logrus.JSONFormatter{}) - if equals { - t.Errorf("initLogger() wanted to set JSON logging formatter to %t, but got %t", tt.want, equals) - } - - }) - } } func Test_configureChatApplication(t *testing.T) { diff --git a/core/matcher.go b/core/matcher.go index 3c48b078..94081380 100644 --- a/core/matcher.go +++ b/core/matcher.go @@ -75,15 +75,15 @@ func handleChatServiceRule(outputMsgs chan<- models.Message, message models.Mess if rule.Respond != "" || rule.Hear != "" { // You can only use 'respond' OR 'hear' if rule.Respond != "" && rule.Hear != "" { - bot.Log.Debugf("Rule '%s' has both 'hear' and 'match' or 'respond' defined. Please choose one or the other", rule.Name) + bot.Log.Debug().Msgf("Rule '%s' has both 'hear' and 'match' or 'respond' defined. Please choose one or the other", rule.Name) } // Args are not implemented for 'hear' if rule.Hear != "" && len(rule.Args) > 0 { - bot.Log.Debugf("Rule '%s' has both 'args' and 'hear' set. To use 'args', use 'respond' instead of 'hear'", rule.Name) + bot.Log.Debug().Msgf("Rule '%s' has both 'args' and 'hear' set. To use 'args', use 'respond' instead of 'hear'", rule.Name) } if hit && message.ThreadTimestamp != "" && rule.IgnoreThreads { - bot.Log.Debug("Response suppressed due to 'ignore_threads' being set") + bot.Log.Debug().Msg("Response suppressed due to 'ignore_threads' being set") return true, true } @@ -93,7 +93,7 @@ func handleChatServiceRule(outputMsgs chan<- models.Message, message models.Mess } if hit { - bot.Log.Debugf("Found rule match '%s' for input '%s'", rule.Name, message.Input) + bot.Log.Debug().Msgf("Found rule match '%s' for input '%s'", rule.Name, message.Input) // Don't go through more rules if rule is matched match, stopSearch = true, true // Publish metric to prometheus - metricname will be combination of bot name and rule name @@ -136,7 +136,7 @@ func handleNoMatch(outputMsgs chan<- models.Message, message models.Message, hit if message.Type == models.MsgTypeDirect || message.BotMentioned { // Do not send help message if DisableNoMatchHelp is true if !bot.DisableNoMatchHelp { - bot.Log.Debug("Bot was addressed, but no rule matched. Showing help") + bot.Log.Debug().Msg("Bot was addressed, but no rule matched. Showing help") // Publish metric as none Prommetric(bot.Name+"-None", bot) // Set custom_help_text if it is set in bot.yml @@ -250,15 +250,15 @@ func doRuleActions(message models.Message, outputMsgs chan<- models.Message, rul switch strings.ToLower(action.Type) { // HTTP actions. case "get", "post", "put": - bot.Log.Debugf("Executing action '%s'...", action.Name) + bot.Log.Debug().Msgf("Executing action '%s'...", action.Name) err = handleHTTP(action, &message, bot) // Exec (script) actions case "exec": - bot.Log.Debugf("Executing action '%s'...", action.Name) + bot.Log.Debug().Msgf("Executing action '%s'...", action.Name) err = handleExec(action, &message, bot) // Normal message/log actions case "message", "log": - bot.Log.Debugf("Executing action '%s'...", action.Name) + bot.Log.Debug().Msgf("Executing action '%s'...", action.Name) // Log actions cannot direct message users by default directive := rule.DirectMessageOnly if action.Type == "log" { @@ -269,7 +269,7 @@ func doRuleActions(message models.Message, outputMsgs chan<- models.Message, rul err = handleMessage(action, outputMsgs, ©, directive, rule.StartMessageThread, hitRule, bot) // Fallback to error if action type is invalid default: - bot.Log.Errorf("The rule '%s' of type %s is not a supported action", action.Name, action.Type) + bot.Log.Error().Msgf("The rule '%s' of type %s is not a supported action", action.Name, action.Type) } // Handle reaction update @@ -277,7 +277,7 @@ func doRuleActions(message models.Message, outputMsgs chan<- models.Message, rul // Handle error if err != nil { - bot.Log.Error(err) + bot.Log.Error().Msg(err.Error()) } } @@ -296,7 +296,7 @@ func doRuleActions(message models.Message, outputMsgs chan<- models.Message, rul // After running through all the actions, compose final message val, err := craftResponse(rule, message, bot) if err != nil { - bot.Log.Error(err) + bot.Log.Error().Msg(err.Error()) message.Output = err.Error() outputMsgs <- message } else { @@ -327,12 +327,12 @@ func craftResponse(rule models.Rule, msg models.Message, bot *models.Bot) (strin if len(rule.OutputToUsers) == 0 { return "", errors.New(msg) } - bot.Log.Warn(msg) + bot.Log.Warn().Msg(msg) } // Simple warning that we will ignore 'output_to_rooms' when 'direct_message_only' is set if rule.DirectMessageOnly && len(rule.OutputToRooms) > 0 { - bot.Log.Debugf("The rule '%s' has 'direct_message_only' set, 'output_to_rooms' will be ignored", rule.Name) + bot.Log.Debug().Msgf("The rule '%s' has 'direct_message_only' set, 'output_to_rooms' will be ignored", rule.Name) } // Use FormatOutput as source for output and find variables and replace content the variable exists @@ -392,11 +392,11 @@ func handleHTTP(action models.Action, msg *models.Message, bot *models.Bot) erro // Just a friendly debugger warning on failed requests if resp.Status >= 400 { - bot.Log.Debugf("Error in request made by action '%s'. %s returned %d with response: `%s`", action.Name, action.URL, resp.Status, resp.Raw) + bot.Log.Debug().Msgf("Error in request made by action '%s'. %s returned %d with response: `%s`", action.Name, action.URL, resp.Status, resp.Raw) } // Always store raw response - bot.Log.Debugf("Successfully executed action '%s'", action.Name) + bot.Log.Debug().Msgf("Successfully executed action '%s'", action.Name) // Set explicit variables to make raw response output, http status code accessible in rules msg.Vars["_raw_http_output"] = resp.Raw msg.Vars["_raw_http_status"] = strconv.Itoa(resp.Status) @@ -454,7 +454,7 @@ func handleMessage(action models.Action, outputMsgs chan<- models.Message, msg * msg.Output = output // Send to desired room(s) if direct && len(action.LimitToRooms) > 0 { // direct=true and limit_to_rooms is specified - bot.Log.Debugf("You have specified to send only direct messages. The 'limit_to_rooms' field on the '%s' action will be ignored", action.Name) + bot.Log.Debug().Msgf("You have specified to send only direct messages. The 'limit_to_rooms' field on the '%s' action will be ignored", action.Name) } else if !direct && len(action.LimitToRooms) > 0 { // direct=false and limit_to_rooms is specified msg.OutputToRooms = utils.GetRoomIDs(action.LimitToRooms, bot) @@ -487,7 +487,7 @@ func updateReaction(action models.Action, rule *models.Rule, vars map[string]str if strings.Contains(action.Reaction, "{{") { reaction, err := utils.Substitute(action.Reaction, vars) if err != nil { - bot.Log.Error(err) + bot.Log.Error().Msg(err.Error()) return } action.Reaction = reaction @@ -497,7 +497,7 @@ func updateReaction(action models.Action, rule *models.Rule, vars map[string]str t, err = template.New("update_reaction").Funcs(sprig.FuncMap()).Parse(action.Reaction) if err != nil { - bot.Log.Errorf("Failed to update Reaction %s", rule.Reaction) + bot.Log.Error().Msgf("Failed to update Reaction %s", rule.Reaction) return } buf := new(bytes.Buffer) diff --git a/core/outputs.go b/core/outputs.go index e34fede4..0575c93c 100644 --- a/core/outputs.go +++ b/core/outputs.go @@ -23,7 +23,7 @@ func Outputs(outputMsgs <-chan models.Message, hitRule <-chan models.Rule, bot * switch chatApp { case "discord": if service == models.MsgServiceScheduler { - bot.Log.Warn("Scheduler does not currently support Discord") + bot.Log.Warn().Msg("Scheduler does not currently support Discord") break } remoteDiscord := &discord.Client{Token: bot.DiscordToken} @@ -49,15 +49,15 @@ func Outputs(outputMsgs <-chan models.Message, hitRule <-chan models.Rule, bot * } remoteTelegram.Send(message, bot) default: - bot.Log.Debugf("Chat application %s is not supported", chatApp) + bot.Log.Debug().Msgf("Chat application %s is not supported", chatApp) } case models.MsgServiceCLI: remoteCLI := &cli.Client{} remoteCLI.Send(message, bot) case models.MsgServiceUnknown: - bot.Log.Error("Found unknown service") + bot.Log.Error().Msg("Found unknown service") default: - bot.Log.Errorf("No service found") + bot.Log.Error().Msg("No service found") } } } diff --git a/core/prommetric.go b/core/prommetric.go index 5ada0864..2d9b75ef 100644 --- a/core/prommetric.go +++ b/core/prommetric.go @@ -31,11 +31,11 @@ func Prommetric(input string, bot *models.Bot) { // metrics health check handler promHealthHandle := func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { - bot.Log.Errorf("Prometheus Server: invalid method %s", r.Method) + bot.Log.Error().Msgf("Prometheus Server: invalid method %s", r.Method) w.WriteHeader(http.StatusMethodNotAllowed) return } - bot.Log.Info("Prometheus Server: health check hit!") + bot.Log.Info().Msg("Prometheus Server: health check hit!") w.WriteHeader(http.StatusOK) w.Write([]byte("OK")) } @@ -47,7 +47,7 @@ func Prommetric(input string, bot *models.Bot) { // start prometheus server go http.ListenAndServe(":8080", promRouter) - bot.Log.Info("Prometheus Server: serving metrics at /metrics") + bot.Log.Info().Msg("Prometheus Server: serving metrics at /metrics") } else { botResponseCollector.With(prometheus.Labels{"rulename": input}).Inc() } diff --git a/core/remotes.go b/core/remotes.go index 30080b81..55b43e3a 100644 --- a/core/remotes.go +++ b/core/remotes.go @@ -30,7 +30,7 @@ func Remotes(inputMsgs chan<- models.Message, rules map[string]models.Rule, bot // Run a chat application if bot.RunChat { chatApp := strings.ToLower(bot.ChatApplication) - bot.Log.Infof("Running %s on %s", bot.Name, strings.Title(chatApp)) + bot.Log.Info().Msgf("Running %s on %s", bot.Name, strings.Title(chatApp)) switch chatApp { // Setup remote to use the Discord client to read from Discord case "discord": @@ -58,13 +58,13 @@ func Remotes(inputMsgs chan<- models.Message, rules map[string]models.Rule, bot // Read messages from Telegram go remoteTelegram.Read(inputMsgs, rules, bot) default: - bot.Log.Errorf("Chat application '%s' is not supported", chatApp) + bot.Log.Error().Msgf("Chat application '%s' is not supported", chatApp) } } // Run CLI mode if bot.RunCLI { - bot.Log.Infof("Running CLI mode for %s", bot.Name) + bot.Log.Info().Msgf("Running CLI mode for %s", bot.Name) remoteCLI := &cli.Client{} go remoteCLI.Read(inputMsgs, rules, bot) } @@ -72,7 +72,7 @@ func Remotes(inputMsgs chan<- models.Message, rules map[string]models.Rule, bot // Run Scheduler // CAUTION: Will not work properly when multiple instances of your bot are deployed (i.e. will get duplicated scheduled output) if bot.RunScheduler { - bot.Log.Infof("Running Scheduler for %s", bot.Name) + bot.Log.Info().Msgf("Running Scheduler for %s", bot.Name) remoteScheduler := &scheduler.Client{} go remoteScheduler.Read(inputMsgs, rules, bot) } diff --git a/core/rules.go b/core/rules.go index 2c2a28e6..d93d3ccd 100644 --- a/core/rules.go +++ b/core/rules.go @@ -6,7 +6,7 @@ import ( "path" "path/filepath" - log "github.com/sirupsen/logrus" + "github.com/rs/zerolog/log" "github.com/spf13/viper" "github.com/target/flottbot/models" @@ -19,14 +19,14 @@ import ( // The rules map is used to dictate the bots behavior and response patterns. func Rules(rules *map[string]models.Rule, bot *models.Bot) { // Check if the rules directory even exists - bot.Log.Debug("Looking for rules directory...") + bot.Log.Debug().Msg("Looking for rules directory...") searchDir, err := utils.PathExists(path.Join("config", "rules")) if err != nil { - bot.Log.Fatalf("Could not parse rules: %v", err) + bot.Log.Fatal().Msgf("Could not parse rules: %s", err) } // Loop through the rules directory and create a list of rules - bot.Log.Debug("Fetching all rule files...") + bot.Log.Debug().Msg("Fetching all rule files...") fileList := []string{} err = filepath.Walk(searchDir, func(path string, f os.FileInfo, err error) error { if !f.IsDir() { @@ -35,39 +35,39 @@ func Rules(rules *map[string]models.Rule, bot *models.Bot) { return nil }) if err != nil { - bot.Log.Fatalf("Could not parse rules: %v", err) + bot.Log.Fatal().Msgf("Could not parse rules: %s", err) } // If the rules directory is empty, log a warning and exit the function if len(fileList) == 0 { - bot.Log.Warn("Looks like there aren't any rules") + bot.Log.Warn().Msg("Looks like there aren't any rules") return } // Loop through the list of rules, creating a Rule object // for each rule, then populate the map of Rule objects - bot.Log.Debug("Reading and parsing rule files...") + bot.Log.Debug().Msg("Reading and parsing rule files...") for _, ruleFile := range fileList { ruleConf := viper.New() ruleConf.SetConfigFile(ruleFile) err := ruleConf.ReadInConfig() if err != nil { - bot.Log.Errorf("Error while reading rule file '%s': %s \n", ruleFile, err) + bot.Log.Error().Msgf("Error while reading rule file '%s': %s", ruleFile, err) } rule := models.Rule{} err = ruleConf.Unmarshal(&rule) if err != nil { - log.Fatalf(err.Error()) + log.Fatal().Msg(err.Error()) } err = validateRule(bot, &rule) if err != nil { - log.Fatalf(err.Error()) + log.Fatal().Msg(err.Error()) } (*rules)[ruleFile] = rule } - bot.Log.Infof("Configured '%s' rules!", bot.Name) + bot.Log.Info().Msgf("Configured '%s' rules!", bot.Name) } // Validate applies any environmental changes diff --git a/go.mod b/go.mod index 8602e691..d47d2d6e 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/prometheus/client_golang v1.10.0 github.com/robfig/cron/v3 v3.0.1 github.com/rs/xid v1.3.0 - github.com/sirupsen/logrus v1.8.1 + github.com/rs/zerolog v1.21.0 github.com/slack-go/slack v0.8.2 github.com/spf13/afero v1.5.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect diff --git a/go.sum b/go.sum index 21654d3e..2020219a 100644 --- a/go.sum +++ b/go.sum @@ -336,6 +336,8 @@ github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.21.0 h1:Q3vdXlfLNT+OftyBHsU0Y445MD+8m8axjKgf2si0QcM= +github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= @@ -346,8 +348,6 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/slack-go/slack v0.8.2 h1:D7jNu0AInBfdQ4QyKPtVSp+ZxQes3EzWW17RZ/va4JE= github.com/slack-go/slack v0.8.2/go.mod h1:FGqNzJBmxIsZURAxh2a8D21AnOVvvXZvGligs4npPUM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= @@ -392,6 +392,7 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= @@ -440,6 +441,7 @@ golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCc golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -459,6 +461,7 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -468,6 +471,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -494,6 +498,8 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -529,11 +535,15 @@ golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= 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-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= diff --git a/handlers/script.go b/handlers/script.go index 140fe80e..a0719569 100644 --- a/handlers/script.go +++ b/handlers/script.go @@ -15,7 +15,7 @@ import ( // ScriptExec handles 'exec' actions; script executions for rules func ScriptExec(args models.Action, msg *models.Message, bot *models.Bot) (*models.ScriptResponse, error) { - bot.Log.Debugf("Executing process for action '%s'", args.Name) + bot.Log.Debug().Msgf("Executing process for action '%s'", args.Name) // Default timeout of 20 seconds for any script execution, modifyable in rule file if args.Timeout == 0 { args.Timeout = 20 @@ -31,9 +31,9 @@ func ScriptExec(args models.Action, msg *models.Message, bot *models.Bot) (*mode defer cancel() // Deal with variable substitution in command - bot.Log.Debugf("Command is: [%s]", args.Cmd) + bot.Log.Debug().Msgf("Command is: [%s]", args.Cmd) cmdProcessed, err := utils.Substitute(args.Cmd, msg.Vars) - bot.Log.Debugf("Substituted: [%s]", cmdProcessed) + bot.Log.Debug().Msgf("Substituted: [%s]", cmdProcessed) if err != nil { return result, err } @@ -58,16 +58,16 @@ func ScriptExec(args models.Action, msg *models.Message, bot *models.Bot) (*mode case *exec.ExitError: ws := err.(*exec.ExitError).Sys().(syscall.WaitStatus) stderr := strings.Trim(string(err.(*exec.ExitError).Stderr), " \n") - bot.Log.Debugf("Process for action '%s' exited with status %d: %s", args.Name, ws.ExitStatus(), stderr) + bot.Log.Debug().Msgf("Process for action '%s' exited with status %d: %s", args.Name, ws.ExitStatus(), stderr) result.Status = ws.ExitStatus() result.Output = stderr case *os.PathError: - bot.Log.Debugf("Process for action '%s' exited with status %d: %s", args.Name, result.Status, err) + bot.Log.Debug().Msgf("Process for action '%s' exited with status %d: %s", args.Name, result.Status, err) result.Status = 127 result.Output = err.Error() default: // this should rarely/never get hit - bot.Log.Debugf("Couldn't get exit status for action '%s'", args.Name) + bot.Log.Debug().Msgf("Couldn't get exit status for action '%s'", args.Name) result.Output = strings.Trim(err.Error(), " \n") } // if something was printed to stdout before the error, use that as output @@ -79,7 +79,7 @@ func ScriptExec(args models.Action, msg *models.Message, bot *models.Bot) (*mode } // should be exit code 0 here - bot.Log.Debugf("Process finished for action '%s'", args.Name) + bot.Log.Debug().Msgf("Process finished for action '%s'", args.Name) ws := cmd.ProcessState.Sys().(syscall.WaitStatus) result.Status = ws.ExitStatus() result.Output = strings.Trim(string(out), " \n") diff --git a/models/bot.go b/models/bot.go index 67a664b0..b0d009ac 100644 --- a/models/bot.go +++ b/models/bot.go @@ -1,6 +1,6 @@ package models -import "github.com/sirupsen/logrus" +import "github.com/rs/zerolog" // Bot is a struct representation of bot.yml type Bot struct { @@ -23,14 +23,13 @@ type Bot struct { Scheduler bool `mapstructure:"scheduler,omitempty"` ChatApplication string `mapstructure:"chat_application" binding:"required"` Debug bool `mapstructure:"debug,omitempty"` - LogJSON bool `mapstructure:"log_json,omitempty"` InteractiveComponents bool `mapstructure:"interactive_components,omitempty"` Metrics bool `mapstructure:"metrics,omitempty"` CustomHelpText string `mapstructure:"custom_help_text,omitempty"` DisableNoMatchHelp bool `mapstructure:"disable_no_match_help,omitempty"` RespondToBots bool `mapstructure:"respond_to_bots,omitempty"` // System - Log logrus.Logger + Log zerolog.Logger RunChat bool RunCLI bool RunScheduler bool diff --git a/remote/cli/remote.go b/remote/cli/remote.go index c0f93e89..d615b742 100644 --- a/remote/cli/remote.go +++ b/remote/cli/remote.go @@ -60,7 +60,7 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R } } if err := scanner.Err(); err != nil { - bot.Log.Debugf("Error reading standard input: %v", err) + bot.Log.Debug().Msgf("Error reading standard input: %s", err) } } diff --git a/remote/discord/helper.go b/remote/discord/helper.go index 38f30bd4..559deae9 100644 --- a/remote/discord/helper.go +++ b/remote/discord/helper.go @@ -26,7 +26,7 @@ func populateMessage(message models.Message, msgType models.MessageType, channel if msgType != models.MsgTypeDirect { name, ok := findKey(bot.Rooms, channel) if !ok { - bot.Log.Warnf("Could not find name of channel '%s'.", channel) + bot.Log.Warn().Msgf("Could not find name of channel '%s'.", channel) } message.ChannelName = name @@ -55,12 +55,12 @@ func send(dg *discordgo.Session, message models.Message, bot *models.Bot) { if message.DirectMessageOnly { err := handleDirectMessage(dg, message, bot) if err != nil { - bot.Log.Errorf("Problem sending message: %s", err.Error()) + bot.Log.Error().Msgf("Problem sending message: %s", err) } } else { err := handleNonDirectMessage(dg, message, bot) if err != nil { - bot.Log.Errorf("Problem sending message: %s", err.Error()) + bot.Log.Error().Msgf("Problem sending message: %s", err) } } } @@ -69,13 +69,13 @@ func send(dg *discordgo.Session, message models.Message, bot *models.Bot) { func handleDirectMessage(dg *discordgo.Session, message models.Message, bot *models.Bot) error { // Is output to rooms set? if len(message.OutputToRooms) > 0 { - bot.Log.Warn("You have specified 'direct_message_only' as 'true' and provided 'output_to_rooms'." + + bot.Log.Warn().Msg("You have specified 'direct_message_only' as 'true' and provided 'output_to_rooms'." + " Messages will not be sent to listed rooms. If you want to send messages to these rooms," + " please set 'direct_message_only' to 'false'.") } // Is output to users set? if len(message.OutputToUsers) > 0 { - bot.Log.Warn("You have specified 'direct_message_only' as 'true' and provided 'output_to_users'." + + bot.Log.Warn().Msg("You have specified 'direct_message_only' as 'true' and provided 'output_to_users'." + " Messages will not be sent to the listed users (other than you). If you want to send messages to other users," + " please set 'direct_message_only' to 'false'.") } diff --git a/remote/discord/remote.go b/remote/discord/remote.go index 5b35697b..b4de1267 100644 --- a/remote/discord/remote.go +++ b/remote/discord/remote.go @@ -44,11 +44,11 @@ func (c *Client) Reaction(message models.Message, rule models.Rule, bot *models. dg := c.new() // Remove bot reaction from message if err := dg.MessageReactionRemove(message.ChannelID, message.ID, rule.RemoveReaction, "@me"); err != nil { - bot.Log.Errorf("Could not add reaction '%s'. Make sure to use actual emoji unicode characters.", err) + bot.Log.Error().Msgf("Could not add reaction '%s'. Make sure to use actual emoji unicode characters.", err) return } - bot.Log.Debugf("Removed reaction '%s' for rule %s", rule.RemoveReaction, rule.Name) + bot.Log.Debug().Msgf("Removed reaction '%s' for rule %s", rule.RemoveReaction, rule.Name) } if rule.Reaction != "" { @@ -56,11 +56,11 @@ func (c *Client) Reaction(message models.Message, rule models.Rule, bot *models. dg := c.new() // React with desired reaction if err := dg.MessageReactionAdd(message.ChannelID, message.ID, rule.Reaction); err != nil { - bot.Log.Errorf("Could not add reaction '%s'", err) + bot.Log.Error().Msgf("Could not add reaction '%s'", err) return } - bot.Log.Debugf("Added reaction '%s' for rule %s", rule.Reaction, rule.Name) + bot.Log.Debug().Msgf("Added reaction '%s' for rule %s", rule.Reaction, rule.Name) } } @@ -68,22 +68,22 @@ func (c *Client) Reaction(message models.Message, rule models.Rule, bot *models. func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.Rule, bot *models.Bot) { dg := c.new() if dg == nil { - bot.Log.Error("Failed to initialize Discord client") + bot.Log.Error().Msg("Failed to initialize Discord client") return } err := dg.Open() if err != nil { - bot.Log.Errorf("Failed to open connection to Discord server. Error: %s", err.Error()) + bot.Log.Error().Msgf("Failed to open connection to Discord server. Error: %s", err) return } // Wait here until CTRL-C or other term signal is received - bot.Log.Infof("Discord is now running '%s'. Press CTRL-C to exit", bot.Name) + bot.Log.Info().Msgf("Discord is now running '%s'. Press CTRL-C to exit", bot.Name) // get informatiom about ourself botuser, err := dg.User("@me") if err != nil { - bot.Log.Errorf("Failed to get bot name from Discord. Error: %s", err.Error()) + bot.Log.Error().Msgf("Failed to get bot name from Discord. Error: %s", err) return } @@ -101,7 +101,7 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R } if !foundGuild { - bot.Log.Error("Unable to find server defined in 'discord_server_id'. Has the bot been added to the server?") + bot.Log.Error().Msg("Unable to find server defined in 'discord_server_id'. Has the bot been added to the server?") return } @@ -112,7 +112,7 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R // populate rooms gchans, err := dg.GuildChannels(bot.DiscordServerID) if err != nil { - bot.Log.Debugf("Unable to get channels. Error: %v", err) + bot.Log.Debug().Msgf("Unable to get channels. Error: %s", err) } for _, gchan := range gchans { @@ -124,7 +124,7 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R // from prev results and pass in as second param to .GuildMembers gmembers, err := dg.GuildMembers(bot.DiscordServerID, "", 1000) if err != nil { - bot.Log.Debugf("Unable to get users") + bot.Log.Debug().Msg("Unable to get users") } for _, gmember := range gmembers { @@ -134,7 +134,7 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R // populate user groups groles, err := dg.GuildRoles(bot.DiscordServerID) if err != nil { - bot.Log.Debugf("Unable to get roles") + bot.Log.Debug().Msg("Unable to get roles") } for _, grole := range groles { @@ -160,7 +160,7 @@ func (c *Client) Send(message models.Message, bot *models.Bot) { case models.MsgTypeDirect, models.MsgTypeChannel: send(dg, message, bot) default: - bot.Log.Errorf("Unable to send message of type %d", message.Type) + bot.Log.Error().Msgf("Unable to send message of type %d", message.Type) } } @@ -191,12 +191,12 @@ func handleDiscordMessage(bot *models.Bot, inputMsgs chan<- models.Message) inte ch, err := s.Channel(m.ChannelID) if err != nil { - bot.Log.Errorf("Discord Remote: Failed to retrieve channel.") + bot.Log.Error().Msg("Discord Remote: Failed to retrieve channel.") } t, err := m.Timestamp.Parse() if err != nil { - bot.Log.Errorf("Discord Remote: Failed to parse message timestamp.") + bot.Log.Error().Msgf("Discord Remote: Failed to parse message timestamp.") } timestamp := strconv.FormatInt(t.Unix(), 10) @@ -208,13 +208,13 @@ func handleDiscordMessage(bot *models.Bot, inputMsgs chan<- models.Message) inte msgType = models.MsgTypeChannel default: msgType = models.MsgTypeChannel - bot.Log.Debugf("Discord Remote: read message from unsupported channel type '%d'. Defaulting to use channel type 0 ('GUILD_TEXT')", ch.Type) + bot.Log.Debug().Msgf("Discord Remote: read message from unsupported channel type '%d'. Defaulting to use channel type 0 ('GUILD_TEXT')", ch.Type) } contents, mentioned := removeBotMention(m.Content, s.State.User.ID) message = populateMessage(message, msgType, m.ChannelID, m.Message.ID, contents, timestamp, mentioned, m.Author, bot) default: - bot.Log.Errorf("Discord Remote: read message of unsupported type '%d'. Unable to populate message attributes", m.Type) + bot.Log.Error().Msgf("Discord Remote: read message of unsupported type '%d'. Unable to populate message attributes", m.Type) } inputMsgs <- message } diff --git a/remote/scheduler/remote.go b/remote/scheduler/remote.go index 71716372..d123b447 100644 --- a/remote/scheduler/remote.go +++ b/remote/scheduler/remote.go @@ -30,7 +30,7 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R for { _nil := bot.Rooms[""] if len(bot.Rooms) > 0 { - bot.Log.Debugf("scheduler connected to %s channels: %s", strings.Title(bot.ChatApplication), _nil) + bot.Log.Debug().Msgf("scheduler connected to %s channels: %s", strings.Title(bot.ChatApplication), _nil) break } } @@ -44,17 +44,17 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R if rule.Active && rule.Schedule != "" { // Pre-checks before executing rule as a cron job if len(rule.OutputToRooms) == 0 && len(rule.OutputToUsers) == 0 { - bot.Log.Debug("scheduling rules require the 'output_to_rooms' and/or 'output_to_users' fields to be set") + bot.Log.Debug().Msg("scheduling rules require the 'output_to_rooms' and/or 'output_to_users' fields to be set") continue } else if len(rule.OutputToRooms) > 0 && len(bot.Rooms) == 0 { - bot.Log.Debugf("unable to connect scheduler to these rooms: %s", rule.OutputToRooms) + bot.Log.Debug().Msgf("unable to connect scheduler to these rooms: %s", rule.OutputToRooms) continue } else if rule.Respond != "" || rule.Hear != "" { - bot.Log.Debug("scheduling rules does not allow the 'respond' and 'hear' fields") + bot.Log.Debug().Msg("scheduling rules does not allow the 'respond' and 'hear' fields") continue } - bot.Log.Debugf("scheduler is adding rule '%s'", rule.Name) + bot.Log.Debug().Msgf("scheduler is adding rule '%s'", rule.Name) scheduleName := rule.Name input := fmt.Sprintf("<@%s> ", bot.ID) // send message as self @@ -63,7 +63,7 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R // prepare the job function jobFunc := func() { - bot.Log.Debugf("executing scheduler for rule '%s'", scheduleName) + bot.Log.Debug().Msgf("executing scheduler for rule '%s'", scheduleName) // build the message message := models.NewMessage() message.Service = models.MsgServiceScheduler @@ -92,10 +92,11 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R _, err = job.AddFunc(rule.Schedule, jobFunc) if err != nil { // typically the error is due to incorrect cron format - bot.Log.Errorf("unable to add schedule for rule '%s': verify that the supplied schedule is supported", rule.Name) + bot.Log.Error(). + Msgf("unable to add schedule for rule '%s': verify that the supplied schedule is supported", rule.Name) // more verbose log. note: will probably convey that spec // needs to be 6 fields, although any supported format will work. - bot.Log.Debugf("error while adding job: %v", err) + bot.Log.Debug().Msgf("error while adding job: %s", err) continue } @@ -104,7 +105,7 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R } if len(jobs) == 0 { - bot.Log.Warn("no schedules were added - please check for errors") + bot.Log.Warn().Msg("no schedules were added - please check for errors") return } @@ -133,5 +134,5 @@ func processJobs(jobs []*cron.Cron, bot *models.Bot) { defer job.Stop() } wg.Wait() - bot.Log.Warn("scheduler is closing") + bot.Log.Warn().Msg("scheduler is closing") } diff --git a/remote/slack/helper.go b/remote/slack/helper.go index f2ffb680..e8adb252 100644 --- a/remote/slack/helper.go +++ b/remote/slack/helper.go @@ -35,7 +35,7 @@ func constructInteractiveComponentMessage(callback slack.AttachmentActionCallbac message := models.NewMessage() messageType, err := getMessageType(callback.Channel.ID) if err != nil { - bot.Log.Debug(err.Error()) + bot.Log.Debug().Msg(err.Error()) } userNames := strings.Split(callback.User.Name, ".") @@ -70,7 +70,7 @@ func constructInteractiveComponentMessage(callback slack.AttachmentActionCallbac msgType, err := getMessageType(callback.Channel.ID) if err != nil { - bot.Log.Debug(err.Error()) + bot.Log.Debug().Msg(err.Error()) } if msgType == models.MsgTypePrivateChannel { @@ -85,11 +85,11 @@ func constructInteractiveComponentMessage(callback slack.AttachmentActionCallbac func getEventsAPIHealthHandler(bot *models.Bot) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { - bot.Log.Errorf("getEventsAPIHealthHandler: Received invalid method: %s", r.Method) + bot.Log.Error().Msgf("getEventsAPIHealthHandler: Received invalid method: %s", r.Method) w.WriteHeader(http.StatusMethodNotAllowed) return } - bot.Log.Info("Bot event health endpoint hit!") + bot.Log.Info().Msg("Bot event health endpoint hit!") w.WriteHeader(http.StatusOK) w.Write([]byte("OK")) } @@ -117,7 +117,7 @@ func handleCallBack(api *slack.Client, event slackevents.EventsAPIInnerEvent, bo sendHTTPResponse(http.StatusOK, "{}", w, r) // process the event - bot.Log.Debugf("getEventsAPIEventHandler: received event '%s'", event.Type) + bot.Log.Debug().Msgf("getEventsAPIEventHandler: received event '%s'", event.Type) switch ev := event.Data.(type) { // There are Events API specific MessageEvents @@ -132,7 +132,7 @@ func handleCallBack(api *slack.Client, event slackevents.EventsAPIInnerEvent, bo // the associated user id user, err := api.GetBotInfo(ev.BotID) if err != nil { - bot.Log.Infof("unable to retrieve bot info for %s", ev.BotID) + bot.Log.Info().Msgf("unable to retrieve bot info for %s", ev.BotID) return } @@ -146,7 +146,7 @@ func handleCallBack(api *slack.Client, event slackevents.EventsAPIInnerEvent, bo channel := ev.Channel msgType, err := getMessageType(channel) if err != nil { - bot.Log.Debug(err.Error()) + bot.Log.Debug().Msg(err.Error()) } text, mentioned := removeBotMention(ev.Text, bot.ID) @@ -154,7 +154,7 @@ func handleCallBack(api *slack.Client, event slackevents.EventsAPIInnerEvent, bo // get the full user object for the given ID user, err := api.GetUserInfo(senderID) if err != nil { - bot.Log.Errorf("getEventsAPIEventHandler: error getting Slack user info: %s", err.Error()) + bot.Log.Error().Msgf("getEventsAPIEventHandler: error getting Slack user info: %s", err) } timestamp := ev.TimeStamp @@ -162,7 +162,7 @@ func handleCallBack(api *slack.Client, event slackevents.EventsAPIInnerEvent, bo link, err := api.GetPermalink(&slack.PermalinkParameters{Channel: channel, Ts: timestamp}) if err != nil { - bot.Log.Errorf("unable to retrieve link to message: %s", err.Error()) + bot.Log.Error().Msgf("unable to retrieve link to message: %s", err) link = "" } @@ -175,17 +175,17 @@ func handleCallBack(api *slack.Client, event slackevents.EventsAPIInnerEvent, bo // look up channel info, since 'ev' only gives us ID channel, err := api.GetChannelInfo(ev.Channel) if err != nil { - bot.Log.Debugf("unable to fetch channel info for channel joined event: %v", err) + bot.Log.Debug().Msgf("unable to fetch channel info for channel joined event: %s", err) } else { // add the room to the lookup if bot.Rooms[channel.Name] == "" { bot.Rooms[channel.Name] = channel.ID - bot.Log.Debugf("Joined new channel. %s(%s) added to lookup", channel.Name, channel.ID) + bot.Log.Debug().Msgf("Joined new channel. %s(%s) added to lookup", channel.Name, channel.ID) } } } default: - bot.Log.Debugf("getEventsAPIEventHandler: Unrecognized event type: %v", ev) + bot.Log.Debug().Msgf("getEventsAPIEventHandler: Unrecognized event type: %v", ev) } } @@ -194,7 +194,7 @@ func getEventsAPIEventHandler(api *slack.Client, signingSecret string, inputMsgs return func(w http.ResponseWriter, r *http.Request) { // silently throw away anything that's not a POST if r.Method != http.MethodPost { - bot.Log.Error("Slack API Server: method not allowed") + bot.Log.Error().Msg("Slack API Server: method not allowed") sendHTTPResponse(http.StatusMethodNotAllowed, "method not allowed", w, r) return } @@ -202,7 +202,7 @@ func getEventsAPIEventHandler(api *slack.Client, signingSecret string, inputMsgs // read in the body of the incoming payload body, err := ioutil.ReadAll(r.Body) if err != nil { - bot.Log.Error("Slack API Server: error reading request body") + bot.Log.Error().Msg("Slack API Server: error reading request body") sendHTTPResponse(http.StatusBadRequest, "error reading request body", w, r) return } @@ -211,21 +211,21 @@ func getEventsAPIEventHandler(api *slack.Client, signingSecret string, inputMsgs // the request header and signing secret sv, err := slack.NewSecretsVerifier(r.Header, signingSecret) if err != nil { - bot.Log.Error("Slack API Server: error creating secrets verifier") + bot.Log.Error().Msg("Slack API Server: error creating secrets verifier") sendHTTPResponse(http.StatusBadRequest, "error creating secrets verifier", w, r) return } // write the request body's hash if _, err := sv.Write(body); err != nil { - bot.Log.Error("Slack API Server: error while writing body") + bot.Log.Error().Msg("Slack API Server: error while writing body") sendHTTPResponse(http.StatusInternalServerError, "error while writing body", w, r) return } // validate signing secret with computed hash if err := sv.Ensure(); err != nil { - bot.Log.Error("Slack API Server: request unauthorized") + bot.Log.Error().Msg("Slack API Server: request unauthorized") sendHTTPResponse(http.StatusUnauthorized, "request unauthorized", w, r) return } @@ -233,14 +233,14 @@ func getEventsAPIEventHandler(api *slack.Client, signingSecret string, inputMsgs // parse the event from the request eventsAPIEvent, err := slackevents.ParseEvent(json.RawMessage(body), slackevents.OptionNoVerifyToken()) if err != nil { - bot.Log.Error("Slack API Server: error while parsing event") + bot.Log.Error().Msg("Slack API Server: error while parsing event") sendHTTPResponse(http.StatusInternalServerError, "error while parsing event", w, r) return } // validate a URLVerification event with signing secret if eventsAPIEvent.Type == slackevents.URLVerification { - bot.Log.Debug("Slack API Server: received Slack challenge request. sending challenge response.") + bot.Log.Debug().Msg("Slack API Server: received Slack challenge request. sending challenge response.") handleURLVerification(body, w, r) } @@ -256,11 +256,11 @@ func getEventsAPIEventHandler(api *slack.Client, signingSecret string, inputMsgs func getInteractiveComponentHealthHandler(bot *models.Bot) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { - bot.Log.Errorf("getInteractiveComponentHealthHandler: Received invalid method %s", r.Method) + bot.Log.Error().Msgf("getInteractiveComponentHealthHandler: Received invalid method %s", r.Method) w.WriteHeader(http.StatusMethodNotAllowed) return } - bot.Log.Info("Bot interaction health endpoint hit!") + bot.Log.Info().Msg("Bot interaction health endpoint hit!") w.WriteHeader(http.StatusOK) w.Write([]byte("OK")) } @@ -270,7 +270,7 @@ func getInteractiveComponentHealthHandler(bot *models.Bot) func(w http.ResponseW func getInteractiveComponentRuleHandler(signingSecret string, inputMsgs chan<- models.Message, message *models.Message, rule models.Rule, bot *models.Bot) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { - bot.Log.Errorf("getInteractiveComponentRuleHandler: Received invalid method: %s", r.Method) + bot.Log.Error().Msgf("getInteractiveComponentRuleHandler: Received invalid method: %s", r.Method) w.WriteHeader(http.StatusMethodNotAllowed) w.Header().Set("Content-Type", "text/plain") w.Write([]byte("Oops! I encountered an unexpected HTTP verb")) @@ -279,17 +279,17 @@ func getInteractiveComponentRuleHandler(signingSecret string, inputMsgs chan<- m buff, err := ioutil.ReadAll(r.Body) if err != nil { - bot.Log.Errorf("getInteractiveComponentRuleHandler: Failed to read request body: %s", err.Error()) + bot.Log.Error().Msgf("getInteractiveComponentRuleHandler: Failed to read request body: %s", err) } contents, err := sanitizeContents(buff) if err != nil { - bot.Log.Debugf("failed to sanitize content: %v", err) + bot.Log.Debug().Msgf("failed to sanitize content: %s", err) } var callback slack.AttachmentActionCallback if err := json.Unmarshal([]byte(contents), &callback); err != nil { - bot.Log.Errorf("getInteractiveComponentRuleHandler: Failed to decode callback json\n %s\n because %s", contents, err) + bot.Log.Error().Msgf("getInteractiveComponentRuleHandler: Failed to decode callback json %s because %s", contents, err) w.WriteHeader(http.StatusInternalServerError) w.Header().Set("Content-Type", "text/plain") w.Write([]byte("Oops! Looks like I failed to decode some JSON in the backend. Please contact admins for more info!")) @@ -298,7 +298,7 @@ func getInteractiveComponentRuleHandler(signingSecret string, inputMsgs chan<- m // Only accept message from slack with valid token if callback.Token != bot.SlackSigningSecret { - bot.Log.Errorf("getInteractiveComponentRuleHandler: Invalid token %s", callback.Token) + bot.Log.Error().Msgf("getInteractiveComponentRuleHandler: Invalid token %s", callback.Token) w.WriteHeader(http.StatusUnauthorized) w.Header().Set("Content-Type", "text/plain") w.Write([]byte("Sorry, but I didn't recognize your signing secret! Perhaps check if it's a valid secret.")) @@ -314,7 +314,7 @@ func getInteractiveComponentRuleHandler(signingSecret string, inputMsgs chan<- m w.Header().Set("Content-Type", "text/plain") w.Write([]byte("Rodger that!")) - bot.Log.Debugf("getInteractiveComponentRuleHandler: triggering rule: %s", rule.Name) + bot.Log.Debug().Msgf("getInteractiveComponentRuleHandler: triggering rule: %s", rule.Name) } } @@ -379,7 +379,7 @@ func getUserID(email string, users []slack.User, bot *models.Bot) string { return u.ID } } - bot.Log.Errorf("Could not find user '%s'", email) + bot.Log.Error().Msgf("Could not find user '%s'", email) return "" } @@ -387,13 +387,13 @@ func getUserID(email string, users []slack.User, bot *models.Bot) string { func handleDirectMessage(api *slack.Client, message models.Message, bot *models.Bot) error { // Is output to rooms set? if len(message.OutputToRooms) > 0 { - bot.Log.Warn("You have specified 'direct_message_only' as 'true' and provided 'output_to_rooms'." + + bot.Log.Warn().Msg("You have specified 'direct_message_only' as 'true' and provided 'output_to_rooms'." + " Messages will not be sent to listed rooms. If you want to send messages to these rooms," + " please set 'direct_message_only' to 'false'.") } // Is output to users set? if len(message.OutputToUsers) > 0 { - bot.Log.Warn("You have specified 'direct_message_only' as 'true' and provided 'output_to_users'." + + bot.Log.Warn().Msg("You have specified 'direct_message_only' as 'true' and provided 'output_to_users'." + " Messages will not be sent to the listed users (other than you). If you want to send messages to other users," + " please set 'direct_message_only' to 'false'.") } @@ -422,7 +422,7 @@ func handleNonDirectMessage(api *slack.Client, users []slack.User, message model if userID != "" { // If 'direct_message_only' is 'false' but the user listed himself in the 'output_to_users' if userID == message.Vars["_user.id"] && !message.DirectMessageOnly { - bot.Log.Warn("You have specified 'direct_message_only' as 'false' but listed yourself in 'output_to_users'") + bot.Log.Warn().Msg("You have specified 'direct_message_only' as 'false' but listed yourself in 'output_to_users'") } // Respond back to these users via direct message err := sendDirectMessage(api, userID, message) @@ -463,7 +463,7 @@ func populateUserGroups(bot *models.Bot) { ugroups, err := api.GetUserGroups() if err != nil { - bot.Log.Debugf("unable to retrieve usergroups: %s - confirm you have usergroups:read permission set", err.Error()) + bot.Log.Debug().Msgf("unable to retrieve usergroups: %s - confirm you have usergroups:read permission set", err) } for _, usergroup := range ugroups { @@ -492,7 +492,7 @@ func populateMessage(message models.Message, msgType models.MessageType, channel if msgType != models.MsgTypeDirect { name, ok := findKey(bot.Rooms, channel) if !ok { - bot.Log.Warnf("populateMessage: Could not find name of channel '%s'.", channel) + bot.Log.Warn().Msgf("populateMessage: Could not find name of channel '%s'.", channel) } message.ChannelName = name } @@ -536,7 +536,7 @@ func populateMessage(message models.Message, msgType models.MessageType, channel message.Debug = true // TODO: is this even needed? return message default: - bot.Log.Debugf("Read message of unsupported type '%T'. Unable to populate message attributes", msgType) + bot.Log.Debug().Msgf("Read message of unsupported type '%T'. Unable to populate message attributes", msgType) return message } } @@ -547,13 +547,13 @@ func processInteractiveComponentRule(rule models.Rule, message *models.Message, // Get slack attachments from hit rule and append to outgoing message config := rule.Remotes.Slack if config.Attachments != nil { - bot.Log.Debugf("Found attachment for rule '%s'", rule.Name) + bot.Log.Debug().Msgf("Found attachment for rule '%s'", rule.Name) config.Attachments[0].CallbackID = message.ID if len(config.Attachments[0].Actions) > 0 { for i, action := range config.Attachments[0].Actions { actionValue, err := utils.Substitute(action.Value, message.Vars) if err != nil { - bot.Log.Warn(err) + bot.Log.Warn().Msg(err.Error()) } config.Attachments[0].Actions[i].Value = actionValue } @@ -570,7 +570,7 @@ func readFromEventsAPI(api *slack.Client, vToken string, inputMsgs chan<- models // get the current users su, err := getSlackUsers(api, models.Message{}) if err != nil { - bot.Log.Error(err) + bot.Log.Error().Msg(err.Error()) } // populate users populateBotUsers(su, bot) @@ -589,7 +589,7 @@ func readFromEventsAPI(api *slack.Client, vToken string, inputMsgs chan<- models // Start listening to Slack events maskedPort := fmt.Sprintf(":%s", bot.SlackListenerPort) go http.ListenAndServe(maskedPort, router) - bot.Log.Infof("Slack Events API server is listening to %s on port %s", + bot.Log.Info().Msgf("Slack Events API server is listening to %s on port %s", bot.SlackEventsCallbackPath, bot.SlackListenerPort) } @@ -613,7 +613,7 @@ func readFromRTM(rtm *slack.RTM, inputMsgs chan<- models.Message, bot *models.Bo // the associated user id user, err := rtm.GetBotInfo(ev.BotID) if err != nil { - bot.Log.Infof("unable to retrieve bot info for %s", ev.BotID) + bot.Log.Info().Msgf("unable to retrieve bot info for %s", ev.BotID) return } @@ -627,7 +627,7 @@ func readFromRTM(rtm *slack.RTM, inputMsgs chan<- models.Message, bot *models.Bo channel := ev.Channel msgType, err := getMessageType(channel) if err != nil { - bot.Log.Debug(err.Error()) + bot.Log.Debug().Msg(err.Error()) } text, mentioned := removeBotMention(ev.Text, bot.ID) @@ -635,7 +635,7 @@ func readFromRTM(rtm *slack.RTM, inputMsgs chan<- models.Message, bot *models.Bo // get the full user object for the given ID user, err := rtm.GetUserInfo(senderID) if err != nil { - bot.Log.Errorf("Did not get Slack user info: %s", err.Error()) + bot.Log.Error().Msgf("Did not get Slack user info: %s", err) } timestamp := ev.Timestamp @@ -643,7 +643,7 @@ func readFromRTM(rtm *slack.RTM, inputMsgs chan<- models.Message, bot *models.Bo link, err := rtm.GetPermalink(&slack.PermalinkParameters{Channel: channel, Ts: timestamp}) if err != nil { - bot.Log.Errorf("unable to retrieve link to message: %s", err.Error()) + bot.Log.Error().Msgf("unable to retrieve link to message: %s", err) link = "" } @@ -653,30 +653,30 @@ func readFromRTM(rtm *slack.RTM, inputMsgs chan<- models.Message, bot *models.Bo // populate users users, err := rtm.GetUsers() if err != nil { - bot.Log.Errorf("Unable to get users: %v", err) + bot.Log.Error().Msgf("Unable to get users: %s", err) } populateBotUsers(users, bot) // populate user groups populateUserGroups(bot) - bot.Log.Debugf("RTM connection established!") + bot.Log.Debug().Msg("RTM connection established!") case *slack.ChannelJoinedEvent: // when the bot joins a channel add it to the internal lookup if bot.Rooms[ev.Channel.Name] == "" { bot.Rooms[ev.Channel.Name] = ev.Channel.ID - bot.Log.Debugf("Joined new channel. %s(%s) added to lookup", ev.Channel.Name, ev.Channel.ID) + bot.Log.Debug().Msgf("Joined new channel. %s(%s) added to lookup", ev.Channel.Name, ev.Channel.ID) } case *slack.HelloEvent: // ignore - this is the very first initial event sent when connecting to Slack case *slack.RTMError: - bot.Log.Error(ev.Error()) + bot.Log.Error().Msg(ev.Error()) case *slack.ConnectionErrorEvent: - bot.Log.Errorf("RTM connection error: %+v", ev) + bot.Log.Error().Msgf("RTM connection error: %+v", ev) case *slack.InvalidAuthEvent: if !bot.CLI { - bot.Log.Debug("Invalid Authorization. Please double check your Slack token.") + bot.Log.Debug().Msg("Invalid Authorization. Please double check your Slack token.") } default: - bot.Log.Debugf("readFromRTM: Unrecognized event type: %v", ev) + bot.Log.Debug().Msgf("readFromRTM: Unrecognized event type: %v", ev) } } } @@ -685,17 +685,17 @@ func readFromRTM(rtm *slack.RTM, inputMsgs chan<- models.Message, bot *models.Bo func send(api *slack.Client, message models.Message, bot *models.Bot) { users, err := getSlackUsers(api, message) if err != nil { - bot.Log.Errorf("Problem sending message: %s", err.Error()) + bot.Log.Error().Msgf("Problem sending message: %s", err) } if message.DirectMessageOnly { err := handleDirectMessage(api, message, bot) if err != nil { - bot.Log.Errorf("Problem sending message: %s", err.Error()) + bot.Log.Error().Msgf("Problem sending message: %s", err) } } else { err := handleNonDirectMessage(api, users, message, bot) if err != nil { - bot.Log.Errorf("Problem sending message: %s", err.Error()) + bot.Log.Error().Msgf("Problem sending message: %s", err) } } } diff --git a/remote/slack/remote.go b/remote/slack/remote.go index ded69c9f..aa611dfe 100644 --- a/remote/slack/remote.go +++ b/remote/slack/remote.go @@ -40,10 +40,10 @@ func (c *Client) Reaction(message models.Message, rule models.Rule, bot *models. msgRef := slack.NewRefToMessage(message.ChannelID, message.Timestamp) // Remove bot reaction from message if err := api.RemoveReaction(rule.RemoveReaction, msgRef); err != nil { - bot.Log.Errorf("Could not add reaction '%s'", err) + bot.Log.Error().Msgf("Could not add reaction '%s'", err) return } - bot.Log.Debugf("Removed reaction '%s' for rule %s", rule.RemoveReaction, rule.Name) + bot.Log.Debug().Msgf("Removed reaction '%s' for rule %s", rule.RemoveReaction, rule.Name) } if rule.Reaction != "" { // Init api client @@ -52,10 +52,10 @@ func (c *Client) Reaction(message models.Message, rule models.Rule, bot *models. msgRef := slack.NewRefToMessage(message.ChannelID, message.Timestamp) // React with desired reaction if err := api.AddReaction(rule.Reaction, msgRef); err != nil { - bot.Log.Errorf("Could not add reaction '%s'", err) + bot.Log.Error().Msgf("Could not add reaction '%s'", err) return } - bot.Log.Debugf("Added reaction '%s' for rule %s", rule.Reaction, rule.Name) + bot.Log.Debug().Msgf("Added reaction '%s' for rule %s", rule.Reaction, rule.Name) } } @@ -71,21 +71,21 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R // get bot id rat, err := api.AuthTest() if err != nil { - bot.Log.Errorf("The Slack bot token that was provided was invalid or is unauthorized") - bot.Log.Warn("Closing Slack message reader") + bot.Log.Error().Msg("The Slack bot token that was provided was invalid or is unauthorized") + bot.Log.Warn().Msg("Closing Slack message reader") return } // read messages if c.SigningSecret != "" { if bot.SlackEventsCallbackPath == "" { - bot.Log.Error("Need to specify a callback path for the 'slack_events_callback_path' field in the bot.yml (e.g. \"/slack_events/v1/mybot-v1_events\")") - bot.Log.Debug("Closing events reader (will not be able to read messages)") + bot.Log.Error().Msg("Need to specify a callback path for the 'slack_events_callback_path' field in the bot.yml (e.g. \"/slack_events/v1/mybot-v1_events\")") + bot.Log.Debug().Msg("Closing events reader (will not be able to read messages)") return } if !isValidPath(bot.SlackEventsCallbackPath) { // valid path e.g. /slack_events/v1/mybot_dev-v1_events - bot.Log.Error("Invalid events path. Please double check your path value/syntax (e.g. \"/slack_events/v1/mybot_dev-v1_events\")") - bot.Log.Debug("Closing events reader (will not be able to read messages)") + bot.Log.Error().Msg("Invalid events path. Please double check your path value/syntax (e.g. \"/slack_events/v1/mybot_dev-v1_events\")") + bot.Log.Debug().Msg("Closing events reader (will not be able to read messages)") return } bot.ID = rat.UserID @@ -96,16 +96,16 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R readFromRTM(rtm, inputMsgs, bot) } else { if !bot.CLI { - bot.Log.Fatal("Did not find either Slack Token or Slack Signing Secret. Unable to read from Slack") + bot.Log.Fatal().Msg("Did not find either Slack Token or Slack Signing Secret. Unable to read from Slack") } else { - bot.Log.Warn("Slack was specified as your chat_application but no Slack Token or Slack Signing Secret was provided") + bot.Log.Warn().Msg("Slack was specified as your chat_application but no Slack Token or Slack Signing Secret was provided") } } } // Send implementation to satisfy remote interface func (c *Client) Send(message models.Message, bot *models.Bot) { - bot.Log.Debugf("Sending message %s", message.ID) + bot.Log.Debug().Msgf("Sending message %s", message.ID) api := c.new() @@ -124,7 +124,7 @@ func (c *Client) Send(message models.Message, bot *models.Bot) { case models.MsgTypeDirect, models.MsgTypeChannel, models.MsgTypePrivateChannel: send(api, message, bot) default: - bot.Log.Warn("Received unknown message type - no message to send") + bot.Log.Warn().Msg("Received unknown message type - no message to send") } } @@ -136,8 +136,8 @@ var interactionsRouter *mux.Router func (c *Client) InteractiveComponents(inputMsgs chan<- models.Message, message *models.Message, rule models.Rule, bot *models.Bot) { if bot.InteractiveComponents && c.SigningSecret != "" { if bot.SlackInteractionsCallbackPath == "" { - bot.Log.Error("Need to specify a callback path for the 'slack_interactions_callback_path' field in the bot.yml (e.g. \"/slack_events/v1/mybot_dev-v1_interactions\")") - bot.Log.Warn("Closing interactions reader (will not be able to read interactive components)") + bot.Log.Error().Msg("Need to specify a callback path for the 'slack_interactions_callback_path' field in the bot.yml (e.g. \"/slack_events/v1/mybot_dev-v1_interactions\")") + bot.Log.Warn().Msg("Closing interactions reader (will not be able to read interactive components)") return } if interactionsRouter == nil { @@ -153,15 +153,15 @@ func (c *Client) InteractiveComponents(inputMsgs chan<- models.Message, message // We use regex for interactions routing for any bot using this framework // e.g. /slack_events/v1/mybot_dev-v1_interactions if !isValidPath(bot.SlackInteractionsCallbackPath) { - bot.Log.Error("Invalid events path. Please double check your path value/syntax (e.g. \"/slack_events/v1/mybot_dev-v1_interactions\")") - bot.Log.Warn("Closing interaction components reader (will not be able to read interactive components)") + bot.Log.Error().Msg("Invalid events path. Please double check your path value/syntax (e.g. \"/slack_events/v1/mybot_dev-v1_interactions\")") + bot.Log.Warn().Msg("Closing interaction components reader (will not be able to read interactive components)") return } interactionsRouter.HandleFunc(bot.SlackInteractionsCallbackPath, ruleHandle).Methods("POST") // start Interactive Components server go http.ListenAndServe(":4000", interactionsRouter) - bot.Log.Infof("Slack Interactive Components server is listening to %s", bot.SlackInteractionsCallbackPath) + bot.Log.Info().Msgf("Slack Interactive Components server is listening to %s", bot.SlackInteractionsCallbackPath) } // Process the hit rule for Interactive Components, e.g. interactive messages diff --git a/remote/telegram/remote.go b/remote/telegram/remote.go index facdd695..6a92d4e3 100644 --- a/remote/telegram/remote.go +++ b/remote/telegram/remote.go @@ -46,7 +46,7 @@ func (c *Client) Read(inputMsgs chan<- models.Message, rules map[string]models.R botuser, err := telegramAPI.GetMe() if err != nil { - bot.Log.Error("Failed to initialize Telegram client") + bot.Log.Error().Msg("Failed to initialize Telegram client") return } bot.Name = botuser.UserName @@ -123,7 +123,7 @@ func (c *Client) Send(message models.Message, bot *models.Bot) { telegramAPI := c.new() chatID, err := strconv.ParseInt(message.ChannelID, 10, 64) if err != nil { - bot.Log.Errorf("unable to retrieve chat ID %s", message.ChannelID) + bot.Log.Error().Msgf("unable to retrieve chat ID %s", message.ChannelID) return } @@ -132,7 +132,7 @@ func (c *Client) Send(message models.Message, bot *models.Bot) { if message.DirectMessageOnly { chatID, err = strconv.ParseInt(message.Vars["_user.id"], 10, 64) if err != nil { - bot.Log.Errorf("unable to retrieve user ID %s for direct message", message.Vars["_user.id"]) + bot.Log.Error().Msgf("unable to retrieve user ID %s for direct message", message.Vars["_user.id"]) return } } diff --git a/utils/access_check.go b/utils/access_check.go index 1a1bd16e..fee86b3f 100644 --- a/utils/access_check.go +++ b/utils/access_check.go @@ -20,7 +20,7 @@ func CanTrigger(currentUserName string, currentUserID string, rule models.Rule, // are they ignored directly? deny for _, name := range rule.IgnoreUsers { if name == currentUserName { - bot.Log.Debugf("'%s' is on the ignore_users list for rule: '%s'", currentUserName, rule.Name) + bot.Log.Debug().Msgf("'%s' is on the ignore_users list for rule: '%s'", currentUserName, rule.Name) return false } } @@ -33,7 +33,8 @@ func CanTrigger(currentUserName string, currentUserID string, rule models.Rule, } if isIgnored { - bot.Log.Debugf("'%s' is part of a group in ignore_usergroups: %s", currentUserName, strings.Join(rule.IgnoreUserGroups, ", ")) + bot.Log.Debug(). + Msgf("'%s' is part of a group in ignore_usergroups: %s", currentUserName, strings.Join(rule.IgnoreUserGroups, ", ")) return false } @@ -72,15 +73,18 @@ func CanTrigger(currentUserName string, currentUserID string, rule models.Rule, if !canRunRule { if len(rule.AllowUsers) > 0 { - bot.Log.Debugf("'%s' is not part of allow_users: %s", currentUserName, strings.Join(rule.AllowUsers, ", ")) + bot.Log.Debug(). + Msgf("'%s' is not part of allow_users: %s", currentUserName, strings.Join(rule.AllowUsers, ", ")) } if len(rule.AllowUserIds) > 0 { - bot.Log.Debugf("'%s' is not part of allow_userids: %s", currentUserID, strings.Join(rule.AllowUserIds, ", ")) + bot.Log.Debug(). + Msgf("'%s' is not part of allow_userids: %s", currentUserID, strings.Join(rule.AllowUserIds, ", ")) } if len(rule.AllowUserGroups) > 0 { - bot.Log.Debugf("'%s' is not part of any groups in allow_usergroups: %s", currentUserName, strings.Join(rule.AllowUserGroups, ", ")) + bot.Log.Debug(). + Msgf("'%s' is not part of any groups in allow_usergroups: %s", currentUserName, strings.Join(rule.AllowUserGroups, ", ")) } } @@ -107,7 +111,7 @@ func isMemberOfGroup(currentUserID string, userGroups []string, bot *models.Bot) usr, err = dg.GuildMember(bot.DiscordServerID, currentUserID) if err != nil { - bot.Log.Debugf("Error while searching for user. Error: %v", err) + bot.Log.Debug().Msgf("Error while searching for user. Error: %s", err) return false, nil } @@ -131,7 +135,7 @@ func isMemberOfGroup(currentUserID string, userGroups []string, bot *models.Bot) // Get the members of the group userGroupMembers, err := api.GetUserGroupMembers(knownUserGroupID) if err != nil { - bot.Log.Debugf("Unable to retrieve user group members, %s", err.Error()) + bot.Log.Debug().Msgf("Unable to retrieve user group members, %s", err) } // Check if any of the members are the current user for _, userGroupMemberID := range userGroupMembers { @@ -147,7 +151,7 @@ func isMemberOfGroup(currentUserID string, userGroups []string, bot *models.Bot) return false, nil default: - bot.Log.Errorf("Chat application %s is not supported", capp) + bot.Log.Error().Msgf("Chat application %s is not supported", capp) return false, nil } } diff --git a/utils/rooms.go b/utils/rooms.go index 404d4f50..112b1bda 100644 --- a/utils/rooms.go +++ b/utils/rooms.go @@ -15,7 +15,7 @@ func GetRoomIDs(wantRooms []string, bot *models.Bot) []string { if roomMatch != "" { rooms = append(rooms, roomMatch) } else { - bot.Log.Debugf("Room '%s' does not exist", room) + bot.Log.Debug().Msgf("Room '%s' does not exist", room) } } From 14705c00c74724789a4cf07f8c4a2b78d76383cb Mon Sep 17 00:00:00 2001 From: alankan886 Date: Mon, 26 Apr 2021 18:09:49 -0400 Subject: [PATCH 2/3] Fix setting logger level --- core/configure.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/configure.go b/core/configure.go index 46835802..d6c55706 100644 --- a/core/configure.go +++ b/core/configure.go @@ -32,7 +32,7 @@ func initLogger(b *models.Bot) { b.Log = zerolog.New(os.Stdout).Level(zerolog.ErrorLevel) if b.Debug { - b.Log.Level(zerolog.DebugLevel) + b.Log = zerolog.New(os.Stdout).Level(zerolog.DebugLevel) } } From 8b8213e462224cd0e9985f3795214b9e357ae94e Mon Sep 17 00:00:00 2001 From: alankan886 Date: Tue, 27 Apr 2021 22:32:04 -0400 Subject: [PATCH 3/3] Upgrade go version and go mod tidy --- go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.sum b/go.sum index 2020219a..f242ab58 100644 --- a/go.sum +++ b/go.sum @@ -332,7 +332,6 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= @@ -540,7 +539,6 @@ golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= 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-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=