diff --git a/README.md b/README.md index 46b41c0d..2c293bbb 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ That is beginning to change. There is now a Xop is currently the only Go structured logs and tracing system. Performance-wise, it's better that Zap, and about on par with Zerolog. -Where Xop shines is in API design. +Where Xop shines is in it's API design. ## The problem with the existing model @@ -59,7 +59,7 @@ The industry model of tracing as documented in the W3C spec requires that spans have full identifiers. If you give each part of dealing with a request inside a single server, lots of different spans, then how can you quickly reference the request-level span from one the sub-spans or one of the other requests that -is a child of the main request. There is no standard way to distinguish a span +is a child of the main request? There is no standard way to distinguish a span that is simply a separate thread of execution or one that is a related request on a different server. diff --git a/config.go b/config.go index 6ccf172a..610f7cbb 100644 --- a/config.go +++ b/config.go @@ -16,9 +16,6 @@ type Config struct { // too high. It would discourage logging. That said, // there is a an error, we don't want to completely // ignore it. - // - // TODO: If ErrorReporter is called too frequently, - // it will automatically be throttled ErrorReporter func(error) } diff --git a/xoptest/testlogger.go b/xoptest/testlogger.go index 270df1fe..9331a852 100644 --- a/xoptest/testlogger.go +++ b/xoptest/testlogger.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "regexp" + "runtime" "strings" "sync" "sync/atomic" @@ -121,6 +122,7 @@ type Line struct { Message string // Prefill text + line text (template evaluated) Text string // Complete text of line including key=value pairs Tmpl string // un-evaluated template + Stack []runtime.Frame } type Event struct { @@ -286,9 +288,8 @@ func (p *Prefilling) PrefillComplete(m string) xopbase.Prefilled { } } -func (p *Prefilled) Line(level xopnum.Level, t time.Time, _ []uintptr) xopbase.Line { +func (p *Prefilled) Line(level xopnum.Level, t time.Time, pc []uintptr) xopbase.Line { atomic.StoreInt64(&p.Span.EndTime, t.UnixNano()) - // TODO: stack traces line := &Line{ Builder: Builder{ Data: make(map[string]interface{}), @@ -298,6 +299,21 @@ func (p *Prefilled) Line(level xopnum.Level, t time.Time, _ []uintptr) xopbase.L Level: level, Timestamp: t, } + if len(pc) > 0 { + frames := runtime.CallersFrames(pc) + stack := make([]runtime.Frame, 0, len(pc)) + for { + frame, more := frames.Next() + if !strings.Contains(frame.File, "runtime/") { + break + } + stack = append(stack, frame) + if !more { + break + } + } + line.Stack = stack + } for k, v := range p.Data { line.Data[k] = v line.DataType[k] = p.DataType[k] diff --git a/xoptest/testlogger.zzzgo b/xoptest/testlogger.zzzgo index bf5ae1f2..2ea9ba5c 100644 --- a/xoptest/testlogger.zzzgo +++ b/xoptest/testlogger.zzzgo @@ -117,6 +117,7 @@ type Line struct { Message string // Prefill text + line text (template evaluated) Text string // Complete text of line including key=value pairs Tmpl string // un-evaluated template + Stack []runtime.Frame } type Event struct { @@ -282,9 +283,8 @@ func (p *Prefilling) PrefillComplete(m string) xopbase.Prefilled { } } -func (p *Prefilled) Line(level xopnum.Level, t time.Time, _ []uintptr) xopbase.Line { +func (p *Prefilled) Line(level xopnum.Level, t time.Time, pc []uintptr) xopbase.Line { atomic.StoreInt64(&p.Span.EndTime, t.UnixNano()) - // TODO: stack traces line := &Line{ Builder: Builder{ Data: make(map[string]interface{}), @@ -294,6 +294,21 @@ func (p *Prefilled) Line(level xopnum.Level, t time.Time, _ []uintptr) xopbase.L Level: level, Timestamp: t, } + if len(pc) > 0 { + frames := runtime.CallersFrames(pc) + stack := make([]runtime.Frame, 0, len(pc)) + for { + frame, more := frames.Next() + if !strings.Contains(frame.File, "runtime/") { + break + } + stack = append(stack, frame) + if !more { + break + } + } + line.Stack = stack + } for k, v := range p.Data { line.Data[k] = v line.DataType[k] = p.DataType[k] diff --git a/xoptest/xoptestutil/enums.go b/xoptest/xoptestutil/enums.go index 3098e7c5..3e36db93 100644 --- a/xoptest/xoptestutil/enums.go +++ b/xoptest/xoptestutil/enums.go @@ -93,10 +93,8 @@ var ( ExampleMetadataDistinctXEnum = xopat.Make{Key: "d-xenum", Multiple: true, Distinct: true, Namespace: "test"}.EnumAttribute(xopconst.SpanKindServer) ) -// TODO: why the skips? -var ExampleMetadataSingleBool = xopat.Make{Key: "s-bool", Namespace: "test"}.BoolAttribute() - var ( + ExampleMetadataSingleBool = xopat.Make{Key: "s-bool", Namespace: "test"}.BoolAttribute() ExampleMetadataLockedBool = xopat.Make{Key: "l-bool", Locked: true, Namespace: "test"}.BoolAttribute() ExampleMetadataMultipleBool = xopat.Make{Key: "m-bool", Multiple: true, Namespace: "test"}.BoolAttribute() ExampleMetadataDistinctBool = xopat.Make{Key: "d-bool", Multiple: true, Distinct: true, Namespace: "test"}.BoolAttribute() diff --git a/xoptest/xoptestutil/enums.zzzgo b/xoptest/xoptestutil/enums.zzzgo index 3d810781..8389f91c 100644 --- a/xoptest/xoptestutil/enums.zzzgo +++ b/xoptest/xoptestutil/enums.zzzgo @@ -83,7 +83,6 @@ var ExampleMetadataLockedXEnum = xopat.Make{Key: "l-xenum", Locked: true, Namesp var ExampleMetadataMultipleXEnum = xopat.Make{Key: "m-xenum", Multiple: true, Namespace: "test"}.EnumAttribute(xopconst.SpanKindServer) var ExampleMetadataDistinctXEnum = xopat.Make{Key: "d-xenum", Multiple: true, Distinct: true, Namespace: "test"}.EnumAttribute(xopconst.SpanKindServer) -// TODO: why the skips? // MACRO ZZZAttribute SKIP:Any,Enum var ExampleMetadataSingleZZZ = xopat.Make{Key: "s-zzz", Namespace: "test"}.ZZZAttribute() var ExampleMetadataLockedZZZ = xopat.Make{Key: "l-zzz", Locked: true, Namespace: "test"}.ZZZAttribute()