Skip to content

Commit 5cd6bc4

Browse files
committed
Add caller to log messages; start changelog
1 parent a365ffb commit 5cd6bc4

3 files changed

Lines changed: 72 additions & 15 deletions

File tree

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Changelog
2+
All notable changes to this project will be documented in this file.
3+
4+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6+
7+
## [Unreleased]
8+
9+
These are changes that will probably be included in the next release.
10+
11+
### Added
12+
* New AddCaller and CallerSkip options to add caller information to log messages
13+
14+
### Fixed
15+
16+
### Changed
17+
18+
### Removed
19+
20+
## [v0.1.0] - 2020-07-31
21+
22+
Initial release

examples/example.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ func main() {
2323
opts := logfmtr.DefaultOptions()
2424
opts.Humanize = true
2525
opts.Colorize = true
26+
opts.CallerSkip = 0
2627
demo(logfmtr.NewWithOptions(opts))
2728
}
2829

@@ -33,5 +34,4 @@ func demo(base logr.Logger) {
3334
log.V(1).V(1).Info("you should NOT see this")
3435
log.Error(nil, "uh oh", "trouble", true, "reasons", []float64{0.1, 0.11, 3.14})
3536
log.Error(fmt.Errorf("an error occurred"), "goodbye", "code", -1)
36-
3737
}

logfmtr.go

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"fmt"
66
"io"
77
"os"
8+
"path"
9+
"runtime"
810
"strconv"
911
"strings"
1012
"sync/atomic"
@@ -35,11 +37,13 @@ func NewWithOptions(opts Options) *Logger {
3537
panic("logger was supplied with nil writer")
3638
}
3739
l := &Logger{
38-
w: opts.Writer,
39-
humanize: opts.Humanize,
40-
tsFormat: opts.TimestampFormat,
41-
nameDelim: opts.NameDelim,
42-
colorize: opts.Colorize && opts.Humanize,
40+
w: opts.Writer,
41+
humanize: opts.Humanize,
42+
tsFormat: opts.TimestampFormat,
43+
nameDelim: opts.NameDelim,
44+
colorize: opts.Colorize && opts.Humanize,
45+
addCaller: opts.AddCaller,
46+
callerSkip: opts.CallerSkip,
4347
}
4448
return l
4549
}
@@ -71,21 +75,30 @@ type Options struct {
7175

7276
// NameDelim is the delimiter character used when appending names of loggers.
7377
NameDelim string
78+
79+
// AddCaller indicates that log messages should include the file and line number of the caller of the logger.
80+
AddCaller bool
81+
82+
// CallerSkip adds frames to skip when determing the caller of the logger. Useful when the logger is wrapped
83+
// by another logger.
84+
CallerSkip int
7485
}
7586

7687
var _ logr.Logger = (*Logger)(nil)
7788

7889
// Logger is a logger that writes messages in the logfmt style.
7990
// See https://www.brandur.org/logfmt for more information.
8091
type Logger struct {
81-
w io.Writer
82-
level int
83-
name string
84-
values string
85-
humanize bool
86-
tsFormat string
87-
nameDelim string
88-
colorize bool
92+
w io.Writer
93+
level int
94+
name string
95+
values string
96+
humanize bool
97+
tsFormat string
98+
nameDelim string
99+
colorize bool
100+
addCaller bool
101+
callerSkip int
89102
}
90103

91104
// Enabled repoorts whether this Logger is enabled with respect to the current global log level.
@@ -125,6 +138,12 @@ func (l *Logger) write(humanprefix, msg string, values string, extras ...interfa
125138
b.WriteString("=")
126139
b.WriteString(l.name)
127140
}
141+
if l.addCaller {
142+
b.WriteRune(' ')
143+
b.WriteString(l.key("caller"))
144+
b.WriteString("=")
145+
b.WriteString(l.caller(2))
146+
}
128147
} else {
129148
b.WriteString("level=")
130149
b.WriteString(strconv.Itoa(l.level))
@@ -141,11 +160,17 @@ func (l *Logger) write(humanprefix, msg string, values string, extras ...interfa
141160
b.WriteString("ts=")
142161
b.WriteString(quote(time.Now().UTC().Format(l.tsFormat)))
143162
}
163+
if l.addCaller {
164+
b.WriteRune(' ')
165+
b.WriteString("caller=")
166+
b.WriteString(l.caller(2))
167+
}
144168
}
145169
if len(extras) > 0 {
146170
b.WriteRune(' ')
147171
b.WriteString(l.flatten(extras...))
148172
}
173+
149174
if l.values != "" {
150175
b.WriteRune(' ')
151176
b.WriteString(l.values)
@@ -158,6 +183,16 @@ func (l *Logger) write(humanprefix, msg string, values string, extras ...interfa
158183
l.w.Write(b.Bytes())
159184
}
160185

186+
func (l *Logger) caller(skip int) string {
187+
for i := 1; i < 3; i++ {
188+
_, file, line, ok := runtime.Caller(skip + l.callerSkip + i)
189+
if ok && file != "<autogenerated>" {
190+
return path.Base(file) + ":" + strconv.Itoa(line)
191+
}
192+
}
193+
return "unknown"
194+
}
195+
161196
// V returns a logger for a specific verbosity level, relative to this Logger.
162197
func (l *Logger) V(level int) logr.Logger {
163198
l2 := *l
@@ -245,7 +280,7 @@ func stringify(v interface{}) string {
245280
}
246281

247282
func quote(s string) string {
248-
if strings.ContainsAny(s, " .") {
283+
if strings.ContainsAny(s, " ") {
249284
return fmt.Sprintf("%q", s)
250285
}
251286
return s

0 commit comments

Comments
 (0)