diff --git a/eth-log-alerting.go b/eth-log-alerting.go new file mode 100644 index 0000000000000000000000000000000000000000..6d5a0df9727a341c88797701ac3cb33d6976a815 --- /dev/null +++ b/eth-log-alerting.go @@ -0,0 +1,124 @@ +package main + +import ( + "flag" + "fmt" + "log" + "os" + "os/signal" + "path/filepath" + "syscall" + + "github.com/asaskevich/govalidator" + "github.com/hpcloud/tail" +) + +var ( + logPath string + webhookURL string + username string + channel string + color string + iconURL string + + logger *log.Logger + debugDest string + debug bool + + tailer *tail.Tail +) + +func init() { + flag.StringVar(&logPath, "log-path", "", "Log to monitor") + flag.StringVar(&webhookURL, "webhook", "", "Webhook to forward log entries to") + flag.StringVar(&username, "username", "logbot", "Username to post as") + flag.StringVar(&channel, "channel", "", "Channel to post log entries to") + flag.StringVar(&color, "color", "default", "Color for entry, either named or hex with `#`") + flag.StringVar(&iconURL, "icon-url", "", "URL of icon to use for bot") + flag.StringVar(&debugDest, "debug-dest", "os.Stdout", "Destination for debug and other messages, omit to log to Stdout") + flag.BoolVar(&debug, "debug", false, "Include additional log data for debugging") + flag.Parse() + + setUpLogger() + + validatePath(&logPath) + + if !govalidator.IsURL(webhookURL) || len(channel) < 2 { + usage() + } +} + +func main() { + logger.Printf("Monitoring %s", logPath) + logger.Printf("Forwarding to channel \"%s\" as user \"%s\" at %s", channel, username, webhookURL) + sig := make(chan os.Signal, 1) + signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) + + go tailLog() + + caughtSig := <-sig + tailer.Stop() + tailer.Cleanup() + logger.Printf("Stopping, got signal %s", caughtSig) +} + +func tailLog() { + t, err := tail.TailFile(logPath, tail.Config{Follow: true, MustExist: true, ReOpen: true}) + tailer = t + + if err != nil { + logger.Println(err) + usage() + } + + for line := range t.Lines { + sendLine(line) + } +} + +func sendLine(line *tail.Line) { + logger.Println(line.Text) +} + +func setUpLogger() { + logOpts := log.Ldate | log.Ltime | log.LUTC | log.Lshortfile + + if debugDest == "os.Stdout" { + logger = log.New(os.Stdout, "DEBUG: ", logOpts) + } else { + path, err := filepath.Abs(debugDest) + if err != nil { + logger.Fatal(err) + } + + logFile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + log.Fatal(err) + } + + logger = log.New(logFile, "", logOpts) + } +} + +func validatePath(path *string) { + if len(*path) > 1 { + var err error + *path, err = filepath.Abs(*path) + + if err != nil { + fmt.Printf("Error: %s", err.Error()) + os.Exit(3) + } + + if _, err = os.Stat(*path); os.IsNotExist(err) { + usage() + } + } else { + usage() + } +} + +func usage() { + flag.Usage() + os.Exit(3) +}