From ec0cf4a0cb7e6fe724ddd61c6ee830a5c08e47cf Mon Sep 17 00:00:00 2001 From: David Muir Sharnoff Date: Fri, 29 Dec 2023 18:13:03 -0800 Subject: [PATCH] use a key type use "type K string" instead of a struct --- basegroup.go | 32 ++-- basegroup.zzzgo | 12 +- line.go | 44 ++--- line.zzzgo | 24 +-- logger.go | 3 +- sub.go | 82 +++++----- sub.zzzgo | 38 +++-- sub_test.go | 10 +- xopat/attributes.go | 6 +- xopat/attributes.zzzgo | 12 +- xopat/json.go | 6 +- xopat/key.go | 43 +++++ xopat/key_test.go | 19 +++ xopbase/base.go | 16 +- xopbase/base.zzzgo | 5 +- xopbase/skip.go | 18 +-- xopbase/skip.zzzgo | 6 +- xopbase/xopbaseutil/metadata.go | 32 ++-- xopbase/xopbaseutil/metadata.zzzgo | 4 +- xopcon/console.go | 22 +-- xopcon/console.zzzgo | 10 +- xopconsole/attributes.go | 8 +- xopconsole/attributes.zzzgo | 8 +- xopconsole/console.go | 20 +-- xopconsole/replay.go | 32 ++-- xopconsole/replay.zzzgo | 32 ++-- xopjson/jsonlogger.go | 42 ++--- xopjson/jsonlogger.zzzgo | 42 ++--- xopjson/jsonlogger_test.go | 2 +- xopjson/models.go | 4 + xopjson/replay.go | 6 +- xopjson/replay.zzzgo | 6 +- xopjson/xopjsonutil/attributes.go | 32 ++-- xopjson/xopjsonutil/attributes.zzzgo | 4 +- xopotel/buffered.go | 11 +- xopotel/buffered.zzzgo | 11 +- xopotel/export.go | 103 ++++++------ xopotel/export.zzzgo | 49 +++--- xopotel/models.go | 15 +- xopotel/otel.go | 230 +++++++++++++-------------- xopotel/otel.zzzgo | 92 +++++------ xopotel/otel_test.go | 3 +- xoppb/pb.go | 66 ++++---- xoppb/pb.zzzgo | 43 ++--- xoppb/replay.go | 160 +++++++++---------- xoppb/replay.zzzgo | 138 ++++++++-------- xoprecorder/recorder.go | 58 +++---- xoprecorder/recorder.zzzgo | 46 +++--- xoprecorder/recorder_test.go | 1 - xoprecorder/replay.go | 46 +++--- xoprecorder/replay.zzzgo | 21 ++- xopresty/resty.go | 15 +- xoptest/redact_test.go | 19 +-- xoptest/testlogger_test.go | 5 +- xoptest/xoptestutil/cases.go | 20 +-- 55 files changed, 981 insertions(+), 853 deletions(-) create mode 100644 xopat/key.go create mode 100644 xopat/key_test.go diff --git a/basegroup.go b/basegroup.go index 1f9be0d1..e4cb897c 100644 --- a/basegroup.go +++ b/basegroup.go @@ -230,97 +230,97 @@ func (l lines) Model(k string, v xopbase.ModelArg) { } } -func (p prefillings) Any(k string, v xopbase.ModelArg) { +func (p prefillings) Any(k xopat.K, v xopbase.ModelArg) { for _, prefilling := range p { prefilling.Any(k, v) } } -func (p prefillings) Bool(k string, v bool) { +func (p prefillings) Bool(k xopat.K, v bool) { for _, prefilling := range p { prefilling.Bool(k, v) } } -func (p prefillings) Duration(k string, v time.Duration) { +func (p prefillings) Duration(k xopat.K, v time.Duration) { for _, prefilling := range p { prefilling.Duration(k, v) } } -func (p prefillings) Time(k string, v time.Time) { +func (p prefillings) Time(k xopat.K, v time.Time) { for _, prefilling := range p { prefilling.Time(k, v) } } -func (p prefillings) Float64(k string, v float64, dt xopbase.DataType) { +func (p prefillings) Float64(k xopat.K, v float64, dt xopbase.DataType) { for _, prefilling := range p { prefilling.Float64(k, v, dt) } } -func (p prefillings) Int64(k string, v int64, dt xopbase.DataType) { +func (p prefillings) Int64(k xopat.K, v int64, dt xopbase.DataType) { for _, prefilling := range p { prefilling.Int64(k, v, dt) } } -func (p prefillings) String(k string, v string, dt xopbase.DataType) { +func (p prefillings) String(k xopat.K, v string, dt xopbase.DataType) { for _, prefilling := range p { prefilling.String(k, v, dt) } } -func (p prefillings) Uint64(k string, v uint64, dt xopbase.DataType) { +func (p prefillings) Uint64(k xopat.K, v uint64, dt xopbase.DataType) { for _, prefilling := range p { prefilling.Uint64(k, v, dt) } } -func (l lines) Any(k string, v xopbase.ModelArg) { +func (l lines) Any(k xopat.K, v xopbase.ModelArg) { for _, line := range l { line.Any(k, v) } } -func (l lines) Bool(k string, v bool) { +func (l lines) Bool(k xopat.K, v bool) { for _, line := range l { line.Bool(k, v) } } -func (l lines) Duration(k string, v time.Duration) { +func (l lines) Duration(k xopat.K, v time.Duration) { for _, line := range l { line.Duration(k, v) } } -func (l lines) Time(k string, v time.Time) { +func (l lines) Time(k xopat.K, v time.Time) { for _, line := range l { line.Time(k, v) } } -func (l lines) Float64(k string, v float64, dt xopbase.DataType) { +func (l lines) Float64(k xopat.K, v float64, dt xopbase.DataType) { for _, line := range l { line.Float64(k, v, dt) } } -func (l lines) Int64(k string, v int64, dt xopbase.DataType) { +func (l lines) Int64(k xopat.K, v int64, dt xopbase.DataType) { for _, line := range l { line.Int64(k, v, dt) } } -func (l lines) String(k string, v string, dt xopbase.DataType) { +func (l lines) String(k xopat.K, v string, dt xopbase.DataType) { for _, line := range l { line.String(k, v, dt) } } -func (l lines) Uint64(k string, v uint64, dt xopbase.DataType) { +func (l lines) Uint64(k xopat.K, v uint64, dt xopbase.DataType) { for _, line := range l { line.Uint64(k, v, dt) } diff --git a/basegroup.zzzgo b/basegroup.zzzgo index 4a2f2f5b..a69e669b 100644 --- a/basegroup.zzzgo +++ b/basegroup.zzzgo @@ -1,3 +1,7 @@ +// TEMPLATE-FILE +// TEMPLATE-FILE +// TEMPLATE-FILE + package xop import ( @@ -213,28 +217,28 @@ func (l lines) ZZZ(k string, v zzz) { } // MACRO BaseDataWithoutType -func (p prefillings) ZZZ(k string, v zzz) { +func (p prefillings) ZZZ(k xopat.K, v zzz) { for _, prefilling := range p { prefilling.ZZZ(k, v) } } // MACRO BaseDataWithType -func (p prefillings) ZZZ(k string, v zzz, dt xopbase.DataType) { +func (p prefillings) ZZZ(k xopat.K, v zzz, dt xopbase.DataType) { for _, prefilling := range p { prefilling.ZZZ(k, v, dt) } } // MACRO BaseDataWithoutType -func (l lines) ZZZ(k string, v zzz) { +func (l lines) ZZZ(k xopat.K, v zzz) { for _, line := range l { line.ZZZ(k, v) } } // MACRO BaseDataWithType -func (l lines) ZZZ(k string, v zzz, dt xopbase.DataType) { +func (l lines) ZZZ(k xopat.K, v zzz, dt xopbase.DataType) { for _, line := range l { line.ZZZ(k, v, dt) } diff --git a/line.go b/line.go index 549c1f31..3afc16ac 100644 --- a/line.go +++ b/line.go @@ -12,9 +12,11 @@ import ( "github.com/mohae/deepcopy" ) +type Key = xopat.K + // AnyWithoutRedaction // The return value must be consumed for the line to be logged. -func (line *Line) AnyWithoutRedaction(k string, v interface{}) *Line { +func (line *Line) AnyWithoutRedaction(k xopat.K, v interface{}) *Line { line.line.Any(k, xopbase.ModelArg{Model: v}) return line } @@ -23,7 +25,7 @@ func (line *Line) AnyWithoutRedaction(k string, v interface{}) *Line { // logger does not immediately serialize, then the object will be copied using // https://github.com/mohae/deepcopy 's Copy(). // The return value must be consumed for the line to be logged. -func (line *Line) Any(k string, v interface{}) *Line { +func (line *Line) Any(k xopat.K, v interface{}) *Line { if line.skip { return line } @@ -40,7 +42,7 @@ func (line *Line) Any(k string, v interface{}) *Line { // Float32 adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Float32(k string, v float32) *Line { +func (line *Line) Float32(k xopat.K, v float32) *Line { line.line.Float64(k, float64(v), xopbase.Float32DataType) return line } @@ -63,7 +65,7 @@ func (line *Line) Enum(k *xopat.EnumAttribute, v xopat.Enum) *Line { // The default logging of an error is simply err.Error() to change // that, set a redaction function. // The return value must be consumed for the line to be logged. -func (line *Line) Error(k string, v error) *Line { +func (line *Line) Error(k xopat.K, v error) *Line { if line.skip { return line } @@ -78,7 +80,7 @@ func (line *Line) Error(k string, v error) *Line { // Stringer adds a key/value pair to the current log line. // The string can be redacted if a redaction function has been set. // The return value must be consumed for the line to be logged. -func (line *Line) Stringer(k string, v fmt.Stringer) *Line { +func (line *Line) Stringer(k xopat.K, v fmt.Stringer) *Line { if line.skip { return line } @@ -93,7 +95,7 @@ func (line *Line) Stringer(k string, v fmt.Stringer) *Line { // String adds a key/value pair to the current log line. // The string can be redacted if a redaction function has been set. // The return value must be consumed for the line to be logged. -func (line *Line) String(k string, v string) *Line { +func (line *Line) String(k xopat.K, v string) *Line { if line.skip { return line } @@ -107,96 +109,96 @@ func (line *Line) String(k string, v string) *Line { // Bool adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Bool(k string, v bool) *Line { line.line.Bool(k, v); return line } +func (line *Line) Bool(k xopat.K, v bool) *Line { line.line.Bool(k, v); return line } // Duration adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Duration(k string, v time.Duration) *Line { line.line.Duration(k, v); return line } +func (line *Line) Duration(k xopat.K, v time.Duration) *Line { line.line.Duration(k, v); return line } // Time adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Time(k string, v time.Time) *Line { line.line.Time(k, v); return line } +func (line *Line) Time(k xopat.K, v time.Time) *Line { line.line.Time(k, v); return line } // Float64 adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Float64(k string, v float64) *Line { +func (line *Line) Float64(k xopat.K, v float64) *Line { line.line.Float64(k, v, xopbase.Float64DataType) return line } // Int64 adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Int64(k string, v int64) *Line { +func (line *Line) Int64(k xopat.K, v int64) *Line { line.line.Int64(k, v, xopbase.Int64DataType) return line } // Uint64 adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Uint64(k string, v uint64) *Line { +func (line *Line) Uint64(k xopat.K, v uint64) *Line { line.line.Uint64(k, v, xopbase.Uint64DataType) return line } // Int adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Int(k string, v int) *Line { +func (line *Line) Int(k xopat.K, v int) *Line { line.line.Int64(k, int64(v), xopbase.IntDataType) return line } // Int16 adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Int16(k string, v int16) *Line { +func (line *Line) Int16(k xopat.K, v int16) *Line { line.line.Int64(k, int64(v), xopbase.Int16DataType) return line } // Int32 adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Int32(k string, v int32) *Line { +func (line *Line) Int32(k xopat.K, v int32) *Line { line.line.Int64(k, int64(v), xopbase.Int32DataType) return line } // Int8 adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Int8(k string, v int8) *Line { +func (line *Line) Int8(k xopat.K, v int8) *Line { line.line.Int64(k, int64(v), xopbase.Int8DataType) return line } // Uint adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Uint(k string, v uint) *Line { +func (line *Line) Uint(k xopat.K, v uint) *Line { line.line.Uint64(k, uint64(v), xopbase.UintDataType) return line } // Uint16 adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Uint16(k string, v uint16) *Line { +func (line *Line) Uint16(k xopat.K, v uint16) *Line { line.line.Uint64(k, uint64(v), xopbase.Uint16DataType) return line } // Uint32 adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Uint32(k string, v uint32) *Line { +func (line *Line) Uint32(k xopat.K, v uint32) *Line { line.line.Uint64(k, uint64(v), xopbase.Uint32DataType) return line } // Uint8 adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Uint8(k string, v uint8) *Line { +func (line *Line) Uint8(k xopat.K, v uint8) *Line { line.line.Uint64(k, uint64(v), xopbase.Uint8DataType) return line } // Uintptr adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Uintptr(k string, v uintptr) *Line { +func (line *Line) Uintptr(k xopat.K, v uintptr) *Line { line.line.Uint64(k, uint64(v), xopbase.UintptrDataType) return line } diff --git a/line.zzzgo b/line.zzzgo index 69615bcc..4f8cdc99 100644 --- a/line.zzzgo +++ b/line.zzzgo @@ -1,15 +1,19 @@ package xop import ( + "fmt" + "github.com/xoplog/xop-go/xopat" "github.com/xoplog/xop-go/xopbase" "github.com/mohae/deepcopy" ) +type Key = xopat.K + // AnyWithoutRedaction // The return value must be consumed for the line to be logged. -func (line *Line) AnyWithoutRedaction(k string, v interface{}) *Line { +func (line *Line) AnyWithoutRedaction(k xopat.K, v interface{}) *Line { line.line.Any(k, xopbase.ModelArg{Model: v}) return line } @@ -18,7 +22,7 @@ func (line *Line) AnyWithoutRedaction(k string, v interface{}) *Line { // logger does not immediately serialize, then the object will be copied using // https://github.com/mohae/deepcopy 's Copy(). // The return value must be consumed for the line to be logged. -func (line *Line) Any(k string, v interface{}) *Line { +func (line *Line) Any(k xopat.K, v interface{}) *Line { if line.skip { return line } @@ -35,7 +39,7 @@ func (line *Line) Any(k string, v interface{}) *Line { // Float32 adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) Float32(k string, v float32) *Line { +func (line *Line) Float32(k xopat.K, v float32) *Line { line.line.Float64(k, float64(v), xopbase.Float32DataType) return line } @@ -58,7 +62,7 @@ func (line *Line) Enum(k *xopat.EnumAttribute, v xopat.Enum) *Line { // The default logging of an error is simply err.Error() to change // that, set a redaction function. // The return value must be consumed for the line to be logged. -func (line *Line) Error(k string, v error) *Line { +func (line *Line) Error(k xopat.K, v error) *Line { if line.skip { return line } @@ -73,7 +77,7 @@ func (line *Line) Error(k string, v error) *Line { // Stringer adds a key/value pair to the current log line. // The string can be redacted if a redaction function has been set. // The return value must be consumed for the line to be logged. -func (line *Line) Stringer(k string, v fmt.Stringer) *Line { +func (line *Line) Stringer(k xopat.K, v fmt.Stringer) *Line { if line.skip { return line } @@ -88,7 +92,7 @@ func (line *Line) Stringer(k string, v fmt.Stringer) *Line { // String adds a key/value pair to the current log line. // The string can be redacted if a redaction function has been set. // The return value must be consumed for the line to be logged. -func (line *Line) String(k string, v string) *Line { +func (line *Line) String(k xopat.K, v string) *Line { if line.skip { return line } @@ -103,12 +107,12 @@ func (line *Line) String(k string, v string) *Line { // MACRO BaseDataWithoutType SKIP:Any // ZZZ adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) ZZZ(k string, v zzz) *Line { line.line.ZZZ(k, v); return line } +func (line *Line) ZZZ(k xopat.K, v zzz) *Line { line.line.ZZZ(k, v); return line } // MACRO BaseDataWithType SKIP:String // ZZZ adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) ZZZ(k string, v zzz) *Line { +func (line *Line) ZZZ(k xopat.K, v zzz) *Line { line.line.ZZZ(k, v, xopbase.ZZZDataType) return line } @@ -116,7 +120,7 @@ func (line *Line) ZZZ(k string, v zzz) *Line { // MACRO Ints SKIP:Int64 // ZZZ adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) ZZZ(k string, v zzz) *Line { +func (line *Line) ZZZ(k xopat.K, v zzz) *Line { line.line.Int64(k, int64(v), xopbase.ZZZDataType) return line } @@ -124,7 +128,7 @@ func (line *Line) ZZZ(k string, v zzz) *Line { // MACRO Uints SKIP:Uint64 // ZZZ adds a key/value pair to the current log line. // The return value must be consumed for the line to be logged. -func (line *Line) ZZZ(k string, v zzz) *Line { +func (line *Line) ZZZ(k xopat.K, v zzz) *Line { line.line.Uint64(k, uint64(v), xopbase.ZZZDataType) return line } diff --git a/logger.go b/logger.go index 4f78606a..3a21b4da 100644 --- a/logger.go +++ b/logger.go @@ -8,10 +8,11 @@ import ( "sync/atomic" "time" - "github.com/mohae/deepcopy" "github.com/xoplog/xop-go/xopbase" "github.com/xoplog/xop-go/xopnum" "github.com/xoplog/xop-go/xoptrace" + + "github.com/mohae/deepcopy" ) type Logger struct { diff --git a/sub.go b/sub.go index ed0c297a..aef761de 100644 --- a/sub.go +++ b/sub.go @@ -45,7 +45,7 @@ type Detaching struct { // // The provided xopbase.Line may not be retained beyond the duration of // the function call. -type RedactAnyFunc func(baseLine xopbase.Line, k string, v interface{}, alreadyImmutable bool) +type RedactAnyFunc func(baseLine xopbase.Line, k xopat.K, v interface{}, alreadyImmutable bool) // RedactStringFunc is used to redact strings as they're being logged. // It is RedactStringFunc's responsiblity to call @@ -59,7 +59,7 @@ type RedactAnyFunc func(baseLine xopbase.Line, k string, v interface{}, alreadyI // // The provided xopbase.Line may not be retained beyond the duration of // the function call. -type RedactStringFunc func(baseLine xopbase.Line, k string, v string) +type RedactStringFunc func(baseLine xopbase.Line, k xopat.K, v string) // RedactErrorFunc is used to redact or format errors as they're being // logged. It is RedactErrorFunc's responsibility to call @@ -73,7 +73,7 @@ type RedactStringFunc func(baseLine xopbase.Line, k string, v string) // // The provided xopbase.Line may not be retained beyond the duration of // the function call. -type RedactErrorFunc func(baseLine xopbase.Line, k string, v error) +type RedactErrorFunc func(baseLine xopbase.Line, k xopat.K, v error) type LogSettings struct { prefillMsg string @@ -344,7 +344,7 @@ func (settings *LogSettings) PrefillEnum(k *xopat.EnumAttribute, v xopat.Enum) { // PrefillError is used to set a data element that is included on every log // line. Errors will always be formatted with v.Error(). Redaction is // not supported. -func (sub *Sub) PrefillError(k string, v error) *Sub { +func (sub *Sub) PrefillError(k xopat.K, v error) *Sub { sub.settings.PrefillError(k, v) return sub } @@ -352,7 +352,7 @@ func (sub *Sub) PrefillError(k string, v error) *Sub { // PrefillError is used to set a data element that is included on every log // line. Errors will always be formatted with v.Error(). Redaction is // not supported. -func (settings *LogSettings) PrefillError(k string, v error) { +func (settings *LogSettings) PrefillError(k xopat.K, v error) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.String(k, v.Error(), xopbase.ErrorDataType) }) @@ -364,7 +364,7 @@ func (settings *LogSettings) PrefillError(k string, v error) { // PrefillAny is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. // Redaction is not supported. -func (sub *Sub) PrefillAny(k string, v interface{}) *Sub { +func (sub *Sub) PrefillAny(k xopat.K, v interface{}) *Sub { sub.settings.PrefillAny(k, v) return sub } @@ -375,7 +375,7 @@ func (sub *Sub) PrefillAny(k string, v interface{}) *Sub { // PrefillAny is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. // Redaction is not supported. -func (settings *LogSettings) PrefillAny(k string, v interface{}) { +func (settings *LogSettings) PrefillAny(k xopat.K, v interface{}) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Any(k, xopbase.ModelArg{Model: v}) }) @@ -385,12 +385,12 @@ func (settings *LogSettings) PrefillAny(k string, v interface{}) { // line. // PrefillFloat32 is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillFloat32(k string, v float32) *Sub { +func (sub *Sub) PrefillFloat32(k xopat.K, v float32) *Sub { sub.settings.PrefillFloat32(k, v) return sub } -func (settings *LogSettings) PrefillFloat32(k string, v float32) { +func (settings *LogSettings) PrefillFloat32(k xopat.K, v float32) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Float64(k, float64(v), xopbase.Float32DataType) }) @@ -400,12 +400,12 @@ func (settings *LogSettings) PrefillFloat32(k string, v float32) { // line. // PrefillBool is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillBool(k string, v bool) *Sub { +func (sub *Sub) PrefillBool(k xopat.K, v bool) *Sub { sub.settings.PrefillBool(k, v) return sub } -func (settings *LogSettings) PrefillBool(k string, v bool) { +func (settings *LogSettings) PrefillBool(k xopat.K, v bool) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Bool(k, v) }) @@ -415,12 +415,12 @@ func (settings *LogSettings) PrefillBool(k string, v bool) { // line. // PrefillDuration is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillDuration(k string, v time.Duration) *Sub { +func (sub *Sub) PrefillDuration(k xopat.K, v time.Duration) *Sub { sub.settings.PrefillDuration(k, v) return sub } -func (settings *LogSettings) PrefillDuration(k string, v time.Duration) { +func (settings *LogSettings) PrefillDuration(k xopat.K, v time.Duration) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Duration(k, v) }) @@ -430,12 +430,12 @@ func (settings *LogSettings) PrefillDuration(k string, v time.Duration) { // line. // PrefillTime is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillTime(k string, v time.Time) *Sub { +func (sub *Sub) PrefillTime(k xopat.K, v time.Time) *Sub { sub.settings.PrefillTime(k, v) return sub } -func (settings *LogSettings) PrefillTime(k string, v time.Time) { +func (settings *LogSettings) PrefillTime(k xopat.K, v time.Time) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Time(k, v) }) @@ -445,12 +445,12 @@ func (settings *LogSettings) PrefillTime(k string, v time.Time) { // line. // PrefillFloat64 is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillFloat64(k string, v float64) *Sub { +func (sub *Sub) PrefillFloat64(k xopat.K, v float64) *Sub { sub.settings.PrefillFloat64(k, v) return sub } -func (settings *LogSettings) PrefillFloat64(k string, v float64) { +func (settings *LogSettings) PrefillFloat64(k xopat.K, v float64) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Float64(k, v, xopbase.Float64DataType) }) @@ -460,12 +460,12 @@ func (settings *LogSettings) PrefillFloat64(k string, v float64) { // line. // PrefillInt64 is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillInt64(k string, v int64) *Sub { +func (sub *Sub) PrefillInt64(k xopat.K, v int64) *Sub { sub.settings.PrefillInt64(k, v) return sub } -func (settings *LogSettings) PrefillInt64(k string, v int64) { +func (settings *LogSettings) PrefillInt64(k xopat.K, v int64) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Int64(k, v, xopbase.Int64DataType) }) @@ -475,12 +475,12 @@ func (settings *LogSettings) PrefillInt64(k string, v int64) { // line. // PrefillString is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillString(k string, v string) *Sub { +func (sub *Sub) PrefillString(k xopat.K, v string) *Sub { sub.settings.PrefillString(k, v) return sub } -func (settings *LogSettings) PrefillString(k string, v string) { +func (settings *LogSettings) PrefillString(k xopat.K, v string) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.String(k, v, xopbase.StringDataType) }) @@ -490,12 +490,12 @@ func (settings *LogSettings) PrefillString(k string, v string) { // line. // PrefillUint64 is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillUint64(k string, v uint64) *Sub { +func (sub *Sub) PrefillUint64(k xopat.K, v uint64) *Sub { sub.settings.PrefillUint64(k, v) return sub } -func (settings *LogSettings) PrefillUint64(k string, v uint64) { +func (settings *LogSettings) PrefillUint64(k xopat.K, v uint64) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Uint64(k, v, xopbase.Uint64DataType) }) @@ -505,12 +505,12 @@ func (settings *LogSettings) PrefillUint64(k string, v uint64) { // line. // PrefillInt is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillInt(k string, v int) *Sub { +func (sub *Sub) PrefillInt(k xopat.K, v int) *Sub { sub.settings.PrefillInt(k, v) return sub } -func (settings *LogSettings) PrefillInt(k string, v int) { +func (settings *LogSettings) PrefillInt(k xopat.K, v int) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Int64(k, int64(v), xopbase.IntDataType) }) @@ -520,12 +520,12 @@ func (settings *LogSettings) PrefillInt(k string, v int) { // line. // PrefillInt16 is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillInt16(k string, v int16) *Sub { +func (sub *Sub) PrefillInt16(k xopat.K, v int16) *Sub { sub.settings.PrefillInt16(k, v) return sub } -func (settings *LogSettings) PrefillInt16(k string, v int16) { +func (settings *LogSettings) PrefillInt16(k xopat.K, v int16) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Int64(k, int64(v), xopbase.Int16DataType) }) @@ -535,12 +535,12 @@ func (settings *LogSettings) PrefillInt16(k string, v int16) { // line. // PrefillInt32 is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillInt32(k string, v int32) *Sub { +func (sub *Sub) PrefillInt32(k xopat.K, v int32) *Sub { sub.settings.PrefillInt32(k, v) return sub } -func (settings *LogSettings) PrefillInt32(k string, v int32) { +func (settings *LogSettings) PrefillInt32(k xopat.K, v int32) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Int64(k, int64(v), xopbase.Int32DataType) }) @@ -550,12 +550,12 @@ func (settings *LogSettings) PrefillInt32(k string, v int32) { // line. // PrefillInt8 is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillInt8(k string, v int8) *Sub { +func (sub *Sub) PrefillInt8(k xopat.K, v int8) *Sub { sub.settings.PrefillInt8(k, v) return sub } -func (settings *LogSettings) PrefillInt8(k string, v int8) { +func (settings *LogSettings) PrefillInt8(k xopat.K, v int8) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Int64(k, int64(v), xopbase.Int8DataType) }) @@ -565,12 +565,12 @@ func (settings *LogSettings) PrefillInt8(k string, v int8) { // line. // PrefillUint is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillUint(k string, v uint) *Sub { +func (sub *Sub) PrefillUint(k xopat.K, v uint) *Sub { sub.settings.PrefillUint(k, v) return sub } -func (settings *LogSettings) PrefillUint(k string, v uint) { +func (settings *LogSettings) PrefillUint(k xopat.K, v uint) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Uint64(k, uint64(v), xopbase.UintDataType) }) @@ -580,12 +580,12 @@ func (settings *LogSettings) PrefillUint(k string, v uint) { // line. // PrefillUint16 is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillUint16(k string, v uint16) *Sub { +func (sub *Sub) PrefillUint16(k xopat.K, v uint16) *Sub { sub.settings.PrefillUint16(k, v) return sub } -func (settings *LogSettings) PrefillUint16(k string, v uint16) { +func (settings *LogSettings) PrefillUint16(k xopat.K, v uint16) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Uint64(k, uint64(v), xopbase.Uint16DataType) }) @@ -595,12 +595,12 @@ func (settings *LogSettings) PrefillUint16(k string, v uint16) { // line. // PrefillUint32 is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillUint32(k string, v uint32) *Sub { +func (sub *Sub) PrefillUint32(k xopat.K, v uint32) *Sub { sub.settings.PrefillUint32(k, v) return sub } -func (settings *LogSettings) PrefillUint32(k string, v uint32) { +func (settings *LogSettings) PrefillUint32(k xopat.K, v uint32) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Uint64(k, uint64(v), xopbase.Uint32DataType) }) @@ -610,12 +610,12 @@ func (settings *LogSettings) PrefillUint32(k string, v uint32) { // line. // PrefillUint8 is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillUint8(k string, v uint8) *Sub { +func (sub *Sub) PrefillUint8(k xopat.K, v uint8) *Sub { sub.settings.PrefillUint8(k, v) return sub } -func (settings *LogSettings) PrefillUint8(k string, v uint8) { +func (settings *LogSettings) PrefillUint8(k xopat.K, v uint8) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Uint64(k, uint64(v), xopbase.Uint8DataType) }) @@ -625,12 +625,12 @@ func (settings *LogSettings) PrefillUint8(k string, v uint8) { // line. // PrefillUintptr is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillUintptr(k string, v uintptr) *Sub { +func (sub *Sub) PrefillUintptr(k xopat.K, v uintptr) *Sub { sub.settings.PrefillUintptr(k, v) return sub } -func (settings *LogSettings) PrefillUintptr(k string, v uintptr) { +func (settings *LogSettings) PrefillUintptr(k xopat.K, v uintptr) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Uint64(k, uint64(v), xopbase.UintptrDataType) }) diff --git a/sub.zzzgo b/sub.zzzgo index 0c62540d..76e36fa6 100644 --- a/sub.zzzgo +++ b/sub.zzzgo @@ -1,3 +1,7 @@ +// TEMPLATE-FILE +// TEMPLATE-FILE +// TEMPLATE-FILE + package xop import ( @@ -42,7 +46,7 @@ type Detaching struct { // // The provided xopbase.Line may not be retained beyond the duration of // the function call. -type RedactAnyFunc func(baseLine xopbase.Line, k string, v interface{}, alreadyImmutable bool) +type RedactAnyFunc func(baseLine xopbase.Line, k xopat.K, v interface{}, alreadyImmutable bool) // RedactStringFunc is used to redact strings as they're being logged. // It is RedactStringFunc's responsiblity to call @@ -56,7 +60,7 @@ type RedactAnyFunc func(baseLine xopbase.Line, k string, v interface{}, alreadyI // // The provided xopbase.Line may not be retained beyond the duration of // the function call. -type RedactStringFunc func(baseLine xopbase.Line, k string, v string) +type RedactStringFunc func(baseLine xopbase.Line, k xopat.K, v string) // RedactErrorFunc is used to redact or format errors as they're being // logged. It is RedactErrorFunc's responsibility to call @@ -70,7 +74,7 @@ type RedactStringFunc func(baseLine xopbase.Line, k string, v string) // // The provided xopbase.Line may not be retained beyond the duration of // the function call. -type RedactErrorFunc func(baseLine xopbase.Line, k string, v error) +type RedactErrorFunc func(baseLine xopbase.Line, k xopat.K, v error) type LogSettings struct { prefillMsg string @@ -339,7 +343,7 @@ func (settings *LogSettings) PrefillEnum(k *xopat.EnumAttribute, v xopat.Enum) { // PrefillError is used to set a data element that is included on every log // line. Errors will always be formatted with v.Error(). Redaction is // not supported. -func (sub *Sub) PrefillError(k string, v error) *Sub { +func (sub *Sub) PrefillError(k xopat.K, v error) *Sub { sub.settings.PrefillError(k, v) return sub } @@ -347,7 +351,7 @@ func (sub *Sub) PrefillError(k string, v error) *Sub { // PrefillError is used to set a data element that is included on every log // line. Errors will always be formatted with v.Error(). Redaction is // not supported. -func (settings *LogSettings) PrefillError(k string, v error) { +func (settings *LogSettings) PrefillError(k xopat.K, v error) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.String(k, v.Error(), xopbase.ErrorDataType) }) @@ -359,7 +363,7 @@ func (settings *LogSettings) PrefillError(k string, v error) { // PrefillAny is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. // Redaction is not supported. -func (sub *Sub) PrefillAny(k string, v interface{}) *Sub { +func (sub *Sub) PrefillAny(k xopat.K, v interface{}) *Sub { sub.settings.PrefillAny(k, v) return sub } @@ -370,7 +374,7 @@ func (sub *Sub) PrefillAny(k string, v interface{}) *Sub { // PrefillAny is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. // Redaction is not supported. -func (settings *LogSettings) PrefillAny(k string, v interface{}) { +func (settings *LogSettings) PrefillAny(k xopat.K, v interface{}) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Any(k, xopbase.ModelArg{Model: v}) }) @@ -380,11 +384,11 @@ func (settings *LogSettings) PrefillAny(k string, v interface{}) { // line. // PrefillFloat32 is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillFloat32(k string, v float32) *Sub { +func (sub *Sub) PrefillFloat32(k xopat.K, v float32) *Sub { sub.settings.PrefillFloat32(k, v) return sub } -func (settings *LogSettings) PrefillFloat32(k string, v float32) { +func (settings *LogSettings) PrefillFloat32(k xopat.K, v float32) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Float64(k, float64(v), xopbase.Float32DataType) }) @@ -395,11 +399,11 @@ func (settings *LogSettings) PrefillFloat32(k string, v float32) { // line. // PrefillZZZ is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillZZZ(k string, v zzz) *Sub { +func (sub *Sub) PrefillZZZ(k xopat.K, v zzz) *Sub { sub.settings.PrefillZZZ(k, v) return sub } -func (settings *LogSettings) PrefillZZZ(k string, v zzz) { +func (settings *LogSettings) PrefillZZZ(k xopat.K, v zzz) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.ZZZ(k, v) }) @@ -410,11 +414,11 @@ func (settings *LogSettings) PrefillZZZ(k string, v zzz) { // line. // PrefillZZZ is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillZZZ(k string, v zzz) *Sub { +func (sub *Sub) PrefillZZZ(k xopat.K, v zzz) *Sub { sub.settings.PrefillZZZ(k, v) return sub } -func (settings *LogSettings) PrefillZZZ(k string, v zzz) { +func (settings *LogSettings) PrefillZZZ(k xopat.K, v zzz) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.ZZZ(k, v, xopbase.ZZZDataType) }) @@ -425,11 +429,11 @@ func (settings *LogSettings) PrefillZZZ(k string, v zzz) { // line. // PrefillZZZ is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillZZZ(k string, v zzz) *Sub { +func (sub *Sub) PrefillZZZ(k xopat.K, v zzz) *Sub { sub.settings.PrefillZZZ(k, v) return sub } -func (settings *LogSettings) PrefillZZZ(k string, v zzz) { +func (settings *LogSettings) PrefillZZZ(k xopat.K, v zzz) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Int64(k, int64(v), xopbase.ZZZDataType) }) @@ -440,11 +444,11 @@ func (settings *LogSettings) PrefillZZZ(k string, v zzz) { // line. // PrefillZZZ is not threadsafe with respect to other calls on the same *Sub. // Should not be used after Step(), Fork(), or Logger() is called. -func (sub *Sub) PrefillZZZ(k string, v zzz) *Sub { +func (sub *Sub) PrefillZZZ(k xopat.K, v zzz) *Sub { sub.settings.PrefillZZZ(k, v) return sub } -func (settings *LogSettings) PrefillZZZ(k string, v zzz) { +func (settings *LogSettings) PrefillZZZ(k xopat.K, v zzz) { settings.prefillData = append(settings.prefillData, func(line xopbase.Prefilling) { line.Uint64(k, uint64(v), xopbase.ZZZDataType) }) diff --git a/sub_test.go b/sub_test.go index b5959717..d6737fbf 100644 --- a/sub_test.go +++ b/sub_test.go @@ -58,7 +58,7 @@ func TestSub_NoPrefill(t *testing.T) { sub := Default.Sub() assert.Nil(t, sub.settings.prefillData) assert.Empty(t, sub.settings.prefillMsg) - sub.PrefillAny("foo", "bar") + sub.PrefillAny(Key("foo"), "bar") sub.PrefillText("text") assert.NotNil(t, sub.settings.prefillData) assert.NotEmpty(t, sub.settings.prefillMsg) @@ -69,24 +69,24 @@ func TestSub_NoPrefill(t *testing.T) { func TestSub_PrefillBool(t *testing.T) { sub := Default.Sub() - sub.PrefillBool("key", true) + sub.PrefillBool(Key("key"), true) assert.Len(t, sub.settings.prefillData, 1) } func TestSub_PrefillDuration(t *testing.T) { sub := Default.Sub() - sub.PrefillDuration("key", 1*time.Second) + sub.PrefillDuration(Key("key"), 1*time.Second) assert.Len(t, sub.settings.prefillData, 1) } func TestSub_PrefillError(t *testing.T) { sub := Default.Sub() - sub.PrefillError("key", errors.New("error")) + sub.PrefillError(Key("key"), errors.New("error")) assert.Len(t, sub.settings.prefillData, 1) } func TestSub_PrefillFloat64(t *testing.T) { sub := Default.Sub() - sub.PrefillFloat64("key", 64) + sub.PrefillFloat64(Key("key"), 64) assert.Len(t, sub.settings.prefillData, 1) } diff --git a/xopat/attributes.go b/xopat/attributes.go index 3088d858..a6cedd32 100644 --- a/xopat/attributes.go +++ b/xopat/attributes.go @@ -33,6 +33,7 @@ type Attribute struct { namespace string version string properties Make + key K jsonKey JSONKey consoleKey []byte exampleValue interface{} @@ -155,6 +156,7 @@ func (s Make) make(registry *Registry, exampleValue interface{}, subType Attribu } ra := Attribute{ + key: K(s.Key), namespace: namespace, version: sver.String(), properties: s, @@ -197,7 +199,7 @@ func (r Attribute) ReflectType() reflect.Type { return r.reflectType } // ConsoleKey includes an = func (r Attribute) ConsoleKey() []byte { return r.consoleKey } -func (r Attribute) Key() string { return r.properties.Key } +func (r Attribute) Key() K { return r.key } func (r Attribute) Description() string { return r.properties.Description } func (r Attribute) Namespace() string { return r.namespace } func (r Attribute) Indexed() bool { return r.properties.Indexed } @@ -224,7 +226,7 @@ type AttributeInterface interface { JSONKey() JSONKey ConsoleKey() []byte // includes an '=' ReflectType() reflect.Type - Key() string + Key() K Description() string Namespace() string Indexed() bool diff --git a/xopat/attributes.zzzgo b/xopat/attributes.zzzgo index 5977696d..7df52f5a 100644 --- a/xopat/attributes.zzzgo +++ b/xopat/attributes.zzzgo @@ -1,3 +1,9 @@ +// TEMPLATE-FILE +// TEMPLATE-FILE +// TEMPLATE-FILE +// TEMPLATE-FILE +// TEMPLATE-FILE + package xopat import ( @@ -29,6 +35,7 @@ type Attribute struct { namespace string version string properties Make + key K jsonKey JSONKey consoleKey []byte exampleValue interface{} @@ -149,6 +156,7 @@ func (s Make) make(registry *Registry, exampleValue interface{}, subType Attribu } ra := Attribute{ + key: K(s.Key), namespace: namespace, version: sver.String(), properties: s, @@ -191,7 +199,7 @@ func (r Attribute) ReflectType() reflect.Type { return r.reflectType } // ConsoleKey includes an = func (r Attribute) ConsoleKey() []byte { return r.consoleKey } -func (r Attribute) Key() string { return r.properties.Key } +func (r Attribute) Key() K { return r.key } func (r Attribute) Description() string { return r.properties.Description } func (r Attribute) Namespace() string { return r.namespace } func (r Attribute) Indexed() bool { return r.properties.Indexed } @@ -218,7 +226,7 @@ type AttributeInterface interface { JSONKey() JSONKey ConsoleKey() []byte // includes an '=' ReflectType() reflect.Type - Key() string + Key() K Description() string Namespace() string Indexed() bool diff --git a/xopat/json.go b/xopat/json.go index 1c64da84..c12b84af 100644 --- a/xopat/json.go +++ b/xopat/json.go @@ -4,14 +4,14 @@ import ( "github.com/xoplog/xop-go/xoputil" ) -var defineAttributeStarter = []byte(`{"type":"defineKey","key":"`) // } +var defineAttributeStarter = []byte(`{"type":"defineKey","key":`) // } func jsonAttributeDefinition(k *Attribute) []byte { b := xoputil.JBuilder{} b.B = make([]byte, len(defineAttributeStarter), len(defineAttributeStarter)+100) copy(b.B, defineAttributeStarter) - b.AddStringBody(k.Key()) - b.AppendBytes([]byte(`","desc":"`)) + b.AppendBytes(k.Key().JSON()) + b.AppendBytes([]byte(`,"desc":"`)) b.AddStringBody(k.Description()) b.AppendBytes([]byte(`","ns":"`)) b.AddStringBody(k.Namespace()) diff --git a/xopat/key.go b/xopat/key.go new file mode 100644 index 00000000..eeb77f75 --- /dev/null +++ b/xopat/key.go @@ -0,0 +1,43 @@ +package xopat + +import ( + "github.com/xoplog/xop-go/xoputil" + + "github.com/muir/gwrap" +) + +type K string + +func (k K) String() string { return string(k) } + +// JSONBody is the original key with escapes needed for being used +// as a JSON string body. Do not modify the slice. +func (k K) JSONBody() []byte { + qjs := k.JSON() + return qjs[1 : len(qjs)-1] +} + +// JSONBody is the original key as a quoted JSON string. +// Do not modify the slice. +func (k K) JSON() []byte { + qjs, ok := cachedKeys.Load(k) + if ok { + return qjs + } + b := xoputil.JBuilder{} + b.B = make([]byte, 0, len(k)+2) + b.AppendByte('"') + b.AddStringBody(string(k)) + b.AppendByte('"') + qjs, _ = cachedKeys.LoadOrStore(k, b.B) + return qjs +} + +var cachedKeys gwrap.SyncMap[K, []byte] + +func ResetCachedKeys() { + cachedKeys.Range(func(key K, value []byte) bool { + cachedKeys.Delete(key) + return true + }) +} diff --git a/xopat/key_test.go b/xopat/key_test.go new file mode 100644 index 00000000..b1300ccb --- /dev/null +++ b/xopat/key_test.go @@ -0,0 +1,19 @@ +package xopat_test + +import ( + "testing" + + "github.com/xoplog/xop-go/xopat" + + "github.com/stretchr/testify/assert" +) + +func TestKey(t *testing.T) { + k := xopat.K(`foo " bar`) + jsBody := `foo \" bar` + js := `"` + jsBody + `"` + + assert.Equal(t, string(k), k.String()) + assert.Equal(t, js, string(k.JSON())) + assert.Equal(t, jsBody, string(k.JSONBody())) +} diff --git a/xopbase/base.go b/xopbase/base.go index 4f7cfc77..80db16ce 100644 --- a/xopbase/base.go +++ b/xopbase/base.go @@ -239,36 +239,36 @@ type Builder interface { // Float64 adds a key/value pair. Calls to Float64 are expected to be // sequenced with other calls to add attributes to prefill and/or // lines. - Float64(string, float64, DataType) + Float64(xopat.K, float64, DataType) // Int64 adds a key/value pair. Calls to Int64 are expected to be // sequenced with other calls to add attributes to prefill and/or // lines. - Int64(string, int64, DataType) + Int64(xopat.K, int64, DataType) // String adds a key/value pair. Calls to String are expected to be // sequenced with other calls to add attributes to prefill and/or // lines. - String(string, string, DataType) + String(xopat.K, string, DataType) // Uint64 adds a key/value pair. Calls to Uint64 are expected to be // sequenced with other calls to add attributes to prefill and/or // lines. - Uint64(string, uint64, DataType) + Uint64(xopat.K, uint64, DataType) // Any adds a key/value pair. Calls to Any are expected to be // sequenced with other calls to add attributes to prefill and/or // lines. - Any(string, ModelArg) + Any(xopat.K, ModelArg) // Bool adds a key/value pair. Calls to Bool are expected to be // sequenced with other calls to add attributes to prefill and/or // lines. - Bool(string, bool) + Bool(xopat.K, bool) // Duration adds a key/value pair. Calls to Duration are expected to be // sequenced with other calls to add attributes to prefill and/or // lines. - Duration(string, time.Duration) + Duration(xopat.K, time.Duration) // Time adds a key/value pair. Calls to Time are expected to be // sequenced with other calls to add attributes to prefill and/or // lines. - Time(string, time.Time) + Time(xopat.K, time.Time) // TODO: RedactedString(name string, value string, unredaction string) } diff --git a/xopbase/base.zzzgo b/xopbase/base.zzzgo index c37c626b..27c2ec1c 100644 --- a/xopbase/base.zzzgo +++ b/xopbase/base.zzzgo @@ -13,6 +13,7 @@ package xopbase import ( "context" + "runtime" "time" "github.com/xoplog/xop-go/xopat" @@ -220,13 +221,13 @@ type Builder interface { // ZZZ adds a key/value pair. Calls to ZZZ are expected to be // sequenced with other calls to add attributes to prefill and/or // lines. - ZZZ(string, zzz, DataType) + ZZZ(xopat.K, zzz, DataType) // MACRO BaseDataWithoutType // ZZZ adds a key/value pair. Calls to ZZZ are expected to be // sequenced with other calls to add attributes to prefill and/or // lines. - ZZZ(string, zzz) + ZZZ(xopat.K, zzz) // TODO: RedactedString(name string, value string, unredaction string) } diff --git a/xopbase/skip.go b/xopbase/skip.go index 8b0702b2..8c267e08 100644 --- a/xopbase/skip.go +++ b/xopbase/skip.go @@ -17,7 +17,7 @@ type skipLine struct{} var _ Line = skipLine{} -func (_ skipLine) AnyImmutable(string, interface{}) {} +func (_ skipLine) AnyImmutable(xopat.K, interface{}) {} func (_ skipLine) Enum(k *xopat.EnumAttribute, v xopat.Enum) {} func (_ skipLine) Msg(string) {} @@ -25,12 +25,12 @@ func (_ skipLine) Link(string, xoptrace.Trace) {} func (_ skipLine) Model(string, ModelArg) {} func (_ skipLine) Template(string) {} -func (_ skipLine) Any(string, ModelArg) {} -func (_ skipLine) Bool(string, bool) {} -func (_ skipLine) Duration(string, time.Duration) {} -func (_ skipLine) Time(string, time.Time) {} +func (_ skipLine) Any(xopat.K, ModelArg) {} +func (_ skipLine) Bool(xopat.K, bool) {} +func (_ skipLine) Duration(xopat.K, time.Duration) {} +func (_ skipLine) Time(xopat.K, time.Time) {} -func (_ skipLine) Float64(string, float64, DataType) {} -func (_ skipLine) Int64(string, int64, DataType) {} -func (_ skipLine) String(string, string, DataType) {} -func (_ skipLine) Uint64(string, uint64, DataType) {} +func (_ skipLine) Float64(xopat.K, float64, DataType) {} +func (_ skipLine) Int64(xopat.K, int64, DataType) {} +func (_ skipLine) String(xopat.K, string, DataType) {} +func (_ skipLine) Uint64(xopat.K, uint64, DataType) {} diff --git a/xopbase/skip.zzzgo b/xopbase/skip.zzzgo index db3df3fd..003f7e96 100644 --- a/xopbase/skip.zzzgo +++ b/xopbase/skip.zzzgo @@ -13,7 +13,7 @@ type skipLine struct{} var _ Line = skipLine{} -func (_ skipLine) AnyImmutable(string, interface{}) {} +func (_ skipLine) AnyImmutable(xopat.K, interface{}) {} func (_ skipLine) Enum(k *xopat.EnumAttribute, v xopat.Enum) {} func (_ skipLine) Msg(string) {} @@ -22,7 +22,7 @@ func (_ skipLine) Model(string, ModelArg) {} func (_ skipLine) Template(string) {} // MACRO BaseDataWithoutType -func (_ skipLine) ZZZ(string, zzz) {} +func (_ skipLine) ZZZ(xopat.K, zzz) {} // MACRO BaseDataWithType -func (_ skipLine) ZZZ(string, zzz, DataType) {} +func (_ skipLine) ZZZ(xopat.K, zzz, DataType) {} diff --git a/xopbase/xopbaseutil/metadata.go b/xopbase/xopbaseutil/metadata.go index c5537bea..4c78f556 100644 --- a/xopbase/xopbaseutil/metadata.go +++ b/xopbase/xopbaseutil/metadata.go @@ -44,13 +44,13 @@ func (s SpanMetadata) Get(k string) *MetadataTracker { // MetadataAny is a required method for xopbase.Span func (s *SpanMetadata) MetadataAny(k *xopat.AnyAttribute, v xopbase.ModelArg) { v.Encode() - tracker, loaded := s.Map.Load(k.Key()) + tracker, loaded := s.Map.Load(k.Key().String()) if loaded { tracker.Mu.Lock() } else { n := &MetadataTracker{} n.Mu.Lock() - tracker, loaded = s.Map.LoadOrStore(k.Key(), n) + tracker, loaded = s.Map.LoadOrStore(k.Key().String(), n) if loaded { tracker.Mu.Lock() } else { @@ -96,13 +96,13 @@ func (s *SpanMetadata) MetadataAny(k *xopat.AnyAttribute, v xopbase.ModelArg) { // MetadataBool is a required method for xopbase.Span func (s *SpanMetadata) MetadataBool(k *xopat.BoolAttribute, v bool) { - tracker, loaded := s.Map.Load(k.Key()) + tracker, loaded := s.Map.Load(k.Key().String()) if loaded { tracker.Mu.Lock() } else { n := &MetadataTracker{} n.Mu.Lock() - tracker, loaded = s.Map.LoadOrStore(k.Key(), n) + tracker, loaded = s.Map.LoadOrStore(k.Key().String(), n) if loaded { tracker.Mu.Lock() } else { @@ -146,13 +146,13 @@ func (s *SpanMetadata) MetadataBool(k *xopat.BoolAttribute, v bool) { // MetadataEnum is a required method for xopbase.Span func (s *SpanMetadata) MetadataEnum(k *xopat.EnumAttribute, v xopat.Enum) { - tracker, loaded := s.Map.Load(k.Key()) + tracker, loaded := s.Map.Load(k.Key().String()) if loaded { tracker.Mu.Lock() } else { n := &MetadataTracker{} n.Mu.Lock() - tracker, loaded = s.Map.LoadOrStore(k.Key(), n) + tracker, loaded = s.Map.LoadOrStore(k.Key().String(), n) if loaded { tracker.Mu.Lock() } else { @@ -196,13 +196,13 @@ func (s *SpanMetadata) MetadataEnum(k *xopat.EnumAttribute, v xopat.Enum) { // MetadataFloat64 is a required method for xopbase.Span func (s *SpanMetadata) MetadataFloat64(k *xopat.Float64Attribute, v float64) { - tracker, loaded := s.Map.Load(k.Key()) + tracker, loaded := s.Map.Load(k.Key().String()) if loaded { tracker.Mu.Lock() } else { n := &MetadataTracker{} n.Mu.Lock() - tracker, loaded = s.Map.LoadOrStore(k.Key(), n) + tracker, loaded = s.Map.LoadOrStore(k.Key().String(), n) if loaded { tracker.Mu.Lock() } else { @@ -246,13 +246,13 @@ func (s *SpanMetadata) MetadataFloat64(k *xopat.Float64Attribute, v float64) { // MetadataInt64 is a required method for xopbase.Span func (s *SpanMetadata) MetadataInt64(k *xopat.Int64Attribute, v int64) { - tracker, loaded := s.Map.Load(k.Key()) + tracker, loaded := s.Map.Load(k.Key().String()) if loaded { tracker.Mu.Lock() } else { n := &MetadataTracker{} n.Mu.Lock() - tracker, loaded = s.Map.LoadOrStore(k.Key(), n) + tracker, loaded = s.Map.LoadOrStore(k.Key().String(), n) if loaded { tracker.Mu.Lock() } else { @@ -296,13 +296,13 @@ func (s *SpanMetadata) MetadataInt64(k *xopat.Int64Attribute, v int64) { // MetadataLink is a required method for xopbase.Span func (s *SpanMetadata) MetadataLink(k *xopat.LinkAttribute, v xoptrace.Trace) { - tracker, loaded := s.Map.Load(k.Key()) + tracker, loaded := s.Map.Load(k.Key().String()) if loaded { tracker.Mu.Lock() } else { n := &MetadataTracker{} n.Mu.Lock() - tracker, loaded = s.Map.LoadOrStore(k.Key(), n) + tracker, loaded = s.Map.LoadOrStore(k.Key().String(), n) if loaded { tracker.Mu.Lock() } else { @@ -346,13 +346,13 @@ func (s *SpanMetadata) MetadataLink(k *xopat.LinkAttribute, v xoptrace.Trace) { // MetadataString is a required method for xopbase.Span func (s *SpanMetadata) MetadataString(k *xopat.StringAttribute, v string) { - tracker, loaded := s.Map.Load(k.Key()) + tracker, loaded := s.Map.Load(k.Key().String()) if loaded { tracker.Mu.Lock() } else { n := &MetadataTracker{} n.Mu.Lock() - tracker, loaded = s.Map.LoadOrStore(k.Key(), n) + tracker, loaded = s.Map.LoadOrStore(k.Key().String(), n) if loaded { tracker.Mu.Lock() } else { @@ -396,13 +396,13 @@ func (s *SpanMetadata) MetadataString(k *xopat.StringAttribute, v string) { // MetadataTime is a required method for xopbase.Span func (s *SpanMetadata) MetadataTime(k *xopat.TimeAttribute, v time.Time) { - tracker, loaded := s.Map.Load(k.Key()) + tracker, loaded := s.Map.Load(k.Key().String()) if loaded { tracker.Mu.Lock() } else { n := &MetadataTracker{} n.Mu.Lock() - tracker, loaded = s.Map.LoadOrStore(k.Key(), n) + tracker, loaded = s.Map.LoadOrStore(k.Key().String(), n) if loaded { tracker.Mu.Lock() } else { diff --git a/xopbase/xopbaseutil/metadata.zzzgo b/xopbase/xopbaseutil/metadata.zzzgo index b31fc2b0..58a2d37c 100644 --- a/xopbase/xopbaseutil/metadata.zzzgo +++ b/xopbase/xopbaseutil/metadata.zzzgo @@ -43,13 +43,13 @@ func (s *SpanMetadata) MetadataZZZ(k *xopat.ZZZAttribute, v zzz) { //CONDITIONAL ONLY:Any v.Encode() //END CONDITIONAL - tracker, loaded := s.Map.Load(k.Key()) + tracker, loaded := s.Map.Load(k.Key().String()) if loaded { tracker.Mu.Lock() } else { n := &MetadataTracker{} n.Mu.Lock() - tracker, loaded = s.Map.LoadOrStore(k.Key(), n) + tracker, loaded = s.Map.LoadOrStore(k.Key().String(), n) if loaded { tracker.Mu.Lock() } else { diff --git a/xopcon/console.go b/xopcon/console.go index 0d208c51..6c43b71d 100644 --- a/xopcon/console.go +++ b/xopcon/console.go @@ -332,38 +332,38 @@ func (line Line) send(text string) { line.Span.logger.output(text) } -func (b *Builder) any(k string, v interface{}) { - b.Data[k] = v +func (b *Builder) any(k xopat.K, v interface{}) { + b.Data[k.String()] = v b.kvText = append(b.kvText, fmt.Sprintf("%s=%+v", k, v)) } // Enum is a required method for xopbase.ObjectParts func (b *Builder) Enum(k *xopat.EnumAttribute, v xopat.Enum) { - ks := k.Key() + ks := k.Key().String() b.Data[ks] = v b.kvText = append(b.kvText, fmt.Sprintf("%s=%s(%d)", ks, v.String(), v.Int64())) } // Any is a required method for xopbase.ObjectParts -func (b *Builder) Any(k string, v xopbase.ModelArg) { b.any(k, v) } +func (b *Builder) Any(k xopat.K, v xopbase.ModelArg) { b.any(k, v) } // Bool is a required method for xopbase.ObjectParts -func (b *Builder) Bool(k string, v bool) { b.any(k, v) } +func (b *Builder) Bool(k xopat.K, v bool) { b.any(k, v) } // Duration is a required method for xopbase.ObjectParts -func (b *Builder) Duration(k string, v time.Duration) { b.any(k, v) } +func (b *Builder) Duration(k xopat.K, v time.Duration) { b.any(k, v) } // Time is a required method for xopbase.ObjectParts -func (b *Builder) Time(k string, v time.Time) { b.any(k, v) } +func (b *Builder) Time(k xopat.K, v time.Time) { b.any(k, v) } // Float64 is a required method for xopbase.ObjectParts -func (b *Builder) Float64(k string, v float64, dt xopbase.DataType) { b.any(k, v) } +func (b *Builder) Float64(k xopat.K, v float64, dt xopbase.DataType) { b.any(k, v) } // Int64 is a required method for xopbase.ObjectParts -func (b *Builder) Int64(k string, v int64, dt xopbase.DataType) { b.any(k, v) } +func (b *Builder) Int64(k xopat.K, v int64, dt xopbase.DataType) { b.any(k, v) } // String is a required method for xopbase.ObjectParts -func (b *Builder) String(k string, v string, dt xopbase.DataType) { b.any(k, v) } +func (b *Builder) String(k xopat.K, v string, dt xopbase.DataType) { b.any(k, v) } // Uint64 is a required method for xopbase.ObjectParts -func (b *Builder) Uint64(k string, v uint64, dt xopbase.DataType) { b.any(k, v) } +func (b *Builder) Uint64(k xopat.K, v uint64, dt xopbase.DataType) { b.any(k, v) } diff --git a/xopcon/console.zzzgo b/xopcon/console.zzzgo index b8a8caec..fa05f886 100644 --- a/xopcon/console.zzzgo +++ b/xopcon/console.zzzgo @@ -332,22 +332,22 @@ func (line Line) send(text string) { line.Span.logger.output(text) } -func (b *Builder) any(k string, v interface{}) { - b.Data[k] = v +func (b *Builder) any(k xopat.K, v interface{}) { + b.Data[k.String()] = v b.kvText = append(b.kvText, fmt.Sprintf("%s=%+v", k, v)) } // Enum is a required method for xopbase.ObjectParts func (b *Builder) Enum(k *xopat.EnumAttribute, v xopat.Enum) { - ks := k.Key() + ks := k.Key().String() b.Data[ks] = v b.kvText = append(b.kvText, fmt.Sprintf("%s=%s(%d)", ks, v.String(), v.Int64())) } // MACRO BaseDataWithoutType // ZZZ is a required method for xopbase.ObjectParts -func (b *Builder) ZZZ(k string, v zzz) { b.any(k, v) } +func (b *Builder) ZZZ(k xopat.K, v zzz) { b.any(k, v) } // MACRO BaseDataWithType // ZZZ is a required method for xopbase.ObjectParts -func (b *Builder) ZZZ(k string, v zzz, dt xopbase.DataType) { b.any(k, v) } +func (b *Builder) ZZZ(k xopat.K, v zzz, dt xopbase.DataType) { b.any(k, v) } diff --git a/xopconsole/attributes.go b/xopconsole/attributes.go index 7dea8f4c..579383bb 100644 --- a/xopconsole/attributes.go +++ b/xopconsole/attributes.go @@ -31,8 +31,8 @@ type AttributeBuilder struct { singles []singleAttribute multis []multiAttribute Type xopbase.DataType - singleMap map[string]*singleAttribute - multiMap map[string]*multiAttribute + singleMap map[xopat.K]*singleAttribute + multiMap map[xopat.K]*multiAttribute anyChanged bool encodeTarget *[]byte encoder *json.Encoder @@ -61,8 +61,8 @@ type attribute struct { func (a *AttributeBuilder) Init(request *Span) { a.singles = a.singlesBuf[:0] a.multis = a.multiBuf[:0] - a.singleMap = make(map[string]*singleAttribute) - a.multiMap = make(map[string]*multiAttribute) + a.singleMap = make(map[xopat.K]*singleAttribute) + a.multiMap = make(map[xopat.K]*multiAttribute) a.anyChanged = false a.request = request } diff --git a/xopconsole/attributes.zzzgo b/xopconsole/attributes.zzzgo index 974ef1a1..3763c191 100644 --- a/xopconsole/attributes.zzzgo +++ b/xopconsole/attributes.zzzgo @@ -32,8 +32,8 @@ type AttributeBuilder struct { singles []singleAttribute multis []multiAttribute Type xopbase.DataType - singleMap map[string]*singleAttribute - multiMap map[string]*multiAttribute + singleMap map[xopat.K]*singleAttribute + multiMap map[xopat.K]*multiAttribute anyChanged bool encodeTarget *[]byte encoder *json.Encoder @@ -62,8 +62,8 @@ type attribute struct { func (a *AttributeBuilder) Init(request *Span) { a.singles = a.singlesBuf[:0] a.multis = a.multiBuf[:0] - a.singleMap = make(map[string]*singleAttribute) - a.multiMap = make(map[string]*multiAttribute) + a.singleMap = make(map[xopat.K]*singleAttribute) + a.multiMap = make(map[xopat.K]*multiAttribute) a.anyChanged = false a.request = request } diff --git a/xopconsole/console.go b/xopconsole/console.go index 64f874ec..fb0d9361 100644 --- a/xopconsole/console.go +++ b/xopconsole/console.go @@ -373,9 +373,9 @@ func (line Line) send(prefix []byte, text string, postfix []byte) { } } -func (b *Builder) addKey(k string) { +func (b *Builder) addKey(k xopat.K) { b.B = append(b.B, ' ') - b.AddConsoleString(k) + b.AddConsoleString(string(k)) b.B = append(b.B, '=') } @@ -385,19 +385,19 @@ func (b *Builder) addType(t string) { b.B = append(b.B, ')') } -func (b *Builder) Duration(k string, v time.Duration) { +func (b *Builder) Duration(k xopat.K, v time.Duration) { b.addKey(k) b.B = append(b.B, []byte(v.String())...) b.addType(xopbase.DurationDataTypeAbbr) } -func (b *Builder) Float64(k string, v float64, t xopbase.DataType) { +func (b *Builder) Float64(k xopat.K, v float64, t xopbase.DataType) { b.addKey(k) b.AddFloat64(v) b.addType(xopbase.DataTypeToString[t]) } -func (b *Builder) String(k string, v string, t xopbase.DataType) { +func (b *Builder) String(k xopat.K, v string, t xopbase.DataType) { b.addKey(k) b.AddConsoleString(v) if t != xopbase.StringDataType { @@ -405,7 +405,7 @@ func (b *Builder) String(k string, v string, t xopbase.DataType) { } } -func (b *Builder) Int64(k string, v int64, t xopbase.DataType) { +func (b *Builder) Int64(k xopat.K, v int64, t xopbase.DataType) { b.addKey(k) b.B = strconv.AppendInt(b.B, v, 10) if t != xopbase.IntDataType { @@ -413,13 +413,13 @@ func (b *Builder) Int64(k string, v int64, t xopbase.DataType) { } } -func (b *Builder) Uint64(k string, v uint64, t xopbase.DataType) { +func (b *Builder) Uint64(k xopat.K, v uint64, t xopbase.DataType) { b.addKey(k) b.AddUint64(v) b.addType(xopbase.DataTypeToString[t]) } -func (b *Builder) Bool(k string, v bool) { +func (b *Builder) Bool(k xopat.K, v bool) { b.addKey(k) if v { b.B = append(b.B, 't') @@ -429,7 +429,7 @@ func (b *Builder) Bool(k string, v bool) { b.addType(xopbase.BoolDataTypeAbbr) } -func (b *Builder) Time(k string, t time.Time) { +func (b *Builder) Time(k xopat.K, t time.Time) { b.addKey(k) b.B = t.AppendFormat(b.B, time.RFC3339Nano) b.addType(xopbase.TimeDataTypeAbbr) @@ -442,7 +442,7 @@ func (b *Builder) Enum(k *xopat.EnumAttribute, v xopat.Enum) { b.AttributeEnum(v) } -func (b *Builder) Any(k string, v xopbase.ModelArg) { +func (b *Builder) Any(k xopat.K, v xopbase.ModelArg) { b.addKey(k) b.AnyCommon(v) } diff --git a/xopconsole/replay.go b/xopconsole/replay.go index b9330028..558a9ef2 100644 --- a/xopconsole/replay.go +++ b/xopconsole/replay.go @@ -194,7 +194,7 @@ func (x replayLine) replayLine(ctx context.Context, t string) error { if err != nil { return errors.Wrap(err, "parse any attribute") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Any(key, ma) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Any(xopat.K(key), ma) }) if sep == '\000' { break } @@ -203,7 +203,7 @@ func (x replayLine) replayLine(ctx context.Context, t string) error { value, t = oneString(t) if len(t) == 0 { // valid for a terminal string value - x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(key, value, xopbase.StringDataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(xopat.K(key), value, xopbase.StringDataType) }) break } sep, t = t[0], t[1:] @@ -231,49 +231,49 @@ func (x replayLine) replayLine(ctx context.Context, t string) error { if err != nil { return errors.Wrap(err, "invalid bool") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Bool(key, b) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Bool(xopat.K(key), b) }) case "dur": dur, err := time.ParseDuration(value) if err != nil { return errors.Wrap(err, "invalid duration") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Duration(key, dur) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Duration(xopat.K(key), dur) }) case "f32": f, err := strconv.ParseFloat(value, 32) if err != nil { return errors.Wrap(err, "invalid float") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Float64(key, f, xopbase.Float32DataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Float64(xopat.K(key), f, xopbase.Float32DataType) }) case "f64": f, err := strconv.ParseFloat(value, 64) if err != nil { return errors.Wrap(err, "invalid float") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Float64(key, f, xopbase.Float64DataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Float64(xopat.K(key), f, xopbase.Float64DataType) }) case "string": - x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(key, value, xopbase.StringDataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(xopat.K(key), value, xopbase.StringDataType) }) case "stringer": - x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(key, value, xopbase.StringerDataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(xopat.K(key), value, xopbase.StringerDataType) }) case "error": - x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(key, value, xopbase.ErrorDataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(xopat.K(key), value, xopbase.ErrorDataType) }) case "i8", "i16", "i32", "i64", "int": i, err := strconv.ParseInt(value, 10, 64) if err != nil { return errors.Wrap(err, "invalid int") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Int64(key, i, xopbase.StringToDataType[typ]) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Int64(xopat.K(key), i, xopbase.StringToDataType[typ]) }) case "u", "u8", "u16", "u32", "u64", "uintptr": i, err := strconv.ParseUint(value, 10, 64) if err != nil { return errors.Wrap(err, "invalid uint") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Uint64(key, i, xopbase.StringToDataType[typ]) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Uint64(xopat.K(key), i, xopbase.StringToDataType[typ]) }) case "time": ts, err := time.Parse(time.RFC3339Nano, value) if err != nil { return errors.Wrap(err, "invalid time") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Time(key, ts) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Time(xopat.K(key), ts) }) default: return errors.Errorf("invalid type: %s", typ) } @@ -287,15 +287,15 @@ func (x replayLine) replayLine(ctx context.Context, t string) error { if err != nil { return errors.Wrap(err, "invalid int") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Int64(key, i, xopbase.IntDataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Int64(xopat.K(key), i, xopbase.IntDataType) }) default: switch value { case "t": - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Bool(key, true) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Bool(xopat.K(key), true) }) case "f": - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Bool(key, false) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Bool(xopat.K(key), false) }) default: - x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(key, value, xopbase.StringDataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(xopat.K(key), value, xopbase.StringDataType) }) } } if sep == '\000' { diff --git a/xopconsole/replay.zzzgo b/xopconsole/replay.zzzgo index df33d7f0..45ebc074 100644 --- a/xopconsole/replay.zzzgo +++ b/xopconsole/replay.zzzgo @@ -195,7 +195,7 @@ func (x replayLine) replayLine(ctx context.Context, t string) error { if err != nil { return errors.Wrap(err, "parse any attribute") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Any(key, ma) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Any(xopat.K(key), ma) }) if sep == '\000' { break } @@ -204,7 +204,7 @@ func (x replayLine) replayLine(ctx context.Context, t string) error { value, t = oneString(t) if len(t) == 0 { // valid for a terminal string value - x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(key, value, xopbase.StringDataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(xopat.K(key), value, xopbase.StringDataType) }) break } sep, t = t[0], t[1:] @@ -232,49 +232,49 @@ func (x replayLine) replayLine(ctx context.Context, t string) error { if err != nil { return errors.Wrap(err, "invalid bool") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Bool(key, b) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Bool(xopat.K(key), b) }) case "dur": dur, err := time.ParseDuration(value) if err != nil { return errors.Wrap(err, "invalid duration") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Duration(key, dur) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Duration(xopat.K(key), dur) }) case "f32": f, err := strconv.ParseFloat(value, 32) if err != nil { return errors.Wrap(err, "invalid float") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Float64(key, f, xopbase.Float32DataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Float64(xopat.K(key), f, xopbase.Float32DataType) }) case "f64": f, err := strconv.ParseFloat(value, 64) if err != nil { return errors.Wrap(err, "invalid float") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Float64(key, f, xopbase.Float64DataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Float64(xopat.K(key), f, xopbase.Float64DataType) }) case "string": - x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(key, value, xopbase.StringDataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(xopat.K(key), value, xopbase.StringDataType) }) case "stringer": - x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(key, value, xopbase.StringerDataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(xopat.K(key), value, xopbase.StringerDataType) }) case "error": - x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(key, value, xopbase.ErrorDataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(xopat.K(key), value, xopbase.ErrorDataType) }) case "i8", "i16", "i32", "i64", "int": i, err := strconv.ParseInt(value, 10, 64) if err != nil { return errors.Wrap(err, "invalid int") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Int64(key, i, xopbase.StringToDataType[typ]) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Int64(xopat.K(key), i, xopbase.StringToDataType[typ]) }) case "u", "u8", "u16", "u32", "u64", "uintptr": i, err := strconv.ParseUint(value, 10, 64) if err != nil { return errors.Wrap(err, "invalid uint") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Uint64(key, i, xopbase.StringToDataType[typ]) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Uint64(xopat.K(key), i, xopbase.StringToDataType[typ]) }) case "time": ts, err := time.Parse(time.RFC3339Nano, value) if err != nil { return errors.Wrap(err, "invalid time") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Time(key, ts) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Time(xopat.K(key), ts) }) default: return errors.Errorf("invalid type: %s", typ) } @@ -288,15 +288,15 @@ func (x replayLine) replayLine(ctx context.Context, t string) error { if err != nil { return errors.Wrap(err, "invalid int") } - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Int64(key, i, xopbase.IntDataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Int64(xopat.K(key), i, xopbase.IntDataType) }) default: switch value { case "t": - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Bool(key, true) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Bool(xopat.K(key), true) }) case "f": - x.attributes = append(x.attributes, func(line xopbase.Line) { line.Bool(key, false) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.Bool(xopat.K(key), false) }) default: - x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(key, value, xopbase.StringDataType) }) + x.attributes = append(x.attributes, func(line xopbase.Line) { line.String(xopat.K(key), value, xopbase.StringDataType) }) } } if sep == '\000' { diff --git a/xopjson/jsonlogger.go b/xopjson/jsonlogger.go index 590f85e1..6116e395 100644 --- a/xopjson/jsonlogger.go +++ b/xopjson/jsonlogger.go @@ -482,9 +482,9 @@ func (b *builder) startAttributes() { } } -func (b *builder) Any(k string, v xopbase.ModelArg) { +func (b *builder) Any(k xopat.K, v xopbase.ModelArg) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) // } b.AnyCommon(v) // { @@ -502,9 +502,9 @@ func (b *builder) Enum(k *xopat.EnumAttribute, v xopat.Enum) { b.AppendBytes([]byte(`,"t":"enum"}`)) } -func (b *builder) Time(k string, t time.Time) { +func (b *builder) Time(k xopat.K, t time.Time) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) b.AttributeTime(t) b.AppendBytes([]byte(`,"t":"time"}`)) @@ -514,17 +514,17 @@ func (b *builder) AttributeTime(t time.Time) { b.B = b.span.logger.timeFormatter(b.B, t) } -func (b *builder) Bool(k string, v bool) { +func (b *builder) Bool(k xopat.K, v bool) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) b.AddBool(v) b.AppendBytes([]byte(`,"t":"bool"}`)) } -func (b *builder) Int64(k string, v int64, t xopbase.DataType) { +func (b *builder) Int64(k xopat.K, v int64, t xopbase.DataType) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) b.AddInt64(v) b.AppendBytes([]byte(`,"t":`)) @@ -532,9 +532,9 @@ func (b *builder) Int64(k string, v int64, t xopbase.DataType) { b.AppendByte('}') } -func (b *builder) Uint64(k string, v uint64, t xopbase.DataType) { +func (b *builder) Uint64(k xopat.K, v uint64, t xopbase.DataType) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) b.AddUint64(v) b.AppendBytes([]byte(`,"t":`)) @@ -542,15 +542,15 @@ func (b *builder) Uint64(k string, v uint64, t xopbase.DataType) { b.AppendByte('}') } -func (b *builder) stringKV(k string, v string) { +func (b *builder) stringKV(k xopat.K, v string) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AddString(v) } -func (b *builder) String(k string, v string, t xopbase.DataType) { +func (b *builder) String(k xopat.K, v string, t xopbase.DataType) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) b.AddString(v) b.AppendBytes([]byte(`,"t":`)) @@ -558,9 +558,9 @@ func (b *builder) String(k string, v string, t xopbase.DataType) { b.AppendByte('}') } -func (b *builder) Float64(k string, v float64, t xopbase.DataType) { +func (b *builder) Float64(k xopat.K, v float64, t xopbase.DataType) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) b.AddFloat64(v) b.AppendBytes([]byte(`,"t":`)) @@ -568,9 +568,9 @@ func (b *builder) Float64(k string, v float64, t xopbase.DataType) { b.AppendByte('}') } -func (b *builder) Duration(k string, v time.Duration) { +func (b *builder) Duration(k xopat.K, v time.Duration) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) b.AddSafeString(v.String()) b.AppendBytes([]byte(`,"t":"dur"}`)) @@ -593,6 +593,12 @@ func (b *builder) AttributeDuration(v time.Duration) { } } +func (b *builder) addKey(k xopat.K) { + b.Comma() + b.AppendBytes(k.JSON()) + b.AppendByte(':') +} + func (s *span) MetadataAny(k *xopat.AnyAttribute, v xopbase.ModelArg) { var err error switch s.logger.attributeOption { diff --git a/xopjson/jsonlogger.zzzgo b/xopjson/jsonlogger.zzzgo index dfd40839..10c98724 100644 --- a/xopjson/jsonlogger.zzzgo +++ b/xopjson/jsonlogger.zzzgo @@ -484,9 +484,9 @@ func (b *builder) startAttributes() { } } -func (b *builder) Any(k string, v xopbase.ModelArg) { +func (b *builder) Any(k xopat.K, v xopbase.ModelArg) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) // } b.AnyCommon(v) // { @@ -504,9 +504,9 @@ func (b *builder) Enum(k *xopat.EnumAttribute, v xopat.Enum) { b.AppendBytes([]byte(`,"t":"enum"}`)) } -func (b *builder) Time(k string, t time.Time) { +func (b *builder) Time(k xopat.K, t time.Time) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) b.AttributeTime(t) b.AppendBytes([]byte(`,"t":"time"}`)) @@ -516,17 +516,17 @@ func (b *builder) AttributeTime(t time.Time) { b.B = b.span.logger.timeFormatter(b.B, t) } -func (b *builder) Bool(k string, v bool) { +func (b *builder) Bool(k xopat.K, v bool) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) b.AddBool(v) b.AppendBytes([]byte(`,"t":"bool"}`)) } -func (b *builder) Int64(k string, v int64, t xopbase.DataType) { +func (b *builder) Int64(k xopat.K, v int64, t xopbase.DataType) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) b.AddInt64(v) b.AppendBytes([]byte(`,"t":`)) @@ -534,9 +534,9 @@ func (b *builder) Int64(k string, v int64, t xopbase.DataType) { b.AppendByte('}') } -func (b *builder) Uint64(k string, v uint64, t xopbase.DataType) { +func (b *builder) Uint64(k xopat.K, v uint64, t xopbase.DataType) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) b.AddUint64(v) b.AppendBytes([]byte(`,"t":`)) @@ -544,15 +544,15 @@ func (b *builder) Uint64(k string, v uint64, t xopbase.DataType) { b.AppendByte('}') } -func (b *builder) stringKV(k string, v string) { +func (b *builder) stringKV(k xopat.K, v string) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AddString(v) } -func (b *builder) String(k string, v string, t xopbase.DataType) { +func (b *builder) String(k xopat.K, v string, t xopbase.DataType) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) b.AddString(v) b.AppendBytes([]byte(`,"t":`)) @@ -560,9 +560,9 @@ func (b *builder) String(k string, v string, t xopbase.DataType) { b.AppendByte('}') } -func (b *builder) Float64(k string, v float64, t xopbase.DataType) { +func (b *builder) Float64(k xopat.K, v float64, t xopbase.DataType) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) b.AddFloat64(v) b.AppendBytes([]byte(`,"t":`)) @@ -570,9 +570,9 @@ func (b *builder) Float64(k string, v float64, t xopbase.DataType) { b.AppendByte('}') } -func (b *builder) Duration(k string, v time.Duration) { +func (b *builder) Duration(k xopat.K, v time.Duration) { b.startAttributes() - b.AddKey(k) + b.addKey(k) b.AppendBytes([]byte(`{"v":`)) b.AddSafeString(v.String()) b.AppendBytes([]byte(`,"t":"dur"}`)) @@ -595,6 +595,12 @@ func (b *builder) AttributeDuration(v time.Duration) { } } +func (b *builder) addKey(k xopat.K) { + b.Comma() + b.AppendBytes(k.JSON()) + b.AppendByte(':') +} + // MACRO BaseAttribute func (s *span) MetadataZZZ(k *xopat.ZZZAttribute, v zzz) { var err error diff --git a/xopjson/jsonlogger_test.go b/xopjson/jsonlogger_test.go index b7f549cb..3aa35aff 100644 --- a/xopjson/jsonlogger_test.go +++ b/xopjson/jsonlogger_test.go @@ -40,7 +40,7 @@ func TestASingleLineJSON(t *testing.T) { }) }), ).Request(t.Name()) - log.Alert().String("foo", "bar").Int("blast", 99).Msg("a test line") + log.Alert().String(xop.Key("foo"), "bar").Int(xop.Key("blast"), 99).Msg("a test line") log.Done() s := buffer.String() t.Log(s) diff --git a/xopjson/models.go b/xopjson/models.go index 56f1f559..171099bb 100644 --- a/xopjson/models.go +++ b/xopjson/models.go @@ -4,6 +4,7 @@ import ( "sync" "time" + "github.com/xoplog/xop-go" "github.com/xoplog/xop-go/xopbase" "github.com/xoplog/xop-go/xopbytes" "github.com/xoplog/xop-go/xopjson/xopjsonutil" @@ -115,6 +116,9 @@ type builder struct { attributesWanted bool } +var spanName = xop.Key("span.name") +var spanParentSpan = xop.Key("span.parent_span") + type DurationOption int const ( diff --git a/xopjson/replay.go b/xopjson/replay.go index dc51b2fc..9e6d8a93 100644 --- a/xopjson/replay.go +++ b/xopjson/replay.go @@ -139,6 +139,7 @@ type baseReplay struct { } func ReplayFromStrings(ctx context.Context, data string, logger xopbase.Logger) error { + xopat.ResetCachedKeys() // prevent memory exhaustion var requests []*decodedRequest var spans []*decodedSpan x := baseReplay{ @@ -823,7 +824,8 @@ type replayLineAttribute struct { baseReplay } -func (x replayLineAttribute) Replay(line xopbase.Line, lineInput decodedLine, k string, enc []byte) error { +func (x replayLineAttribute) Replay(line xopbase.Line, lineInput decodedLine, ks string, enc []byte) error { + k := xopat.K(ks) var la lineAttribute err := json.Unmarshal(enc, &la) if err != nil { @@ -840,7 +842,7 @@ func (x replayLineAttribute) Replay(line xopbase.Line, lineInput decodedLine, k return errors.Errorf("invalid enum string (%T)", la.Value) } m := xopat.Make{ - Key: k, + Key: ks, } ea, err := x.attributeRegistry.ConstructEnumAttribute(m, xopat.AttributeTypeEnum) if err != nil { diff --git a/xopjson/replay.zzzgo b/xopjson/replay.zzzgo index 61dac3a7..824131bd 100644 --- a/xopjson/replay.zzzgo +++ b/xopjson/replay.zzzgo @@ -139,6 +139,7 @@ type baseReplay struct { } func ReplayFromStrings(ctx context.Context, data string, logger xopbase.Logger) error { + xopat.ResetCachedKeys() // prevent memory exhaustion var requests []*decodedRequest var spans []*decodedSpan x := baseReplay{ @@ -528,7 +529,8 @@ type replayLineAttribute struct { baseReplay } -func (x replayLineAttribute) Replay(line xopbase.Line, lineInput decodedLine, k string, enc []byte) error { +func (x replayLineAttribute) Replay(line xopbase.Line, lineInput decodedLine, ks string, enc []byte) error { + k := xopat.K(ks) var la lineAttribute err := json.Unmarshal(enc, &la) if err != nil { @@ -545,7 +547,7 @@ func (x replayLineAttribute) Replay(line xopbase.Line, lineInput decodedLine, k return errors.Errorf("invalid enum string (%T)", la.Value) } m := xopat.Make{ - Key: k, + Key: ks, } ea, err := x.attributeRegistry.ConstructEnumAttribute(m, xopat.AttributeTypeEnum) if err != nil { diff --git a/xopjson/xopjsonutil/attributes.go b/xopjson/xopjsonutil/attributes.go index 6907ae7f..b80d5a5b 100644 --- a/xopjson/xopjsonutil/attributes.go +++ b/xopjson/xopjsonutil/attributes.go @@ -158,7 +158,7 @@ func (a *AttributeBuilder) MetadataAny(k *xopat.AnyAttribute, v xopbase.ModelArg a.encoder.SetEscapeHTML(false) } if !k.Multiple() { - s, preExisting := a.addSingle(k.Key(), k.JSONKey()) + s, preExisting := a.addSingle(k.Key().String(), k.JSONKey()) if preExisting { if k.Locked() { return @@ -180,7 +180,7 @@ func (a *AttributeBuilder) MetadataAny(k *xopat.AnyAttribute, v xopbase.ModelArg s.KeyValue = b.B return } - m := a.addMulti(k.Key(), k.JSONKey()) + m := a.addMulti(k.Key().String(), k.JSONKey()) m.Type = xopbase.AnyDataType a.encodeTarget = &m.Builder.B m.Builder.encoder = a.encoder @@ -210,7 +210,7 @@ func (a *AttributeBuilder) MetadataBool(k *xopat.BoolAttribute, v bool) { defer a.lock.Unlock() a.anyChanged = true if !k.Multiple() { - s, preExisting := a.addSingle(k.Key(), k.JSONKey()) + s, preExisting := a.addSingle(k.Key().String(), k.JSONKey()) if preExisting { if k.Locked() { return @@ -230,7 +230,7 @@ func (a *AttributeBuilder) MetadataBool(k *xopat.BoolAttribute, v bool) { s.KeyValue = b.B return } - m := a.addMulti(k.Key(), k.JSONKey()) + m := a.addMulti(k.Key().String(), k.JSONKey()) m.Type = xopbase.BoolDataType lenBefore := len(m.Builder.B) // we add the new value unconditionally but can remove it by shortening to lenBefore @@ -258,7 +258,7 @@ func (a *AttributeBuilder) MetadataEnum(k *xopat.EnumAttribute, v xopat.Enum) { defer a.lock.Unlock() a.anyChanged = true if !k.Multiple() { - s, preExisting := a.addSingle(k.Key(), k.JSONKey()) + s, preExisting := a.addSingle(k.Key().String(), k.JSONKey()) if preExisting { if k.Locked() { return @@ -278,7 +278,7 @@ func (a *AttributeBuilder) MetadataEnum(k *xopat.EnumAttribute, v xopat.Enum) { s.KeyValue = b.B return } - m := a.addMulti(k.Key(), k.JSONKey()) + m := a.addMulti(k.Key().String(), k.JSONKey()) m.Type = xopbase.EnumDataType lenBefore := len(m.Builder.B) // we add the new value unconditionally but can remove it by shortening to lenBefore @@ -306,7 +306,7 @@ func (a *AttributeBuilder) MetadataFloat64(k *xopat.Float64Attribute, v float64) defer a.lock.Unlock() a.anyChanged = true if !k.Multiple() { - s, preExisting := a.addSingle(k.Key(), k.JSONKey()) + s, preExisting := a.addSingle(k.Key().String(), k.JSONKey()) if preExisting { if k.Locked() { return @@ -326,7 +326,7 @@ func (a *AttributeBuilder) MetadataFloat64(k *xopat.Float64Attribute, v float64) s.KeyValue = b.B return } - m := a.addMulti(k.Key(), k.JSONKey()) + m := a.addMulti(k.Key().String(), k.JSONKey()) m.Type = xopbase.Float64DataType lenBefore := len(m.Builder.B) // we add the new value unconditionally but can remove it by shortening to lenBefore @@ -354,7 +354,7 @@ func (a *AttributeBuilder) MetadataInt64(k *xopat.Int64Attribute, v int64) { defer a.lock.Unlock() a.anyChanged = true if !k.Multiple() { - s, preExisting := a.addSingle(k.Key(), k.JSONKey()) + s, preExisting := a.addSingle(k.Key().String(), k.JSONKey()) if preExisting { if k.Locked() { return @@ -374,7 +374,7 @@ func (a *AttributeBuilder) MetadataInt64(k *xopat.Int64Attribute, v int64) { s.KeyValue = b.B return } - m := a.addMulti(k.Key(), k.JSONKey()) + m := a.addMulti(k.Key().String(), k.JSONKey()) m.Type = xopbase.Int64DataType lenBefore := len(m.Builder.B) // we add the new value unconditionally but can remove it by shortening to lenBefore @@ -402,7 +402,7 @@ func (a *AttributeBuilder) MetadataLink(k *xopat.LinkAttribute, v xoptrace.Trace defer a.lock.Unlock() a.anyChanged = true if !k.Multiple() { - s, preExisting := a.addSingle(k.Key(), k.JSONKey()) + s, preExisting := a.addSingle(k.Key().String(), k.JSONKey()) if preExisting { if k.Locked() { return @@ -422,7 +422,7 @@ func (a *AttributeBuilder) MetadataLink(k *xopat.LinkAttribute, v xoptrace.Trace s.KeyValue = b.B return } - m := a.addMulti(k.Key(), k.JSONKey()) + m := a.addMulti(k.Key().String(), k.JSONKey()) m.Type = xopbase.LinkDataType lenBefore := len(m.Builder.B) // we add the new value unconditionally but can remove it by shortening to lenBefore @@ -450,7 +450,7 @@ func (a *AttributeBuilder) MetadataString(k *xopat.StringAttribute, v string) { defer a.lock.Unlock() a.anyChanged = true if !k.Multiple() { - s, preExisting := a.addSingle(k.Key(), k.JSONKey()) + s, preExisting := a.addSingle(k.Key().String(), k.JSONKey()) if preExisting { if k.Locked() { return @@ -470,7 +470,7 @@ func (a *AttributeBuilder) MetadataString(k *xopat.StringAttribute, v string) { s.KeyValue = b.B return } - m := a.addMulti(k.Key(), k.JSONKey()) + m := a.addMulti(k.Key().String(), k.JSONKey()) m.Type = xopbase.StringDataType lenBefore := len(m.Builder.B) // we add the new value unconditionally but can remove it by shortening to lenBefore @@ -498,7 +498,7 @@ func (a *AttributeBuilder) MetadataTime(k *xopat.TimeAttribute, v time.Time) { defer a.lock.Unlock() a.anyChanged = true if !k.Multiple() { - s, preExisting := a.addSingle(k.Key(), k.JSONKey()) + s, preExisting := a.addSingle(k.Key().String(), k.JSONKey()) if preExisting { if k.Locked() { return @@ -518,7 +518,7 @@ func (a *AttributeBuilder) MetadataTime(k *xopat.TimeAttribute, v time.Time) { s.KeyValue = b.B return } - m := a.addMulti(k.Key(), k.JSONKey()) + m := a.addMulti(k.Key().String(), k.JSONKey()) m.Type = xopbase.TimeDataType lenBefore := len(m.Builder.B) // we add the new value unconditionally but can remove it by shortening to lenBefore diff --git a/xopjson/xopjsonutil/attributes.zzzgo b/xopjson/xopjsonutil/attributes.zzzgo index cb63355a..a830b4a3 100644 --- a/xopjson/xopjsonutil/attributes.zzzgo +++ b/xopjson/xopjsonutil/attributes.zzzgo @@ -155,7 +155,7 @@ func (a *AttributeBuilder) MetadataZZZ(k *xopat.ZZZAttribute, v zzz) { } //END CONDITIONAL if !k.Multiple() { - s, preExisting := a.addSingle(k.Key(), k.JSONKey()) + s, preExisting := a.addSingle(k.Key().String(), k.JSONKey()) if preExisting { if k.Locked() { return @@ -181,7 +181,7 @@ func (a *AttributeBuilder) MetadataZZZ(k *xopat.ZZZAttribute, v zzz) { s.KeyValue = b.B return } - m := a.addMulti(k.Key(), k.JSONKey()) + m := a.addMulti(k.Key().String(), k.JSONKey()) m.Type = xopbase.ZZZDataType //CONDITIONAL ONLY:Any a.encodeTarget = &m.Builder.B diff --git a/xopotel/buffered.go b/xopotel/buffered.go index e567b3d8..131d77f2 100644 --- a/xopotel/buffered.go +++ b/xopotel/buffered.go @@ -11,6 +11,7 @@ import ( "github.com/muir/gwrap" "github.com/xoplog/xop-go/internal/util/pointer" + "github.com/xoplog/xop-go/xopat" "github.com/xoplog/xop-go/xopbase" "github.com/xoplog/xop-go/xopbase/xopbaseutil" "github.com/xoplog/xop-go/xoprecorder" @@ -255,17 +256,17 @@ func (req *bufferedRequest) getStuff(bundle xoptrace.Bundle, augment bool) (stuf } if failure := func() string { - md := span.SpanMetadata.Get(otelReplayStuff.Key()) + md := span.SpanMetadata.Get(otelReplayStuff.Key().String()) if md == nil { - return "span metdata missing replay key expected for BufferedReplayLogger " + string(otelReplayStuff.Key()) + return "span metdata missing replay key expected for BufferedReplayLogger " + otelReplayStuff.Key().String() } ma, ok := md.Value.(xopbase.ModelArg) if !ok { - return fmt.Sprintf("cast of %s data to ModelArg failed, is %T", string(otelReplayStuff.Key()), md.Value) + return fmt.Sprintf("cast of %s data to ModelArg failed, is %T", otelReplayStuff.Key(), md.Value) } err := ma.DecodeTo(&otelStuff) if err != nil { - return fmt.Sprintf("failed to decode encoded data in %s: %s", string(otelReplayStuff.Key()), err) + return fmt.Sprintf("failed to decode encoded data in %s: %s", otelReplayStuff.Key(), err) } return "" }(); failure != "" { @@ -284,7 +285,7 @@ func (req *bufferedRequest) getStuff(bundle xoptrace.Bundle, augment bool) (stuf return } -func extractValue[T any](linkLine *xoprecorder.Line, name string, dataType xopbase.DataType, errorKey string) (T, bool) { +func extractValue[T any](linkLine *xoprecorder.Line, name xopat.K, dataType xopbase.DataType, errorKey xopat.K) (T, bool) { var zero T if raw, ok := linkLine.Data[name]; ok { if linkLine.DataType[name] == dataType { diff --git a/xopotel/buffered.zzzgo b/xopotel/buffered.zzzgo index 8a3c5608..73cad2ca 100644 --- a/xopotel/buffered.zzzgo +++ b/xopotel/buffered.zzzgo @@ -12,6 +12,7 @@ import ( "github.com/muir/gwrap" "github.com/xoplog/xop-go/internal/util/pointer" + "github.com/xoplog/xop-go/xopat" "github.com/xoplog/xop-go/xopbase" "github.com/xoplog/xop-go/xopbase/xopbaseutil" "github.com/xoplog/xop-go/xoprecorder" @@ -255,17 +256,17 @@ func (req *bufferedRequest) getStuff(bundle xoptrace.Bundle, augment bool) (stuf } if failure := func() string { - md := span.SpanMetadata.Get(otelReplayStuff.Key()) + md := span.SpanMetadata.Get(otelReplayStuff.Key().String()) if md == nil { - return "span metdata missing replay key expected for BufferedReplayLogger " + string(otelReplayStuff.Key()) + return "span metdata missing replay key expected for BufferedReplayLogger " + otelReplayStuff.Key().String() } ma, ok := md.Value.(xopbase.ModelArg) if !ok { - return fmt.Sprintf("cast of %s data to ModelArg failed, is %T", string(otelReplayStuff.Key()), md.Value) + return fmt.Sprintf("cast of %s data to ModelArg failed, is %T", otelReplayStuff.Key(), md.Value) } err := ma.DecodeTo(&otelStuff) if err != nil { - return fmt.Sprintf("failed to decode encoded data in %s: %s", string(otelReplayStuff.Key()), err) + return fmt.Sprintf("failed to decode encoded data in %s: %s", otelReplayStuff.Key(), err) } return "" }(); failure != "" { @@ -284,7 +285,7 @@ func (req *bufferedRequest) getStuff(bundle xoptrace.Bundle, augment bool) (stuf return } -func extractValue[T any](linkLine *xoprecorder.Line, name string, dataType xopbase.DataType, errorKey string) (T, bool) { +func extractValue[T any](linkLine *xoprecorder.Line, name xopat.K, dataType xopbase.DataType, errorKey xopat.K) (T, bool) { var zero T if raw, ok := linkLine.Data[name]; ok { if linkLine.DataType[name] == dataType { diff --git a/xopotel/export.go b/xopotel/export.go index 52f2c884..76f5ae80 100644 --- a/xopotel/export.go +++ b/xopotel/export.go @@ -93,7 +93,9 @@ type wrappedReadOnlySpan struct { // originally using xoputil, then the exported data should almost // exactly match the original inputs. func ExportToXOP(base xopbase.Logger) sdktrace.SpanExporter { - return &spanExporter{base: base} + return &spanExporter{ + base: base, + } } func (e *spanExporter) ExportSpans(ctx context.Context, spans []sdktrace.ReadOnlySpan) (err error) { @@ -307,7 +309,7 @@ func (x spanReplay) Replay(ctx context.Context, span sdktrace.ReadOnlySpan, data line.Int64(xopOTELLinkDroppedAttributeCount, int64(link.DroppedAttributeCount), xopbase.IntDataType) } - err = z.finishLine(ctx, "link", xopOTELLinkDetail, line) + err = z.finishLine(ctx, "link", xopOTELLinkDetail.String(), line) if err != nil { return func() {}, err } @@ -687,7 +689,6 @@ func defaulted[T comparable](a, b T) T { } func (x baseSpanReplay) AddXopEventAttribute(ctx context.Context, a attribute.KeyValue, line xopbase.Line) error { - key := string(a.Key) switch a.Value.Type() { case attribute.STRINGSLICE: slice := a.Value.AsStringSlice() @@ -697,7 +698,7 @@ func (x baseSpanReplay) AddXopEventAttribute(ctx context.Context, a attribute.Ke switch slice[1] { case "any": if len(slice) != 4 { - return errors.Errorf("key %s invalid any encoding, slice too short", key) + return errors.Errorf("key %s invalid any encoding, slice too short", a.Key) } var ma xopbase.ModelArg ma.Encoded = []byte(slice[0]) @@ -707,125 +708,125 @@ func (x baseSpanReplay) AddXopEventAttribute(ctx context.Context, a attribute.Ke } ma.Encoding = xopproto.Encoding(e) ma.ModelType = slice[3] - line.Any(key, ma) + line.Any(xopat.K(a.Key), ma) case "bool": case "dur": dur, err := time.ParseDuration(slice[0]) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Duration(key, dur) + line.Duration(xopat.K(a.Key), dur) case "enum": if len(slice) != 3 { - return errors.Errorf("key %s invalid enum encoding, slice too short", key) + return errors.Errorf("key %s invalid enum encoding, slice too short", a.Key) } ea, err := x.registry.ConstructEnumAttribute(xopat.Make{ - Key: key, + Key: string(a.Key), }, xopat.AttributeTypeEnum) if err != nil { - return errors.Errorf("could not turn key %s into an enum", key) + return errors.Errorf("could not turn key %s into an enum", a.Key) } i, err := strconv.ParseInt(slice[2], 10, 64) if err != nil { - return errors.Wrapf(err, "could not turn key %s into an enum", key) + return errors.Wrapf(err, "could not turn key %s into an enum", a.Key) } enum := ea.Add64(i, slice[0]) line.Enum(&ea.EnumAttribute, enum) case "error": - line.String(key, slice[0], xopbase.StringToDataType["error"]) + line.String(xopat.K(a.Key), slice[0], xopbase.StringToDataType["error"]) case "f32": f, err := strconv.ParseFloat(slice[0], 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Float64(key, f, xopbase.StringToDataType["f32"]) + line.Float64(xopat.K(a.Key), f, xopbase.StringToDataType["f32"]) case "f64": f, err := strconv.ParseFloat(slice[0], 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Float64(key, f, xopbase.StringToDataType["f64"]) + line.Float64(xopat.K(a.Key), f, xopbase.StringToDataType["f64"]) case "i": i, err := strconv.ParseInt(slice[0], 10, 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Int64(key, i, xopbase.StringToDataType["i"]) + line.Int64(xopat.K(a.Key), i, xopbase.StringToDataType["i"]) case "i16": i, err := strconv.ParseInt(slice[0], 10, 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Int64(key, i, xopbase.StringToDataType["i16"]) + line.Int64(xopat.K(a.Key), i, xopbase.StringToDataType["i16"]) case "i32": i, err := strconv.ParseInt(slice[0], 10, 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Int64(key, i, xopbase.StringToDataType["i32"]) + line.Int64(xopat.K(a.Key), i, xopbase.StringToDataType["i32"]) case "i64": i, err := strconv.ParseInt(slice[0], 10, 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Int64(key, i, xopbase.StringToDataType["i64"]) + line.Int64(xopat.K(a.Key), i, xopbase.StringToDataType["i64"]) case "i8": i, err := strconv.ParseInt(slice[0], 10, 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Int64(key, i, xopbase.StringToDataType["i8"]) + line.Int64(xopat.K(a.Key), i, xopbase.StringToDataType["i8"]) case "s": - line.String(key, slice[0], xopbase.StringToDataType["s"]) + line.String(xopat.K(a.Key), slice[0], xopbase.StringToDataType["s"]) case "stringer": - line.String(key, slice[0], xopbase.StringToDataType["stringer"]) + line.String(xopat.K(a.Key), slice[0], xopbase.StringToDataType["stringer"]) case "time": ts, err := time.Parse(time.RFC3339Nano, slice[0]) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Time(key, ts) + line.Time(xopat.K(a.Key), ts) case "u": i, err := strconv.ParseUint(slice[0], 10, 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Uint64(key, i, xopbase.StringToDataType["u"]) + line.Uint64(xopat.K(a.Key), i, xopbase.StringToDataType["u"]) case "u16": i, err := strconv.ParseUint(slice[0], 10, 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Uint64(key, i, xopbase.StringToDataType["u16"]) + line.Uint64(xopat.K(a.Key), i, xopbase.StringToDataType["u16"]) case "u32": i, err := strconv.ParseUint(slice[0], 10, 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Uint64(key, i, xopbase.StringToDataType["u32"]) + line.Uint64(xopat.K(a.Key), i, xopbase.StringToDataType["u32"]) case "u64": i, err := strconv.ParseUint(slice[0], 10, 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Uint64(key, i, xopbase.StringToDataType["u64"]) + line.Uint64(xopat.K(a.Key), i, xopbase.StringToDataType["u64"]) case "u8": i, err := strconv.ParseUint(slice[0], 10, 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Uint64(key, i, xopbase.StringToDataType["u8"]) + line.Uint64(xopat.K(a.Key), i, xopbase.StringToDataType["u8"]) case "uintptr": i, err := strconv.ParseUint(slice[0], 10, 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.Uint64(key, i, xopbase.StringToDataType["uintptr"]) + line.Uint64(xopat.K(a.Key), i, xopbase.StringToDataType["uintptr"]) } case attribute.BOOL: - line.Bool(key, a.Value.AsBool()) + line.Bool(xopat.K(a.Key), a.Value.AsBool()) default: return errors.Errorf("unexpected event attribute type %s for xop-encoded line", a.Value.Type()) } @@ -835,33 +836,33 @@ func (x baseSpanReplay) AddXopEventAttribute(ctx context.Context, a attribute.Ke func (x baseSpanReplay) AddEventAttribute(ctx context.Context, a attribute.KeyValue, line xopbase.Line) error { switch a.Value.Type() { case attribute.BOOL: - line.Bool(string(a.Key), a.Value.AsBool()) + line.Bool(xopat.K(a.Key), a.Value.AsBool()) case attribute.BOOLSLICE: var ma xopbase.ModelArg ma.Model = a.Value.AsBoolSlice() ma.ModelType = toTypeSliceName["BOOL"] - line.Any(string(a.Key), ma) + line.Any(xopat.K(a.Key), ma) case attribute.FLOAT64: - line.Float64(string(a.Key), a.Value.AsFloat64(), xopbase.Float64DataType) + line.Float64(xopat.K(a.Key), a.Value.AsFloat64(), xopbase.Float64DataType) case attribute.FLOAT64SLICE: var ma xopbase.ModelArg ma.Model = a.Value.AsFloat64Slice() ma.ModelType = toTypeSliceName["FLOAT64"] - line.Any(string(a.Key), ma) + line.Any(xopat.K(a.Key), ma) case attribute.INT64: - line.Int64(string(a.Key), a.Value.AsInt64(), xopbase.Int64DataType) + line.Int64(xopat.K(a.Key), a.Value.AsInt64(), xopbase.Int64DataType) case attribute.INT64SLICE: var ma xopbase.ModelArg ma.Model = a.Value.AsInt64Slice() ma.ModelType = toTypeSliceName["INT64"] - line.Any(string(a.Key), ma) + line.Any(xopat.K(a.Key), ma) case attribute.STRING: - line.String(string(a.Key), a.Value.AsString(), xopbase.StringDataType) + line.String(xopat.K(a.Key), a.Value.AsString(), xopbase.StringDataType) case attribute.STRINGSLICE: var ma xopbase.ModelArg ma.Model = a.Value.AsStringSlice() ma.ModelType = toTypeSliceName["STRING"] - line.Any(string(a.Key), ma) + line.Any(xopat.K(a.Key), ma) case attribute.INVALID: fallthrough diff --git a/xopotel/export.zzzgo b/xopotel/export.zzzgo index cd064755..995bef77 100644 --- a/xopotel/export.zzzgo +++ b/xopotel/export.zzzgo @@ -93,7 +93,9 @@ type wrappedReadOnlySpan struct { // originally using xoputil, then the exported data should almost // exactly match the original inputs. func ExportToXOP(base xopbase.Logger) sdktrace.SpanExporter { - return &spanExporter{base: base} + return &spanExporter{ + base: base, + } } func (e *spanExporter) ExportSpans(ctx context.Context, spans []sdktrace.ReadOnlySpan) (err error) { @@ -307,7 +309,7 @@ func (x spanReplay) Replay(ctx context.Context, span sdktrace.ReadOnlySpan, data line.Int64(xopOTELLinkDroppedAttributeCount, int64(link.DroppedAttributeCount), xopbase.IntDataType) } - err = z.finishLine(ctx, "link", xopOTELLinkDetail, line) + err = z.finishLine(ctx, "link", xopOTELLinkDetail.String(), line) if err != nil { return func() {}, err } @@ -687,7 +689,6 @@ func defaulted[T comparable](a, b T) T { } func (x baseSpanReplay) AddXopEventAttribute(ctx context.Context, a attribute.KeyValue, line xopbase.Line) error { - key := string(a.Key) switch a.Value.Type() { case attribute.STRINGSLICE: slice := a.Value.AsStringSlice() @@ -700,54 +701,54 @@ func (x baseSpanReplay) AddXopEventAttribute(ctx context.Context, a attribute.Ke // CONDITIONAL ONLY:i,i8,i16,i32,i64 i, err := strconv.ParseInt(slice[0], 10, 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.zzz(key, i, xopbase.StringToDataType["ZZZ"]) + line.zzz(xopat.K(a.Key), i, xopbase.StringToDataType["ZZZ"]) // CONDITIONAL ONLY:u,u8,u16,u32,u64,uintptr i, err := strconv.ParseUint(slice[0], 10, 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.zzz(key, i, xopbase.StringToDataType["ZZZ"]) + line.zzz(xopat.K(a.Key), i, xopbase.StringToDataType["ZZZ"]) // CONDITIONAL ONLY:s,stringer,error - line.zzz(key, slice[0], xopbase.StringToDataType["ZZZ"]) + line.zzz(xopat.K(a.Key), slice[0], xopbase.StringToDataType["ZZZ"]) // CONDITIONAL ONLY:dur dur, err := time.ParseDuration(slice[0]) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.zzz(key, dur) + line.zzz(xopat.K(a.Key), dur) // CONDITIONAL ONLY:f32,f64 f, err := strconv.ParseFloat(slice[0], 64) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.zzz(key, f, xopbase.StringToDataType["ZZZ"]) + line.zzz(xopat.K(a.Key), f, xopbase.StringToDataType["ZZZ"]) // CONDITIONAL ONLY:time ts, err := time.Parse(time.RFC3339Nano, slice[0]) if err != nil { - return errors.Wrapf(err, "key %s invalid %s", key, slice[1]) + return errors.Wrapf(err, "key %s invalid %s", a.Key, slice[1]) } - line.zzz(key, ts) + line.zzz(xopat.K(a.Key), ts) // CONDITIONAL ONLY:enum if len(slice) != 3 { - return errors.Errorf("key %s invalid enum encoding, slice too short", key) + return errors.Errorf("key %s invalid enum encoding, slice too short", a.Key) } ea, err := x.registry.ConstructEnumAttribute(xopat.Make{ - Key: key, + Key: string(a.Key), }, xopat.AttributeTypeEnum) if err != nil { - return errors.Errorf("could not turn key %s into an enum", key) + return errors.Errorf("could not turn key %s into an enum", a.Key) } i, err := strconv.ParseInt(slice[2], 10, 64) if err != nil { - return errors.Wrapf(err, "could not turn key %s into an enum", key) + return errors.Wrapf(err, "could not turn key %s into an enum", a.Key) } enum := ea.Add64(i, slice[0]) line.Enum(&ea.EnumAttribute, enum) // CONDITIONAL ONLY:any if len(slice) != 4 { - return errors.Errorf("key %s invalid any encoding, slice too short", key) + return errors.Errorf("key %s invalid any encoding, slice too short", a.Key) } var ma xopbase.ModelArg ma.Encoded = []byte(slice[0]) @@ -757,13 +758,13 @@ func (x baseSpanReplay) AddXopEventAttribute(ctx context.Context, a attribute.Ke } ma.Encoding = xopproto.Encoding(e) ma.ModelType = slice[3] - line.zzz(key, ma) + line.zzz(xopat.K(a.Key), ma) // END CONDITIONAL } case attribute.BOOL: - line.Bool(key, a.Value.AsBool()) + line.Bool(xopat.K(a.Key), a.Value.AsBool()) default: return errors.Errorf("unexpected event attribute type %s for xop-encoded line", a.Value.Type()) } @@ -775,15 +776,15 @@ func (x baseSpanReplay) AddEventAttribute(ctx context.Context, a attribute.KeyVa // MACRO OTELTypes case attribute.ZZZ: // CONDITIONAL SKIP:BOOL - line.Zzz(string(a.Key), a.Value.AsZzz(), xopbase.ZzzDataType) + line.Zzz(xopat.K(a.Key), a.Value.AsZzz(), xopbase.ZzzDataType) // ELSE CONDITIONAL - line.Bool(string(a.Key), a.Value.AsZzz()) + line.Bool(xopat.K(a.Key), a.Value.AsZzz()) // END CONDITIONAL case attribute.ZZZSLICE: var ma xopbase.ModelArg ma.Model = a.Value.AsZzzSlice() ma.ModelType = toTypeSliceName["ZZZ"] - line.Any(string(a.Key), ma) + line.Any(xopat.K(a.Key), ma) case attribute.INVALID: fallthrough diff --git a/xopotel/models.go b/xopotel/models.go index d05950b2..34f6a722 100644 --- a/xopotel/models.go +++ b/xopotel/models.go @@ -7,6 +7,7 @@ import ( "sync/atomic" "time" + "github.com/xoplog/xop-go" "github.com/xoplog/xop-go/xopat" "github.com/xoplog/xop-go/xopbase" "github.com/xoplog/xop-go/xopconst" @@ -134,13 +135,13 @@ var otelLink = xopat.Make{Key: "span.otelLinks", Namespace: "XOP", Indexed: fals Description: "Data origin is OTEL, span links w/o attributes; links also sent as Link()"}.LinkAttribute() var xopLinkMetadataKey = attribute.Key("xop.linkMetadataKey") -const xopLinkTraceStateError = "xop.linkTraceStateError" -const xopOTELLinkTranceState = "xop.otelLinkTraceState" -const xopOTELLinkIsRemote = "xop.otelLinkIsRemote" -const xopOTELLinkDetail = "xop.otelLinkDetail" -const xopLinkRemoteError = "xop.otelLinkRemoteError" -const xopOTELLinkDroppedAttributeCount = "xop.otelLinkDroppedAttributeCount" -const xopLinkeDroppedError = "xop.otelLinkDroppedError" +var xopLinkTraceStateError = xop.Key("xop.linkTraceStateError") +var xopOTELLinkTranceState = xop.Key("xop.otelLinkTraceState") +var xopOTELLinkIsRemote = xop.Key("xop.otelLinkIsRemote") +var xopOTELLinkDetail = xop.Key("xop.otelLinkDetail") +var xopLinkRemoteError = xop.Key("xop.otelLinkRemoteError") +var xopOTELLinkDroppedAttributeCount = xop.Key("xop.otelLinkDroppedAttributeCount") +var xopLinkeDroppedError = xop.Key("xop.otelLinkDroppedError") var otelReplayStuff = xopat.Make{Key: "span.replayedFromOTEL", Namespace: "XOP", Indexed: false, Prominence: 300, Description: "Data origin is OTEL, translated through xopotel.ExportToXOP, bundle of span config"}.AnyAttribute(&otelStuff{}) diff --git a/xopotel/otel.go b/xopotel/otel.go index c911bd5f..edbe7863 100644 --- a/xopotel/otel.go +++ b/xopotel/otel.go @@ -324,7 +324,7 @@ func (prefilled *prefilled) Line(level xopnum.Level, ts time.Time, frames []runt } func (line *line) Link(k string, v xoptrace.Trace) { - if k == xopOTELLinkDetail { + if k == xopOTELLinkDetail.String() { // Link will not be called with OTEL->XOP->OTEL so no need to // suppress anything return @@ -439,56 +439,56 @@ func (line *line) Template(template string) { } func (builder *builder) Enum(k *xopat.EnumAttribute, v xopat.Enum) { - builder.attributes = append(builder.attributes, attribute.StringSlice(k.Key(), []string{v.String(), "enum", strconv.FormatInt(v.Int64(), 10)})) + builder.attributes = append(builder.attributes, attribute.StringSlice(k.Key().String(), []string{v.String(), "enum", strconv.FormatInt(v.Int64(), 10)})) } -func (builder *builder) Any(k string, v xopbase.ModelArg) { +func (builder *builder) Any(k xopat.K, v xopbase.ModelArg) { v.Encode() - builder.attributes = append(builder.attributes, attribute.StringSlice(k, []string{string(v.Encoded), "any", v.Encoding.String(), v.ModelType})) + builder.attributes = append(builder.attributes, attribute.StringSlice(k.String(), []string{string(v.Encoded), "any", v.Encoding.String(), v.ModelType})) } -func (builder *builder) Time(k string, v time.Time) { - builder.attributes = append(builder.attributes, attribute.StringSlice(k, []string{v.Format(time.RFC3339Nano), "time"})) +func (builder *builder) Time(k xopat.K, v time.Time) { + builder.attributes = append(builder.attributes, attribute.StringSlice(k.String(), []string{v.Format(time.RFC3339Nano), "time"})) } -func (builder *builder) Duration(k string, v time.Duration) { - builder.attributes = append(builder.attributes, attribute.StringSlice(k, []string{v.String(), "dur"})) +func (builder *builder) Duration(k xopat.K, v time.Duration) { + builder.attributes = append(builder.attributes, attribute.StringSlice(k.String(), []string{v.String(), "dur"})) } -func (builder *builder) Uint64(k string, v uint64, dt xopbase.DataType) { - builder.attributes = append(builder.attributes, attribute.StringSlice(k, []string{strconv.FormatUint(v, 10), xopbase.DataTypeToString[dt]})) +func (builder *builder) Uint64(k xopat.K, v uint64, dt xopbase.DataType) { + builder.attributes = append(builder.attributes, attribute.StringSlice(k.String(), []string{strconv.FormatUint(v, 10), xopbase.DataTypeToString[dt]})) } -func (builder *builder) Int64(k string, v int64, dt xopbase.DataType) { - builder.attributes = append(builder.attributes, attribute.StringSlice(k, []string{strconv.FormatInt(v, 10), xopbase.DataTypeToString[dt]})) +func (builder *builder) Int64(k xopat.K, v int64, dt xopbase.DataType) { + builder.attributes = append(builder.attributes, attribute.StringSlice(k.String(), []string{strconv.FormatInt(v, 10), xopbase.DataTypeToString[dt]})) } -func (builder *builder) Float64(k string, v float64, dt xopbase.DataType) { - builder.attributes = append(builder.attributes, attribute.StringSlice(k, []string{strconv.FormatFloat(v, 'g', -1, 64), xopbase.DataTypeToString[dt]})) +func (builder *builder) Float64(k xopat.K, v float64, dt xopbase.DataType) { + builder.attributes = append(builder.attributes, attribute.StringSlice(k.String(), []string{strconv.FormatFloat(v, 'g', -1, 64), xopbase.DataTypeToString[dt]})) } -func (builder *builder) String(k string, v string, dt xopbase.DataType) { - builder.attributes = append(builder.attributes, attribute.StringSlice(k, []string{v, xopbase.DataTypeToString[dt]})) +func (builder *builder) String(k xopat.K, v string, dt xopbase.DataType) { + builder.attributes = append(builder.attributes, attribute.StringSlice(k.String(), []string{v, xopbase.DataTypeToString[dt]})) } -func (builder *builder) Bool(k string, v bool) { - builder.attributes = append(builder.attributes, attribute.Bool(k, v)) +func (builder *builder) Bool(k xopat.K, v bool) { + builder.attributes = append(builder.attributes, attribute.Bool(k.String(), v)) } var skipIfOTEL = map[string]struct{}{ - otelReplayStuff.Key(): {}, + otelReplayStuff.Key().String(): {}, } func (span *span) MetadataAny(k *xopat.AnyAttribute, v xopbase.ModelArg) { - if k.Key() == otelReplayStuff.Key() { + if k.Key().String() == otelReplayStuff.Key().String() { return } key := k.Key() if span.isXOP { - if _, ok := span.request.attributesDefined[key]; !ok { + if _, ok := span.request.attributesDefined[key.String()]; !ok { if k.Description() != xopSynthesizedForOTEL { - span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key, k.DefinitionJSONString())) - span.request.attributesDefined[key] = struct{}{} + span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key.String(), k.DefinitionJSONString())) + span.request.attributesDefined[key.String()] = struct{}{} } } } @@ -506,12 +506,12 @@ func (span *span) MetadataAny(k *xopat.AnyAttribute, v xopbase.ModelArg) { if span.hasPrior == nil { span.hasPrior = make(map[string]struct{}) } - if _, ok := span.hasPrior[key]; ok { + if _, ok := span.hasPrior[key.String()]; ok { return } - span.hasPrior[key] = struct{}{} + span.hasPrior[key.String()] = struct{}{} } - span.otelSpan.SetAttributes(attribute.String(key, value)) + span.otelSpan.SetAttributes(attribute.String(key.String(), value)) return } span.lock.Lock() @@ -520,10 +520,10 @@ func (span *span) MetadataAny(k *xopat.AnyAttribute, v xopbase.ModelArg) { if span.metadataSeen == nil { span.metadataSeen = make(map[string]interface{}) } - seenRaw, ok := span.metadataSeen[key] + seenRaw, ok := span.metadataSeen[key.String()] if !ok { seen := make(map[string]struct{}) - span.metadataSeen[key] = seen + span.metadataSeen[key.String()] = seen seen[value] = struct{}{} } else { seen := seenRaw.(map[string]struct{}) @@ -536,19 +536,19 @@ func (span *span) MetadataAny(k *xopat.AnyAttribute, v xopbase.ModelArg) { if span.priorStringSlices == nil { span.priorStringSlices = make(map[string][]string) } - s := span.priorStringSlices[key] + s := span.priorStringSlices[key.String()] s = append(s, value) - span.priorStringSlices[key] = s - span.otelSpan.SetAttributes(attribute.StringSlice(key, s)) + span.priorStringSlices[key.String()] = s + span.otelSpan.SetAttributes(attribute.StringSlice(key.String(), s)) } func (span *span) MetadataBool(k *xopat.BoolAttribute, v bool) { key := k.Key() if span.isXOP { - if _, ok := span.request.attributesDefined[key]; !ok { + if _, ok := span.request.attributesDefined[key.String()]; !ok { if k.Description() != xopSynthesizedForOTEL { - span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key, k.DefinitionJSONString())) - span.request.attributesDefined[key] = struct{}{} + span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key.String(), k.DefinitionJSONString())) + span.request.attributesDefined[key.String()] = struct{}{} } } } @@ -560,12 +560,12 @@ func (span *span) MetadataBool(k *xopat.BoolAttribute, v bool) { if span.hasPrior == nil { span.hasPrior = make(map[string]struct{}) } - if _, ok := span.hasPrior[key]; ok { + if _, ok := span.hasPrior[key.String()]; ok { return } - span.hasPrior[key] = struct{}{} + span.hasPrior[key.String()] = struct{}{} } - span.otelSpan.SetAttributes(attribute.Bool(key, value)) + span.otelSpan.SetAttributes(attribute.Bool(key.String(), value)) return } span.lock.Lock() @@ -574,10 +574,10 @@ func (span *span) MetadataBool(k *xopat.BoolAttribute, v bool) { if span.metadataSeen == nil { span.metadataSeen = make(map[string]interface{}) } - seenRaw, ok := span.metadataSeen[key] + seenRaw, ok := span.metadataSeen[key.String()] if !ok { seen := make(map[bool]struct{}) - span.metadataSeen[key] = seen + span.metadataSeen[key.String()] = seen seen[value] = struct{}{} } else { seen := seenRaw.(map[bool]struct{}) @@ -590,19 +590,19 @@ func (span *span) MetadataBool(k *xopat.BoolAttribute, v bool) { if span.priorBoolSlices == nil { span.priorBoolSlices = make(map[string][]bool) } - s := span.priorBoolSlices[key] + s := span.priorBoolSlices[key.String()] s = append(s, value) - span.priorBoolSlices[key] = s - span.otelSpan.SetAttributes(attribute.BoolSlice(key, s)) + span.priorBoolSlices[key.String()] = s + span.otelSpan.SetAttributes(attribute.BoolSlice(key.String(), s)) } func (span *span) MetadataEnum(k *xopat.EnumAttribute, v xopat.Enum) { key := k.Key() if span.isXOP { - if _, ok := span.request.attributesDefined[key]; !ok { + if _, ok := span.request.attributesDefined[key.String()]; !ok { if k.Description() != xopSynthesizedForOTEL { - span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key, k.DefinitionJSONString())) - span.request.attributesDefined[key] = struct{}{} + span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key.String(), k.DefinitionJSONString())) + span.request.attributesDefined[key.String()] = struct{}{} } } } @@ -614,12 +614,12 @@ func (span *span) MetadataEnum(k *xopat.EnumAttribute, v xopat.Enum) { if span.hasPrior == nil { span.hasPrior = make(map[string]struct{}) } - if _, ok := span.hasPrior[key]; ok { + if _, ok := span.hasPrior[key.String()]; ok { return } - span.hasPrior[key] = struct{}{} + span.hasPrior[key.String()] = struct{}{} } - span.otelSpan.SetAttributes(attribute.String(key, value)) + span.otelSpan.SetAttributes(attribute.String(key.String(), value)) return } span.lock.Lock() @@ -628,10 +628,10 @@ func (span *span) MetadataEnum(k *xopat.EnumAttribute, v xopat.Enum) { if span.metadataSeen == nil { span.metadataSeen = make(map[string]interface{}) } - seenRaw, ok := span.metadataSeen[key] + seenRaw, ok := span.metadataSeen[key.String()] if !ok { seen := make(map[string]struct{}) - span.metadataSeen[key] = seen + span.metadataSeen[key.String()] = seen seen[value] = struct{}{} } else { seen := seenRaw.(map[string]struct{}) @@ -644,19 +644,19 @@ func (span *span) MetadataEnum(k *xopat.EnumAttribute, v xopat.Enum) { if span.priorStringSlices == nil { span.priorStringSlices = make(map[string][]string) } - s := span.priorStringSlices[key] + s := span.priorStringSlices[key.String()] s = append(s, value) - span.priorStringSlices[key] = s - span.otelSpan.SetAttributes(attribute.StringSlice(key, s)) + span.priorStringSlices[key.String()] = s + span.otelSpan.SetAttributes(attribute.StringSlice(key.String(), s)) } func (span *span) MetadataFloat64(k *xopat.Float64Attribute, v float64) { key := k.Key() if span.isXOP { - if _, ok := span.request.attributesDefined[key]; !ok { + if _, ok := span.request.attributesDefined[key.String()]; !ok { if k.Description() != xopSynthesizedForOTEL { - span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key, k.DefinitionJSONString())) - span.request.attributesDefined[key] = struct{}{} + span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key.String(), k.DefinitionJSONString())) + span.request.attributesDefined[key.String()] = struct{}{} } } } @@ -668,12 +668,12 @@ func (span *span) MetadataFloat64(k *xopat.Float64Attribute, v float64) { if span.hasPrior == nil { span.hasPrior = make(map[string]struct{}) } - if _, ok := span.hasPrior[key]; ok { + if _, ok := span.hasPrior[key.String()]; ok { return } - span.hasPrior[key] = struct{}{} + span.hasPrior[key.String()] = struct{}{} } - span.otelSpan.SetAttributes(attribute.Float64(key, value)) + span.otelSpan.SetAttributes(attribute.Float64(key.String(), value)) return } span.lock.Lock() @@ -682,10 +682,10 @@ func (span *span) MetadataFloat64(k *xopat.Float64Attribute, v float64) { if span.metadataSeen == nil { span.metadataSeen = make(map[string]interface{}) } - seenRaw, ok := span.metadataSeen[key] + seenRaw, ok := span.metadataSeen[key.String()] if !ok { seen := make(map[float64]struct{}) - span.metadataSeen[key] = seen + span.metadataSeen[key.String()] = seen seen[value] = struct{}{} } else { seen := seenRaw.(map[float64]struct{}) @@ -698,19 +698,19 @@ func (span *span) MetadataFloat64(k *xopat.Float64Attribute, v float64) { if span.priorFloat64Slices == nil { span.priorFloat64Slices = make(map[string][]float64) } - s := span.priorFloat64Slices[key] + s := span.priorFloat64Slices[key.String()] s = append(s, value) - span.priorFloat64Slices[key] = s - span.otelSpan.SetAttributes(attribute.Float64Slice(key, s)) + span.priorFloat64Slices[key.String()] = s + span.otelSpan.SetAttributes(attribute.Float64Slice(key.String(), s)) } func (span *span) MetadataInt64(k *xopat.Int64Attribute, v int64) { key := k.Key() if span.isXOP { - if _, ok := span.request.attributesDefined[key]; !ok { + if _, ok := span.request.attributesDefined[key.String()]; !ok { if k.Description() != xopSynthesizedForOTEL { - span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key, k.DefinitionJSONString())) - span.request.attributesDefined[key] = struct{}{} + span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key.String(), k.DefinitionJSONString())) + span.request.attributesDefined[key.String()] = struct{}{} } } } @@ -722,15 +722,15 @@ func (span *span) MetadataInt64(k *xopat.Int64Attribute, v int64) { if span.hasPrior == nil { span.hasPrior = make(map[string]struct{}) } - if _, ok := span.hasPrior[key]; ok { + if _, ok := span.hasPrior[key.String()]; ok { return } - span.hasPrior[key] = struct{}{} + span.hasPrior[key.String()] = struct{}{} } if k.SubType() == xopat.AttributeTypeDuration { - span.otelSpan.SetAttributes(attribute.String(key, time.Duration(value).String())) + span.otelSpan.SetAttributes(attribute.String(key.String(), time.Duration(value).String())) } else { - span.otelSpan.SetAttributes(attribute.Int64(key, value)) + span.otelSpan.SetAttributes(attribute.Int64(key.String(), value)) } return } @@ -740,10 +740,10 @@ func (span *span) MetadataInt64(k *xopat.Int64Attribute, v int64) { if span.metadataSeen == nil { span.metadataSeen = make(map[string]interface{}) } - seenRaw, ok := span.metadataSeen[key] + seenRaw, ok := span.metadataSeen[key.String()] if !ok { seen := make(map[int64]struct{}) - span.metadataSeen[key] = seen + span.metadataSeen[key.String()] = seen seen[value] = struct{}{} } else { seen := seenRaw.(map[int64]struct{}) @@ -757,37 +757,37 @@ func (span *span) MetadataInt64(k *xopat.Int64Attribute, v int64) { if span.priorStringSlices == nil { span.priorStringSlices = make(map[string][]string) } - s := span.priorStringSlices[key] + s := span.priorStringSlices[key.String()] s = append(s, time.Duration(value).String()) - span.priorStringSlices[key] = s - span.otelSpan.SetAttributes(attribute.StringSlice(key, s)) + span.priorStringSlices[key.String()] = s + span.otelSpan.SetAttributes(attribute.StringSlice(key.String(), s)) } else { if span.priorInt64Slices == nil { span.priorInt64Slices = make(map[string][]int64) } - s := span.priorInt64Slices[key] + s := span.priorInt64Slices[key.String()] s = append(s, value) - span.priorInt64Slices[key] = s - span.otelSpan.SetAttributes(attribute.Int64Slice(key, s)) + span.priorInt64Slices[key.String()] = s + span.otelSpan.SetAttributes(attribute.Int64Slice(key.String(), s)) } } func (span *span) MetadataLink(k *xopat.LinkAttribute, v xoptrace.Trace) { key := k.Key() if span.isXOP { - if _, ok := span.request.attributesDefined[key]; !ok { + if _, ok := span.request.attributesDefined[key.String()]; !ok { if k.Description() != xopSynthesizedForOTEL { - span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key, k.DefinitionJSONString())) - span.request.attributesDefined[key] = struct{}{} + span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key.String(), k.DefinitionJSONString())) + span.request.attributesDefined[key.String()] = struct{}{} } } } - if k.Key() == otelLink.Key() { + if k.Key().String() == otelLink.Key().String() { return } value := v.String() if span.logger.bufferedRequest == nil { - _, tmpSpan := span.logger.tracer.Start(span.ctx, k.Key(), + _, tmpSpan := span.logger.tracer.Start(span.ctx, k.Key().String(), oteltrace.WithLinks( oteltrace.Link{ SpanContext: oteltrace.NewSpanContext(oteltrace.SpanContextConfig{ @@ -798,7 +798,7 @@ func (span *span) MetadataLink(k *xopat.LinkAttribute, v xoptrace.Trace) { Remote: true, // information not available }), Attributes: []attribute.KeyValue{ - xopLinkMetadataKey.String(key), + xopLinkMetadataKey.String(key.String()), }, }), oteltrace.WithAttributes( @@ -815,12 +815,12 @@ func (span *span) MetadataLink(k *xopat.LinkAttribute, v xoptrace.Trace) { if span.hasPrior == nil { span.hasPrior = make(map[string]struct{}) } - if _, ok := span.hasPrior[key]; ok { + if _, ok := span.hasPrior[key.String()]; ok { return } - span.hasPrior[key] = struct{}{} + span.hasPrior[key.String()] = struct{}{} } - span.otelSpan.SetAttributes(attribute.String(key, value)) + span.otelSpan.SetAttributes(attribute.String(key.String(), value)) return } span.lock.Lock() @@ -829,10 +829,10 @@ func (span *span) MetadataLink(k *xopat.LinkAttribute, v xoptrace.Trace) { if span.metadataSeen == nil { span.metadataSeen = make(map[string]interface{}) } - seenRaw, ok := span.metadataSeen[key] + seenRaw, ok := span.metadataSeen[key.String()] if !ok { seen := make(map[string]struct{}) - span.metadataSeen[key] = seen + span.metadataSeen[key.String()] = seen seen[value] = struct{}{} } else { seen := seenRaw.(map[string]struct{}) @@ -845,19 +845,19 @@ func (span *span) MetadataLink(k *xopat.LinkAttribute, v xoptrace.Trace) { if span.priorStringSlices == nil { span.priorStringSlices = make(map[string][]string) } - s := span.priorStringSlices[key] + s := span.priorStringSlices[key.String()] s = append(s, value) - span.priorStringSlices[key] = s - span.otelSpan.SetAttributes(attribute.StringSlice(key, s)) + span.priorStringSlices[key.String()] = s + span.otelSpan.SetAttributes(attribute.StringSlice(key.String(), s)) } func (span *span) MetadataString(k *xopat.StringAttribute, v string) { key := k.Key() if span.isXOP { - if _, ok := span.request.attributesDefined[key]; !ok { + if _, ok := span.request.attributesDefined[key.String()]; !ok { if k.Description() != xopSynthesizedForOTEL { - span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key, k.DefinitionJSONString())) - span.request.attributesDefined[key] = struct{}{} + span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key.String(), k.DefinitionJSONString())) + span.request.attributesDefined[key.String()] = struct{}{} } } } @@ -869,12 +869,12 @@ func (span *span) MetadataString(k *xopat.StringAttribute, v string) { if span.hasPrior == nil { span.hasPrior = make(map[string]struct{}) } - if _, ok := span.hasPrior[key]; ok { + if _, ok := span.hasPrior[key.String()]; ok { return } - span.hasPrior[key] = struct{}{} + span.hasPrior[key.String()] = struct{}{} } - span.otelSpan.SetAttributes(attribute.String(key, value)) + span.otelSpan.SetAttributes(attribute.String(key.String(), value)) return } span.lock.Lock() @@ -883,10 +883,10 @@ func (span *span) MetadataString(k *xopat.StringAttribute, v string) { if span.metadataSeen == nil { span.metadataSeen = make(map[string]interface{}) } - seenRaw, ok := span.metadataSeen[key] + seenRaw, ok := span.metadataSeen[key.String()] if !ok { seen := make(map[string]struct{}) - span.metadataSeen[key] = seen + span.metadataSeen[key.String()] = seen seen[value] = struct{}{} } else { seen := seenRaw.(map[string]struct{}) @@ -899,19 +899,19 @@ func (span *span) MetadataString(k *xopat.StringAttribute, v string) { if span.priorStringSlices == nil { span.priorStringSlices = make(map[string][]string) } - s := span.priorStringSlices[key] + s := span.priorStringSlices[key.String()] s = append(s, value) - span.priorStringSlices[key] = s - span.otelSpan.SetAttributes(attribute.StringSlice(key, s)) + span.priorStringSlices[key.String()] = s + span.otelSpan.SetAttributes(attribute.StringSlice(key.String(), s)) } func (span *span) MetadataTime(k *xopat.TimeAttribute, v time.Time) { key := k.Key() if span.isXOP { - if _, ok := span.request.attributesDefined[key]; !ok { + if _, ok := span.request.attributesDefined[key.String()]; !ok { if k.Description() != xopSynthesizedForOTEL { - span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key, k.DefinitionJSONString())) - span.request.attributesDefined[key] = struct{}{} + span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key.String(), k.DefinitionJSONString())) + span.request.attributesDefined[key.String()] = struct{}{} } } } @@ -923,12 +923,12 @@ func (span *span) MetadataTime(k *xopat.TimeAttribute, v time.Time) { if span.hasPrior == nil { span.hasPrior = make(map[string]struct{}) } - if _, ok := span.hasPrior[key]; ok { + if _, ok := span.hasPrior[key.String()]; ok { return } - span.hasPrior[key] = struct{}{} + span.hasPrior[key.String()] = struct{}{} } - span.otelSpan.SetAttributes(attribute.String(key, value)) + span.otelSpan.SetAttributes(attribute.String(key.String(), value)) return } span.lock.Lock() @@ -937,10 +937,10 @@ func (span *span) MetadataTime(k *xopat.TimeAttribute, v time.Time) { if span.metadataSeen == nil { span.metadataSeen = make(map[string]interface{}) } - seenRaw, ok := span.metadataSeen[key] + seenRaw, ok := span.metadataSeen[key.String()] if !ok { seen := make(map[string]struct{}) - span.metadataSeen[key] = seen + span.metadataSeen[key.String()] = seen seen[value] = struct{}{} } else { seen := seenRaw.(map[string]struct{}) @@ -953,10 +953,10 @@ func (span *span) MetadataTime(k *xopat.TimeAttribute, v time.Time) { if span.priorStringSlices == nil { span.priorStringSlices = make(map[string][]string) } - s := span.priorStringSlices[key] + s := span.priorStringSlices[key.String()] s = append(s, value) - span.priorStringSlices[key] = s - span.otelSpan.SetAttributes(attribute.StringSlice(key, s)) + span.priorStringSlices[key.String()] = s + span.otelSpan.SetAttributes(attribute.StringSlice(key.String(), s)) } var spanKindFromString = map[string]oteltrace.SpanKind{ diff --git a/xopotel/otel.zzzgo b/xopotel/otel.zzzgo index f534b2ee..90ee7939 100644 --- a/xopotel/otel.zzzgo +++ b/xopotel/otel.zzzgo @@ -324,7 +324,7 @@ func (prefilled *prefilled) Line(level xopnum.Level, ts time.Time, frames []runt } func (line *line) Link(k string, v xoptrace.Trace) { - if k == xopOTELLinkDetail { + if k == xopOTELLinkDetail.String() { // Link will not be called with OTEL->XOP->OTEL so no need to // suppress anything return @@ -439,69 +439,69 @@ func (line *line) Template(template string) { } func (builder *builder) Enum(k *xopat.EnumAttribute, v xopat.Enum) { - builder.attributes = append(builder.attributes, attribute.StringSlice(k.Key(), []string{v.String(), "enum", strconv.FormatInt(v.Int64(), 10)})) + builder.attributes = append(builder.attributes, attribute.StringSlice(k.Key().String(), []string{v.String(), "enum", strconv.FormatInt(v.Int64(), 10)})) } -func (builder *builder) Any(k string, v xopbase.ModelArg) { +func (builder *builder) Any(k xopat.K, v xopbase.ModelArg) { v.Encode() - builder.attributes = append(builder.attributes, attribute.StringSlice(k, []string{string(v.Encoded), "any", v.Encoding.String(), v.ModelType})) + builder.attributes = append(builder.attributes, attribute.StringSlice(k.String(), []string{string(v.Encoded), "any", v.Encoding.String(), v.ModelType})) } -func (builder *builder) Time(k string, v time.Time) { - builder.attributes = append(builder.attributes, attribute.StringSlice(k, []string{v.Format(time.RFC3339Nano), "time"})) +func (builder *builder) Time(k xopat.K, v time.Time) { + builder.attributes = append(builder.attributes, attribute.StringSlice(k.String(), []string{v.Format(time.RFC3339Nano), "time"})) } -func (builder *builder) Duration(k string, v time.Duration) { - builder.attributes = append(builder.attributes, attribute.StringSlice(k, []string{v.String(), "dur"})) +func (builder *builder) Duration(k xopat.K, v time.Duration) { + builder.attributes = append(builder.attributes, attribute.StringSlice(k.String(), []string{v.String(), "dur"})) } -func (builder *builder) Uint64(k string, v uint64, dt xopbase.DataType) { - builder.attributes = append(builder.attributes, attribute.StringSlice(k, []string{strconv.FormatUint(v, 10), xopbase.DataTypeToString[dt]})) +func (builder *builder) Uint64(k xopat.K, v uint64, dt xopbase.DataType) { + builder.attributes = append(builder.attributes, attribute.StringSlice(k.String(), []string{strconv.FormatUint(v, 10), xopbase.DataTypeToString[dt]})) } -func (builder *builder) Int64(k string, v int64, dt xopbase.DataType) { - builder.attributes = append(builder.attributes, attribute.StringSlice(k, []string{strconv.FormatInt(v, 10), xopbase.DataTypeToString[dt]})) +func (builder *builder) Int64(k xopat.K, v int64, dt xopbase.DataType) { + builder.attributes = append(builder.attributes, attribute.StringSlice(k.String(), []string{strconv.FormatInt(v, 10), xopbase.DataTypeToString[dt]})) } -func (builder *builder) Float64(k string, v float64, dt xopbase.DataType) { - builder.attributes = append(builder.attributes, attribute.StringSlice(k, []string{strconv.FormatFloat(v, 'g', -1, 64), xopbase.DataTypeToString[dt]})) +func (builder *builder) Float64(k xopat.K, v float64, dt xopbase.DataType) { + builder.attributes = append(builder.attributes, attribute.StringSlice(k.String(), []string{strconv.FormatFloat(v, 'g', -1, 64), xopbase.DataTypeToString[dt]})) } -func (builder *builder) String(k string, v string, dt xopbase.DataType) { - builder.attributes = append(builder.attributes, attribute.StringSlice(k, []string{v, xopbase.DataTypeToString[dt]})) +func (builder *builder) String(k xopat.K, v string, dt xopbase.DataType) { + builder.attributes = append(builder.attributes, attribute.StringSlice(k.String(), []string{v, xopbase.DataTypeToString[dt]})) } -func (builder *builder) Bool(k string, v bool) { - builder.attributes = append(builder.attributes, attribute.Bool(k, v)) +func (builder *builder) Bool(k xopat.K, v bool) { + builder.attributes = append(builder.attributes, attribute.Bool(k.String(), v)) } var skipIfOTEL = map[string]struct{}{ - otelReplayStuff.Key(): {}, + otelReplayStuff.Key().String(): {}, } // MACRO BaseAttribute func (span *span) MetadataZZZ(k *xopat.ZZZAttribute, v zzz) { //CONDITIONAL ONLY:Any - if k.Key() == otelReplayStuff.Key() { + if k.Key().String() == otelReplayStuff.Key().String() { return } //END CONDITIONAL key := k.Key() if span.isXOP { - if _, ok := span.request.attributesDefined[key]; !ok { + if _, ok := span.request.attributesDefined[key.String()]; !ok { if k.Description() != xopSynthesizedForOTEL { - span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key, k.DefinitionJSONString())) - span.request.attributesDefined[key] = struct{}{} + span.request.otelSpan.SetAttributes(attribute.String(attributeDefinitionPrefix+key.String(), k.DefinitionJSONString())) + span.request.attributesDefined[key.String()] = struct{}{} } } } //CONDITIONAL ONLY:Link - if k.Key() == otelLink.Key() { + if k.Key().String() == otelLink.Key().String() { return } value := v.String() if span.logger.bufferedRequest == nil { - _, tmpSpan := span.logger.tracer.Start(span.ctx, k.Key(), + _, tmpSpan := span.logger.tracer.Start(span.ctx, k.Key().String(), oteltrace.WithLinks( oteltrace.Link{ SpanContext: oteltrace.NewSpanContext(oteltrace.SpanContextConfig{ @@ -512,7 +512,7 @@ func (span *span) MetadataZZZ(k *xopat.ZZZAttribute, v zzz) { Remote: true, // information not available }), Attributes: []attribute.KeyValue{ - xopLinkMetadataKey.String(key), + xopLinkMetadataKey.String(key.String()), }, }), oteltrace.WithAttributes( @@ -544,21 +544,21 @@ func (span *span) MetadataZZZ(k *xopat.ZZZAttribute, v zzz) { if span.hasPrior == nil { span.hasPrior = make(map[string]struct{}) } - if _, ok := span.hasPrior[key]; ok { + if _, ok := span.hasPrior[key.String()]; ok { return } - span.hasPrior[key] = struct{}{} + span.hasPrior[key.String()] = struct{}{} } //CONDITIONAL ONLY:Enum,Time,String,Any,Link - span.otelSpan.SetAttributes(attribute.String(key, value)) + span.otelSpan.SetAttributes(attribute.String(key.String(), value)) //CONDITIONAL ONLY:Int64 if k.SubType() == xopat.AttributeTypeDuration { - span.otelSpan.SetAttributes(attribute.String(key, time.Duration(value).String())) + span.otelSpan.SetAttributes(attribute.String(key.String(), time.Duration(value).String())) } else { - span.otelSpan.SetAttributes(attribute.ZZZ(key, value)) + span.otelSpan.SetAttributes(attribute.ZZZ(key.String(), value)) } //CONDITIONAL SKIP:Enum,Time,String,Any,Link,Int64 - span.otelSpan.SetAttributes(attribute.ZZZ(key, value)) + span.otelSpan.SetAttributes(attribute.ZZZ(key.String(), value)) //END CONDITIONAL return } @@ -568,14 +568,14 @@ func (span *span) MetadataZZZ(k *xopat.ZZZAttribute, v zzz) { if span.metadataSeen == nil { span.metadataSeen = make(map[string]interface{}) } - seenRaw, ok := span.metadataSeen[key] + seenRaw, ok := span.metadataSeen[key.String()] if !ok { //CONDITIONAL ONLY:Enum,Time,String,Any,Link seen := make(map[string]struct{}) //ELSE CONDITIONAL seen := make(map[zzz]struct{}) //END CONDITIONAL - span.metadataSeen[key] = seen + span.metadataSeen[key.String()] = seen seen[value] = struct{}{} } else { //CONDITIONAL ONLY:Enum,Time,String,Any,Link @@ -593,36 +593,36 @@ func (span *span) MetadataZZZ(k *xopat.ZZZAttribute, v zzz) { if span.priorStringSlices == nil { span.priorStringSlices = make(map[string][]string) } - s := span.priorStringSlices[key] + s := span.priorStringSlices[key.String()] s = append(s, value) - span.priorStringSlices[key] = s - span.otelSpan.SetAttributes(attribute.StringSlice(key, s)) + span.priorStringSlices[key.String()] = s + span.otelSpan.SetAttributes(attribute.StringSlice(key.String(), s)) //CONDITIONAL ONLY:Int64 if k.SubType() == xopat.AttributeTypeDuration { if span.priorStringSlices == nil { span.priorStringSlices = make(map[string][]string) } - s := span.priorStringSlices[key] + s := span.priorStringSlices[key.String()] s = append(s, time.Duration(value).String()) - span.priorStringSlices[key] = s - span.otelSpan.SetAttributes(attribute.StringSlice(key, s)) + span.priorStringSlices[key.String()] = s + span.otelSpan.SetAttributes(attribute.StringSlice(key.String(), s)) } else { if span.priorZZZSlices == nil { span.priorZZZSlices = make(map[string][]zzz) } - s := span.priorZZZSlices[key] + s := span.priorZZZSlices[key.String()] s = append(s, value) - span.priorZZZSlices[key] = s - span.otelSpan.SetAttributes(attribute.ZZZSlice(key, s)) + span.priorZZZSlices[key.String()] = s + span.otelSpan.SetAttributes(attribute.ZZZSlice(key.String(), s)) } //CONDITIONAL SKIP:Enum,Time,String,Any,Link,Int64 if span.priorZZZSlices == nil { span.priorZZZSlices = make(map[string][]zzz) } - s := span.priorZZZSlices[key] + s := span.priorZZZSlices[key.String()] s = append(s, value) - span.priorZZZSlices[key] = s - span.otelSpan.SetAttributes(attribute.ZZZSlice(key, s)) + span.priorZZZSlices[key.String()] = s + span.otelSpan.SetAttributes(attribute.ZZZSlice(key.String(), s)) //END CONDITIONAL } diff --git a/xopotel/otel_test.go b/xopotel/otel_test.go index f62d4bb8..12a3486b 100644 --- a/xopotel/otel_test.go +++ b/xopotel/otel_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/xoplog/xop-go" + "github.com/xoplog/xop-go/xopat" "github.com/xoplog/xop-go/xopbytes" "github.com/xoplog/xop-go/xopjson" "github.com/xoplog/xop-go/xopotel" @@ -50,7 +51,7 @@ func TestSingleLineOTEL(t *testing.T) { ctx, span := tracer.Start(ctx, "test-span") log := xopotel.SpanToLog(ctx, "test-span") - log.Alert().String("foo", "bar").Int("blast", 99).Msg("a test line") + log.Alert().String(xopat.K("foo"), "bar").Int(xopat.K("blast"), 99).Msg("a test line") log.Done() span.End() tracerProvider.ForceFlush(context.Background()) diff --git a/xoppb/pb.go b/xoppb/pb.go index 9f73af3a..413b4a00 100644 --- a/xoppb/pb.go +++ b/xoppb/pb.go @@ -136,7 +136,7 @@ func (r *request) defineAttribute(k xopat.AttributeInterface) uint32 { i := uint32(len(r.attributeDefinitions)) r.attributeIndex[n] = i r.attributeDefinitions = append(r.attributeDefinitions, &xopproto.AttributeDefinition{ - Key: k.Key(), + Key: k.Key().String(), Description: k.Description(), Namespace: k.Namespace(), NamespaceSemver: k.SemverString(), @@ -295,10 +295,10 @@ func (l *line) GetTime() time.Time { return time.Unix(0, l.protoLine. func (l *line) ReclaimMemory() {} -func (b *builder) Any(k string, v xopbase.ModelArg) { +func (b *builder) Any(k xopat.K, v xopbase.ModelArg) { v.Encode() b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k, + Key: k.String(), Type: xopproto.AttributeType_Any, Value: &xopproto.AttributeValue{ StringValue: v.ModelType, @@ -310,7 +310,7 @@ func (b *builder) Any(k string, v xopbase.ModelArg) { func (b *builder) Enum(k *xopat.EnumAttribute, v xopat.Enum) { b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k.Key(), + Key: k.Key().String(), Type: xopproto.AttributeType_Enum, Value: &xopproto.AttributeValue{ StringValue: v.String(), @@ -319,9 +319,9 @@ func (b *builder) Enum(k *xopat.EnumAttribute, v xopat.Enum) { }) } -func (b *builder) Time(k string, t time.Time) { +func (b *builder) Time(k xopat.K, t time.Time) { b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k, + Key: k.String(), Type: xopproto.AttributeType_Time, Value: &xopproto.AttributeValue{ IntValue: t.UnixNano(), @@ -329,9 +329,9 @@ func (b *builder) Time(k string, t time.Time) { }) } -func (b *builder) Bool(k string, v bool) { +func (b *builder) Bool(k xopat.K, v bool) { b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k, + Key: k.String(), Type: xopproto.AttributeType_Bool, Value: &xopproto.AttributeValue{ IntValue: boolToInt64(v), @@ -346,9 +346,9 @@ func boolToInt64(b bool) int64 { return 0 } -func (b *builder) Int64(k string, v int64, dataType xopbase.DataType) { +func (b *builder) Int64(k xopat.K, v int64, dataType xopbase.DataType) { b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k, + Key: k.String(), Type: xopproto.AttributeType(dataType), Value: &xopproto.AttributeValue{ IntValue: v, @@ -356,9 +356,9 @@ func (b *builder) Int64(k string, v int64, dataType xopbase.DataType) { }) } -func (b *builder) Uint64(k string, v uint64, dataType xopbase.DataType) { +func (b *builder) Uint64(k xopat.K, v uint64, dataType xopbase.DataType) { b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k, + Key: k.String(), Type: xopproto.AttributeType(dataType), Value: &xopproto.AttributeValue{ UintValue: v, @@ -366,9 +366,9 @@ func (b *builder) Uint64(k string, v uint64, dataType xopbase.DataType) { }) } -func (b *builder) String(k string, v string, dataType xopbase.DataType) { +func (b *builder) String(k xopat.K, v string, dataType xopbase.DataType) { b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k, + Key: k.String(), Type: xopproto.AttributeType(dataType), Value: &xopproto.AttributeValue{ StringValue: v, @@ -376,9 +376,9 @@ func (b *builder) String(k string, v string, dataType xopbase.DataType) { }) } -func (b *builder) Float64(k string, v float64, dataType xopbase.DataType) { +func (b *builder) Float64(k xopat.K, v float64, dataType xopbase.DataType) { b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k, + Key: k.String(), Type: xopproto.AttributeType(dataType), Value: &xopproto.AttributeValue{ FloatValue: v, @@ -386,7 +386,7 @@ func (b *builder) Float64(k string, v float64, dataType xopbase.DataType) { }) } -func (b *builder) Duration(k string, v time.Duration) { +func (b *builder) Duration(k xopat.K, v time.Duration) { b.Int64(k, int64(v), xopbase.DurationDataType) } @@ -394,7 +394,7 @@ func (s *span) MetadataAny(k *xopat.AnyAttribute, v xopbase.ModelArg) { var distinct *distinction s.mu.Lock() defer s.mu.Unlock() - attribute, existingAttribute := s.attributeMap[k.Key()] + attribute, existingAttribute := s.attributeMap[k.Key().String()] if !existingAttribute { var c int if !k.Multiple() { @@ -410,7 +410,7 @@ func (s *span) MetadataAny(k *xopat.AnyAttribute, v xopbase.ModelArg) { if s.distinctMaps == nil { s.distinctMaps = make(map[string]*distinction) } - s.distinctMaps[k.Key()] = distinct + s.distinctMaps[k.Key().String()] = distinct } } v.Encode() @@ -453,7 +453,7 @@ func (s *span) MetadataBool(k *xopat.BoolAttribute, v bool) { var distinct *distinction s.mu.Lock() defer s.mu.Unlock() - attribute, existingAttribute := s.attributeMap[k.Key()] + attribute, existingAttribute := s.attributeMap[k.Key().String()] if !existingAttribute { var c int if !k.Multiple() { @@ -469,7 +469,7 @@ func (s *span) MetadataBool(k *xopat.BoolAttribute, v bool) { if s.distinctMaps == nil { s.distinctMaps = make(map[string]*distinction) } - s.distinctMaps[k.Key()] = distinct + s.distinctMaps[k.Key().String()] = distinct } } setValue := func(value *xopproto.AttributeValue) { @@ -516,7 +516,7 @@ func (s *span) MetadataEnum(k *xopat.EnumAttribute, v xopat.Enum) { var distinct *distinction s.mu.Lock() defer s.mu.Unlock() - attribute, existingAttribute := s.attributeMap[k.Key()] + attribute, existingAttribute := s.attributeMap[k.Key().String()] if !existingAttribute { var c int if !k.Multiple() { @@ -532,7 +532,7 @@ func (s *span) MetadataEnum(k *xopat.EnumAttribute, v xopat.Enum) { if s.distinctMaps == nil { s.distinctMaps = make(map[string]*distinction) } - s.distinctMaps[k.Key()] = distinct + s.distinctMaps[k.Key().String()] = distinct } } setValue := func(value *xopproto.AttributeValue) { @@ -565,7 +565,7 @@ func (s *span) MetadataFloat64(k *xopat.Float64Attribute, v float64) { var distinct *distinction s.mu.Lock() defer s.mu.Unlock() - attribute, existingAttribute := s.attributeMap[k.Key()] + attribute, existingAttribute := s.attributeMap[k.Key().String()] if !existingAttribute { var c int if !k.Multiple() { @@ -581,7 +581,7 @@ func (s *span) MetadataFloat64(k *xopat.Float64Attribute, v float64) { if s.distinctMaps == nil { s.distinctMaps = make(map[string]*distinction) } - s.distinctMaps[k.Key()] = distinct + s.distinctMaps[k.Key().String()] = distinct } } setValue := func(value *xopproto.AttributeValue) { @@ -620,7 +620,7 @@ func (s *span) MetadataInt64(k *xopat.Int64Attribute, v int64) { var distinct *distinction s.mu.Lock() defer s.mu.Unlock() - attribute, existingAttribute := s.attributeMap[k.Key()] + attribute, existingAttribute := s.attributeMap[k.Key().String()] if !existingAttribute { var c int if !k.Multiple() { @@ -636,7 +636,7 @@ func (s *span) MetadataInt64(k *xopat.Int64Attribute, v int64) { if s.distinctMaps == nil { s.distinctMaps = make(map[string]*distinction) } - s.distinctMaps[k.Key()] = distinct + s.distinctMaps[k.Key().String()] = distinct } } setValue := func(value *xopproto.AttributeValue) { @@ -676,7 +676,7 @@ func (s *span) MetadataLink(k *xopat.LinkAttribute, v xoptrace.Trace) { var distinct *distinction s.mu.Lock() defer s.mu.Unlock() - attribute, existingAttribute := s.attributeMap[k.Key()] + attribute, existingAttribute := s.attributeMap[k.Key().String()] if !existingAttribute { var c int if !k.Multiple() { @@ -692,7 +692,7 @@ func (s *span) MetadataLink(k *xopat.LinkAttribute, v xoptrace.Trace) { if s.distinctMaps == nil { s.distinctMaps = make(map[string]*distinction) } - s.distinctMaps[k.Key()] = distinct + s.distinctMaps[k.Key().String()] = distinct } } setValue := func(value *xopproto.AttributeValue) { @@ -732,7 +732,7 @@ func (s *span) MetadataString(k *xopat.StringAttribute, v string) { var distinct *distinction s.mu.Lock() defer s.mu.Unlock() - attribute, existingAttribute := s.attributeMap[k.Key()] + attribute, existingAttribute := s.attributeMap[k.Key().String()] if !existingAttribute { var c int if !k.Multiple() { @@ -748,7 +748,7 @@ func (s *span) MetadataString(k *xopat.StringAttribute, v string) { if s.distinctMaps == nil { s.distinctMaps = make(map[string]*distinction) } - s.distinctMaps[k.Key()] = distinct + s.distinctMaps[k.Key().String()] = distinct } } setValue := func(value *xopproto.AttributeValue) { @@ -788,7 +788,7 @@ func (s *span) MetadataTime(k *xopat.TimeAttribute, v time.Time) { var distinct *distinction s.mu.Lock() defer s.mu.Unlock() - attribute, existingAttribute := s.attributeMap[k.Key()] + attribute, existingAttribute := s.attributeMap[k.Key().String()] if !existingAttribute { var c int if !k.Multiple() { @@ -804,7 +804,7 @@ func (s *span) MetadataTime(k *xopat.TimeAttribute, v time.Time) { if s.distinctMaps == nil { s.distinctMaps = make(map[string]*distinction) } - s.distinctMaps[k.Key()] = distinct + s.distinctMaps[k.Key().String()] = distinct } } setValue := func(value *xopproto.AttributeValue) { diff --git a/xoppb/pb.zzzgo b/xoppb/pb.zzzgo index 0fda0ff0..aab51ced 100644 --- a/xoppb/pb.zzzgo +++ b/xoppb/pb.zzzgo @@ -1,7 +1,12 @@ +// TEMPLATE-FILE +// TEMPLATE-FILE +// TEMPLATE-FILE + package xoppb import ( "context" + "runtime" "sync/atomic" "time" @@ -133,7 +138,7 @@ func (r *request) defineAttribute(k xopat.AttributeInterface) uint32 { i := uint32(len(r.attributeDefinitions)) r.attributeIndex[n] = i r.attributeDefinitions = append(r.attributeDefinitions, &xopproto.AttributeDefinition{ - Key: k.Key(), + Key: k.Key().String(), Description: k.Description(), Namespace: k.Namespace(), NamespaceSemver: k.SemverString(), @@ -292,10 +297,10 @@ func (l *line) GetTime() time.Time { return time.Unix(0, l.protoLine. func (l *line) ReclaimMemory() {} -func (b *builder) Any(k string, v xopbase.ModelArg) { +func (b *builder) Any(k xopat.K, v xopbase.ModelArg) { v.Encode() b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k, + Key: k.String(), Type: xopproto.AttributeType_Any, Value: &xopproto.AttributeValue{ StringValue: v.ModelType, @@ -307,7 +312,7 @@ func (b *builder) Any(k string, v xopbase.ModelArg) { func (b *builder) Enum(k *xopat.EnumAttribute, v xopat.Enum) { b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k.Key(), + Key: k.Key().String(), Type: xopproto.AttributeType_Enum, Value: &xopproto.AttributeValue{ StringValue: v.String(), @@ -316,9 +321,9 @@ func (b *builder) Enum(k *xopat.EnumAttribute, v xopat.Enum) { }) } -func (b *builder) Time(k string, t time.Time) { +func (b *builder) Time(k xopat.K, t time.Time) { b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k, + Key: k.String(), Type: xopproto.AttributeType_Time, Value: &xopproto.AttributeValue{ IntValue: t.UnixNano(), @@ -326,9 +331,9 @@ func (b *builder) Time(k string, t time.Time) { }) } -func (b *builder) Bool(k string, v bool) { +func (b *builder) Bool(k xopat.K, v bool) { b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k, + Key: k.String(), Type: xopproto.AttributeType_Bool, Value: &xopproto.AttributeValue{ IntValue: boolToInt64(v), @@ -343,9 +348,9 @@ func boolToInt64(b bool) int64 { return 0 } -func (b *builder) Int64(k string, v int64, dataType xopbase.DataType) { +func (b *builder) Int64(k xopat.K, v int64, dataType xopbase.DataType) { b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k, + Key: k.String(), Type: xopproto.AttributeType(dataType), Value: &xopproto.AttributeValue{ IntValue: v, @@ -353,9 +358,9 @@ func (b *builder) Int64(k string, v int64, dataType xopbase.DataType) { }) } -func (b *builder) Uint64(k string, v uint64, dataType xopbase.DataType) { +func (b *builder) Uint64(k xopat.K, v uint64, dataType xopbase.DataType) { b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k, + Key: k.String(), Type: xopproto.AttributeType(dataType), Value: &xopproto.AttributeValue{ UintValue: v, @@ -363,9 +368,9 @@ func (b *builder) Uint64(k string, v uint64, dataType xopbase.DataType) { }) } -func (b *builder) String(k string, v string, dataType xopbase.DataType) { +func (b *builder) String(k xopat.K, v string, dataType xopbase.DataType) { b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k, + Key: k.String(), Type: xopproto.AttributeType(dataType), Value: &xopproto.AttributeValue{ StringValue: v, @@ -373,9 +378,9 @@ func (b *builder) String(k string, v string, dataType xopbase.DataType) { }) } -func (b *builder) Float64(k string, v float64, dataType xopbase.DataType) { +func (b *builder) Float64(k xopat.K, v float64, dataType xopbase.DataType) { b.attributes = append(b.attributes, &xopproto.Attribute{ - Key: k, + Key: k.String(), Type: xopproto.AttributeType(dataType), Value: &xopproto.AttributeValue{ FloatValue: v, @@ -383,7 +388,7 @@ func (b *builder) Float64(k string, v float64, dataType xopbase.DataType) { }) } -func (b *builder) Duration(k string, v time.Duration) { +func (b *builder) Duration(k xopat.K, v time.Duration) { b.Int64(k, int64(v), xopbase.DurationDataType) } @@ -392,7 +397,7 @@ func (s *span) MetadataZZZ(k *xopat.ZZZAttribute, v zzz) { var distinct *distinction s.mu.Lock() defer s.mu.Unlock() - attribute, existingAttribute := s.attributeMap[k.Key()] + attribute, existingAttribute := s.attributeMap[k.Key().String()] if !existingAttribute { var c int if !k.Multiple() { @@ -408,7 +413,7 @@ func (s *span) MetadataZZZ(k *xopat.ZZZAttribute, v zzz) { if s.distinctMaps == nil { s.distinctMaps = make(map[string]*distinction) } - s.distinctMaps[k.Key()] = distinct + s.distinctMaps[k.Key().String()] = distinct } } //CONDITIONAL ONLY:Any diff --git a/xoppb/replay.go b/xoppb/replay.go index 005c2876..bd190d52 100644 --- a/xoppb/replay.go +++ b/xoppb/replay.go @@ -188,6 +188,86 @@ func (x replaySpan) Replay(ctx context.Context, doDone bool) error { return nil } +type replayLine struct { + replayRequest + lineInput *xopproto.Line + span xopbase.Span +} + +func (x replayLine) Replay(ctx context.Context) error { + frames := make([]runtime.Frame, len(x.lineInput.StackFrames)) + for i, frame := range x.lineInput.StackFrames { + frames[i].File = frame.File + frames[i].Line = int(frame.LineNumber) + } + line := x.span.NoPrefill().Line( + xopnum.Level(x.lineInput.LogLevel), + time.Unix(0, x.lineInput.Timestamp), + frames, + ) + for _, attribute := range x.lineInput.Attributes { + switch attribute.Type { + case xopproto.AttributeType_Enum: + m := xopat.Make{ + Key: attribute.Key, + } + ea, err := x.registry.ConstructEnumAttribute(m, xopat.AttributeTypeEnum) + if err != nil { + return errors.Wrapf(err, "build enum attribute for line attribute (%s)", attribute.Key) + } + enum := ea.Add64(attribute.Value.IntValue, attribute.Value.StringValue) + line.Enum(&ea.EnumAttribute, enum) + case xopproto.AttributeType_Float64, xopproto.AttributeType_Float32: + line.Float64(xopat.K(attribute.Key), attribute.Value.FloatValue, xopbase.DataType(attribute.Type)) + case xopproto.AttributeType_Int64, xopproto.AttributeType_Int32, xopproto.AttributeType_Int16, + xopproto.AttributeType_Int8, xopproto.AttributeType_Int: + line.Int64(xopat.K(attribute.Key), attribute.Value.IntValue, xopbase.DataType(attribute.Type)) + case xopproto.AttributeType_String, xopproto.AttributeType_Error, xopproto.AttributeType_Stringer: + line.String(xopat.K(attribute.Key), attribute.Value.StringValue, xopbase.DataType(attribute.Type)) + case xopproto.AttributeType_Uint64, xopproto.AttributeType_Uint32, xopproto.AttributeType_Uint16, + xopproto.AttributeType_Uint8, xopproto.AttributeType_Uintptr, xopproto.AttributeType_Uint: + line.Uint64(xopat.K(attribute.Key), attribute.Value.UintValue, xopbase.DataType(attribute.Type)) + case xopproto.AttributeType_Any: + line.Any(xopat.K(attribute.Key), xopbase.ModelArg{ + ModelType: attribute.Value.StringValue, + Encoded: attribute.Value.BytesValue, + Encoding: xopproto.Encoding(attribute.Value.IntValue), + }) + case xopproto.AttributeType_Bool: + var b bool + if attribute.Value.IntValue != 0 { + b = true + } + line.Bool(xopat.K(attribute.Key), b) + case xopproto.AttributeType_Duration: + line.Duration(xopat.K(attribute.Key), time.Duration(attribute.Value.IntValue)) + case xopproto.AttributeType_Time: + line.Time(xopat.K(attribute.Key), time.Unix(0, attribute.Value.IntValue)) + default: + return errors.Errorf("unknown data type %s", attribute.Type) + } + } + switch { + case x.lineInput.Model != nil: + line.Model(x.lineInput.Message, xopbase.ModelArg{ + ModelType: x.lineInput.Model.Type, + Encoded: x.lineInput.Model.Encoded, + Encoding: x.lineInput.Model.Encoding, + }) + case x.lineInput.Link != "": + trace, ok := xoptrace.TraceFromString(x.lineInput.Link) + if !ok { + return errors.Errorf("invalid trace (%s)", x.lineInput.Link) + } + line.Link(x.lineInput.Message, trace) + case x.lineInput.MessageTemplate != "": + line.Template(x.lineInput.MessageTemplate) + default: + line.Msg(x.lineInput.Message) + } + return nil +} + func (x replaySpan) replayAttribute(attribute *xopproto.SpanAttribute) error { def := x.requestInput.AttributeDefinitions[attribute.AttributeDefinitionSequenceNumber] m := xopat.Make{ @@ -292,83 +372,3 @@ func (x replaySpan) replayAttribute(attribute *xopproto.SpanAttribute) error { return errors.Errorf("unexpected attribute type %s", def.Type) } } - -type replayLine struct { - replayRequest - lineInput *xopproto.Line - span xopbase.Span -} - -func (x replayLine) Replay(ctx context.Context) error { - frames := make([]runtime.Frame, len(x.lineInput.StackFrames)) - for i, frame := range x.lineInput.StackFrames { - frames[i].File = frame.File - frames[i].Line = int(frame.LineNumber) - } - line := x.span.NoPrefill().Line( - xopnum.Level(x.lineInput.LogLevel), - time.Unix(0, x.lineInput.Timestamp), - frames, - ) - for _, attribute := range x.lineInput.Attributes { - switch attribute.Type { - case xopproto.AttributeType_Enum: - m := xopat.Make{ - Key: attribute.Key, - } - ea, err := x.registry.ConstructEnumAttribute(m, xopat.AttributeTypeEnum) - if err != nil { - return errors.Wrapf(err, "build enum attribute for line attribute (%s)", attribute.Key) - } - enum := ea.Add64(attribute.Value.IntValue, attribute.Value.StringValue) - line.Enum(&ea.EnumAttribute, enum) - case xopproto.AttributeType_Float64, xopproto.AttributeType_Float32: - line.Float64(attribute.Key, attribute.Value.FloatValue, xopbase.DataType(attribute.Type)) - case xopproto.AttributeType_Int64, xopproto.AttributeType_Int32, xopproto.AttributeType_Int16, - xopproto.AttributeType_Int8, xopproto.AttributeType_Int: - line.Int64(attribute.Key, attribute.Value.IntValue, xopbase.DataType(attribute.Type)) - case xopproto.AttributeType_String, xopproto.AttributeType_Error, xopproto.AttributeType_Stringer: - line.String(attribute.Key, attribute.Value.StringValue, xopbase.DataType(attribute.Type)) - case xopproto.AttributeType_Uint64, xopproto.AttributeType_Uint32, xopproto.AttributeType_Uint16, - xopproto.AttributeType_Uint8, xopproto.AttributeType_Uintptr, xopproto.AttributeType_Uint: - line.Uint64(attribute.Key, attribute.Value.UintValue, xopbase.DataType(attribute.Type)) - case xopproto.AttributeType_Any: - line.Any(attribute.Key, xopbase.ModelArg{ - ModelType: attribute.Value.StringValue, - Encoded: attribute.Value.BytesValue, - Encoding: xopproto.Encoding(attribute.Value.IntValue), - }) - case xopproto.AttributeType_Bool: - var b bool - if attribute.Value.IntValue != 0 { - b = true - } - line.Bool(attribute.Key, b) - case xopproto.AttributeType_Duration: - line.Duration(attribute.Key, time.Duration(attribute.Value.IntValue)) - case xopproto.AttributeType_Time: - line.Time(attribute.Key, time.Unix(0, attribute.Value.IntValue)) - default: - return errors.Errorf("unknown data type %s", attribute.Type) - } - } - switch { - case x.lineInput.Model != nil: - line.Model(x.lineInput.Message, xopbase.ModelArg{ - ModelType: x.lineInput.Model.Type, - Encoded: x.lineInput.Model.Encoded, - Encoding: x.lineInput.Model.Encoding, - }) - case x.lineInput.Link != "": - trace, ok := xoptrace.TraceFromString(x.lineInput.Link) - if !ok { - return errors.Errorf("invalid trace (%s)", x.lineInput.Link) - } - line.Link(x.lineInput.Message, trace) - case x.lineInput.MessageTemplate != "": - line.Template(x.lineInput.MessageTemplate) - default: - line.Msg(x.lineInput.Message) - } - return nil -} diff --git a/xoppb/replay.zzzgo b/xoppb/replay.zzzgo index 025d03df..6f13d900 100644 --- a/xoppb/replay.zzzgo +++ b/xoppb/replay.zzzgo @@ -1,7 +1,11 @@ +// TEMPLATE-FILE +// TEMPLATE-FILE + package xoppb import ( "context" + "runtime" "time" "github.com/xoplog/xop-go/xopat" @@ -185,65 +189,6 @@ func (x replaySpan) Replay(ctx context.Context, doDone bool) error { return nil } -func (x replaySpan) replayAttribute(attribute *xopproto.SpanAttribute) error { - def := x.requestInput.AttributeDefinitions[attribute.AttributeDefinitionSequenceNumber] - m := xopat.Make{ - Key: def.Key, - Description: def.Description, - Namespace: def.Namespace + " " + def.NamespaceSemver, - Indexed: def.ShouldIndex, - Prominence: int(def.Prominence), - Multiple: def.Multiple, - Distinct: def.Distinct, - Ranged: def.Ranged, - Locked: def.Locked, - } - switch xopat.AttributeType(def.Type).SpanAttributeType() { - // MACRO SimpleAttributeReconstructionPB - case xopat.AttributeTypeZZZ: - registeredAttribute, err := x.registry.ConstructZZZAttribute(m, xopat.AttributeType(def.Type)) - if err != nil { - return err - } - for _, v := range attribute.Values { - // CONDITIONAL ONLY:Float64 - x.span.MetadataFloat64(registeredAttribute, zzz) - // CONDITIONAL ONLY:Int64 - x.span.MetadataInt64(registeredAttribute, zzz) - // CONDITIONAL ONLY:String - x.span.MetadataString(registeredAttribute, zzz) - // CONDITIONAL ONLY:Time - x.span.MetadataZZZ(registeredAttribute, zzz) - // CONDITIONAL ONLY:Bool - var b bool - if v.IntValue != 0 { - b = true - } - x.span.MetadataZZZ(registeredAttribute, b) - // CONDITIONAL ONLY:Link - t, ok := xoptrace.TraceFromString(v.StringValue) - if !ok { - return errors.Errorf("invalid trace attribute '%s'", v.StringValue) - } - x.span.MetadataZZZ(registeredAttribute, t) - // CONDITIONAL ONLY:Any - x.span.MetadataAny(registeredAttribute, xopbase.ModelArg{ - ModelType: v.StringValue, - Encoded: v.BytesValue, - Encoding: xopproto.Encoding(v.IntValue), - }) - // CONDITIONAL ONLY:Enum - enum := registeredAttribute.Add64(v.IntValue, v.StringValue) - x.span.MetadataEnum(®isteredAttribute.EnumAttribute, enum) - // END CONDITIONAL - } - return nil - - default: - return errors.Errorf("unexpected attribute type %s", def.Type) - } -} - type replayLine struct { replayRequest lineInput *xopproto.Line @@ -274,17 +219,17 @@ func (x replayLine) Replay(ctx context.Context) error { enum := ea.Add64(attribute.Value.IntValue, attribute.Value.StringValue) line.Enum(&ea.EnumAttribute, enum) case xopproto.AttributeType_Float64, xopproto.AttributeType_Float32: - line.Float64(attribute.Key, attribute.Value.FloatValue, xopbase.DataType(attribute.Type)) + line.Float64(xopat.K(attribute.Key), attribute.Value.FloatValue, xopbase.DataType(attribute.Type)) case xopproto.AttributeType_Int64, xopproto.AttributeType_Int32, xopproto.AttributeType_Int16, xopproto.AttributeType_Int8, xopproto.AttributeType_Int: - line.Int64(attribute.Key, attribute.Value.IntValue, xopbase.DataType(attribute.Type)) + line.Int64(xopat.K(attribute.Key), attribute.Value.IntValue, xopbase.DataType(attribute.Type)) case xopproto.AttributeType_String, xopproto.AttributeType_Error, xopproto.AttributeType_Stringer: - line.String(attribute.Key, attribute.Value.StringValue, xopbase.DataType(attribute.Type)) + line.String(xopat.K(attribute.Key), attribute.Value.StringValue, xopbase.DataType(attribute.Type)) case xopproto.AttributeType_Uint64, xopproto.AttributeType_Uint32, xopproto.AttributeType_Uint16, xopproto.AttributeType_Uint8, xopproto.AttributeType_Uintptr, xopproto.AttributeType_Uint: - line.Uint64(attribute.Key, attribute.Value.UintValue, xopbase.DataType(attribute.Type)) + line.Uint64(xopat.K(attribute.Key), attribute.Value.UintValue, xopbase.DataType(attribute.Type)) case xopproto.AttributeType_Any: - line.Any(attribute.Key, xopbase.ModelArg{ + line.Any(xopat.K(attribute.Key), xopbase.ModelArg{ ModelType: attribute.Value.StringValue, Encoded: attribute.Value.BytesValue, Encoding: xopproto.Encoding(attribute.Value.IntValue), @@ -294,11 +239,11 @@ func (x replayLine) Replay(ctx context.Context) error { if attribute.Value.IntValue != 0 { b = true } - line.Bool(attribute.Key, b) + line.Bool(xopat.K(attribute.Key), b) case xopproto.AttributeType_Duration: - line.Duration(attribute.Key, time.Duration(attribute.Value.IntValue)) + line.Duration(xopat.K(attribute.Key), time.Duration(attribute.Value.IntValue)) case xopproto.AttributeType_Time: - line.Time(attribute.Key, time.Unix(0, attribute.Value.IntValue)) + line.Time(xopat.K(attribute.Key), time.Unix(0, attribute.Value.IntValue)) default: return errors.Errorf("unknown data type %s", attribute.Type) } @@ -323,3 +268,62 @@ func (x replayLine) Replay(ctx context.Context) error { } return nil } + +func (x replaySpan) replayAttribute(attribute *xopproto.SpanAttribute) error { + def := x.requestInput.AttributeDefinitions[attribute.AttributeDefinitionSequenceNumber] + m := xopat.Make{ + Key: def.Key, + Description: def.Description, + Namespace: def.Namespace + " " + def.NamespaceSemver, + Indexed: def.ShouldIndex, + Prominence: int(def.Prominence), + Multiple: def.Multiple, + Distinct: def.Distinct, + Ranged: def.Ranged, + Locked: def.Locked, + } + switch xopat.AttributeType(def.Type).SpanAttributeType() { + // MACRO SimpleAttributeReconstructionPB + case xopat.AttributeTypeZZZ: + registeredAttribute, err := x.registry.ConstructZZZAttribute(m, xopat.AttributeType(def.Type)) + if err != nil { + return err + } + for _, v := range attribute.Values { + // CONDITIONAL ONLY:Float64 + x.span.MetadataFloat64(registeredAttribute, zzz) + // CONDITIONAL ONLY:Int64 + x.span.MetadataInt64(registeredAttribute, zzz) + // CONDITIONAL ONLY:String + x.span.MetadataString(registeredAttribute, zzz) + // CONDITIONAL ONLY:Time + x.span.MetadataZZZ(registeredAttribute, zzz) + // CONDITIONAL ONLY:Bool + var b bool + if v.IntValue != 0 { + b = true + } + x.span.MetadataZZZ(registeredAttribute, b) + // CONDITIONAL ONLY:Link + t, ok := xoptrace.TraceFromString(v.StringValue) + if !ok { + return errors.Errorf("invalid trace attribute '%s'", v.StringValue) + } + x.span.MetadataZZZ(registeredAttribute, t) + // CONDITIONAL ONLY:Any + x.span.MetadataAny(registeredAttribute, xopbase.ModelArg{ + ModelType: v.StringValue, + Encoded: v.BytesValue, + Encoding: xopproto.Encoding(v.IntValue), + }) + // CONDITIONAL ONLY:Enum + enum := registeredAttribute.Add64(v.IntValue, v.StringValue) + x.span.MetadataEnum(®isteredAttribute.EnumAttribute, enum) + // END CONDITIONAL + } + return nil + + default: + return errors.Errorf("unexpected attribute type %s", def.Type) + } +} diff --git a/xoprecorder/recorder.go b/xoprecorder/recorder.go index 21e25971..803c8d6c 100644 --- a/xoprecorder/recorder.go +++ b/xoprecorder/recorder.go @@ -116,16 +116,16 @@ type Prefilling struct { } type Builder struct { - Enums map[string]*xopat.EnumAttribute - Data map[string]interface{} - DataType map[string]xopbase.DataType + Enums map[xopat.K]*xopat.EnumAttribute + Data map[xopat.K]interface{} + DataType map[xopat.K]xopbase.DataType Span *Span } type Prefilled struct { - Enums map[string]*xopat.EnumAttribute - Data map[string]interface{} - DataType map[string]xopbase.DataType + Enums map[xopat.K]*xopat.EnumAttribute + Data map[xopat.K]interface{} + DataType map[xopat.K]xopbase.DataType Span *Span Msg string } @@ -316,9 +316,9 @@ func (span *Span) NoPrefill() xopbase.Prefilled { func (span *Span) StartPrefill() xopbase.Prefilling { return &Prefilling{ Builder: Builder{ - Enums: make(map[string]*xopat.EnumAttribute), - Data: make(map[string]interface{}), - DataType: make(map[string]xopbase.DataType), + Enums: make(map[xopat.K]*xopat.EnumAttribute), + Data: make(map[xopat.K]interface{}), + DataType: make(map[xopat.K]xopbase.DataType), Span: span, }, } @@ -340,9 +340,9 @@ func (p *Prefilled) Line(level xopnum.Level, t time.Time, frames []runtime.Frame xoputil.AtomicMaxInt64(&p.Span.provisionalEndTime, t.UnixNano()) line := &Line{ Builder: Builder{ - Enums: make(map[string]*xopat.EnumAttribute), - Data: make(map[string]interface{}), - DataType: make(map[string]xopbase.DataType), + Enums: make(map[xopat.K]*xopat.EnumAttribute), + Data: make(map[xopat.K]interface{}), + DataType: make(map[xopat.K]xopbase.DataType), Span: p.Span, }, Level: level, @@ -385,11 +385,11 @@ var templateRE = regexp.MustCompile(`\{.+?\}`) // Template is a required method for xopbase.Line func (line *Line) Template(m string) { line.Tmpl = line.Message + m - used := make(map[string]struct{}) + used := make(map[xopat.K]struct{}) msg := templateRE.ReplaceAllStringFunc(line.Tmpl, func(k string) string { k = k[1 : len(k)-1] - if v, ok := line.Data[k]; ok { - used[k] = struct{}{} + if v, ok := line.Data[xopat.K(k)]; ok { + used[xopat.K(k)] = struct{}{} return fmt.Sprint(v) } return "''" @@ -418,7 +418,7 @@ func (line *Line) Text() string { var start string var end string msg := line.Message - used := make(map[string]struct{}) + used := make(map[xopat.K]struct{}) switch { case line.AsLink != nil: start = "LINK:" @@ -428,11 +428,11 @@ func (line *Line) Text() string { start = "MODEL:" end = string(line.AsModel.Encoded) case line.Tmpl != "": - used := make(map[string]struct{}) + used := make(map[xopat.K]struct{}) msg = templateRE.ReplaceAllStringFunc(line.Tmpl, func(k string) string { k = k[1 : len(k)-1] - if v, ok := line.Data[k]; ok { - used[k] = struct{}{} + if v, ok := line.Data[xopat.K(k)]; ok { + used[xopat.K(k)] = struct{}{} return fmt.Sprint(v) } return "''" @@ -443,7 +443,7 @@ func (line *Line) Text() string { text := line.Span.Short() + " " + start + msg for k, v := range line.Data { if _, ok := used[k]; !ok { - text += " " + k + "=" + fmt.Sprint(v) + text += " " + string(k) + "=" + fmt.Sprint(v) } } if end != "" { @@ -461,7 +461,7 @@ func (line *Line) TemplateOrMessage() string { return line.Message } -func (b *Builder) any(k string, v interface{}, dt xopbase.DataType) { +func (b *Builder) any(k xopat.K, v interface{}, dt xopbase.DataType) { b.Data[k] = v b.DataType[k] = dt } @@ -475,28 +475,28 @@ func (b *Builder) Enum(k *xopat.EnumAttribute, v xopat.Enum) { } // Any is a required method for xopbase.ObjectParts -func (b *Builder) Any(k string, v xopbase.ModelArg) { b.any(k, v, xopbase.AnyDataType) } +func (b *Builder) Any(k xopat.K, v xopbase.ModelArg) { b.any(k, v, xopbase.AnyDataType) } // Bool is a required method for xopbase.ObjectParts -func (b *Builder) Bool(k string, v bool) { b.any(k, v, xopbase.BoolDataType) } +func (b *Builder) Bool(k xopat.K, v bool) { b.any(k, v, xopbase.BoolDataType) } // Duration is a required method for xopbase.ObjectParts -func (b *Builder) Duration(k string, v time.Duration) { b.any(k, v, xopbase.DurationDataType) } +func (b *Builder) Duration(k xopat.K, v time.Duration) { b.any(k, v, xopbase.DurationDataType) } // Time is a required method for xopbase.ObjectParts -func (b *Builder) Time(k string, v time.Time) { b.any(k, v, xopbase.TimeDataType) } +func (b *Builder) Time(k xopat.K, v time.Time) { b.any(k, v, xopbase.TimeDataType) } // Float64 is a required method for xopbase.ObjectParts -func (b *Builder) Float64(k string, v float64, dt xopbase.DataType) { b.any(k, v, dt) } +func (b *Builder) Float64(k xopat.K, v float64, dt xopbase.DataType) { b.any(k, v, dt) } // Int64 is a required method for xopbase.ObjectParts -func (b *Builder) Int64(k string, v int64, dt xopbase.DataType) { b.any(k, v, dt) } +func (b *Builder) Int64(k xopat.K, v int64, dt xopbase.DataType) { b.any(k, v, dt) } // String is a required method for xopbase.ObjectParts -func (b *Builder) String(k string, v string, dt xopbase.DataType) { b.any(k, v, dt) } +func (b *Builder) String(k xopat.K, v string, dt xopbase.DataType) { b.any(k, v, dt) } // Uint64 is a required method for xopbase.ObjectParts -func (b *Builder) Uint64(k string, v uint64, dt xopbase.DataType) { b.any(k, v, dt) } +func (b *Builder) Uint64(k xopat.K, v uint64, dt xopbase.DataType) { b.any(k, v, dt) } // MetadataAny is a required method for xopbase.Span func (s *Span) MetadataAny(k *xopat.AnyAttribute, v xopbase.ModelArg) { diff --git a/xoprecorder/recorder.zzzgo b/xoprecorder/recorder.zzzgo index f49e0fc3..28593068 100644 --- a/xoprecorder/recorder.zzzgo +++ b/xoprecorder/recorder.zzzgo @@ -116,16 +116,16 @@ type Prefilling struct { } type Builder struct { - Enums map[string]*xopat.EnumAttribute - Data map[string]interface{} - DataType map[string]xopbase.DataType + Enums map[xopat.K]*xopat.EnumAttribute + Data map[xopat.K]interface{} + DataType map[xopat.K]xopbase.DataType Span *Span } type Prefilled struct { - Enums map[string]*xopat.EnumAttribute - Data map[string]interface{} - DataType map[string]xopbase.DataType + Enums map[xopat.K]*xopat.EnumAttribute + Data map[xopat.K]interface{} + DataType map[xopat.K]xopbase.DataType Span *Span Msg string } @@ -316,9 +316,9 @@ func (span *Span) NoPrefill() xopbase.Prefilled { func (span *Span) StartPrefill() xopbase.Prefilling { return &Prefilling{ Builder: Builder{ - Enums: make(map[string]*xopat.EnumAttribute), - Data: make(map[string]interface{}), - DataType: make(map[string]xopbase.DataType), + Enums: make(map[xopat.K]*xopat.EnumAttribute), + Data: make(map[xopat.K]interface{}), + DataType: make(map[xopat.K]xopbase.DataType), Span: span, }, } @@ -340,9 +340,9 @@ func (p *Prefilled) Line(level xopnum.Level, t time.Time, frames []runtime.Frame xoputil.AtomicMaxInt64(&p.Span.provisionalEndTime, t.UnixNano()) line := &Line{ Builder: Builder{ - Enums: make(map[string]*xopat.EnumAttribute), - Data: make(map[string]interface{}), - DataType: make(map[string]xopbase.DataType), + Enums: make(map[xopat.K]*xopat.EnumAttribute), + Data: make(map[xopat.K]interface{}), + DataType: make(map[xopat.K]xopbase.DataType), Span: p.Span, }, Level: level, @@ -385,11 +385,11 @@ var templateRE = regexp.MustCompile(`\{.+?\}`) // Template is a required method for xopbase.Line func (line *Line) Template(m string) { line.Tmpl = line.Message + m - used := make(map[string]struct{}) + used := make(map[xopat.K]struct{}) msg := templateRE.ReplaceAllStringFunc(line.Tmpl, func(k string) string { k = k[1 : len(k)-1] - if v, ok := line.Data[k]; ok { - used[k] = struct{}{} + if v, ok := line.Data[xopat.K(k)]; ok { + used[xopat.K(k)] = struct{}{} return fmt.Sprint(v) } return "''" @@ -418,7 +418,7 @@ func (line *Line) Text() string { var start string var end string msg := line.Message - used := make(map[string]struct{}) + used := make(map[xopat.K]struct{}) switch { case line.AsLink != nil: start = "LINK:" @@ -428,11 +428,11 @@ func (line *Line) Text() string { start = "MODEL:" end = string(line.AsModel.Encoded) case line.Tmpl != "": - used := make(map[string]struct{}) + used := make(map[xopat.K]struct{}) msg = templateRE.ReplaceAllStringFunc(line.Tmpl, func(k string) string { k = k[1 : len(k)-1] - if v, ok := line.Data[k]; ok { - used[k] = struct{}{} + if v, ok := line.Data[xopat.K(k)]; ok { + used[xopat.K(k)] = struct{}{} return fmt.Sprint(v) } return "''" @@ -443,7 +443,7 @@ func (line *Line) Text() string { text := line.Span.Short() + " " + start + msg for k, v := range line.Data { if _, ok := used[k]; !ok { - text += " " + k + "=" + fmt.Sprint(v) + text += " " + string(k) + "=" + fmt.Sprint(v) } } if end != "" { @@ -461,7 +461,7 @@ func (line *Line) TemplateOrMessage() string { return line.Message } -func (b *Builder) any(k string, v interface{}, dt xopbase.DataType) { +func (b *Builder) any(k xopat.K, v interface{}, dt xopbase.DataType) { b.Data[k] = v b.DataType[k] = dt } @@ -476,11 +476,11 @@ func (b *Builder) Enum(k *xopat.EnumAttribute, v xopat.Enum) { // MACRO BaseDataWithoutType // ZZZ is a required method for xopbase.ObjectParts -func (b *Builder) ZZZ(k string, v zzz) { b.any(k, v, xopbase.ZZZDataType) } +func (b *Builder) ZZZ(k xopat.K, v zzz) { b.any(k, v, xopbase.ZZZDataType) } // MACRO BaseDataWithType // ZZZ is a required method for xopbase.ObjectParts -func (b *Builder) ZZZ(k string, v zzz, dt xopbase.DataType) { b.any(k, v, dt) } +func (b *Builder) ZZZ(k xopat.K, v zzz, dt xopbase.DataType) { b.any(k, v, dt) } // MACRO BaseAttribute // MetadataZZZ is a required method for xopbase.Span diff --git a/xoprecorder/recorder_test.go b/xoprecorder/recorder_test.go index faad7fc4..511d7764 100644 --- a/xoprecorder/recorder_test.go +++ b/xoprecorder/recorder_test.go @@ -26,7 +26,6 @@ func TestRecorderLogMethods(t *testing.T) { log.Alert().Msg("basic alert message") log.Log().Msg("basic log message") log.Debug().Msg("basic debug message") - log.Trace().Msg("basic trace message") log.Info().String("foo", "bar").Int("num", 38).Template("a test {foo} with {num}") lines := rLog.FindLines(xoprecorder.MessageEquals("basic debug message")) if assert.NotEmpty(t, lines, "found some") { diff --git a/xoprecorder/replay.go b/xoprecorder/replay.go index d904b9d8..d751d6de 100644 --- a/xoprecorder/replay.go +++ b/xoprecorder/replay.go @@ -131,72 +131,72 @@ func (log *Logger) Replay(ctx context.Context, dest xopbase.Logger) error { } func ReplayLineData(source *Line, dest xopbase.Builder) { - for k, v := range source.Data { - dataType := source.DataType[k] + for key, v := range source.Data { + dataType := source.DataType[key] switch dataType { case xopbase.AnyDataType: - dest.Any(k, v.(xopbase.ModelArg)) + dest.Any(key, v.(xopbase.ModelArg)) // next line must be blank to end macro BaseDataWithoutType case xopbase.BoolDataType: - dest.Bool(k, v.(bool)) + dest.Bool(key, v.(bool)) // next line must be blank to end macro BaseDataWithoutType case xopbase.DurationDataType: - dest.Duration(k, v.(time.Duration)) + dest.Duration(key, v.(time.Duration)) // next line must be blank to end macro BaseDataWithoutType case xopbase.TimeDataType: - dest.Time(k, v.(time.Time)) + dest.Time(key, v.(time.Time)) // next line must be blank to end macro BaseDataWithoutType case xopbase.Float64DataType: - dest.Float64(k, v.(float64), dataType) + dest.Float64(key, v.(float64), dataType) // next line must be blank to end macro BaseDataWithType case xopbase.StringDataType: - dest.String(k, v.(string), dataType) + dest.String(key, v.(string), dataType) // next line must be blank to end macro BaseDataWithType case xopbase.IntDataType: - dest.Int64(k, v.(int64), dataType) + dest.Int64(key, v.(int64), dataType) // next line must be blank to end macro Ints case xopbase.Int16DataType: - dest.Int64(k, v.(int64), dataType) + dest.Int64(key, v.(int64), dataType) // next line must be blank to end macro Ints case xopbase.Int32DataType: - dest.Int64(k, v.(int64), dataType) + dest.Int64(key, v.(int64), dataType) // next line must be blank to end macro Ints case xopbase.Int64DataType: - dest.Int64(k, v.(int64), dataType) + dest.Int64(key, v.(int64), dataType) // next line must be blank to end macro Ints case xopbase.Int8DataType: - dest.Int64(k, v.(int64), dataType) + dest.Int64(key, v.(int64), dataType) // next line must be blank to end macro Ints case xopbase.UintDataType: - dest.Uint64(k, v.(uint64), dataType) + dest.Uint64(key, v.(uint64), dataType) // next line must be blank to end macro Ints case xopbase.Uint16DataType: - dest.Uint64(k, v.(uint64), dataType) + dest.Uint64(key, v.(uint64), dataType) // next line must be blank to end macro Ints case xopbase.Uint32DataType: - dest.Uint64(k, v.(uint64), dataType) + dest.Uint64(key, v.(uint64), dataType) // next line must be blank to end macro Ints case xopbase.Uint64DataType: - dest.Uint64(k, v.(uint64), dataType) + dest.Uint64(key, v.(uint64), dataType) // next line must be blank to end macro Ints case xopbase.Uint8DataType: - dest.Uint64(k, v.(uint64), dataType) + dest.Uint64(key, v.(uint64), dataType) // next line must be blank to end macro Ints case xopbase.UintptrDataType: - dest.Uint64(k, v.(uint64), dataType) + dest.Uint64(key, v.(uint64), dataType) // next line must be blank to end macro Ints case xopbase.ErrorDataType, xopbase.StringerDataType: - dest.String(k, v.(string), dataType) + dest.String(key, v.(string), dataType) case xopbase.Float32DataType: - dest.Float64(k, v.(float64), dataType) + dest.Float64(key, v.(float64), dataType) case xopbase.EnumDataType: - dest.Enum(source.Enums[k], v.(xopat.Enum)) + dest.Enum(source.Enums[key], v.(xopat.Enum)) default: - dest.String(k, fmt.Sprintf("unexpected data type %s in line, with value of type %T: %+v", dataType, v, v), xopbase.ErrorDataType) + dest.String(key, fmt.Sprintf("unexpected data type %s in line, with value of type %T: %+v", dataType, v, v), xopbase.ErrorDataType) } } } diff --git a/xoprecorder/replay.zzzgo b/xoprecorder/replay.zzzgo index 087442ca..cdb2665e 100644 --- a/xoprecorder/replay.zzzgo +++ b/xoprecorder/replay.zzzgo @@ -1,6 +1,5 @@ // TEMPLATE-FILE // TEMPLATE-FILE -// TEMPLATE-FILE package xoprecorder @@ -111,37 +110,37 @@ func (log *Logger) Replay(ctx context.Context, dest xopbase.Logger) error { } func ReplayLineData(source *Line, dest xopbase.Builder) { - for k, v := range source.Data { - dataType := source.DataType[k] + for key, v := range source.Data { + dataType := source.DataType[key] switch dataType { //MACRO BaseDataWithoutType case xopbase.ZZZDataType: - dest.ZZZ(k, v.(zzz)) + dest.ZZZ(key, v.(zzz)) // next line must be blank to end macro BaseDataWithoutType //MACRO BaseDataWithType SKIP:Int64,Uint64 case xopbase.ZZZDataType: - dest.ZZZ(k, v.(zzz), dataType) + dest.ZZZ(key, v.(zzz), dataType) // next line must be blank to end macro BaseDataWithType //MACRO Ints case xopbase.ZZZDataType: - dest.Int64(k, v.(int64), dataType) + dest.Int64(key, v.(int64), dataType) // next line must be blank to end macro Ints //MACRO Uints case xopbase.ZZZDataType: - dest.Uint64(k, v.(uint64), dataType) + dest.Uint64(key, v.(uint64), dataType) // next line must be blank to end macro Ints case xopbase.ErrorDataType, xopbase.StringerDataType: - dest.String(k, v.(string), dataType) + dest.String(key, v.(string), dataType) case xopbase.Float32DataType: - dest.Float64(k, v.(float64), dataType) + dest.Float64(key, v.(float64), dataType) case xopbase.EnumDataType: - dest.Enum(source.Enums[k], v.(xopat.Enum)) + dest.Enum(source.Enums[key], v.(xopat.Enum)) default: - dest.String(k, fmt.Sprintf("unexpected data type %s in line, with value of type %T: %+v", dataType, v, v), xopbase.ErrorDataType) + dest.String(key, fmt.Sprintf("unexpected data type %s in line, with value of type %T: %+v", dataType, v, v), xopbase.ErrorDataType) } } } diff --git a/xopresty/resty.go b/xopresty/resty.go index 1882ae1c..c807f29f 100644 --- a/xopresty/resty.go +++ b/xopresty/resty.go @@ -73,6 +73,11 @@ type config struct { type ClientOpt func(*config) +var traceResponseHeaderKey = xop.Key("header") +var requestTimeKey = xop.Key("request_time.total") +var requestTimeServerKey = xop.Key("request_time.server") +var requestTimeDNSKey = xop.Key("request_time.dns") + // WithNameGenerate provides a function to convert a request into // a description for the span. func WithNameGenerate(f func(*resty.Request) string) ClientOpt { @@ -196,10 +201,10 @@ func Client(client *resty.Client, opts ...ClientOpt) *resty.Client { trace, ok := xoptrace.TraceFromString(tr) if ok { cv.response = true - log.Info().Link(trace, xopconst.RemoteTrace.Key()) + log.Info().Link(trace, xopconst.RemoteTrace.Key().String()) log.Span().Link(xopconst.RemoteTrace, trace) } else { - log.Warn().String("header", tr).Msg("invalid traceresponse received") + log.Warn().String(traceResponseHeaderKey, tr).Msg("invalid traceresponse received") } } if r.Result != nil { @@ -208,9 +213,9 @@ func Client(client *resty.Client, opts ...ClientOpt) *resty.Client { ti := r.TraceInfo() if ti.TotalTime != 0 { log.Info(). - Duration("request_time.total", ti.TotalTime). - Duration("request_time.server", ti.ServerTime). - Duration("request_time.dns", ti.DNSLookup). + Duration(requestTimeKey, ti.TotalTime). + Duration(requestTimeServerKey, ti.ServerTime). + Duration(requestTimeDNSKey, ti.DNSLookup). Msg("timings") } return nil diff --git a/xoptest/redact_test.go b/xoptest/redact_test.go index 70118356..2b1018e9 100644 --- a/xoptest/redact_test.go +++ b/xoptest/redact_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/xoplog/xop-go" + "github.com/xoplog/xop-go/xopat" "github.com/xoplog/xop-go/xopbase" "github.com/xoplog/xop-go/xoprecorder" "github.com/xoplog/xop-go/xoptest" @@ -37,11 +38,11 @@ func TestRedaction(t *testing.T) { log := xop.NewSeed( xop.WithBase(tLog), xop.WithSettings(func(settings *xop.LogSettings) { - settings.SetRedactStringFunc(func(baseLine xopbase.Line, k string, v string) { + settings.SetRedactStringFunc(func(baseLine xopbase.Line, k xopat.K, v string) { v = strings.ReplaceAll(v, "sunflower", "daisy") baseLine.String(k, v, xopbase.StringDataType) }) - settings.SetRedactAnyFunc(func(baseLine xopbase.Line, k string, v interface{}, alreadyImmutable bool) { + settings.SetRedactAnyFunc(func(baseLine xopbase.Line, k xopat.K, v interface{}, alreadyImmutable bool) { if !alreadyImmutable { v = deepcopy.Copy(v) } @@ -55,7 +56,7 @@ func TestRedaction(t *testing.T) { }) } }) - settings.SetRedactErrorFunc(func(baseLine xopbase.Line, k string, v error) { + settings.SetRedactErrorFunc(func(baseLine xopbase.Line, k xopat.K, v error) { baseLine.String(k, v.Error()+"(as string)", xopbase.ErrorDataType) }) }), @@ -64,12 +65,12 @@ func TestRedaction(t *testing.T) { a := selfRedactor{V: "I got the contract with a small bribe, just a sunflower cookie"} log.Info(). - String("garden", "nothing in my garden is taller than my sunflower!"). - Any("story", a). - Any("tale", a). - AnyWithoutRedaction("raw", a). - Stringer("success", a). - Error("oops", fmt.Errorf("outer: %w", fmt.Errorf("inner"))). + String(xop.Key("garden"), "nothing in my garden is taller than my sunflower!"). + Any(xop.Key("story"), a). + Any(xop.Key("tale"), a). + AnyWithoutRedaction(xop.Key("raw"), a). + Stringer(xop.Key("success"), a). + Error(xop.Key("oops"), fmt.Errorf("outer: %w", fmt.Errorf("inner"))). Msg("foo") foos := tLog.Recorder().FindLines(xoprecorder.MessageEquals("foo")) diff --git a/xoptest/testlogger_test.go b/xoptest/testlogger_test.go index 84dc67c6..00c9e84f 100644 --- a/xoptest/testlogger_test.go +++ b/xoptest/testlogger_test.go @@ -5,14 +5,15 @@ import ( "testing" "time" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/xoplog/xop-go/xopbase" "github.com/xoplog/xop-go/xopconst" "github.com/xoplog/xop-go/xopnum" "github.com/xoplog/xop-go/xoprecorder" "github.com/xoplog/xop-go/xoptest" "github.com/xoplog/xop-go/xoptest/xoptestutil" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestLogMethods(t *testing.T) { diff --git a/xoptest/xoptestutil/cases.go b/xoptest/xoptestutil/cases.go index bb3bacec..469e236c 100644 --- a/xoptest/xoptestutil/cases.go +++ b/xoptest/xoptestutil/cases.go @@ -32,11 +32,11 @@ var MessageCases = []struct { log.Alert().Msg("basic alert message") log.Debug().Msg("basic debug message") log.Trace().Msg("basic trace message") - log.Info().String("foo", "bar").Int("num", 38).Template("a test {foo} with {num}") + log.Info().String(xop.Key("foo"), "bar").Int(xop.Key("num"), 38).Template("a test {foo} with {num}") ss := log.Sub().Detach().Fork("a fork one span") MicroNap() - ss.Alert().String("frightening", "stuff").Msg("like a rock" + NeedsEscaping) + ss.Alert().String(xop.Key("frightening"), "stuff").Msg("like a rock" + NeedsEscaping) ss.Span().String(xopconst.EndpointRoute, "/some/thing") MicroNap() @@ -404,7 +404,7 @@ var MessageCases = []struct { SkipOTEL: true, Do: func(t *testing.T, log *xop.Logger, tlog *xoptest.Logger) { s2 := log.Sub().Step("S2") - s2.Info().Int8("i8", 9).Msg("a line before done") + s2.Info().Int8(xop.Key("i8"), 9).Msg("a line before done") MicroNap() s2.Done() assert.Empty(t, tlog.Recorder().FindLines(xoprecorder.TextContains("XOP: logger was already done, but was used again")), "no err") @@ -415,7 +415,7 @@ var MessageCases = []struct { s2.Done() assert.NotEmpty(t, tlog.Recorder().FindLines(xoprecorder.TextContains("called on logger object when it was already Done")), "now err") log.Flush() - s2.Warn().Int32("i32", 940940).Msg("another post-done line, should trigger an error log") + s2.Warn().Int32(xop.Key("i32"), 940940).Msg("another post-done line, should trigger an error log") MicroNap() log.Done() }, @@ -466,8 +466,8 @@ var MessageCases = []struct { { Name: "type-duration", Do: func(t *testing.T, log *xop.Logger, tlog *xoptest.Logger) { - p := log.Sub().PrefillDuration("1m", time.Minute).Logger() - p.Warn().Duration("hour", time.Hour).Msg("duration") + p := log.Sub().PrefillDuration(xop.Key("1m"), time.Minute).Logger() + p.Warn().Duration(xop.Key("hour"), time.Hour).Msg("duration") MicroNap() log.Done() }, @@ -504,10 +504,10 @@ var MessageCases = []struct { sc := newStringCounter(&callCount, "foobar") skipper := log.Sub().MinLevel(xopnum.InfoLevel).Logger() skipper.Debug(). - Stringer("avoid", sc). - String("avoid", "blaf"). - Any("null", nil). - Error("no", fmt.Errorf("bar")). + Stringer(xop.Key("avoid"), sc). + String(xop.Key("avoid"), "blaf"). + Any(xop.Key("null"), nil). + Error(xop.Key("no"), fmt.Errorf("bar")). Msg("no foobar") log.Trace().Stringer("don't", sc).Msg("yes, trace") log.Debug().Stringer("do", sc).Msg("yes, debug")