github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/syslog/syslog.go (about) 1 package syslog 2 3 import ( 4 "crypto/tls" 5 "crypto/x509" 6 "errors" 7 "fmt" 8 "io/ioutil" 9 "strings" 10 "sync" 11 "time" 12 13 sl "github.com/racksec/srslog" 14 ) 15 16 const rfc5424time = "2006-01-02T15:04:05.999999Z07:00" 17 const priority = sl.LOG_USER | sl.LOG_INFO 18 19 type Syslog struct { 20 writer *sl.Writer 21 closed bool 22 23 mu sync.RWMutex 24 } 25 26 func Dial(transport, address string, caCerts []string) (*Syslog, error) { 27 var ( 28 syslog *sl.Writer 29 config *tls.Config = nil 30 ) 31 32 if transport == "tls" { 33 certpool, err := x509.SystemCertPool() 34 if err != nil { 35 return nil, err 36 } 37 38 for _, cert := range caCerts { 39 content, err := ioutil.ReadFile(cert) 40 if err != nil { 41 return nil, err 42 } 43 44 ok := certpool.AppendCertsFromPEM(content) 45 if !ok { 46 return nil, errors.New("syslog drainer certificate error") 47 } 48 } 49 // srslog uses "tcp+tls" to specify "tls" connections 50 transport = "tcp+tls" 51 52 config = &tls.Config{ 53 RootCAs: certpool, 54 } 55 } 56 57 syslog, err := sl.DialWithTLSConfig(transport, address, priority, "", config) 58 if err != nil { 59 return nil, err 60 } 61 62 return &Syslog{ 63 writer: syslog, 64 closed: false, 65 }, nil 66 } 67 68 func (s *Syslog) Write(hostname, tag string, ts time.Time, msg string) error { 69 s.mu.RLock() 70 defer s.mu.RUnlock() 71 if s.writer == nil { 72 return errors.New("connection already closed") 73 } 74 75 s.writer.SetFormatter(getSyslogFormatter(hostname, ts, tag)) 76 _, err := s.writer.Write([]byte(msg)) 77 return err 78 } 79 80 func (s *Syslog) Close() error { 81 s.mu.Lock() 82 defer s.mu.Unlock() 83 84 if s.writer == nil { 85 return errors.New("connection already closed") 86 } 87 88 err := s.writer.Close() 89 if err == nil { 90 s.writer = nil 91 } 92 93 return err 94 } 95 96 // generate custom formatter based on hostname and tag 97 func getSyslogFormatter(hostname string, ts time.Time, tag string) sl.Formatter { 98 return func(priority sl.Priority, _, _, content string) string { 99 // strip whitespaces 100 s := strings.Replace(content, "\n", " ", -1) 101 s = strings.Replace(s, "\r", " ", -1) 102 s = strings.Replace(s, "\x00", " ", -1) 103 104 msg := fmt.Sprintf("<%d>1 %s %s %s - - - %s\n", 105 priority, ts.Format(rfc5424time), hostname, tag, s) 106 return msg 107 } 108 }