Skip to content

Commit

Permalink
refactor(log): detach logger from Bot (#210)
Browse files Browse the repository at this point in the history
  • Loading branch information
wass3r authored Nov 27, 2021
1 parent 176c4cf commit f47b01d
Show file tree
Hide file tree
Showing 29 changed files with 433 additions and 391 deletions.
1 change: 0 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"request": "launch",
"mode": "exec",
"remotePath": "",
"port": 2345,
"host": "127.0.0.1",
"program": "${workspaceRoot}/debug",
"preLaunchTask": "build-debug",
Expand Down
50 changes: 22 additions & 28 deletions cmd/flottbot/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,46 @@ package main
import (
"flag"
"fmt"
"log"
"os"
"sync"

"github.com/spf13/viper"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"

"github.com/target/flottbot/core"
"github.com/target/flottbot/models"
"github.com/target/flottbot/version"
)

func newBot() *models.Bot {
bot := viper.New()
bot.AddConfigPath("./config")
bot.AddConfigPath(".")
bot.SetConfigName("bot")
err := bot.ReadInConfig()
if err != nil {
log.Fatalf("Fatal error config file: %s \n", err)
}

var botC models.Bot
err = bot.Unmarshal(&botC)
if err != nil {
log.Fatalf(err.Error())
}
return &botC
}

func main() {
var rules = make(map[string]models.Rule)
var hitRule = make(chan models.Rule, 1)
var inputMsgs = make(chan models.Message, 1)
var outputMsgs = make(chan models.Message, 1)
var (
// version flags
ver = flag.Bool("version", false, "print version information")
v = flag.Bool("v", false, "print version information")

ver := flag.Bool("version", false, "print version information")
v := flag.Bool("v", false, "print version information")
// bot vars
rules = make(map[string]models.Rule)
hitRule = make(chan models.Rule, 1)
inputMsgs = make(chan models.Message, 1)
outputMsgs = make(chan models.Message, 1)
)

// parse the flagS
flag.Parse()

// check to see if the version was requested
if *v || *ver {
fmt.Println(version.String())
os.Exit(0)
}

// set some early defaults for the logger
zerolog.TimeFieldFormat = zerolog.TimeFormatUnixMs
zerolog.SetGlobalLevel(zerolog.InfoLevel)
log.Logger = log.Output(os.Stdout).With().Logger()

// Configure the bot to the core framework
bot := newBot()
bot := models.NewBot()
core.Configure(bot)

// Populate the global rules map
Expand All @@ -61,7 +55,7 @@ func main() {
// Add 3 to the wait group so the three separate processes run concurrently
// - process 1: core.Remotes - reads messages
// - process 2: core.Matcher - processes messages
// - process 3: core.Outpus - sends out messages
// - process 3: core.Outputs - sends out messages
var wg sync.WaitGroup
wg.Add(3)

Expand Down
88 changes: 25 additions & 63 deletions core/configure.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package core

import (
"io"
"os"
"strings"

"github.com/rs/zerolog"
"github.com/rs/zerolog/log"

"github.com/target/flottbot/models"
Expand All @@ -19,34 +16,11 @@ var defaultSlackListenerPort = "3000"
func Configure(bot *models.Bot) {
log.Info().Msg("configuring bot...")

initLogger(bot)

validateRemoteSetup(bot)

configureChatApplication(bot)

bot.Log.Info().Msgf("configured bot '%s'!", bot.Name)
}

// initLogger sets log configuration for the bot
func initLogger(b *models.Bot) {
var out io.Writer
var level zerolog.Level

// defaults
out = os.Stdout
level = zerolog.InfoLevel

// for CLI, use zerolog's ConsoleWriter
if b.CLI {
out = zerolog.ConsoleWriter{Out: os.Stderr}
}

if b.Debug {
level = zerolog.DebugLevel
}

b.Log = zerolog.New(out).With().Timestamp().Logger().Level(level)
log.Info().Msgf("configured bot %#q!", bot.Name)
}

// configureChatApplication configures a user's specified chat application
Expand All @@ -59,7 +33,7 @@ func configureChatApplication(bot *models.Bot) {
// update the bot name
token, err := utils.Substitute(bot.Name, emptyMap)
if err != nil {
bot.Log.Warn().Msgf("could not configure bot 'name' field: %s", err.Error())
log.Warn().Msgf("could not configure bot 'name' field: %s", err.Error())
}

bot.Name = token
Expand All @@ -70,7 +44,7 @@ func configureChatApplication(bot *models.Bot) {
// Discord bot token
token, err := utils.Substitute(bot.DiscordToken, emptyMap)
if err != nil {
bot.Log.Error().Msgf("could not set 'discord_token': %s", err.Error())
log.Error().Msgf("could not set 'discord_token': %s", err.Error())
bot.RunChat = false
}

Expand All @@ -80,14 +54,14 @@ 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, emptyMap)
if err != nil {
bot.Log.Error().Msgf("could not set 'discord_server_id': %s", err.Error())
log.Error().Msgf("could not set 'discord_server_id': %s", err.Error())
bot.RunChat = false
}

bot.DiscordServerID = serverID

if !isSet(token, serverID) {
bot.Log.Error().Msg("bot is not configured correctly for discord - check that 'discord_token' and 'discord_server_id' are set")
if !utils.IsSet(token, serverID) {
log.Error().Msg("bot is not configured correctly for discord - check that 'discord_token' and 'discord_server_id' are set")
bot.RunChat = false
}

Expand All @@ -97,19 +71,19 @@ func configureChatApplication(bot *models.Bot) {
case "telegram":
token, err := utils.Substitute(bot.TelegramToken, emptyMap)
if err != nil {
bot.Log.Error().Msgf("could not set 'telegram_token': %s", err.Error())
log.Error().Msgf("could not set 'telegram_token': %s", err.Error())
bot.RunChat = false
}

if !isSet(token) {
bot.Log.Error().Msg("bot is not configured correctly for telegram - check that 'telegram_token' is set")
if !utils.IsSet(token) {
log.Error().Msg("bot is not configured correctly for telegram - check that 'telegram_token' is set")
bot.RunChat = false
}

bot.TelegramToken = token

default:
bot.Log.Error().Msgf("chat application '%s' is not supported", bot.ChatApplication)
log.Error().Msgf("chat application %#q is not supported", bot.ChatApplication)
bot.RunChat = false
}
}
Expand All @@ -123,53 +97,53 @@ func configureSlackBot(bot *models.Bot) {
// slack_token
token, err := utils.Substitute(bot.SlackToken, emptyMap)
if err != nil {
bot.Log.Error().Msgf("could not set 'slack_token': %s", err.Error())
log.Error().Msgf("could not set 'slack_token': %s", err.Error())
}

bot.SlackToken = token

// slack_app_token
appToken, err := utils.Substitute(bot.SlackAppToken, emptyMap)
if err != nil {
bot.Log.Warn().Msgf("could not set 'slack_app_token': %s", err.Error())
log.Warn().Msgf("could not set 'slack_app_token': %s", err.Error())
}

bot.SlackAppToken = appToken

// slack_signing_secret
signingSecret, err := utils.Substitute(bot.SlackSigningSecret, emptyMap)
if err != nil {
bot.Log.Warn().Msgf("could not set 'slack_signing_secret': %s", err.Error())
log.Warn().Msgf("could not set 'slack_signing_secret': %s", err.Error())
}

bot.SlackSigningSecret = signingSecret

// slack_events_callback_path
eCallbackPath, err := utils.Substitute(bot.SlackEventsCallbackPath, emptyMap)
if err != nil {
bot.Log.Warn().Msgf("could not set 'slack_events_callback_path': %s", err.Error())
log.Warn().Msgf("could not set 'slack_events_callback_path': %s", err.Error())
}

bot.SlackEventsCallbackPath = eCallbackPath

// slack_interactions_callback_path
iCallbackPath, err := utils.Substitute(bot.SlackInteractionsCallbackPath, emptyMap)
if err != nil {
bot.Log.Warn().Msgf("could not set 'slack_interactions_callback_path': %s", err.Error())
log.Warn().Msgf("could not set 'slack_interactions_callback_path': %s", err.Error())
}

bot.SlackInteractionsCallbackPath = iCallbackPath

// slack_listener_port
lPort, err := utils.Substitute(bot.SlackListenerPort, emptyMap)
if err != nil {
bot.Log.Warn().Msgf("could not set 'slack_listener_port': %s", err.Error())
log.Warn().Msgf("could not set 'slack_listener_port': %s", err.Error())
}

// set slack http listener port from config file or default
if !isSet(lPort) {
bot.Log.Warn().Msgf("'slack_listener_port' not set: %s", lPort)
bot.Log.Info().Str("defaultSlackListenerPort", defaultSlackListenerPort).Msg("using default slack listener port.")
if !utils.IsSet(lPort) {
log.Warn().Msgf("'slack_listener_port' not set: %#q", lPort)
log.Info().Str("defaultSlackListenerPort", defaultSlackListenerPort).Msg("using default slack listener port.")
lPort = defaultSlackListenerPort
}

Expand All @@ -179,10 +153,10 @@ func configureSlackBot(bot *models.Bot) {
// needs one of the following to be valid
// 1. SLACK_TOKEN + SLACK_APP_TOKEN (socket mode)
// 2. SLACK_TOKEN + SLACK_SIGNING_SECRET + SLACK_EVENTS_CALLBACK_PATH (events api)
isSocketMode := isSet(token, appToken)
isEventsAPI := isSet(token, signingSecret, eCallbackPath)
isSocketMode := utils.IsSet(token, appToken)
isEventsAPI := utils.IsSet(token, signingSecret, eCallbackPath)
if !isSocketMode && !isEventsAPI {
bot.Log.Error().Msg("must have either 'slack_token', 'slack_app_token' or 'slack_token', 'slack_signing_secret', and 'slack_events_callback_path' set")
log.Error().Msg("must have either 'slack_token', 'slack_app_token' or 'slack_token', 'slack_signing_secret', and 'slack_events_callback_path' set")
bot.RunChat = false
}
}
Expand All @@ -197,31 +171,19 @@ func validateRemoteSetup(bot *models.Bot) {
}

if !bot.CLI && bot.ChatApplication == "" {
bot.Log.Error().Msgf("no 'chat_application' specified and cli mode is not enabled. exiting...")
log.Error().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().Msg("scheduler does not support scheduled outputs to cli mode")
log.Warn().Msg("scheduler does not support scheduled outputs to cli mode")
bot.RunScheduler = false
}

if bot.ChatApplication == "" {
bot.Log.Warn().Msg("scheduler did not find any configured chat applications - scheduler is closing")
log.Warn().Msg("scheduler did not find any configured chat applications - scheduler is closing")
bot.RunScheduler = false
}
}
}

// isSet is a helper function to check whether any of the supplied
// strings are empty or unsubstituted (ie. still in ${<string>} format)
func isSet(s ...string) bool {
for _, v := range s {
if v == "" || strings.HasPrefix(v, "${") {
return false
}
}

return true
}
Loading

0 comments on commit f47b01d

Please sign in to comment.