2023-07-20 08:10:55 +00:00
|
|
|
package loki
|
|
|
|
|
|
|
|
import (
|
2023-07-20 23:21:47 +00:00
|
|
|
"fmt"
|
|
|
|
"strings"
|
2023-07-20 08:10:55 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2024-06-17 20:28:15 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vlinsert/insertutils"
|
2023-07-20 08:10:55 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
|
2023-07-20 23:21:47 +00:00
|
|
|
"github.com/golang/snappy"
|
2023-07-20 08:10:55 +00:00
|
|
|
)
|
|
|
|
|
2024-06-17 20:28:15 +00:00
|
|
|
type testLogMessageProcessor struct {
|
|
|
|
pr PushRequest
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tlp *testLogMessageProcessor) AddRow(timestamp int64, fields []logstorage.Field) {
|
|
|
|
msg := ""
|
|
|
|
for _, f := range fields {
|
|
|
|
if f.Name == "_msg" {
|
|
|
|
msg = f.Value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var a []string
|
|
|
|
for _, f := range fields {
|
|
|
|
if f.Name == "_msg" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
item := fmt.Sprintf("%s=%q", f.Name, f.Value)
|
|
|
|
a = append(a, item)
|
|
|
|
}
|
|
|
|
labels := "{" + strings.Join(a, ", ") + "}"
|
|
|
|
tlp.pr.Streams = append(tlp.pr.Streams, Stream{
|
|
|
|
Labels: labels,
|
|
|
|
Entries: []Entry{
|
|
|
|
{
|
|
|
|
Timestamp: time.Unix(0, timestamp),
|
2024-07-10 00:42:41 +00:00
|
|
|
Line: strings.Clone(msg),
|
2024-06-17 20:28:15 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tlp *testLogMessageProcessor) MustClose() {
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestParseProtobufRequest_Success(t *testing.T) {
|
|
|
|
f := func(s string, timestampsExpected []int64, resultExpected string) {
|
2023-07-20 23:21:47 +00:00
|
|
|
t.Helper()
|
2024-06-17 20:28:15 +00:00
|
|
|
|
|
|
|
tlp := &testLogMessageProcessor{}
|
|
|
|
n, err := parseJSONRequest([]byte(s), tlp)
|
2023-07-20 23:21:47 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error: %s", err)
|
|
|
|
}
|
2024-06-17 20:28:15 +00:00
|
|
|
if n != len(tlp.pr.Streams) {
|
|
|
|
t.Fatalf("unexpected number of streams; got %d; want %d", len(tlp.pr.Streams), n)
|
2023-07-20 23:21:47 +00:00
|
|
|
}
|
|
|
|
|
2024-07-10 00:42:41 +00:00
|
|
|
data := tlp.pr.MarshalProtobuf(nil)
|
2023-07-20 23:21:47 +00:00
|
|
|
encodedData := snappy.Encode(nil, data)
|
2023-07-20 08:10:55 +00:00
|
|
|
|
2024-06-17 20:28:15 +00:00
|
|
|
tlp2 := &insertutils.TestLogMessageProcessor{}
|
|
|
|
n, err = parseProtobufRequest(encodedData, tlp2)
|
2023-07-20 23:21:47 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error: %s", err)
|
|
|
|
}
|
2024-06-17 20:28:15 +00:00
|
|
|
if err := tlp2.Verify(n, timestampsExpected, resultExpected); err != nil {
|
|
|
|
t.Fatal(err)
|
2023-07-20 23:21:47 +00:00
|
|
|
}
|
2023-07-20 08:10:55 +00:00
|
|
|
}
|
|
|
|
|
2023-07-20 23:21:47 +00:00
|
|
|
// Empty streams
|
2024-06-17 20:28:15 +00:00
|
|
|
f(`{"streams":[]}`, nil, ``)
|
|
|
|
f(`{"streams":[{"values":[]}]}`, nil, ``)
|
|
|
|
f(`{"streams":[{"stream":{},"values":[]}]}`, nil, ``)
|
|
|
|
f(`{"streams":[{"stream":{"foo":"bar"},"values":[]}]}`, nil, ``)
|
2023-07-20 08:10:55 +00:00
|
|
|
|
2023-07-20 23:21:47 +00:00
|
|
|
// Empty stream labels
|
2024-06-17 20:28:15 +00:00
|
|
|
f(`{"streams":[{"values":[["1577836800000000001", "foo bar"]]}]}`, []int64{1577836800000000001}, `{"_msg":"foo bar"}`)
|
|
|
|
f(`{"streams":[{"stream":{},"values":[["1577836800000000001", "foo bar"]]}]}`, []int64{1577836800000000001}, `{"_msg":"foo bar"}`)
|
2023-07-20 08:10:55 +00:00
|
|
|
|
2023-07-20 23:21:47 +00:00
|
|
|
// Non-empty stream labels
|
|
|
|
f(`{"streams":[{"stream":{
|
|
|
|
"label1": "value1",
|
|
|
|
"label2": "value2"
|
|
|
|
},"values":[
|
|
|
|
["1577836800000000001", "foo bar"],
|
|
|
|
["1477836900005000002", "abc"],
|
|
|
|
["147.78369e9", "foobar"]
|
2024-06-17 20:28:15 +00:00
|
|
|
]}]}`, []int64{1577836800000000001, 1477836900005000002, 147783690000}, `{"label1":"value1","label2":"value2","_msg":"foo bar"}
|
|
|
|
{"label1":"value1","label2":"value2","_msg":"abc"}
|
|
|
|
{"label1":"value1","label2":"value2","_msg":"foobar"}`)
|
2023-07-20 23:21:47 +00:00
|
|
|
|
|
|
|
// Multiple streams
|
|
|
|
f(`{
|
|
|
|
"streams": [
|
|
|
|
{
|
|
|
|
"stream": {
|
|
|
|
"foo": "bar",
|
|
|
|
"a": "b"
|
|
|
|
},
|
|
|
|
"values": [
|
|
|
|
["1577836800000000001", "foo bar"],
|
|
|
|
["1577836900005000002", "abc"]
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"stream": {
|
|
|
|
"x": "y"
|
|
|
|
},
|
|
|
|
"values": [
|
|
|
|
["1877836900005000002", "yx"]
|
|
|
|
]
|
2023-07-20 08:10:55 +00:00
|
|
|
}
|
2023-07-20 23:21:47 +00:00
|
|
|
]
|
2024-06-17 20:28:15 +00:00
|
|
|
}`, []int64{1577836800000000001, 1577836900005000002, 1877836900005000002}, `{"foo":"bar","a":"b","_msg":"foo bar"}
|
|
|
|
{"foo":"bar","a":"b","_msg":"abc"}
|
|
|
|
{"x":"y","_msg":"yx"}`)
|
2023-07-20 23:21:47 +00:00
|
|
|
}
|
2023-07-20 08:10:55 +00:00
|
|
|
|
2024-06-17 20:28:15 +00:00
|
|
|
func TestParsePromLabels_Success(t *testing.T) {
|
2023-07-20 23:21:47 +00:00
|
|
|
f := func(s string) {
|
|
|
|
t.Helper()
|
|
|
|
fields, err := parsePromLabels(nil, s)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error: %s", err)
|
2023-07-20 08:10:55 +00:00
|
|
|
}
|
|
|
|
|
2023-07-20 23:21:47 +00:00
|
|
|
var a []string
|
|
|
|
for _, f := range fields {
|
|
|
|
a = append(a, fmt.Sprintf("%s=%q", f.Name, f.Value))
|
|
|
|
}
|
|
|
|
result := "{" + strings.Join(a, ", ") + "}"
|
|
|
|
if result != s {
|
|
|
|
t.Fatalf("unexpected result;\ngot\n%s\nwant\n%s", result, s)
|
|
|
|
}
|
2023-07-20 08:10:55 +00:00
|
|
|
}
|
|
|
|
|
2023-07-20 23:21:47 +00:00
|
|
|
f("{}")
|
|
|
|
f(`{foo="bar"}`)
|
|
|
|
f(`{foo="bar", baz="x", y="z"}`)
|
|
|
|
f(`{foo="ba\"r\\z\n", a="", b="\"\\"}`)
|
|
|
|
}
|
|
|
|
|
2024-06-17 20:28:15 +00:00
|
|
|
func TestParsePromLabels_Failure(t *testing.T) {
|
2023-07-20 23:21:47 +00:00
|
|
|
f := func(s string) {
|
|
|
|
t.Helper()
|
|
|
|
fields, err := parsePromLabels(nil, s)
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expecting non-nil error")
|
|
|
|
}
|
|
|
|
if len(fields) > 0 {
|
|
|
|
t.Fatalf("unexpected non-empty fields: %s", fields)
|
|
|
|
}
|
|
|
|
}
|
2023-07-20 08:10:55 +00:00
|
|
|
|
2023-07-20 23:21:47 +00:00
|
|
|
f("")
|
|
|
|
f("{")
|
|
|
|
f(`{foo}`)
|
|
|
|
f(`{foo=bar}`)
|
|
|
|
f(`{foo="bar}`)
|
|
|
|
f(`{foo="ba\",r}`)
|
|
|
|
f(`{foo="bar" baz="aa"}`)
|
|
|
|
f(`foobar`)
|
|
|
|
f(`foo{bar="baz"}`)
|
2023-07-20 08:10:55 +00:00
|
|
|
}
|