blob: 426603ef305c73d54d5d5077184ff2ba89d83fb8 [file] [log] [blame]
divyadesai81bb7ba2020-03-11 11:45:23 +00001// Copyright 2015 CoreOS, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package capnslog
16
17import (
18 "bufio"
19 "bytes"
20 "io"
21 "os"
22 "runtime"
23 "strconv"
24 "strings"
25 "time"
26)
27
28var pid = os.Getpid()
29
30type GlogFormatter struct {
31 StringFormatter
32}
33
34func NewGlogFormatter(w io.Writer) *GlogFormatter {
35 g := &GlogFormatter{}
36 g.w = bufio.NewWriter(w)
37 return g
38}
39
40func (g GlogFormatter) Format(pkg string, level LogLevel, depth int, entries ...interface{}) {
41 g.w.Write(GlogHeader(level, depth+1))
42 g.StringFormatter.Format(pkg, level, depth+1, entries...)
43}
44
45func GlogHeader(level LogLevel, depth int) []byte {
46 // Lmmdd hh:mm:ss.uuuuuu threadid file:line]
47 now := time.Now().UTC()
48 _, file, line, ok := runtime.Caller(depth) // It's always the same number of frames to the user's call.
49 if !ok {
50 file = "???"
51 line = 1
52 } else {
53 slash := strings.LastIndex(file, "/")
54 if slash >= 0 {
55 file = file[slash+1:]
56 }
57 }
58 if line < 0 {
59 line = 0 // not a real line number
60 }
61 buf := &bytes.Buffer{}
62 buf.Grow(30)
63 _, month, day := now.Date()
64 hour, minute, second := now.Clock()
65 buf.WriteString(level.Char())
66 twoDigits(buf, int(month))
67 twoDigits(buf, day)
68 buf.WriteByte(' ')
69 twoDigits(buf, hour)
70 buf.WriteByte(':')
71 twoDigits(buf, minute)
72 buf.WriteByte(':')
73 twoDigits(buf, second)
74 buf.WriteByte('.')
75 buf.WriteString(strconv.Itoa(now.Nanosecond() / 1000))
76 buf.WriteByte('Z')
77 buf.WriteByte(' ')
78 buf.WriteString(strconv.Itoa(pid))
79 buf.WriteByte(' ')
80 buf.WriteString(file)
81 buf.WriteByte(':')
82 buf.WriteString(strconv.Itoa(line))
83 buf.WriteByte(']')
84 buf.WriteByte(' ')
85 return buf.Bytes()
86}
87
88const digits = "0123456789"
89
90func twoDigits(b *bytes.Buffer, d int) {
91 c2 := digits[d%10]
92 d /= 10
93 c1 := digits[d%10]
94 b.WriteByte(c1)
95 b.WriteByte(c2)
96}