blob: b305a845fb2bf185eaadb101c0d443e1b49313ef [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 "fmt"
20 "io"
21 "log"
22 "runtime"
23 "strings"
24 "time"
25)
26
27type Formatter interface {
28 Format(pkg string, level LogLevel, depth int, entries ...interface{})
29 Flush()
30}
31
32func NewStringFormatter(w io.Writer) Formatter {
33 return &StringFormatter{
34 w: bufio.NewWriter(w),
35 }
36}
37
38type StringFormatter struct {
39 w *bufio.Writer
40}
41
42func (s *StringFormatter) Format(pkg string, l LogLevel, i int, entries ...interface{}) {
43 now := time.Now().UTC()
44 s.w.WriteString(now.Format(time.RFC3339))
45 s.w.WriteByte(' ')
46 writeEntries(s.w, pkg, l, i, entries...)
47 s.Flush()
48}
49
50func writeEntries(w *bufio.Writer, pkg string, _ LogLevel, _ int, entries ...interface{}) {
51 if pkg != "" {
52 w.WriteString(pkg + ": ")
53 }
54 str := fmt.Sprint(entries...)
55 endsInNL := strings.HasSuffix(str, "\n")
56 w.WriteString(str)
57 if !endsInNL {
58 w.WriteString("\n")
59 }
60}
61
62func (s *StringFormatter) Flush() {
63 s.w.Flush()
64}
65
66func NewPrettyFormatter(w io.Writer, debug bool) Formatter {
67 return &PrettyFormatter{
68 w: bufio.NewWriter(w),
69 debug: debug,
70 }
71}
72
73type PrettyFormatter struct {
74 w *bufio.Writer
75 debug bool
76}
77
78func (c *PrettyFormatter) Format(pkg string, l LogLevel, depth int, entries ...interface{}) {
79 now := time.Now()
80 ts := now.Format("2006-01-02 15:04:05")
81 c.w.WriteString(ts)
82 ms := now.Nanosecond() / 1000
83 c.w.WriteString(fmt.Sprintf(".%06d", ms))
84 if c.debug {
85 _, file, line, ok := runtime.Caller(depth) // It's always the same number of frames to the user's call.
86 if !ok {
87 file = "???"
88 line = 1
89 } else {
90 slash := strings.LastIndex(file, "/")
91 if slash >= 0 {
92 file = file[slash+1:]
93 }
94 }
95 if line < 0 {
96 line = 0 // not a real line number
97 }
98 c.w.WriteString(fmt.Sprintf(" [%s:%d]", file, line))
99 }
100 c.w.WriteString(fmt.Sprint(" ", l.Char(), " | "))
101 writeEntries(c.w, pkg, l, depth, entries...)
102 c.Flush()
103}
104
105func (c *PrettyFormatter) Flush() {
106 c.w.Flush()
107}
108
109// LogFormatter emulates the form of the traditional built-in logger.
110type LogFormatter struct {
111 logger *log.Logger
112 prefix string
113}
114
115// NewLogFormatter is a helper to produce a new LogFormatter struct. It uses the
116// golang log package to actually do the logging work so that logs look similar.
117func NewLogFormatter(w io.Writer, prefix string, flag int) Formatter {
118 return &LogFormatter{
119 logger: log.New(w, "", flag), // don't use prefix here
120 prefix: prefix, // save it instead
121 }
122}
123
124// Format builds a log message for the LogFormatter. The LogLevel is ignored.
125func (lf *LogFormatter) Format(pkg string, _ LogLevel, _ int, entries ...interface{}) {
126 str := fmt.Sprint(entries...)
127 prefix := lf.prefix
128 if pkg != "" {
129 prefix = fmt.Sprintf("%s%s: ", prefix, pkg)
130 }
131 lf.logger.Output(5, fmt.Sprintf("%s%v", prefix, str)) // call depth is 5
132}
133
134// Flush is included so that the interface is complete, but is a no-op.
135func (lf *LogFormatter) Flush() {
136 // noop
137}
138
139// NilFormatter is a no-op log formatter that does nothing.
140type NilFormatter struct {
141}
142
143// NewNilFormatter is a helper to produce a new LogFormatter struct. It logs no
144// messages so that you can cause part of your logging to be silent.
145func NewNilFormatter() Formatter {
146 return &NilFormatter{}
147}
148
149// Format does nothing.
150func (_ *NilFormatter) Format(_ string, _ LogLevel, _ int, _ ...interface{}) {
151 // noop
152}
153
154// Flush is included so that the interface is complete, but is a no-op.
155func (_ *NilFormatter) Flush() {
156 // noop
157}