caller: support for caller lib
This commit is contained in:
parent
d02962dc65
commit
aec979048e
61
caller/caller.go
Normal file
61
caller/caller.go
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
package caller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Caller struct {
|
||||||
|
PC uintptr
|
||||||
|
Frame runtime.Frame
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ca Caller) File() string {
|
||||||
|
return ca.Frame.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ca Caller) Line() int {
|
||||||
|
return ca.Frame.Line
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ca Caller) Function() string {
|
||||||
|
return ca.Frame.Function
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ca Caller) ShortFunction() string {
|
||||||
|
split := strings.Split(ca.Frame.Function, string(os.PathSeparator))
|
||||||
|
return split[len(split)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ca Caller) LogValue() slog.Value {
|
||||||
|
if ca.PC == 0 {
|
||||||
|
return slog.AnyValue(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
return slog.GroupValue(
|
||||||
|
slog.String("file", ca.File()),
|
||||||
|
slog.Int("line", ca.Line()),
|
||||||
|
slog.String("function", ca.ShortFunction()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(skip int) Caller {
|
||||||
|
var c Caller
|
||||||
|
pcs := make([]uintptr, 1)
|
||||||
|
n := runtime.Callers(skip, pcs)
|
||||||
|
if n == 0 {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
c.PC = pcs[0]
|
||||||
|
c.Frame, _ = runtime.CallersFrames(pcs).Next()
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func From(pc uintptr) Caller {
|
||||||
|
var c Caller
|
||||||
|
c.PC = pc
|
||||||
|
c.Frame, _ = runtime.CallersFrames([]uintptr{pc}).Next()
|
||||||
|
return c
|
||||||
|
}
|
39
log/log.go
39
log/log.go
|
@ -6,13 +6,13 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5/middleware"
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
"github.com/mattn/go-colorable"
|
"github.com/mattn/go-colorable"
|
||||||
"github.com/mattn/go-isatty"
|
"github.com/mattn/go-isatty"
|
||||||
|
"github.com/tigorlazuardi/redmage/caller"
|
||||||
"github.com/tigorlazuardi/redmage/config"
|
"github.com/tigorlazuardi/redmage/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ func NewHandler(cfg *config.Config) slog.Handler {
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
handler slog.Handler
|
handler slog.Handler
|
||||||
caller uintptr
|
caller caller.Caller
|
||||||
time time.Time
|
time time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,13 +60,13 @@ func Log(ctx context.Context) *Entry {
|
||||||
return &Entry{ctx: ctx, handler: h, time: time.Now()}
|
return &Entry{ctx: ctx, handler: h, time: time.Now()}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Caller(pc uintptr) *Entry {
|
func (entry *Entry) Caller(caller caller.Caller) *Entry {
|
||||||
entry.caller = pc
|
entry.caller = caller
|
||||||
return entry
|
return entry
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Info(message string, fields ...any) {
|
func (entry *Entry) Info(message string, fields ...any) {
|
||||||
record := slog.NewRecord(entry.time, slog.LevelInfo, message, entry.getCaller())
|
record := slog.NewRecord(entry.time, slog.LevelInfo, message, entry.getCaller().PC)
|
||||||
record.AddAttrs(entry.getExtra()...)
|
record.AddAttrs(entry.getExtra()...)
|
||||||
record.AddAttrs(slog.Group("context", fields...))
|
record.AddAttrs(slog.Group("context", fields...))
|
||||||
_ = entry.handler.Handle(entry.ctx, record)
|
_ = entry.handler.Handle(entry.ctx, record)
|
||||||
|
@ -74,13 +74,13 @@ func (entry *Entry) Info(message string, fields ...any) {
|
||||||
|
|
||||||
func (entry *Entry) Infof(format string, args ...any) {
|
func (entry *Entry) Infof(format string, args ...any) {
|
||||||
message := fmt.Sprintf(format, args...)
|
message := fmt.Sprintf(format, args...)
|
||||||
record := slog.NewRecord(entry.time, slog.LevelInfo, message, entry.getCaller())
|
record := slog.NewRecord(entry.time, slog.LevelInfo, message, entry.getCaller().PC)
|
||||||
record.AddAttrs(entry.getExtra()...)
|
record.AddAttrs(entry.getExtra()...)
|
||||||
_ = entry.handler.Handle(entry.ctx, record)
|
_ = entry.handler.Handle(entry.ctx, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Error(message string, fields ...any) {
|
func (entry *Entry) Error(message string, fields ...any) {
|
||||||
record := slog.NewRecord(entry.time, slog.LevelError, message, entry.getCaller())
|
record := slog.NewRecord(entry.time, slog.LevelError, message, entry.getCaller().PC)
|
||||||
record.AddAttrs(entry.getExtra()...)
|
record.AddAttrs(entry.getExtra()...)
|
||||||
record.AddAttrs(slog.Group("context", fields...))
|
record.AddAttrs(slog.Group("context", fields...))
|
||||||
_ = entry.handler.Handle(entry.ctx, record)
|
_ = entry.handler.Handle(entry.ctx, record)
|
||||||
|
@ -88,13 +88,13 @@ func (entry *Entry) Error(message string, fields ...any) {
|
||||||
|
|
||||||
func (entry *Entry) Errorf(format string, args ...any) {
|
func (entry *Entry) Errorf(format string, args ...any) {
|
||||||
message := fmt.Sprintf(format, args...)
|
message := fmt.Sprintf(format, args...)
|
||||||
record := slog.NewRecord(entry.time, slog.LevelError, message, entry.getCaller())
|
record := slog.NewRecord(entry.time, slog.LevelError, message, entry.getCaller().PC)
|
||||||
record.AddAttrs(entry.getExtra()...)
|
record.AddAttrs(entry.getExtra()...)
|
||||||
_ = entry.handler.Handle(entry.ctx, record)
|
_ = entry.handler.Handle(entry.ctx, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Debug(message string, fields ...any) {
|
func (entry *Entry) Debug(message string, fields ...any) {
|
||||||
record := slog.NewRecord(entry.time, slog.LevelDebug, message, entry.getCaller())
|
record := slog.NewRecord(entry.time, slog.LevelDebug, message, entry.getCaller().PC)
|
||||||
record.AddAttrs(entry.getExtra()...)
|
record.AddAttrs(entry.getExtra()...)
|
||||||
record.AddAttrs(slog.Group("context", fields...))
|
record.AddAttrs(slog.Group("context", fields...))
|
||||||
_ = entry.handler.Handle(entry.ctx, record)
|
_ = entry.handler.Handle(entry.ctx, record)
|
||||||
|
@ -102,13 +102,13 @@ func (entry *Entry) Debug(message string, fields ...any) {
|
||||||
|
|
||||||
func (entry *Entry) Debugf(format string, args ...any) {
|
func (entry *Entry) Debugf(format string, args ...any) {
|
||||||
message := fmt.Sprintf(format, args...)
|
message := fmt.Sprintf(format, args...)
|
||||||
record := slog.NewRecord(entry.time, slog.LevelDebug, message, entry.getCaller())
|
record := slog.NewRecord(entry.time, slog.LevelDebug, message, entry.getCaller().PC)
|
||||||
record.AddAttrs(entry.getExtra()...)
|
record.AddAttrs(entry.getExtra()...)
|
||||||
_ = entry.handler.Handle(entry.ctx, record)
|
_ = entry.handler.Handle(entry.ctx, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) Warn(message string, fields ...any) {
|
func (entry *Entry) Warn(message string, fields ...any) {
|
||||||
record := slog.NewRecord(entry.time, slog.LevelWarn, message, entry.getCaller())
|
record := slog.NewRecord(entry.time, slog.LevelWarn, message, entry.getCaller().PC)
|
||||||
record.AddAttrs(entry.getExtra()...)
|
record.AddAttrs(entry.getExtra()...)
|
||||||
record.AddAttrs(slog.Group("context", fields...))
|
record.AddAttrs(slog.Group("context", fields...))
|
||||||
_ = entry.handler.Handle(entry.ctx, record)
|
_ = entry.handler.Handle(entry.ctx, record)
|
||||||
|
@ -116,25 +116,16 @@ func (entry *Entry) Warn(message string, fields ...any) {
|
||||||
|
|
||||||
func (entry *Entry) Warnf(format string, args ...any) {
|
func (entry *Entry) Warnf(format string, args ...any) {
|
||||||
message := fmt.Sprintf(format, args...)
|
message := fmt.Sprintf(format, args...)
|
||||||
record := slog.NewRecord(entry.time, slog.LevelWarn, message, entry.getCaller())
|
record := slog.NewRecord(entry.time, slog.LevelWarn, message, entry.getCaller().PC)
|
||||||
record.AddAttrs(entry.getExtra()...)
|
record.AddAttrs(entry.getExtra()...)
|
||||||
_ = entry.handler.Handle(entry.ctx, record)
|
_ = entry.handler.Handle(entry.ctx, record)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) getCaller() uintptr {
|
func (entry *Entry) getCaller() caller.Caller {
|
||||||
if entry.caller != 0 {
|
if entry.caller.PC != 0 {
|
||||||
return entry.caller
|
return entry.caller
|
||||||
}
|
}
|
||||||
return GetCaller(4)
|
return caller.New(4)
|
||||||
}
|
|
||||||
|
|
||||||
func GetCaller(skip int) uintptr {
|
|
||||||
pc := make([]uintptr, 1)
|
|
||||||
n := runtime.Callers(skip, pc)
|
|
||||||
if n == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return pc[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (entry *Entry) getExtra() []slog.Attr {
|
func (entry *Entry) getExtra() []slog.Attr {
|
||||||
|
|
|
@ -7,11 +7,11 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
|
"github.com/tigorlazuardi/redmage/caller"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PrettyHandler struct {
|
type PrettyHandler struct {
|
||||||
|
@ -89,7 +89,7 @@ func (pr *PrettyHandler) Handle(ctx context.Context, record slog.Record) error {
|
||||||
defer putBuffer(jsonBuf)
|
defer putBuffer(jsonBuf)
|
||||||
|
|
||||||
if record.PC != 0 && pr.opts.AddSource {
|
if record.PC != 0 && pr.opts.AddSource {
|
||||||
frame := getFrame(record.PC)
|
frame := caller.From(record.PC).Frame
|
||||||
levelColor.Fprint(buf, frame.File)
|
levelColor.Fprint(buf, frame.File)
|
||||||
levelColor.Fprint(buf, ":")
|
levelColor.Fprint(buf, ":")
|
||||||
levelColor.Fprint(buf, frame.Line)
|
levelColor.Fprint(buf, frame.Line)
|
||||||
|
@ -118,7 +118,7 @@ func (pr *PrettyHandler) Handle(ctx context.Context, record slog.Record) error {
|
||||||
_ = serializer.Handle(ctx, record)
|
_ = serializer.Handle(ctx, record)
|
||||||
if jsonBuf.Len() > 3 { // Ignore empty json like "{}\n"
|
if jsonBuf.Len() > 3 { // Ignore empty json like "{}\n"
|
||||||
_ = json.Indent(buf, jsonBuf.Bytes(), "", " ")
|
_ = json.Indent(buf, jsonBuf.Bytes(), "", " ")
|
||||||
// json indent includes new line, no need to add extra text.
|
// json indent includes new line, no need to add extra new line.
|
||||||
} else {
|
} else {
|
||||||
buf.WriteByte('\n')
|
buf.WriteByte('\n')
|
||||||
}
|
}
|
||||||
|
@ -148,12 +148,6 @@ func (pr *PrettyHandler) createSerializer(w io.Writer) slog.Handler {
|
||||||
return jsonHandler
|
return jsonHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func getFrame(pc uintptr) runtime.Frame {
|
|
||||||
frames := runtime.CallersFrames([]uintptr{pc})
|
|
||||||
frame, _ := frames.Next()
|
|
||||||
return frame
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pr *PrettyHandler) clone() *PrettyHandler {
|
func (pr *PrettyHandler) clone() *PrettyHandler {
|
||||||
return &PrettyHandler{
|
return &PrettyHandler{
|
||||||
opts: pr.opts,
|
opts: pr.opts,
|
||||||
|
|
Loading…
Reference in a new issue