mirror of https://github.com/sirupsen/logrus.git
Merge branch 'master' of https://github.com/dclendenan/logrus
This commit is contained in:
commit
40f571805d
|
@ -1,6 +1,7 @@
|
||||||
# 1.0.4
|
# 1.0.4
|
||||||
|
|
||||||
* feature: Add optional logging of caller method
|
* Add optional logging of caller method
|
||||||
|
|
||||||
# 1.0.3
|
# 1.0.3
|
||||||
|
|
||||||
* Replace example files with testable examples
|
* Replace example files with testable examples
|
||||||
|
|
|
@ -66,6 +66,8 @@ To ensure this behaviour even if a TTY is attached, set your formatter as follow
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Logging Method Name
|
||||||
|
|
||||||
If you wish to add the calling method as a field, instruct the logger via:
|
If you wish to add the calling method as a field, instruct the logger via:
|
||||||
```go
|
```go
|
||||||
log.SetReportCaller(true)
|
log.SetReportCaller(true)
|
||||||
|
@ -73,14 +75,14 @@ log.SetReportCaller(true)
|
||||||
This adds the caller as 'method' like so:
|
This adds the caller as 'method' like so:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{"animal":"penguin","level":"fatal","method":"arcticcreatures.migrate","msg":"a penguin swims by",
|
{"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by",
|
||||||
"time":"2014-03-10 19:57:38.562543129 -0400 EDT"}
|
"time":"2014-03-10 19:57:38.562543129 -0400 EDT"}
|
||||||
```
|
```
|
||||||
|
|
||||||
```text
|
```text
|
||||||
time="2015-03-26T01:27:38-04:00" level=fatal method=arcticcreatures.migrate msg="a penguin swims by" animal=penguin
|
time="2015-03-26T01:27:38-04:00" level=fatal method=github.com/sirupsen/arcticcreatures.migrate msg="a penguin swims by" animal=penguin
|
||||||
```
|
```
|
||||||
Note that this does add measurable overhead - the cost will depend on the of Go, but is
|
Note that this does add measurable overhead - the cost will depend on the version of Go, but is
|
||||||
between 20 and 40% in recent tests with 1.6 and 1.7. You can validate this in your
|
between 20 and 40% in recent tests with 1.6 and 1.7. You can validate this in your
|
||||||
environment via benchmarks:
|
environment via benchmarks:
|
||||||
```
|
```
|
||||||
|
|
8
entry.go
8
entry.go
|
@ -13,7 +13,7 @@ import (
|
||||||
var bufferPool *sync.Pool
|
var bufferPool *sync.Pool
|
||||||
|
|
||||||
// qualified package name, cached at first use
|
// qualified package name, cached at first use
|
||||||
var logrusPackage string
|
var LogrusPackage string
|
||||||
|
|
||||||
// Positions in the call stack when tracing to report the calling method
|
// Positions in the call stack when tracing to report the calling method
|
||||||
var minimumCallerDepth int
|
var minimumCallerDepth int
|
||||||
|
@ -126,8 +126,8 @@ func getCaller() (method string) {
|
||||||
depth := runtime.Callers(minimumCallerDepth, pcs)
|
depth := runtime.Callers(minimumCallerDepth, pcs)
|
||||||
|
|
||||||
// cache this package's fully-qualified name
|
// cache this package's fully-qualified name
|
||||||
if logrusPackage == "" {
|
if LogrusPackage == "" {
|
||||||
logrusPackage = getPackageName(runtime.FuncForPC(pcs[0]).Name())
|
LogrusPackage = getPackageName(runtime.FuncForPC(pcs[0]).Name())
|
||||||
|
|
||||||
// now that we have the cache, we can skip a minimum count of known-logrus functions
|
// now that we have the cache, we can skip a minimum count of known-logrus functions
|
||||||
minimumCallerDepth = knownLogrusFrames
|
minimumCallerDepth = knownLogrusFrames
|
||||||
|
@ -138,7 +138,7 @@ func getCaller() (method string) {
|
||||||
pkg := getPackageName(fullFuncName)
|
pkg := getPackageName(fullFuncName)
|
||||||
|
|
||||||
// If the caller isn't part of this package, we're done
|
// If the caller isn't part of this package, we're done
|
||||||
if pkg != logrusPackage {
|
if pkg != LogrusPackage {
|
||||||
return fullFuncName
|
return fullFuncName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
formatter.go
10
formatter.go
|
@ -1,15 +1,9 @@
|
||||||
package logrus
|
package logrus
|
||||||
|
|
||||||
import (
|
import "time"
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
<<<<<<< HEAD
|
// defaultTimestampFormat is YYYY-mm-DDTHH:MM:SS-TZ
|
||||||
// DefaultTimestampFormat is YYYY-mm-DDTHH:MM:SS-TZ
|
|
||||||
const DefaultTimestampFormat = time.RFC3339
|
|
||||||
=======
|
|
||||||
const defaultTimestampFormat = time.RFC3339
|
const defaultTimestampFormat = time.RFC3339
|
||||||
>>>>>>> 89742aefa4b206dcf400792f3bd35b542998eb3b
|
|
||||||
|
|
||||||
// The Formatter interface is used to implement a custom Formatter. It takes an
|
// The Formatter interface is used to implement a custom Formatter. It takes an
|
||||||
// `Entry`. It exposes all the fields, including the default ones:
|
// `Entry`. It exposes all the fields, including the default ones:
|
||||||
|
|
|
@ -40,12 +40,10 @@ type JSONFormatter struct {
|
||||||
// FieldMap: FieldMap{
|
// FieldMap: FieldMap{
|
||||||
// FieldKeyTime: "@timestamp",
|
// FieldKeyTime: "@timestamp",
|
||||||
// FieldKeyLevel: "@level",
|
// FieldKeyLevel: "@level",
|
||||||
<<<<<<< HEAD
|
|
||||||
// FieldKeyMsg: "@message",
|
// FieldKeyMsg: "@message",
|
||||||
// FieldKeyFunc: "@caller",
|
// FieldKeyFunc: "@caller",
|
||||||
=======
|
// FieldKeyMsg: "@message",
|
||||||
// FieldKeyMsg: "@message",
|
// FieldKeyFunc: "@caller",
|
||||||
>>>>>>> 89742aefa4b206dcf400792f3bd35b542998eb3b
|
|
||||||
// },
|
// },
|
||||||
// }
|
// }
|
||||||
FieldMap FieldMap
|
FieldMap FieldMap
|
||||||
|
|
|
@ -59,7 +59,9 @@ func LogAndAssertText(t *testing.T, log func(*Logger), assertions func(fields ma
|
||||||
|
|
||||||
// TestReportCaller verifies that when ReportCaller is set, the 'func' field
|
// TestReportCaller verifies that when ReportCaller is set, the 'func' field
|
||||||
// is added, and when it is unset it is not set or modified
|
// is added, and when it is unset it is not set or modified
|
||||||
func TestReportCaller(t *testing.T) {
|
// Verify that functions within the Logrus package aren't considered when
|
||||||
|
// discovering the caller.
|
||||||
|
func TestReportCallerWhenConfigured(t *testing.T) {
|
||||||
LogAndAssertJSON(t, func(log *Logger) {
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
log.ReportCaller = false
|
log.ReportCaller = false
|
||||||
log.Print("testNoCaller")
|
log.Print("testNoCaller")
|
||||||
|
@ -79,6 +81,51 @@ func TestReportCaller(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func logSomething(t *testing.T, message string) Fields {
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
var fields Fields
|
||||||
|
|
||||||
|
logger := New()
|
||||||
|
logger.Out = &buffer
|
||||||
|
logger.Formatter = new(JSONFormatter)
|
||||||
|
logger.ReportCaller = true
|
||||||
|
|
||||||
|
// override the filter to allow reporting of functions within the logrus package
|
||||||
|
LogrusPackage = "bogusForTesting"
|
||||||
|
|
||||||
|
entry := logger.WithFields(Fields{
|
||||||
|
"foo": "bar",
|
||||||
|
})
|
||||||
|
|
||||||
|
entry.Info(message)
|
||||||
|
|
||||||
|
err := json.Unmarshal(buffer.Bytes(), &fields)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
// now clear the override so as not to mess with other usage
|
||||||
|
LogrusPackage = ""
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestReportCallerHelperDirect - verify reference when logging from a regular function
|
||||||
|
func TestReportCallerHelperDirect(t *testing.T) {
|
||||||
|
fields := logSomething(t, "direct")
|
||||||
|
|
||||||
|
assert.Equal(t, "direct", fields["msg"])
|
||||||
|
assert.Equal(t, "info", fields["level"])
|
||||||
|
assert.Regexp(t, "github.com/.*/logrus.logSomething", fields["func"])
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestReportCallerHelperDirect - verify reference when logging from a function called via pointer
|
||||||
|
func TestReportCallerHelperViaPointer(t *testing.T) {
|
||||||
|
fptr := logSomething
|
||||||
|
fields := fptr(t, "via pointer")
|
||||||
|
|
||||||
|
assert.Equal(t, "via pointer", fields["msg"])
|
||||||
|
assert.Equal(t, "info", fields["level"])
|
||||||
|
assert.Regexp(t, "github.com/.*/logrus.logSomething", fields["func"])
|
||||||
|
}
|
||||||
|
|
||||||
func TestPrint(t *testing.T) {
|
func TestPrint(t *testing.T) {
|
||||||
LogAndAssertJSON(t, func(log *Logger) {
|
LogAndAssertJSON(t, func(log *Logger) {
|
||||||
log.Print("test")
|
log.Print("test")
|
||||||
|
|
|
@ -149,7 +149,7 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.DisableTimestamp {
|
if f.DisableTimestamp {
|
||||||
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m %-44s ", levelColor, levelText, entry.Message)
|
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m%s %-44s ", levelColor, levelText, caller, entry.Message)
|
||||||
} else if !f.FullTimestamp {
|
} else if !f.FullTimestamp {
|
||||||
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d]%s %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), caller, entry.Message)
|
fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d]%s %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), caller, entry.Message)
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue