github.com/sbuss/deis@v1.6.1/logger/syslogd/syslogd.go (about) 1 package syslogd 2 3 import ( 4 "fmt" 5 "io" 6 "log" 7 "os" 8 "path" 9 "regexp" 10 11 "github.com/deis/deis/logger/syslog" 12 13 "github.com/deis/deis/logger/drain" 14 ) 15 16 var LogRoot string 17 18 type handler struct { 19 // To simplify implementation of our handler we embed helper 20 // syslog.BaseHandler struct. 21 *syslog.BaseHandler 22 } 23 24 // Simple fiter for named/bind messages which can be used with BaseHandler 25 func filter(m syslog.SyslogMessage) bool { 26 return true 27 } 28 29 func newHandler() *handler { 30 h := handler{syslog.NewBaseHandler(5, filter, false)} 31 go h.mainLoop() // BaseHandler needs some gorutine that reads from its queue 32 return &h 33 } 34 35 // check if a file path exists 36 func fileExists(path string) (bool, error) { 37 _, err := os.Stat(path) 38 if err == nil { 39 return true, nil 40 } 41 if os.IsNotExist(err) { 42 return false, nil 43 } 44 return false, err 45 } 46 47 func getLogFile(message string) (io.Writer, error) { 48 r := regexp.MustCompile(`^.* ([-a-z0-9]+)\[[a-z0-9-_\.]+\].*`) 49 match := r.FindStringSubmatch(message) 50 if match == nil { 51 return nil, fmt.Errorf("Could not find app name in message: %s", message) 52 } 53 appName := match[1] 54 filePath := path.Join(LogRoot, appName+".log") 55 // check if file exists 56 exists, err := fileExists(filePath) 57 if err != nil { 58 return nil, err 59 } 60 // return a new file or the existing file for appending 61 var file io.Writer 62 if exists { 63 file, err = os.OpenFile(filePath, os.O_RDWR|os.O_APPEND, 0644) 64 } else { 65 file, err = os.OpenFile(filePath, os.O_RDWR|os.O_CREATE, 0644) 66 } 67 return file, err 68 } 69 70 func writeToDisk(m syslog.SyslogMessage) error { 71 file, err := getLogFile(m.String()) 72 if err != nil { 73 return err 74 } 75 bytes := []byte(m.String() + "\n") 76 file.Write(bytes) 77 return nil 78 } 79 80 // mainLoop reads from BaseHandler queue using h.Get and logs messages to stdout 81 func (h *handler) mainLoop() { 82 for { 83 m := h.Get() 84 if m == nil { 85 break 86 } 87 d := drain.GetDrain() 88 if d != "" { 89 drain.SendToDrain(m.String(), d) 90 } 91 err := writeToDisk(m) 92 if err != nil { 93 log.Println(err) 94 } 95 } 96 h.End() 97 } 98 99 // Listen starts a new syslog server which runs until it receives a signal. 100 func Listen(signalChan chan os.Signal, cleanupDone chan bool, bindAddr string) { 101 fmt.Println("Starting syslog...") 102 // If LogRoot doesn't exist, create it 103 // equivalent to Python's `if not os.path.exists(filename)` 104 if _, err := os.Stat(LogRoot); os.IsNotExist(err) { 105 if err = os.MkdirAll(LogRoot, 0777); err != nil { 106 log.Fatalf("unable to create LogRoot at %s: %v", LogRoot, err) 107 } 108 } 109 // Create a server with one handler and run one listen gorutine 110 s := syslog.NewServer() 111 s.AddHandler(newHandler()) 112 s.Listen(bindAddr) 113 fmt.Println("Syslog server started...") 114 fmt.Println("deis-logger running") 115 116 // Wait for terminating signal 117 for _ = range signalChan { 118 // Shutdown the server 119 fmt.Println("Shutting down...") 120 s.Shutdown() 121 cleanupDone <- true 122 } 123 }