-
Notifications
You must be signed in to change notification settings - Fork 4
/
file.go
136 lines (120 loc) · 2.83 KB
/
file.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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package file
import (
"bytes"
//"errors"
"log"
//"net"
"os"
//"reflect"
"text/template"
"time"
"strconv"
"github.com/gliderlabs/logspout/router"
)
//
// file route exaple:
// file://sample.log?maxfilesize=102400
//
func init() {
router.AdapterFactories.Register(NewFileAdapter, "file")
}
// NewRawAdapter returns a configured raw.Adapter
func NewFileAdapter(route *router.Route) (router.LogAdapter, error) {
// default log dir
logdir := "/var/log/"
// get 'filename' from route.Address
filename := "default.log"
if route.Address != "" {
filename = route.Address
}
//log.Println("filename [",filename,"]")
tmplStr := "{{.Data}}\n"
tmpl, err := template.New("file").Parse(tmplStr)
if err != nil {
return nil, err
}
// default max size (100Mb)
maxfilesize := 1024*1024*100
if route.Options["maxfilesize"] != "" {
szStr := route.Options["maxfilesize"]
sz, err := strconv.Atoi(szStr)
if err == nil {
maxfilesize = sz
}
}
//log.Println("maxfilesize [",maxfilesize,"]")
a := Adapter{
route: route,
filename: filename,
logdir: logdir,
maxfilesize: maxfilesize,
tmpl: tmpl,
}
// rename if exists, otherwise create it
err = a.Rotate()
if err != nil {
return nil, err
}
return &a, nil
}
// Adapter is a simple adapter that streams log output to a connection without any templating
type Adapter struct {
filename string
logdir string
filesize int
maxfilesize int
fp *os.File
route *router.Route
tmpl *template.Template
}
// Stream sends log data to a connection
func (a *Adapter) Stream(logstream chan *router.Message) {
for message := range logstream {
buf := new(bytes.Buffer)
err := a.tmpl.Execute(buf, message)
if err != nil {
log.Println("err:", err)
return
}
//log.Println("debug:", buf.String())
_, err = a.fp.Write(buf.Bytes())
if err != nil {
log.Println("err:", err)
}
// update file size
a.filesize = a.filesize+len(buf.Bytes())
// rotate file if size exceed max size
if a.filesize > a.maxfilesize {
a.Rotate()
}
}
}
// Perform the actual act of rotating and reopening file.
func (a *Adapter) Rotate() (err error) {
// Close existing file if open
if a.fp != nil {
err = a.fp.Close()
//log.Println("Close existing file pointer")
a.fp = nil
if err != nil {
return err
}
}
// Rename dest file if it already exists
_, err = os.Stat(a.logdir+a.filename)
if err == nil {
err = os.Rename(a.logdir+a.filename, a.logdir+a.filename+"."+time.Now().Format(time.RFC3339))
log.Println("Rename existing log file")
if err != nil {
return err
}
}
// Create new file.
a.fp, err = os.Create(a.logdir+a.filename)
log.Println("Create new log file")
if err != nil {
return err
}
a.filesize = 0
return nil
}