@@ -41,6 +41,7 @@ type CompressType int
4141const (
4242 CompressGzip CompressType = iota
4343 CompressZlib
44+ CompressNone
4445)
4546
4647// Message represents the contents of the GELF message. It is gzipped
@@ -49,15 +50,14 @@ type Message struct {
4950 Version string `json:"version"`
5051 Host string `json:"host"`
5152 Short string `json:"short_message"`
52- Full string `json:"full_message"`
53+ Full string `json:"full_message,omitempty "`
5354 TimeUnix float64 `json:"timestamp"`
54- Level int32 `json:"level"`
55- Facility string `json:"facility"`
55+ Level int32 `json:"level,omitempty "`
56+ Facility string `json:"facility,omitempty "`
5657 Extra map [string ]interface {} `json:"-"`
58+ RawExtra json.RawMessage `json:"-"`
5759}
5860
59- type innerMessage Message //against circular (Un)MarshalJSON
60-
6161// Used to control GELF chunking. Should be less than (MTU - len(UDP
6262// header)).
6363//
@@ -76,14 +76,14 @@ var (
7676
7777// Syslog severity levels
7878const (
79- LOG_EMERG = int32 (0 )
80- LOG_ALERT = int32 (1 )
81- LOG_CRIT = int32 (2 )
82- LOG_ERR = int32 (3 )
83- LOG_WARNING = int32 (4 )
84- LOG_NOTICE = int32 (5 )
85- LOG_INFO = int32 (6 )
86- LOG_DEBUG = int32 (7 )
79+ LOG_EMERG = int32 (0 )
80+ LOG_ALERT = int32 (1 )
81+ LOG_CRIT = int32 (2 )
82+ LOG_ERR = int32 (3 )
83+ LOG_WARNING = int32 (4 )
84+ LOG_NOTICE = int32 (5 )
85+ LOG_INFO = int32 (6 )
86+ LOG_DEBUG = int32 (7 )
8787)
8888
8989// numChunks returns the number of GELF chunks necessary to transmit
@@ -176,40 +176,70 @@ func (w *Writer) writeChunked(zBytes []byte) (err error) {
176176 return nil
177177}
178178
179+ // 1k bytes buffer by default
180+ var bufPool = sync.Pool {
181+ New : func () interface {} {
182+ return bytes .NewBuffer (make ([]byte , 0 , 1024 ))
183+ },
184+ }
185+
186+ func newBuffer () * bytes.Buffer {
187+ b := bufPool .Get ().(* bytes.Buffer )
188+ if b != nil {
189+ b .Reset ()
190+ return b
191+ }
192+ return bytes .NewBuffer (nil )
193+ }
194+
179195// WriteMessage sends the specified message to the GELF server
180196// specified in the call to New(). It assumes all the fields are
181197// filled out appropriately. In general, clients will want to use
182198// Write, rather than WriteMessage.
183199func (w * Writer ) WriteMessage (m * Message ) (err error ) {
184- mBytes , err := json .Marshal (m )
185- if err != nil {
186- return
200+ mBuf := newBuffer ()
201+ defer bufPool .Put (mBuf )
202+ if err = m .MarshalJSONBuf (mBuf ); err != nil {
203+ return err
187204 }
205+ mBytes := mBuf .Bytes ()
206+
207+ var (
208+ zBuf * bytes.Buffer
209+ zBytes []byte
210+ )
188211
189- var zBuf bytes.Buffer
190212 var zw io.WriteCloser
191213 switch w .CompressionType {
192214 case CompressGzip :
193- zw , err = gzip .NewWriterLevel (& zBuf , w .CompressionLevel )
215+ zBuf = newBuffer ()
216+ defer bufPool .Put (zBuf )
217+ zw , err = gzip .NewWriterLevel (zBuf , w .CompressionLevel )
194218 case CompressZlib :
195- zw , err = zlib .NewWriterLevel (& zBuf , w .CompressionLevel )
219+ zBuf = newBuffer ()
220+ defer bufPool .Put (zBuf )
221+ zw , err = zlib .NewWriterLevel (zBuf , w .CompressionLevel )
222+ case CompressNone :
223+ zBytes = mBytes
196224 default :
197225 panic (fmt .Sprintf ("unknown compression type %d" ,
198226 w .CompressionType ))
199227 }
200- if err != nil {
201- return
202- }
203- if _ , err = zw .Write (mBytes ); err != nil {
204- return
228+ if zw != nil {
229+ if err != nil {
230+ return
231+ }
232+ if _ , err = zw .Write (mBytes ); err != nil {
233+ zw .Close ()
234+ return
235+ }
236+ zw .Close ()
237+ zBytes = zBuf .Bytes ()
205238 }
206- zw .Close ()
207239
208- zBytes := zBuf .Bytes ()
209240 if numChunks (zBytes ) > 1 {
210241 return w .writeChunked (zBytes )
211242 }
212-
213243 n , err := w .conn .Write (zBytes )
214244 if err != nil {
215245 return
@@ -222,8 +252,8 @@ func (w *Writer) WriteMessage(m *Message) (err error) {
222252}
223253
224254// Close connection and interrupt blocked Read or Write operations
225- func (w * Writer ) Close () ( error ) {
226- return w .conn .Close ()
255+ func (w * Writer ) Close () error {
256+ return w .conn .Close ()
227257}
228258
229259/*
@@ -315,28 +345,43 @@ func (w *Writer) Write(p []byte) (n int, err error) {
315345 return len (p ), nil
316346}
317347
318- func (m * Message ) MarshalJSON () ([]byte , error ) {
319- var err error
320- var b , eb []byte
321-
322- extra := m .Extra
323- b , err = json .Marshal ((* innerMessage )(m ))
324- m .Extra = extra
348+ func (m * Message ) MarshalJSONBuf (buf * bytes.Buffer ) error {
349+ b , err := json .Marshal (m )
325350 if err != nil {
326- return nil , err
351+ return err
327352 }
328-
329- if len (extra ) == 0 {
330- return b , nil
353+ // write up until the final }
354+ if _ , err = buf .Write (b [:len (b )- 1 ]); err != nil {
355+ return err
356+ }
357+ if len (m .Extra ) > 0 {
358+ eb , err := json .Marshal (m .Extra )
359+ if err != nil {
360+ return err
361+ }
362+ // merge serialized message + serialized extra map
363+ if err = buf .WriteByte (',' ); err != nil {
364+ return err
365+ }
366+ // write serialized extra bytes, without enclosing quotes
367+ if _ , err = buf .Write (eb [1 : len (eb )- 1 ]); err != nil {
368+ return err
369+ }
331370 }
332371
333- if eb , err = json .Marshal (extra ); err != nil {
334- return nil , err
372+ if len (m .RawExtra ) > 0 {
373+ if err := buf .WriteByte (',' ); err != nil {
374+ return err
375+ }
376+
377+ // write serialized extra bytes, without enclosing quotes
378+ if _ , err = buf .Write (m .RawExtra [1 : len (m .RawExtra )- 1 ]); err != nil {
379+ return err
380+ }
335381 }
336382
337- // merge serialized message + serialized extra map
338- b [len (b )- 1 ] = ','
339- return append (b , eb [1 :len (eb )]... ), nil
383+ // write final closing quotes
384+ return buf .WriteByte ('}' )
340385}
341386
342387func (m * Message ) UnmarshalJSON (data []byte ) error {
0 commit comments