forked from golang/glog
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathglog_logstash.go
96 lines (83 loc) · 2.98 KB
/
glog_logstash.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/
//
// Modifications copyright 2013 Ernest Micklei. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package glog
import (
"bytes"
"encoding/json"
"flag"
"io"
"os"
)
// ExtraFields contains a set of @fields elements that can be used by the application
// to pass appliction and/or environment specific information.
var ExtraFields = map[string]string{}
// logstash is a logstashPublisher that decodes each glog data,
// encodes it into JSON and writes it to an io.Writer.
var logstash logstashPublisher
// Set the io.Writer to write JSON. This is required if -logstash=true
func SetLogstashWriter(writer io.Writer) {
logstash.writer = newBufferedWriter(writer)
}
func init() {
flag.BoolVar(&logstash.toLogstash, "logstash", false, "log also in JSON using the Logstash writer")
// Write to Stderr until SetLogstashWriter is called so we do not loose events.
SetLogstashWriter(os.Stderr)
}
// logstashPublisher holds global state for publishing messages in JSON.
type logstashPublisher struct {
toLogstash bool // The -logstash flag.
writer *bufferedWriter // Buffered target writer for JSON messages.
}
// WriteWithStack decodes the data and writes a logstash json event
func (p logstashPublisher) WriteWithStack(data []byte, stack []byte) {
buffer := new(bytes.Buffer)
glogJSON{writer: buffer, encoder: json.NewEncoder(buffer)}.WriteWithStack(data, stack)
p.writer.Write(buffer.Bytes())
}
// flush waits until all pending messages are written by the asyncWriter.
func (p logstashPublisher) flush() {
if p.writer != nil { // be robust
p.writer.flush()
}
}
// bufferedWriter collects []byte until a flush.
type bufferedWriter struct {
buffer [][]byte
writer io.Writer
}
// newBufferedWriter decorates the underlyingWriter.
func newBufferedWriter(underlyingWriter io.Writer) *bufferedWriter {
bw := new(bufferedWriter)
bw.buffer = [][]byte{}
bw.writer = underlyingWriter
return bw
}
// Write is for implementing io.Writer
func (b *bufferedWriter) Write(data []byte) (n int, err error) {
b.buffer = append(b.buffer, data)
return len(data), nil
}
// flush drains the buffer. it is called from the daemon goroutine.
func (b *bufferedWriter) flush() {
for _, each := range b.buffer {
_, err := b.writer.Write(each)
if err != nil {
os.Stderr.WriteString("[glog error] unable to flush buffered logstash message:\n")
os.Stderr.WriteString(string(each))
}
}
b.buffer = [][]byte{}
}