Skip to content

Commit

Permalink
Merge pull request #70 from muir/fiftyeight
Browse files Browse the repository at this point in the history
use JSONKey() for enum keys and attribute names
  • Loading branch information
muir committed Sep 25, 2022
2 parents 8ede7c4 + 071a631 commit 74e87c5
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 97 deletions.
13 changes: 13 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,24 @@
- allow custom error formats
- allow go-routine id to be logged
- allow int64 to switch to string encoding when >2**50
- do something useful with Boring

- write to xop server

- keep dictionary of static strings

- Line.Static()
- Enum descriptions and types

- xopbytes.BytesWriter

- write to writing rotating files based time or size

- xopotel

- add wrapper to use otel exporter directly as xopbase
- add wrapper to use xopbase as otel exporter
- do something useful with Boring

- Performmance

Expand Down
19 changes: 12 additions & 7 deletions xopat/attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,26 +156,31 @@ func (s Make) make(exampleValue interface{}, subType AttributeType) (Attribute,
if s.Namespace == "" {
s.Namespace = DefaultNamespace
}
jsonKey, err := json.Marshal(s.Key)
if err != nil {
return Attribute{}, fmt.Errorf("cannot marshal attribute name '%s': %w", s.Key, err)
}
ra := Attribute{
properties: s,
exampleValue: exampleValue,
reflectType: reflect.TypeOf(exampleValue),
typeName: fmt.Sprintf("%T", exampleValue),
subType: subType,
jsonKey: string(jsonKey) + ":",
}
jsonKey, err := json.Marshal(s.Key)
if err != nil {
return ra, fmt.Errorf("cannot marshal attribute name '%s': %w", s.Key, err)
}
ra.jsonKey = string(jsonKey)
registeredNames[s.Key] = &ra
allAttributes = append(allAttributes, &ra)
return ra, nil
}

type JSONKey string

func (jk JSONKey) String() string { return string(jk) }

// JSONKey returns a JSON-quoted string that can be used as the key to the
// name of the attribute. It is a string because []byte is mutable
func (r Attribute) JSONKey() string { return r.jsonKey }
// name of the attribute. It is a string because []byte is mutable. JSONKey
// includes a colon at the end since it's uses is as a key.
func (r Attribute) JSONKey() JSONKey { return JSONKey(r.jsonKey) }

// ReflectType can be nil if the example value was nil
func (r Attribute) ReflectType() reflect.Type { return r.reflectType }
Expand Down
44 changes: 24 additions & 20 deletions xopat/attributes.zzzgo
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,17 @@ var DefaultNamespace = os.Args[0]

// Make is used to construct attributes.
// Some keys are reserved. See https://github.com/muir/xop-go/blob/main/xopconst/reserved.go
// for the list of reserved keys. Some keys are already registered.
// for the list of reserved keys. Some keys are already registered.
type Make struct {
Key string // the attribute name
Description string // the attribute description
Namespace string // the namespace for this attribute (otherwise DefaultNamespace is used)
Indexed bool // hint: this attribute should be indexed
Prominence int // hint: how important is this attribute (lower is more important)
Multiple bool // keep all values if the attribute is given multiple times
Distinct bool // when keeping all values, only keep distinct values (not supported for interface{})
Ranged bool // hint: comparisons between values are meaningful (eg: time, integers)
Locked bool // only keep the first value
Key string // the attribute name
Description string // the attribute description
Namespace string // the namespace for this attribute (otherwise DefaultNamespace is used)
Indexed bool // hint: this attribute should be indexed
Prominence int // hint: how important is this attribute (lower is more important)
Multiple bool // keep all values if the attribute is given multiple times
Distinct bool // when keeping all values, only keep distinct values (not supported for interface{})
Ranged bool // hint: comparisons between values are meaningful (eg: time, integers)
Locked bool // only keep the first value
}

var lock sync.RWMutex
Expand Down Expand Up @@ -140,30 +140,35 @@ func (s Make) make(exampleValue interface{}, subType AttributeType) (Attribute,
if _, ok := reservedKeys[s.Key]; ok {
return Attribute{}, fmt.Errorf("key is reserved for internal use '%s'", s.Key)
}

if s.Namespace == "" {
s.Namespace = DefaultNamespace
}
jsonKey, err := json.Marshal(s.Key)
if err != nil {
return Attribute{}, fmt.Errorf("cannot marshal attribute name '%s': %w", s.Key, err)
}
ra := Attribute{
properties: s,
exampleValue: exampleValue,
reflectType: reflect.TypeOf(exampleValue),
typeName: fmt.Sprintf("%T", exampleValue),
subType: subType,
jsonKey: string(jsonKey) + ":",
}
jsonKey, err := json.Marshal(s.Key)
if err != nil {
return ra, fmt.Errorf("cannot marshal attribute name '%s': %w", s.Key, err)
}
ra.jsonKey = string(jsonKey)
registeredNames[s.Key] = &ra
allAttributes = append(allAttributes, &ra)
return ra, nil
}

type JSONKey string

func (jk JSONKey) String() string { return string(jk) }

// JSONKey returns a JSON-quoted string that can be used as the key to the
// name of the attribute. It is a string because []byte is mutable
func (r Attribute) JSONKey() string { return r.jsonKey }
// name of the attribute. It is a string because []byte is mutable. JSONKey
// includes a colon at the end since it's uses is as a key.
func (r Attribute) JSONKey() JSONKey { return JSONKey(r.jsonKey) }

// ReflectType can be nil if the example value was nil
func (r Attribute) ReflectType() reflect.Type { return r.reflectType }
Expand Down Expand Up @@ -210,10 +215,9 @@ const (
// ZZZAttribute is a just an Int64Attribute that with
// SubType() == AttributeTypeDuration. A base logger may
// look at SubType() to provide specialized behavior.
type ZZZAttribute struct{Int64Attribute}
type ZZZAttribute struct{ Int64Attribute }

//MACRO ZZZAttribute SKIP:Enum,Duration,Int,Int8,Int16,Int32
// ZZZAttribute represents an attribute key that can be used
// with zzz values.
type ZZZAttribute struct{ Attribute }

62 changes: 25 additions & 37 deletions xopjson/attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ type multiAttribute struct {
}

type attribute struct {
Name []byte
Changed bool
Type xopbase.DataType
}
Expand Down Expand Up @@ -101,20 +100,15 @@ func (a *AttributeBuilder) Append(b *xoputil.JBuilder, onlyChanged bool) {
}
}

func (m *multiAttribute) init(a *AttributeBuilder, k string) {
func (m *multiAttribute) init(a *AttributeBuilder, jsonKey xopat.JSONKey) {
m.Builder.B = m.Buf[:0]
m.Builder.reset(a.span)
m.Builder.AddString(k)
if len(m.Builder.B) == len(k)+2 {
m.Name = m.Builder.B[1 : len(m.Builder.B)-1]
} else {
m.Name = []byte(k)
}
m.Builder.AppendBytes([]byte{':', '['}) // ]
m.Builder.AppendString(jsonKey.String())
m.Builder.AppendByte('[') // ]
m.Distinct = nil
}

func (a *AttributeBuilder) addMulti(k string) *multiAttribute {
func (a *AttributeBuilder) addMulti(k string, jsonKey xopat.JSONKey) *multiAttribute {
var m *multiAttribute
var ok bool
m, ok = a.multiMap[k]
Expand All @@ -124,38 +118,32 @@ func (a *AttributeBuilder) addMulti(k string) *multiAttribute {
}
a.multis = a.multis[:len(a.multis)+1]
m = &a.multis[len(a.multis)-1]
m.init(a, k)
m.init(a, jsonKey)
a.multiMap[k] = m
}
m.Changed = true
m.Builder.Comma()
return m
}

func (s *singleAttribute) init(k string) {
func (s *singleAttribute) init(jsonKey xopat.JSONKey) {
b := xoputil.JBuilder{
B: s.Buf[:0],
}
b.AddString(k)
if len(b.B) == len(k)+2 {
s.Name = b.B[1 : len(b.B)-1]
} else {
s.Name = []byte(k)
}
b.AppendByte(':')
b.AppendString(jsonKey.String())
s.Changed = true
s.KeyValue = b.B
}

func (a *AttributeBuilder) addSingle(k string) (*singleAttribute, bool) {
func (a *AttributeBuilder) addSingle(k string, jsonKey xopat.JSONKey) (*singleAttribute, bool) {
s, ok := a.singleMap[k]
if !ok {
if len(a.singles) == cap(a.singles) {
a.singles = make([]singleAttribute, 0, cap(a.singles))
}
a.singles = a.singles[:len(a.singles)+1]
s = &a.singles[len(a.singles)-1]
s.init(k)
s.init(jsonKey)
a.singleMap[k] = s
}
s.Changed = true
Expand All @@ -171,7 +159,7 @@ func (a *AttributeBuilder) MetadataAny(k *xopat.AnyAttribute, v interface{}) {
a.encoder.SetEscapeHTML(false)
}
if !k.Multiple() {
s, preExisting := a.addSingle(k.Key())
s, preExisting := a.addSingle(k.Key(), k.JSONKey())
if preExisting {
if k.Locked() {
return
Expand All @@ -194,7 +182,7 @@ func (a *AttributeBuilder) MetadataAny(k *xopat.AnyAttribute, v interface{}) {
s.KeyValue = b.B
return
}
m := a.addMulti(k.Key())
m := a.addMulti(k.Key(), k.JSONKey())
m.Type = xopbase.AnyDataType
a.encodeTarget = &m.Builder.B
m.Builder.encoder = a.encoder
Expand Down Expand Up @@ -223,7 +211,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())
s, preExisting := a.addSingle(k.Key(), k.JSONKey())
if preExisting {
if k.Locked() {
return
Expand All @@ -244,7 +232,7 @@ func (a *AttributeBuilder) MetadataBool(k *xopat.BoolAttribute, v bool) {
s.KeyValue = b.B
return
}
m := a.addMulti(k.Key())
m := a.addMulti(k.Key(), k.JSONKey())
m.Type = xopbase.BoolDataType
lenBefore := len(m.Builder.B)
m.Builder.AddBool(v)
Expand All @@ -271,7 +259,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())
s, preExisting := a.addSingle(k.Key(), k.JSONKey())
if preExisting {
if k.Locked() {
return
Expand All @@ -292,7 +280,7 @@ func (a *AttributeBuilder) MetadataEnum(k *xopat.EnumAttribute, v xopat.Enum) {
s.KeyValue = b.B
return
}
m := a.addMulti(k.Key())
m := a.addMulti(k.Key(), k.JSONKey())
m.Type = xopbase.EnumDataType
lenBefore := len(m.Builder.B)
m.Builder.AddEnum(v)
Expand All @@ -319,7 +307,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())
s, preExisting := a.addSingle(k.Key(), k.JSONKey())
if preExisting {
if k.Locked() {
return
Expand All @@ -340,7 +328,7 @@ func (a *AttributeBuilder) MetadataFloat64(k *xopat.Float64Attribute, v float64)
s.KeyValue = b.B
return
}
m := a.addMulti(k.Key())
m := a.addMulti(k.Key(), k.JSONKey())
m.Type = xopbase.Float64DataType
lenBefore := len(m.Builder.B)
m.Builder.AddFloat64(v)
Expand All @@ -367,7 +355,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())
s, preExisting := a.addSingle(k.Key(), k.JSONKey())
if preExisting {
if k.Locked() {
return
Expand All @@ -388,7 +376,7 @@ func (a *AttributeBuilder) MetadataInt64(k *xopat.Int64Attribute, v int64) {
s.KeyValue = b.B
return
}
m := a.addMulti(k.Key())
m := a.addMulti(k.Key(), k.JSONKey())
m.Type = xopbase.Int64DataType
lenBefore := len(m.Builder.B)
m.Builder.AddInt64(v)
Expand All @@ -415,7 +403,7 @@ func (a *AttributeBuilder) MetadataLink(k *xopat.LinkAttribute, v trace.Trace) {
defer a.lock.Unlock()
a.anyChanged = true
if !k.Multiple() {
s, preExisting := a.addSingle(k.Key())
s, preExisting := a.addSingle(k.Key(), k.JSONKey())
if preExisting {
if k.Locked() {
return
Expand All @@ -436,7 +424,7 @@ func (a *AttributeBuilder) MetadataLink(k *xopat.LinkAttribute, v trace.Trace) {
s.KeyValue = b.B
return
}
m := a.addMulti(k.Key())
m := a.addMulti(k.Key(), k.JSONKey())
m.Type = xopbase.LinkDataType
lenBefore := len(m.Builder.B)
m.Builder.AddLink(v)
Expand All @@ -463,7 +451,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())
s, preExisting := a.addSingle(k.Key(), k.JSONKey())
if preExisting {
if k.Locked() {
return
Expand All @@ -484,7 +472,7 @@ func (a *AttributeBuilder) MetadataString(k *xopat.StringAttribute, v string) {
s.KeyValue = b.B
return
}
m := a.addMulti(k.Key())
m := a.addMulti(k.Key(), k.JSONKey())
m.Type = xopbase.StringDataType
lenBefore := len(m.Builder.B)
m.Builder.AddString(v)
Expand All @@ -511,7 +499,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())
s, preExisting := a.addSingle(k.Key(), k.JSONKey())
if preExisting {
if k.Locked() {
return
Expand All @@ -532,7 +520,7 @@ func (a *AttributeBuilder) MetadataTime(k *xopat.TimeAttribute, v time.Time) {
s.KeyValue = b.B
return
}
m := a.addMulti(k.Key())
m := a.addMulti(k.Key(), k.JSONKey())
m.Type = xopbase.TimeDataType
lenBefore := len(m.Builder.B)
m.Builder.AddTime(v)
Expand Down
Loading

0 comments on commit 74e87c5

Please sign in to comment.