Newer
Older
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
searchRegex 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(&searchRegex, "search", "", "Search term or regex to match")
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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 {
if line.Err != nil {
continue
}
if len(searchRegex) == 0 {
go sendLine(line)
} else {
matched, _ := regexp.MatchString(searchRegex, line.Text)
if matched {
go sendLine(line)
}
}
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
}
}
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)
}