Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
parent
1cbab38d24
commit
7ef5c5d804
@ -39,8 +39,10 @@ type Options struct {
|
|||||||
SourceKey string
|
SourceKey string
|
||||||
// StacktraceKey is the key used for the stacktrace
|
// StacktraceKey is the key used for the stacktrace
|
||||||
StacktraceKey string
|
StacktraceKey string
|
||||||
// Stacktrace controls writing of stacktaces on error
|
// AddStacktrace controls writing of stacktaces on error
|
||||||
Stacktrace bool
|
AddStacktrace bool
|
||||||
|
// AddSource enabled writing source file and position in log
|
||||||
|
AddSource bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOptions creates new options struct
|
// NewOptions creates new options struct
|
||||||
@ -52,6 +54,7 @@ func NewOptions(opts ...options.Option) Options {
|
|||||||
CallerSkipCount: DefaultCallerSkipCount,
|
CallerSkipCount: DefaultCallerSkipCount,
|
||||||
Context: context.Background(),
|
Context: context.Background(),
|
||||||
ContextAttrFuncs: DefaultContextAttrFuncs,
|
ContextAttrFuncs: DefaultContextAttrFuncs,
|
||||||
|
AddSource: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = WithMicroKeys()(&options)
|
_ = WithMicroKeys()(&options)
|
||||||
@ -207,9 +210,16 @@ func WithMicroKeys() options.Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithStacktrace controls writing stacktrace on error
|
// WithAddStacktrace controls writing stacktrace on error
|
||||||
func WithStacktrace(v bool) options.Option {
|
func WithAddStacktrace(v bool) options.Option {
|
||||||
return func(src interface{}) error {
|
return func(src interface{}) error {
|
||||||
return options.Set(src, v, ".Stacktrace")
|
return options.Set(src, v, ".AddStacktrace")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WitAddSource controls writing source file and pos in log
|
||||||
|
func WithAddSource(v bool) options.Option {
|
||||||
|
return func(src interface{}) error {
|
||||||
|
return options.Set(src, v, ".AddSource")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,18 +80,11 @@ func (s *slogLogger) Clone(opts ...options.Option) logger.Logger {
|
|||||||
opts: options,
|
opts: options,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if slog, ok := s.opts.Context.Value(loggerKey{}).(*slog.Logger); ok {
|
|
||||||
l.slog = slog
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
l.leveler = new(slog.LevelVar)
|
l.leveler = new(slog.LevelVar)
|
||||||
handleOpt := &slog.HandlerOptions{
|
handleOpt := &slog.HandlerOptions{
|
||||||
ReplaceAttr: s.renameAttr,
|
ReplaceAttr: l.renameAttr,
|
||||||
Level: l.leveler,
|
Level: l.leveler,
|
||||||
AddSource: true,
|
AddSource: l.opts.AddSource,
|
||||||
}
|
}
|
||||||
l.leveler.Set(loggerToSlogLevel(l.opts.Level))
|
l.leveler.Set(loggerToSlogLevel(l.opts.Level))
|
||||||
handler := slog.NewJSONHandler(options.Out, handleOpt)
|
handler := slog.NewJSONHandler(options.Out, handleOpt)
|
||||||
@ -116,50 +109,47 @@ func (s *slogLogger) Options() logger.Options {
|
|||||||
|
|
||||||
func (s *slogLogger) Attrs(attrs ...interface{}) logger.Logger {
|
func (s *slogLogger) Attrs(attrs ...interface{}) logger.Logger {
|
||||||
s.mu.RLock()
|
s.mu.RLock()
|
||||||
nl := &slogLogger{opts: s.opts}
|
l := &slogLogger{opts: s.opts}
|
||||||
nl.leveler = new(slog.LevelVar)
|
l.leveler = new(slog.LevelVar)
|
||||||
nl.leveler.Set(s.leveler.Level())
|
l.leveler.Set(s.leveler.Level())
|
||||||
|
|
||||||
handleOpt := &slog.HandlerOptions{
|
handleOpt := &slog.HandlerOptions{
|
||||||
ReplaceAttr: nl.renameAttr,
|
ReplaceAttr: l.renameAttr,
|
||||||
Level: nl.leveler,
|
Level: l.leveler,
|
||||||
AddSource: true,
|
AddSource: l.opts.AddSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
handler := slog.NewJSONHandler(s.opts.Out, handleOpt)
|
handler := slog.NewJSONHandler(s.opts.Out, handleOpt)
|
||||||
nl.slog = slog.New(handler).With(attrs...)
|
l.slog = slog.New(handler).With(attrs...)
|
||||||
|
|
||||||
s.mu.RUnlock()
|
s.mu.RUnlock()
|
||||||
|
|
||||||
return nl
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *slogLogger) Init(opts ...options.Option) error {
|
func (s *slogLogger) Init(opts ...options.Option) error {
|
||||||
|
s.mu.Lock()
|
||||||
|
|
||||||
if len(s.opts.ContextAttrFuncs) == 0 {
|
if len(s.opts.ContextAttrFuncs) == 0 {
|
||||||
s.opts.ContextAttrFuncs = logger.DefaultContextAttrFuncs
|
s.opts.ContextAttrFuncs = logger.DefaultContextAttrFuncs
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
if err := o(&s.opts); err != nil {
|
if err := o(&s.opts); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if slog, ok := s.opts.Context.Value(loggerKey{}).(*slog.Logger); ok {
|
|
||||||
s.slog = slog
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
s.leveler = new(slog.LevelVar)
|
s.leveler = new(slog.LevelVar)
|
||||||
handleOpt := &slog.HandlerOptions{
|
handleOpt := &slog.HandlerOptions{
|
||||||
ReplaceAttr: s.renameAttr,
|
ReplaceAttr: s.renameAttr,
|
||||||
Level: s.leveler,
|
Level: s.leveler,
|
||||||
AddSource: true,
|
AddSource: s.opts.AddSource,
|
||||||
}
|
}
|
||||||
s.leveler.Set(loggerToSlogLevel(s.opts.Level))
|
s.leveler.Set(loggerToSlogLevel(s.opts.Level))
|
||||||
handler := slog.NewJSONHandler(s.opts.Out, handleOpt)
|
handler := slog.NewJSONHandler(s.opts.Out, handleOpt)
|
||||||
s.slog = slog.New(handler).With(s.opts.Attrs...)
|
s.slog = slog.New(handler).With(s.opts.Attrs...)
|
||||||
|
s.mu.Unlock()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -180,7 +170,7 @@ func (s *slogLogger) Log(ctx context.Context, lvl logger.Level, msg string, attr
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.opts.Stacktrace && lvl == logger.ErrorLevel {
|
if s.opts.AddStacktrace && lvl == logger.ErrorLevel {
|
||||||
stackInfo := make([]byte, 1024*1024)
|
stackInfo := make([]byte, 1024*1024)
|
||||||
if stackSize := runtime.Stack(stackInfo, false); stackSize > 0 {
|
if stackSize := runtime.Stack(stackInfo, false); stackSize > 0 {
|
||||||
traceLines := reTrace.Split(string(stackInfo[:stackSize]), -1)
|
traceLines := reTrace.Split(string(stackInfo[:stackSize]), -1)
|
||||||
@ -260,7 +250,7 @@ func (s *slogLogger) Error(ctx context.Context, msg string, attrs ...interface{}
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.opts.Stacktrace {
|
if s.opts.AddStacktrace {
|
||||||
stackInfo := make([]byte, 1024*1024)
|
stackInfo := make([]byte, 1024*1024)
|
||||||
if stackSize := runtime.Stack(stackInfo, false); stackSize > 0 {
|
if stackSize := runtime.Stack(stackInfo, false); stackSize > 0 {
|
||||||
traceLines := reTrace.Split(string(stackInfo[:stackSize]), -1)
|
traceLines := reTrace.Split(string(stackInfo[:stackSize]), -1)
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
func TestError(t *testing.T) {
|
func TestError(t *testing.T) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
l := NewLogger(logger.WithLevel(logger.ErrorLevel), logger.WithOutput(buf), logger.WithStacktrace(true))
|
l := NewLogger(logger.WithLevel(logger.ErrorLevel), logger.WithOutput(buf), logger.WithAddStacktrace(true))
|
||||||
if err := l.Init(); err != nil {
|
if err := l.Init(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -27,12 +27,12 @@ func TestLoggerWithTracer(t *testing.T) {
|
|||||||
logger.Error(ctx, "my test error", fmt.Errorf("error"))
|
logger.Error(ctx, "my test error", fmt.Errorf("error"))
|
||||||
|
|
||||||
if !strings.Contains(buf.String(), span.TraceID()) {
|
if !strings.Contains(buf.String(), span.TraceID()) {
|
||||||
t.Fatalf("log does not contains tracer id: %s", buf.Bytes())
|
t.Fatalf("log does not contains trace id: %s", buf.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
_, _ = tr.Start(ctx, "test2")
|
_, _ = tr.Start(ctx, "test2")
|
||||||
|
|
||||||
for _, s := range tr.Spans() {
|
for _, s := range tr.Spans() {
|
||||||
t.Logf("span %#+v\n", s)
|
_ = s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,26 @@ import (
|
|||||||
// DefaultTracer is the global default tracer
|
// DefaultTracer is the global default tracer
|
||||||
var DefaultTracer = NewTracer()
|
var DefaultTracer = NewTracer()
|
||||||
|
|
||||||
|
var (
|
||||||
|
// TraceIDKey is the key used for the trace id in the log call
|
||||||
|
TraceIDKey = "trace-id"
|
||||||
|
// SpanIDKey is the key used for the span id in the log call
|
||||||
|
SpanIDKey = "span-id"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
logger.DefaultContextAttrFuncs = append(logger.DefaultContextAttrFuncs,
|
||||||
|
func(ctx context.Context) []interface{} {
|
||||||
|
if span, ok := SpanFromContext(ctx); ok {
|
||||||
|
return []interface{}{
|
||||||
|
TraceIDKey, span.TraceID(),
|
||||||
|
SpanIDKey, span.SpanID(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Tracer is an interface for distributed tracing
|
// Tracer is an interface for distributed tracing
|
||||||
type Tracer interface {
|
type Tracer interface {
|
||||||
// Name return tracer name
|
// Name return tracer name
|
||||||
@ -52,16 +72,6 @@ type Span interface {
|
|||||||
SpanID() string
|
SpanID() string
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
logger.DefaultContextAttrFuncs = append(logger.DefaultContextAttrFuncs, func(ctx context.Context) []interface{} {
|
|
||||||
span, ok := SpanFromContext(ctx)
|
|
||||||
if !ok || span == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return []interface{}{"trace", span.TraceID(), "span", span.SpanID()}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort labels alphabeticaly by label name
|
// sort labels alphabeticaly by label name
|
||||||
type byKey []interface{}
|
type byKey []interface{}
|
||||||
|
|
||||||
@ -76,6 +86,7 @@ func UniqLabels(labels []interface{}) []interface{} {
|
|||||||
if len(labels)%2 == 1 {
|
if len(labels)%2 == 1 {
|
||||||
labels = labels[:len(labels)-1]
|
labels = labels[:len(labels)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(labels) > 2 {
|
if len(labels) > 2 {
|
||||||
sort.Sort(byKey(labels))
|
sort.Sort(byKey(labels))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user