github.com/blystad/deis@v0.11.0/logger/syslogd/syslogd.go (about)

     1  package main
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"github.com/deis/deis/logger/syslog"
     7  	"io"
     8  	"os"
     9  	"os/signal"
    10  	"path"
    11  	"regexp"
    12  	"syscall"
    13  )
    14  
    15  const logRoot = "/var/log/deis"
    16  
    17  type handler struct {
    18  	// To simplify implementation of our handler we embed helper
    19  	// syslog.BaseHandler struct.
    20  	*syslog.BaseHandler
    21  }
    22  
    23  // Simple fiter for named/bind messages which can be used with BaseHandler
    24  func filter(m *syslog.Message) bool {
    25  	// return m.Tag == "named" || m.Tag == "bind"
    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(m *syslog.Message) (io.Writer, error) {
    48  	r := regexp.MustCompile(`^.* ([-a-z0-9]+)\[[a-z0-9\.]+\].*`)
    49  	match := r.FindStringSubmatch(m.String())
    50  	if match == nil {
    51  		return nil, errors.New("Could not find app name in 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.Message) error {
    71  	file, err := getLogFile(m)
    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  		fmt.Println(m)
    88  		err := writeToDisk(m)
    89  		if err != nil {
    90  			panic(err)
    91  		}
    92  	}
    93  	fmt.Println("Exit handler")
    94  	h.End()
    95  }
    96  
    97  func main() {
    98  	// Create a server with one handler and run one listen gorutine
    99  	s := syslog.NewServer()
   100  	s.AddHandler(newHandler())
   101  	s.Listen("0.0.0.0:514")
   102  
   103  	// Wait for terminating signal
   104  	sc := make(chan os.Signal, 2)
   105  	signal.Notify(sc, syscall.SIGTERM, syscall.SIGINT)
   106  	<-sc
   107  
   108  	// Shutdown the server
   109  	fmt.Println("Shutdown the server...")
   110  	s.Shutdown()
   111  	fmt.Println("Server is down")
   112  }