@@ -2,6 +2,7 @@ package syslog
22
33import (
44 "bytes"
5+ "crypto/tls"
56 "errors"
67 "fmt"
78 "io/ioutil"
@@ -19,14 +20,25 @@ import (
1920 "github.com/gliderlabs/logspout/router"
2021)
2122
22- const defaultRetryCount = 10
23+ const (
24+ // TraditionalTCPFraming is the traditional LF framing of syslog messages on the wire
25+ TraditionalTCPFraming TCPFraming = "traditional"
26+ // OctetCountedTCPFraming prepends the size of each message before the message. https://tools.ietf.org/html/rfc6587#section-3.4.1
27+ OctetCountedTCPFraming TCPFraming = "octet-counted"
28+
29+ defaultRetryCount = 10
30+ )
2331
2432var (
2533 hostname string
2634 retryCount uint
35+ tcpFraming TCPFraming
2736 econnResetErrStr string
2837)
2938
39+ // TCPFraming represents the type of framing to use for syslog messages
40+ type TCPFraming string
41+
3042func init () {
3143 hostname , _ = os .Hostname ()
3244 econnResetErrStr = fmt .Sprintf ("write: %s" , syscall .ECONNRESET .Error ())
@@ -89,6 +101,12 @@ func NewSyslogAdapter(route *router.Route) (router.LogAdapter, error) {
89101 structuredData = fmt .Sprintf ("[%s]" , structuredData )
90102 }
91103
104+ if isTCPConnecion (conn ) {
105+ if err = setTCPFraming (); err != nil {
106+ return nil , err
107+ }
108+ }
109+
92110 var tmplStr string
93111 switch format {
94112 case "rfc5424" :
@@ -120,6 +138,19 @@ func NewSyslogAdapter(route *router.Route) (router.LogAdapter, error) {
120138 }, nil
121139}
122140
141+ func setTCPFraming () error {
142+ switch s := cfg .GetEnvDefault ("SYSLOG_TCP_FRAMING" , "traditional" ); s {
143+ case "traditional" :
144+ tcpFraming = TraditionalTCPFraming
145+ return nil
146+ case "octet-counted" :
147+ tcpFraming = OctetCountedTCPFraming
148+ return nil
149+ default :
150+ return fmt .Errorf ("unknown SYSLOG_TCP_FRAMING value: %s" , s )
151+ }
152+ }
153+
123154// Adapter streams log output to a connection in the Syslog format
124155type Adapter struct {
125156 conn net.Conn
@@ -137,6 +168,19 @@ func (a *Adapter) Stream(logstream chan *router.Message) {
137168 log .Println ("syslog:" , err )
138169 return
139170 }
171+
172+ if isTCPConnecion (a .conn ) {
173+ switch tcpFraming {
174+ case OctetCountedTCPFraming :
175+ buf = append ([]byte (fmt .Sprintf ("%d " , len (buf ))), buf ... )
176+ case TraditionalTCPFraming :
177+ // leave as-is
178+ default :
179+ // should never get here, validated above
180+ panic ("unknown framing format: " + tcpFraming )
181+ }
182+ }
183+
140184 if _ , err = a .conn .Write (buf ); err != nil {
141185 log .Println ("syslog:" , err )
142186 switch a .conn .(type ) {
@@ -226,6 +270,17 @@ func retryExp(fun func() error, tries uint) error {
226270 }
227271}
228272
273+ func isTCPConnecion (conn net.Conn ) bool {
274+ switch conn .(type ) {
275+ case * net.TCPConn :
276+ return true
277+ case * tls.Conn :
278+ return true
279+ default :
280+ return false
281+ }
282+ }
283+
229284// Message extends router.Message for the syslog standard
230285type Message struct {
231286 * router.Message
0 commit comments