github.com/chenchun/docker@v1.3.2-0.20150629222414-20467faf132b/daemon/logger/syslog/syslog.go (about) 1 // +build linux 2 3 package syslog 4 5 import ( 6 "errors" 7 "io" 8 "log/syslog" 9 "net" 10 "net/url" 11 "os" 12 "path" 13 "strconv" 14 "strings" 15 16 "github.com/Sirupsen/logrus" 17 "github.com/docker/docker/daemon/logger" 18 "github.com/docker/docker/pkg/urlutil" 19 ) 20 21 const name = "syslog" 22 23 var facilities = map[string]syslog.Priority{ 24 "kern": syslog.LOG_KERN, 25 "user": syslog.LOG_USER, 26 "mail": syslog.LOG_MAIL, 27 "daemon": syslog.LOG_DAEMON, 28 "auth": syslog.LOG_AUTH, 29 "syslog": syslog.LOG_SYSLOG, 30 "lpr": syslog.LOG_LPR, 31 "news": syslog.LOG_NEWS, 32 "uucp": syslog.LOG_UUCP, 33 "cron": syslog.LOG_CRON, 34 "authpriv": syslog.LOG_AUTHPRIV, 35 "ftp": syslog.LOG_FTP, 36 "local0": syslog.LOG_LOCAL0, 37 "local1": syslog.LOG_LOCAL1, 38 "local2": syslog.LOG_LOCAL2, 39 "local3": syslog.LOG_LOCAL3, 40 "local4": syslog.LOG_LOCAL4, 41 "local5": syslog.LOG_LOCAL5, 42 "local6": syslog.LOG_LOCAL6, 43 "local7": syslog.LOG_LOCAL7, 44 } 45 46 type Syslog struct { 47 writer *syslog.Writer 48 } 49 50 func init() { 51 if err := logger.RegisterLogDriver(name, New); err != nil { 52 logrus.Fatal(err) 53 } 54 } 55 56 func New(ctx logger.Context) (logger.Logger, error) { 57 tag := ctx.Config["syslog-tag"] 58 if tag == "" { 59 tag = ctx.ContainerID[:12] 60 } 61 62 proto, address, err := parseAddress(ctx.Config["syslog-address"]) 63 if err != nil { 64 return nil, err 65 } 66 67 facility, err := parseFacility(ctx.Config["syslog-facility"]) 68 if err != nil { 69 return nil, err 70 } 71 72 log, err := syslog.Dial( 73 proto, 74 address, 75 facility, 76 path.Base(os.Args[0])+"/"+tag, 77 ) 78 if err != nil { 79 return nil, err 80 } 81 82 return &Syslog{ 83 writer: log, 84 }, nil 85 } 86 87 func (s *Syslog) Log(msg *logger.Message) error { 88 if msg.Source == "stderr" { 89 return s.writer.Err(string(msg.Line)) 90 } 91 return s.writer.Info(string(msg.Line)) 92 } 93 94 func (s *Syslog) Close() error { 95 return s.writer.Close() 96 } 97 98 func (s *Syslog) Name() string { 99 return name 100 } 101 102 func (s *Syslog) GetReader() (io.Reader, error) { 103 return nil, logger.ReadLogsNotSupported 104 } 105 106 func parseAddress(address string) (string, string, error) { 107 if urlutil.IsTransportURL(address) { 108 url, err := url.Parse(address) 109 if err != nil { 110 return "", "", err 111 } 112 113 // unix socket validation 114 if url.Scheme == "unix" { 115 if _, err := os.Stat(url.Path); err != nil { 116 return "", "", err 117 } 118 return url.Scheme, url.Path, nil 119 } 120 121 // here we process tcp|udp 122 host := url.Host 123 if _, _, err := net.SplitHostPort(host); err != nil { 124 if !strings.Contains(err.Error(), "missing port in address") { 125 return "", "", err 126 } 127 host = host + ":514" 128 } 129 130 return url.Scheme, host, nil 131 } 132 133 return "", "", nil 134 } 135 136 func parseFacility(facility string) (syslog.Priority, error) { 137 if facility == "" { 138 return syslog.LOG_DAEMON, nil 139 } 140 141 if syslogFacility, valid := facilities[facility]; valid { 142 return syslogFacility, nil 143 } 144 145 fInt, err := strconv.Atoi(facility) 146 if err == nil && 0 <= fInt && fInt <= 23 { 147 return syslog.Priority(fInt << 3), nil 148 } 149 150 return syslog.Priority(0), errors.New("invalid syslog facility") 151 }