package main import ( "encoding/json" "flag" "log" "net" "os" "strings" "text/template" "time" "gopkg.in/mcuadros/go-syslog.v2" ) func udpConnect(addr string) (conn *net.UDPConn) { if addr != "" { uaddr, err := net.ResolveUDPAddr("udp4", addr) if err != nil { log.Printf("error resolving udp address: %s (%s)\n", addr, err) } if uaddr != nil { conn, err = net.DialUDP("udp4", nil, uaddr) if err != nil { log.Printf("error connecting to udp address: %s (%s)", addr, err) } else { log.Printf("udp client initialized") } } } return } type mapFlag map[string]string func (i *mapFlag) String() string { return "" } func (i *mapFlag) Set(v string) error { s := strings.Split(v, "=") if len(s) > 1 && s[0] != "" { (*i)[s[0]] = strings.Join(s[1:], "=") } return nil } func main() { socketFile := flag.String("socket", "/dev/log", "socket file") stdoutTpl := flag.String("stdoutTpl", "[{{.timestamp}}] {{.content}}", "stdout line template, variables are: timestamp, content, facility, hostname, priority, severity, tag") udpAddr := flag.String("udpAddr", "", "udp address, format is host:port") udpTpl := flag.String("udpTpl", "{{ json . }}", "udp line template, see stdoutTpl for variables") customVars := make(mapFlag) flag.Var(&customVars, "var", "custom variable, pe. type=error, can be used multiple times") flag.Parse() fMap := template.FuncMap{ "json": func(i interface{}) string { b, _ := json.Marshal(i) return string(b) }, } stdoutTemplate := template.Must(template.New("stdout").Funcs(fMap).Parse(*stdoutTpl + "\n")) udpTemplate := template.Must(template.New("udp").Funcs(fMap).Parse(*udpTpl + "\n")) udpConnection := udpConnect(*udpAddr) go func() { for range time.Tick(time.Second * 60) { if udpConnection == nil { udpConnection = udpConnect(*udpAddr) } } }() channel := make(syslog.LogPartsChannel, 1000) handler := syslog.NewChannelHandler(channel) udpChannel := make(syslog.LogPartsChannel, 1000) server := syslog.NewServer() // server.SetFormat(syslog.RFC5424) server.SetFormat(syslog.Automatic) server.SetHandler(handler) //err := server.ListenUDP("0.0.0.0:514") if _, err := os.Stat(*socketFile); err == nil { os.Remove(*socketFile) } err := server.ListenUnixgram(*socketFile) if err != nil { panic(err) } os.Chmod(*socketFile, 0666) err = server.Boot() if err != nil { panic(err) } go func(channel syslog.LogPartsChannel) { for logParts := range channel { for k, v := range customVars { logParts[k] = v } stdoutTemplate.Execute(os.Stdout, logParts) udpChannel <- logParts // fmt.Println(logParts) } }(channel) go func(channel syslog.LogPartsChannel) { for logParts := range channel { if udpConnection != nil { err := udpTemplate.Execute(udpConnection, logParts) if err != nil { log.Printf("error executing udp template: %s", err) } } } }(udpChannel) server.Wait() }