diff --git a/vimebu.go b/vimebu.go index c2412cc..516da0a 100644 --- a/vimebu.go +++ b/vimebu.go @@ -9,11 +9,13 @@ import ( "unsafe" ) -const ( +var ( MetricNameMaxLen = 256 // MetricNameMaxLen is the maximum len in bytes allowed for the metric name. LabelNameMaxLen = 128 // LabelNameMaxLen is the maximum len in bytes allowed for a label name. LabelValueLen = 1024 // LabelValueLen is the maximum len in bytes allowed for a label value. +) +const ( leftBracketByte = byte('{') rightBracketByte = byte('}') commaByte = byte(',') @@ -84,7 +86,7 @@ func (b *Builder) Metric(name string) *Builder { // - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. // - the label value is empty or contains more than [vimebu.LabelValueMaxLen]. func (b *Builder) LabelQuote(name, value string) *Builder { - return b.label(name, true, &value, nil, nil, nil) + return b.label(name, true, &value, nil, nil, nil, nil) } // Label appends a pair of label name and label value to the Builder. @@ -96,7 +98,7 @@ func (b *Builder) LabelQuote(name, value string) *Builder { // - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. // - the label value is empty or contains more than [vimebu.LabelValueMaxLen]. func (b *Builder) Label(name, value string) *Builder { - return b.label(name, false, &value, nil, nil, nil) + return b.label(name, false, &value, nil, nil, nil, nil) } // LabelBool appends a pair of label name and boolean label value to the Builder. @@ -105,25 +107,125 @@ func (b *Builder) Label(name, value string) *Builder { // - no metric name has been set using [vimebu.Builder.Metric]. // - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. func (b *Builder) LabelBool(name string, value bool) *Builder { - return b.label(name, false, nil, &value, nil, nil) + return b.label(name, false, nil, &value, nil, nil, nil) +} + +// LabelUint appends a pair of label name and uint label value to the Builder. +// +// NoOp if : +// - no metric name has been set using [vimebu.Builder.Metric]. +// - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. +func (b *Builder) LabelUint(name string, value uint) *Builder { + i := uint64(value) + return b.label(name, false, nil, nil, &i, nil, nil) } -// LabelInt appends a pair of label name and int64 label value to the Builder. +// LabelUint8 appends a pair of label name and uint8 label value to the Builder. // // NoOp if : // - no metric name has been set using [vimebu.Builder.Metric]. // - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. -func (b *Builder) LabelInt(name string, value int64) *Builder { - return b.label(name, false, nil, nil, &value, nil) +func (b *Builder) LabelUint8(name string, value uint8) *Builder { + i := uint64(value) + return b.label(name, false, nil, nil, &i, nil, nil) } -// LabelFloat appends a pair of label name and float64 label value to the Builder. +// LabelUint16 appends a pair of label name and uint16 label value to the Builder. // // NoOp if : // - no metric name has been set using [vimebu.Builder.Metric]. // - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. -func (b *Builder) LabelFloat(name string, value float64) *Builder { - return b.label(name, false, nil, nil, nil, &value) +func (b *Builder) LabelUint16(name string, value uint16) *Builder { + i := uint64(value) + return b.label(name, false, nil, nil, &i, nil, nil) +} + +// LabelUint32 appends a pair of label name and uint32 label value to the Builder. +// +// NoOp if : +// - no metric name has been set using [vimebu.Builder.Metric]. +// - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. +func (b *Builder) LabelUint32(name string, value uint32) *Builder { + i := uint64(value) + return b.label(name, false, nil, nil, &i, nil, nil) +} + +// LabelUint64 appends a pair of label name and uint64 label value to the Builder. +// +// NoOp if : +// - no metric name has been set using [vimebu.Builder.Metric]. +// - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. +func (b *Builder) LabelUint64(name string, value uint64) *Builder { + return b.label(name, false, nil, nil, &value, nil, nil) +} + +// LabelInt appends a pair of label name and int label value to the Builder. +// +// NoOp if : +// - no metric name has been set using [vimebu.Builder.Metric]. +// - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. +func (b *Builder) LabelInt(name string, value int) *Builder { + i := int64(value) + return b.label(name, false, nil, nil, nil, &i, nil) +} + +// LabelInt8 appends a pair of label name and int8 label value to the Builder. +// +// NoOp if : +// - no metric name has been set using [vimebu.Builder.Metric]. +// - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. +func (b *Builder) LabelInt8(name string, value int8) *Builder { + i := int64(value) + return b.label(name, false, nil, nil, nil, &i, nil) +} + +// LabelInt16 appends a pair of label name and int16 label value to the Builder. +// +// NoOp if : +// - no metric name has been set using [vimebu.Builder.Metric]. +// - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. +func (b *Builder) LabelInt16(name string, value int16) *Builder { + i := int64(value) + return b.label(name, false, nil, nil, nil, &i, nil) +} + +// LabelInt32 appends a pair of label name and int32 label value to the Builder. +// +// NoOp if : +// - no metric name has been set using [vimebu.Builder.Metric]. +// - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. +func (b *Builder) LabelInt32(name string, value int32) *Builder { + i := int64(value) + return b.label(name, false, nil, nil, nil, &i, nil) +} + +// LabelInt64 appends a pair of label name and int64 label value to the Builder. +// +// NoOp if : +// - no metric name has been set using [vimebu.Builder.Metric]. +// - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. +func (b *Builder) LabelInt64(name string, value int64) *Builder { + i := int64(value) + return b.label(name, false, nil, nil, nil, &i, nil) +} + +// LabelFloat32 appends a pair of label name and float32 label value to the Builder. +// +// NoOp if : +// - no metric name has been set using [vimebu.Builder.Metric]. +// - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. +func (b *Builder) LabelFloat32(name string, value float32) *Builder { + f := float64(value) + return b.label(name, false, nil, nil, nil, nil, &f) +} + +// LabelFloat64 appends a pair of label name and float64 label value to the Builder. +// +// NoOp if : +// - no metric name has been set using [vimebu.Builder.Metric]. +// - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. +func (b *Builder) LabelFloat64(name string, value float64) *Builder { + return b.label(name, false, nil, nil, nil, nil, &value) } // LabelStringer appends a pair of label name and label value (implementing [fmt.Stringer]) to the Builder. @@ -135,7 +237,7 @@ func (b *Builder) LabelFloat(name string, value float64) *Builder { // - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. func (b *Builder) LabelStringer(name string, value fmt.Stringer) *Builder { s := value.String() - return b.label(name, false, &s, nil, nil, nil) + return b.label(name, false, &s, nil, nil, nil, nil) } // LabelStringerQuote appends a pair of label name and label value (implementing [fmt.Stringer]) to the Builder. @@ -146,10 +248,10 @@ func (b *Builder) LabelStringer(name string, value fmt.Stringer) *Builder { // - the label name is empty or contains more than [vimebu.LabelNameMaxLen]. func (b *Builder) LabelStringerQuote(name string, value fmt.Stringer) *Builder { s := value.String() - return b.label(name, true, &s, nil, nil, nil) + return b.label(name, true, &s, nil, nil, nil, nil) } -func (b *Builder) label(name string, escapeQuote bool, stringValue *string, boolValue *bool, int64Value *int64, float64Value *float64) *Builder { +func (b *Builder) label(name string, escapeQuote bool, stringValue *string, boolValue *bool, uint64Value *uint64, int64Value *int64, float64Value *float64) *Builder { if !b.flName { log.Println("metric has not been called on this builder, skipping") return b @@ -192,6 +294,8 @@ func (b *Builder) label(name string, escapeQuote bool, stringValue *string, bool b.appendString(*stringValue, escapeQuote) case boolValue != nil: b.appendBool(*boolValue) + case uint64Value != nil: + b.appendUint64(*uint64Value) case int64Value != nil: b.appendInt64(*int64Value) case float64Value != nil: @@ -234,6 +338,15 @@ func (b *Builder) appendInt64(i int64) { b.underlying.Write(buf) } +// appendUint64 appends i to b's underlying buffer. +func (b *Builder) appendUint64(i uint64) { + buf := b.underlying.AvailableBuffer() + buf = append(buf, doubleQuotesByte) + buf = strconv.AppendUint(buf, i, 10) + buf = append(buf, doubleQuotesByte) + b.underlying.Write(buf) +} + // appendFloat64 appends f to b's underlying buffer. func (b *Builder) appendFloat64(f float64) { buf := b.underlying.AvailableBuffer() diff --git a/vimebu_test.go b/vimebu_test.go index b45ff49..9be2936 100644 --- a/vimebu_test.go +++ b/vimebu_test.go @@ -146,9 +146,11 @@ var testCases = []testCase{ {"point", float64(123.456), false}, {"num", int64(1234), false}, {"stringer", stringerValue{"spiderman"}, false}, + {"uint8", uint8(128), false}, + {"int", int(-42), false}, }, }, - expected: `cassandra_query_count{path="/\"some\"/path",is_bidule="true",is_tac="false",point="123.456",num="1234",stringer="spiderman"}`, + expected: `cassandra_query_count{path="/\"some\"/path",is_bidule="true",is_tac="false",point="123.456",num="1234",stringer="spiderman",uint8="128",int="-42"}`, }, { name: "bool label values", @@ -162,25 +164,40 @@ var testCases = []testCase{ expected: `cassandra_query_count{is_bidule="true",is_tac="false"}`, }, { - name: "int64 label values", + name: "int label values", input: input{ name: "cassandra_query_count", labels: []label{ - {"a", int64(69002), false}, - {"b", int64(0), false}, - {"c", int64(0000001), false}, - {"d", int64(1), false}, + {"a", int8(12), false}, + {"b", int16(5555), false}, + {"c", int32(69002), false}, + {"d", int64(80085), false}, + {"e", int(-1234), false}, }, }, - expected: `cassandra_query_count{a="69002",b="0",c="1",d="1"}`, + expected: `cassandra_query_count{a="12",b="5555",c="69002",d="80085",e="-1234"}`, }, { - name: "float64 label values", + name: "uint label values", input: input{ name: "cassandra_query_count", labels: []label{ - {"a", float64(1), false}, - {"b", float64(0), false}, + {"a", uint8(12), false}, + {"b", uint16(5555), false}, + {"c", uint32(69002), false}, + {"d", uint64(80085), false}, + {"e", uint(1234), false}, + }, + }, + expected: `cassandra_query_count{a="12",b="5555",c="69002",d="80085",e="1234"}`, + }, + { + name: "float label values", + input: input{ + name: "cassandra_query_count", + labels: []label{ + {"a", float32(1), false}, + {"b", float32(0), false}, {"c", float64(11111111.22222222), false}, {"d", float64(1234.456789), false}, {"e", float64(1234.4567890000), false}, @@ -216,10 +233,30 @@ func handleTestCase(t *testing.T, tc testCase) { } case bool: b.LabelBool(label.name, v) + case uint8: + b.LabelUint8(label.name, v) + case uint16: + b.LabelUint16(label.name, v) + case uint32: + b.LabelUint32(label.name, v) + case uint64: + b.LabelUint64(label.name, v) + case uint: + b.LabelUint(label.name, v) + case int8: + b.LabelInt8(label.name, v) + case int16: + b.LabelInt16(label.name, v) + case int32: + b.LabelInt32(label.name, v) case int64: + b.LabelInt64(label.name, v) + case int: b.LabelInt(label.name, v) + case float32: + b.LabelFloat32(label.name, v) case float64: - b.LabelFloat(label.name, v) + b.LabelFloat64(label.name, v) case fmt.Stringer: if label.shouldQuote { b.LabelStringerQuote(label.name, v) @@ -309,10 +346,30 @@ func BenchmarkBuilderTestCases(b *testing.B) { } case bool: builder.LabelBool(label.name, v) + case uint8: + builder.LabelUint8(label.name, v) + case uint16: + builder.LabelUint16(label.name, v) + case uint32: + builder.LabelUint32(label.name, v) + case uint64: + builder.LabelUint64(label.name, v) + case uint: + builder.LabelUint(label.name, v) + case int8: + builder.LabelInt8(label.name, v) + case int16: + builder.LabelInt16(label.name, v) + case int32: + builder.LabelInt32(label.name, v) case int64: + builder.LabelInt64(label.name, v) + case int: builder.LabelInt(label.name, v) + case float32: + builder.LabelFloat32(label.name, v) case float64: - builder.LabelFloat(label.name, v) + builder.LabelFloat64(label.name, v) case fmt.Stringer: if label.shouldQuote { builder.LabelStringerQuote(label.name, v)