feat: add caller information
This commit is contained in:
parent
6353cb045a
commit
a98708a4a9
4 changed files with 86 additions and 6 deletions
2
entry.go
2
entry.go
|
@ -16,6 +16,7 @@ package golog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@ type Entry struct {
|
||||||
Message string
|
Message string
|
||||||
Level Level
|
Level Level
|
||||||
Time time.Time
|
Time time.Time
|
||||||
|
CallStack []runtime.Frame
|
||||||
}
|
}
|
||||||
|
|
||||||
type Content struct {
|
type Content struct {
|
||||||
|
|
|
@ -16,6 +16,7 @@ package golog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -47,6 +48,13 @@ func (formatter *FormatterJSON) Process(entry *Entry) {
|
||||||
// add message
|
// add message
|
||||||
formatter.data["message"] = entry.Message
|
formatter.data["message"] = entry.Message
|
||||||
|
|
||||||
|
// add call stack
|
||||||
|
if len(entry.CallStack) > 0 {
|
||||||
|
caller := entry.CallStack[0]
|
||||||
|
formatter.data["file"] = fmt.Sprintf("%s:%d", caller.File, caller.Line)
|
||||||
|
formatter.data["function"] = caller.Function
|
||||||
|
}
|
||||||
|
|
||||||
// add additional fields
|
// add additional fields
|
||||||
if formatter.FlatContent {
|
if formatter.FlatContent {
|
||||||
for _, content := range entry.Content {
|
for _, content := range entry.Content {
|
||||||
|
|
|
@ -47,6 +47,13 @@ func (formatter *FormatterKeyValue) Process(entry *Entry) {
|
||||||
// add message
|
// add message
|
||||||
formatter.addKV("message", entry.Message)
|
formatter.addKV("message", entry.Message)
|
||||||
|
|
||||||
|
// add call stack
|
||||||
|
if len(entry.CallStack) > 0 {
|
||||||
|
caller := entry.CallStack[0]
|
||||||
|
formatter.addKV("file", fmt.Sprintf("%s:%d", caller.File, caller.Line))
|
||||||
|
formatter.addKV("function", caller.Function)
|
||||||
|
}
|
||||||
|
|
||||||
// add additional fields
|
// add additional fields
|
||||||
for _, content := range entry.Content {
|
for _, content := range entry.Content {
|
||||||
formatter.addKV(content.Key, content.Value)
|
formatter.addKV(content.Key, content.Value)
|
||||||
|
|
65
logger.go
65
logger.go
|
@ -14,10 +14,17 @@
|
||||||
|
|
||||||
package golog
|
package golog
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"log"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
var Default = NewLoggerDefault()
|
var Default = NewLoggerDefault()
|
||||||
|
|
||||||
|
const maxCallersPCs = 20
|
||||||
|
|
||||||
type Logger struct {
|
type Logger struct {
|
||||||
Outputs []*Output
|
Outputs []*Output
|
||||||
}
|
}
|
||||||
|
@ -36,12 +43,68 @@ func (logger *Logger) LogEntry(entry *Entry) {
|
||||||
// set execution time
|
// set execution time
|
||||||
entry.Time = time.Now()
|
entry.Time = time.Now()
|
||||||
|
|
||||||
|
// set call stack
|
||||||
|
entry.CallStack = logger.callStack()
|
||||||
|
|
||||||
// run each output
|
// run each output
|
||||||
for _, output := range logger.Outputs {
|
for _, output := range logger.Outputs {
|
||||||
output.Send(entry)
|
output.Send(entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (logger *Logger) callStack() (response []runtime.Frame) {
|
||||||
|
// get call stack
|
||||||
|
pcs := make([]uintptr, maxCallersPCs)
|
||||||
|
runtime.Callers(1, pcs)
|
||||||
|
frames := runtime.CallersFrames(pcs)
|
||||||
|
|
||||||
|
var self string
|
||||||
|
for {
|
||||||
|
// check for next frame
|
||||||
|
frame, more := frames.Next()
|
||||||
|
if !more {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract self package
|
||||||
|
if self == "" {
|
||||||
|
self = logger.framePackage(frame)
|
||||||
|
log.Println("self:", self, frame.Function) // TODO: remove
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore self
|
||||||
|
currentPackage := logger.framePackage(frame)
|
||||||
|
log.Println("package:", currentPackage, frame.Function) // TODO: remove
|
||||||
|
if currentPackage != self {
|
||||||
|
response = append(response, frame)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (logger *Logger) framePackage(frame runtime.Frame) string {
|
||||||
|
s := frame.Function
|
||||||
|
|
||||||
|
// special handling, if no full qualified package exists
|
||||||
|
lastSlash := strings.LastIndexByte(s, '/')
|
||||||
|
if lastSlash == -1 {
|
||||||
|
firstDot := strings.IndexByte(s, '.')
|
||||||
|
if firstDot == -1 {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return s[:firstDot]
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract package
|
||||||
|
firstDot := strings.IndexByte(s[:lastSlash], '.')
|
||||||
|
if firstDot == -1 {
|
||||||
|
return s[:lastSlash]
|
||||||
|
}
|
||||||
|
return s[:lastSlash+firstDot]
|
||||||
|
}
|
||||||
|
|
||||||
func (logger *Logger) Log(level Level, args ...any) {
|
func (logger *Logger) Log(level Level, args ...any) {
|
||||||
entry := NewEntry(logger)
|
entry := NewEntry(logger)
|
||||||
entry.Log(level, args...)
|
entry.Log(level, args...)
|
||||||
|
|
Loading…
Add table
Reference in a new issue