diff --git a/go.mod b/go.mod index 0994ae21b162a..b6a3293081eb9 100644 --- a/go.mod +++ b/go.mod @@ -351,3 +351,6 @@ replace github.com/grafana/loki/pkg/push => ./pkg/push // Pin grpc to previous version: using newer version breaks kuberesolver, but updating kuberesolver needs to be done in weaveworks/common. replace google.golang.org/grpc => google.golang.org/grpc v1.53.0 + +// Leave this until https://github.com/buger/jsonparser/pull/180 is merged +replace github.com/buger/jsonparser => github.com/floren/jsonparser v0.0.0-20221212180010-bf73ef709df6 diff --git a/go.sum b/go.sum index bc9aaf5a7c756..5e30c8cd08ac2 100644 --- a/go.sum +++ b/go.sum @@ -613,8 +613,6 @@ github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9 github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee h1:BnPxIde0gjtTnc9Er7cxvBk8DHLWhEux0SxayC8dP6I= github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/caio/go-tdigest v2.3.0+incompatible/go.mod h1:sHQM/ubZStBUmF1WbB8FAm8q9GjDajLC5T7ydxE3JHI= @@ -777,6 +775,8 @@ github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/floren/jsonparser v0.0.0-20221212180010-bf73ef709df6 h1:kDHOghcSsQENgHxvQM/OmWndRPpxdv/uVwKzvGOXHbg= +github.com/floren/jsonparser v0.0.0-20221212180010-bf73ef709df6/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/fluent/fluent-bit-go v0.0.0-20190925192703-ea13c021720c h1:QwbffUs/+ptC4kTFPEN9Ej2latTq3bZJ5HO/OwPXYMs= github.com/fluent/fluent-bit-go v0.0.0-20190925192703-ea13c021720c/go.mod h1:WQX+afhrekY9rGK+WT4xvKSlzmia9gDoLYu4GGYGASQ= diff --git a/pkg/logql/log/parser_test.go b/pkg/logql/log/parser_test.go index a81748775304f..3d094da480727 100644 --- a/pkg/logql/log/parser_test.go +++ b/pkg/logql/log/parser_test.go @@ -236,7 +236,7 @@ func (p *fakeParseHints) ShouldContinueParsingLine(_ string, _ *LabelsBuilder) b } func TestJSONExpressionParser(t *testing.T) { - testLine := []byte(`{"app":"foo","field with space":"value","field with ÜFT8👌":"value","null_field":null,"bool_field":false,"namespace":"prod","pod":{"uuid":"foo","deployment":{"ref":"foobar", "params": [1,2,3]}}}`) + testLine := []byte(`{"app":"foo","field with space":"value","field with ÜFT8👌":"value","null_field":null,"bool_field":false,"namespace":"prod","pod":{"uuid":"foo","deployment":{"ref":"foobar", "params": [1,2,3,"string_value"]}}}`) tests := []struct { name string @@ -339,6 +339,16 @@ func TestJSONExpressionParser(t *testing.T) { labels.FromStrings("param", "1"), noParserHints, }, + { + "array string element", + testLine, + []LabelExtractionExpr{ + NewLabelExtractionExpr("param", `pod.deployment.params[3]`), + }, + labels.EmptyLabels(), + labels.FromStrings("param", "string_value"), + noParserHints, + }, { "full array", testLine, @@ -346,7 +356,7 @@ func TestJSONExpressionParser(t *testing.T) { NewLabelExtractionExpr("params", `pod.deployment.params`), }, labels.EmptyLabels(), - labels.FromStrings("params", "[1,2,3]"), + labels.FromStrings("params", `[1,2,3,"string_value"]`), noParserHints, }, { @@ -356,7 +366,7 @@ func TestJSONExpressionParser(t *testing.T) { NewLabelExtractionExpr("deployment", `pod.deployment`), }, labels.EmptyLabels(), - labels.FromStrings("deployment", `{"ref":"foobar", "params": [1,2,3]}`), + labels.FromStrings("deployment", `{"ref":"foobar", "params": [1,2,3,"string_value"]}`), noParserHints, }, { diff --git a/vendor/github.com/buger/jsonparser/.travis.yml b/vendor/github.com/buger/jsonparser/.travis.yml index dbfb7cf988305..56f9c9c421234 100644 --- a/vendor/github.com/buger/jsonparser/.travis.yml +++ b/vendor/github.com/buger/jsonparser/.travis.yml @@ -3,9 +3,10 @@ arch: - amd64 - ppc64le go: - - 1.7.x - - 1.8.x - - 1.9.x - - 1.10.x - - 1.11.x + - 1.13.x + - 1.14.x + - 1.15.x + - 1.16.x + - 1.17.x + - 1.18.x script: go test -v ./. diff --git a/vendor/github.com/buger/jsonparser/README.md b/vendor/github.com/buger/jsonparser/README.md index d7e0ec397affe..0b2f1fb037123 100644 --- a/vendor/github.com/buger/jsonparser/README.md +++ b/vendor/github.com/buger/jsonparser/README.md @@ -90,10 +90,6 @@ jsonparser.EachKey(data, func(idx int, value []byte, vt jsonparser.ValueType, er // For more information see docs below ``` -## Need to speedup your app? - -I'm available for consulting and can help you push your app performance to the limits. Ping me at: leonsbox@gmail.com. - ## Reference Library API is really simple. You just need the `Get` method to perform any operation. The rest is just helpers around it. diff --git a/vendor/github.com/buger/jsonparser/bytes.go b/vendor/github.com/buger/jsonparser/bytes.go index 0bb0ff39562cb..9d6e701f58364 100644 --- a/vendor/github.com/buger/jsonparser/bytes.go +++ b/vendor/github.com/buger/jsonparser/bytes.go @@ -1,11 +1,8 @@ package jsonparser -import ( - bio "bytes" -) - -// minInt64 '-9223372036854775808' is the smallest representable number in int64 -const minInt64 = `9223372036854775808` +const absMinInt64 = 1 << 63 +const maxInt64 = 1<<63 - 1 +const maxUint64 = 1<<64 - 1 // About 2x faster then strconv.ParseInt because it only supports base 10, which is enough for JSON func parseInt(bytes []byte) (v int64, ok bool, overflow bool) { @@ -19,29 +16,32 @@ func parseInt(bytes []byte) (v int64, ok bool, overflow bool) { bytes = bytes[1:] } - var b int64 = 0 + var n uint64 = 0 for _, c := range bytes { - if c >= '0' && c <= '9' { - b = (10 * v) + int64(c-'0') - } else { + if c < '0' || c > '9' { return 0, false, false } - if overflow = (b < v); overflow { - break + if n > maxUint64/10 { + return 0, false, true + } + n *= 10 + n1 := n + uint64(c-'0') + if n1 < n { + return 0, false, true } - v = b + n = n1 } - if overflow { - if neg && bio.Equal(bytes, []byte(minInt64)) { - return b, true, false + if n > maxInt64 { + if neg && n == absMinInt64 { + return -absMinInt64, true, false } return 0, false, true } if neg { - return -v, true, false + return -int64(n), true, false } else { - return v, true, false + return int64(n), true, false } } diff --git a/vendor/github.com/buger/jsonparser/parser.go b/vendor/github.com/buger/jsonparser/parser.go index 14b80bc4838c5..5df2a463dcee3 100644 --- a/vendor/github.com/buger/jsonparser/parser.go +++ b/vendor/github.com/buger/jsonparser/parser.go @@ -18,6 +18,7 @@ var ( MalformedValueError = errors.New("Value looks like Number/Boolean/None, but can't find its end: ',' or '}' symbol") OverflowIntegerError = errors.New("Value is number, but overflowed while parsing") MalformedStringEscapeError = errors.New("Encountered an invalid escape sequence in a string") + NullValueError = errors.New("Value is null") ) // How much stack space to allocate for unescaping JSON strings; if a string longer @@ -49,10 +50,13 @@ func findTokenStart(data []byte, token byte) int { } func findKeyStart(data []byte, key string) (int, error) { - i := 0 + i := nextToken(data) + if i == -1 { + return i, KeyPathNotFoundError + } ln := len(data) - if ln > 0 && (data[0] == '{' || data[0] == '[') { - i = 1 + if ln > 0 && (data[i] == '{' || data[i] == '[') { + i += 1 } var stackbuf [unescapeStackBufSize]byte // stack-allocated array for allocation-free unescaping of small strings @@ -308,7 +312,7 @@ func searchKeys(data []byte, keys ...string) int { case '[': // If we want to get array element by index if keyLevel == level && keys[level][0] == '[' { - var keyLen = len(keys[level]) + keyLen := len(keys[level]) if keyLen < 3 || keys[level][0] != '[' || keys[level][keyLen-1] != ']' { return -1 } @@ -319,7 +323,7 @@ func searchKeys(data []byte, keys ...string) int { var curIdx int var valueFound []byte var valueOffset int - var curI = i + curI := i ArrayEach(data[i:], func(value []byte, dataType ValueType, offset int, err error) { if curIdx == aIdx { valueFound = value @@ -374,12 +378,19 @@ func sameTree(p1, p2 []string) bool { return true } +const stackArraySize = 128 + func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]string) int { var x struct{} - pathFlags := make([]bool, len(paths)) var level, pathsMatched, i int ln := len(data) + pathFlags := make([]bool, stackArraySize)[:] + if len(paths) > cap(pathFlags) { + pathFlags = make([]bool, len(paths))[:] + } + pathFlags = pathFlags[0:len(paths)] + var maxPath int for _, p := range paths { if len(p) > maxPath { @@ -387,7 +398,11 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str } } - pathsBuf := make([]string, maxPath) + pathsBuf := make([]string, stackArraySize)[:] + if maxPath > cap(pathsBuf) { + pathsBuf = make([]string, maxPath)[:] + } + pathsBuf = pathsBuf[0:maxPath] for i < ln { switch data[i] { @@ -484,7 +499,12 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str case '[': var ok bool arrIdxFlags := make(map[int]struct{}) - pIdxFlags := make([]bool, len(paths)) + + pIdxFlags := make([]bool, stackArraySize)[:] + if len(paths) > cap(pIdxFlags) { + pIdxFlags = make([]bool, len(paths))[:] + } + pIdxFlags = pIdxFlags[0:len(paths)] if level < 0 { cb(-1, nil, Unknown, MalformedJsonError) @@ -519,8 +539,13 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str pathFlags[pi] = true if of != -1 { - v, dt, _, e := Get(value[of:]) - cb(pi, v, dt, e) + if dataType == String { + // the double-quotes were stripped, so we cannot call Get again. + cb(pi, value[of:], dataType, nil) + } else { + v, dt, _, e := Get(value[of:]) + cb(pi, v, dt, e) + } } } } @@ -662,7 +687,6 @@ func calcAllocateSpace(keys []string, setValue []byte, comma, object bool) int { } } - lk += len(setValue) for i := 1; i < len(keys); i++ { if string(keys[i][0]) == "[" { @@ -1178,6 +1202,9 @@ func GetString(data []byte, keys ...string) (val string, err error) { } if t != String { + if t == Null { + return "", NullValueError + } return "", fmt.Errorf("Value is not a string: %s", string(v)) } @@ -1200,6 +1227,9 @@ func GetFloat(data []byte, keys ...string) (val float64, err error) { } if t != Number { + if t == Null { + return 0, NullValueError + } return 0, fmt.Errorf("Value is not a number: %s", string(v)) } @@ -1216,6 +1246,9 @@ func GetInt(data []byte, keys ...string) (val int64, err error) { } if t != Number { + if t == Null { + return 0, NullValueError + } return 0, fmt.Errorf("Value is not a number: %s", string(v)) } @@ -1233,6 +1266,9 @@ func GetBoolean(data []byte, keys ...string) (val bool, err error) { } if t != Boolean { + if t == Null { + return false, NullValueError + } return false, fmt.Errorf("Value is not a boolean: %s", string(v)) } diff --git a/vendor/modules.txt b/vendor/modules.txt index bb227893cef2f..cc41cfb444e41 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -420,7 +420,7 @@ github.com/beorn7/perks/quantile # github.com/bmatcuk/doublestar v1.3.4 ## explicit; go 1.12 github.com/bmatcuk/doublestar -# github.com/buger/jsonparser v1.1.1 +# github.com/buger/jsonparser v1.1.1 => github.com/floren/jsonparser v0.0.0-20221212180010-bf73ef709df6 ## explicit; go 1.13 github.com/buger/jsonparser # github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee @@ -2171,3 +2171,4 @@ sigs.k8s.io/yaml # github.com/grafana/regexp => github.com/grafana/regexp v0.0.0-20221005093135-b4c2bcb0a4b6 # github.com/grafana/loki/pkg/push => ./pkg/push # google.golang.org/grpc => google.golang.org/grpc v1.53.0 +# github.com/buger/jsonparser => github.com/floren/jsonparser v0.0.0-20221212180010-bf73ef709df6