@@ -2,6 +2,7 @@ package syslog
2
2
3
3
import (
4
4
"bytes"
5
+ "crypto/tls"
5
6
"errors"
6
7
"fmt"
7
8
"io/ioutil"
@@ -19,14 +20,25 @@ import (
19
20
"github.com/gliderlabs/logspout/router"
20
21
)
21
22
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
+ )
23
31
24
32
var (
25
33
hostname string
26
34
retryCount uint
35
+ tcpFraming TCPFraming
27
36
econnResetErrStr string
28
37
)
29
38
39
+ // TCPFraming represents the type of framing to use for syslog messages
40
+ type TCPFraming string
41
+
30
42
func init () {
31
43
hostname , _ = os .Hostname ()
32
44
econnResetErrStr = fmt .Sprintf ("write: %s" , syscall .ECONNRESET .Error ())
@@ -89,6 +101,12 @@ func NewSyslogAdapter(route *router.Route) (router.LogAdapter, error) {
89
101
structuredData = fmt .Sprintf ("[%s]" , structuredData )
90
102
}
91
103
104
+ if isTCPConnecion (conn ) {
105
+ if err = setTCPFraming (); err != nil {
106
+ return nil , err
107
+ }
108
+ }
109
+
92
110
var tmplStr string
93
111
switch format {
94
112
case "rfc5424" :
@@ -120,6 +138,19 @@ func NewSyslogAdapter(route *router.Route) (router.LogAdapter, error) {
120
138
}, nil
121
139
}
122
140
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
+
123
154
// Adapter streams log output to a connection in the Syslog format
124
155
type Adapter struct {
125
156
conn net.Conn
@@ -137,6 +168,19 @@ func (a *Adapter) Stream(logstream chan *router.Message) {
137
168
log .Println ("syslog:" , err )
138
169
return
139
170
}
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
+
140
184
if _ , err = a .conn .Write (buf ); err != nil {
141
185
log .Println ("syslog:" , err )
142
186
switch a .conn .(type ) {
@@ -226,6 +270,17 @@ func retryExp(fun func() error, tries uint) error {
226
270
}
227
271
}
228
272
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
+
229
284
// Message extends router.Message for the syslog standard
230
285
type Message struct {
231
286
* router.Message
0 commit comments