2023-06-20 05:55:12 +00:00
|
|
|
package elasticsearch
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"compress/gzip"
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logstorage"
|
|
|
|
)
|
|
|
|
|
2023-06-21 04:16:11 +00:00
|
|
|
func TestReadBulkRequestFailure(t *testing.T) {
|
|
|
|
f := func(data string) {
|
|
|
|
t.Helper()
|
|
|
|
|
2023-10-02 14:26:02 +00:00
|
|
|
processLogMessage := func(timestamp int64, fields []logstorage.Field) {
|
2023-06-21 04:16:11 +00:00
|
|
|
t.Fatalf("unexpected call to processLogMessage with timestamp=%d, fields=%s", timestamp, fields)
|
|
|
|
}
|
|
|
|
|
|
|
|
r := bytes.NewBufferString(data)
|
|
|
|
rows, err := readBulkRequest(r, false, "_time", "_msg", processLogMessage)
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("expecting non-empty error")
|
|
|
|
}
|
|
|
|
if rows != 0 {
|
|
|
|
t.Fatalf("unexpected non-zero rows=%d", rows)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f("foobar")
|
|
|
|
f(`{}`)
|
|
|
|
f(`{"create":{}}`)
|
|
|
|
f(`{"creat":{}}
|
|
|
|
{}`)
|
|
|
|
f(`{"create":{}}
|
|
|
|
foobar`)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestReadBulkRequestSuccess(t *testing.T) {
|
2023-06-20 05:55:12 +00:00
|
|
|
f := func(data, timeField, msgField string, rowsExpected int, timestampsExpected []int64, resultExpected string) {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
var timestamps []int64
|
|
|
|
var result string
|
2023-10-02 14:26:02 +00:00
|
|
|
processLogMessage := func(timestamp int64, fields []logstorage.Field) {
|
2023-06-20 05:55:12 +00:00
|
|
|
timestamps = append(timestamps, timestamp)
|
2024-06-17 10:13:18 +00:00
|
|
|
result += string(logstorage.MarshalFieldsToJSON(nil, fields)) + "\n"
|
2023-06-20 05:55:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Read the request without compression
|
|
|
|
r := bytes.NewBufferString(data)
|
|
|
|
rows, err := readBulkRequest(r, false, timeField, msgField, processLogMessage)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error: %s", err)
|
|
|
|
}
|
|
|
|
if rows != rowsExpected {
|
|
|
|
t.Fatalf("unexpected rows read; got %d; want %d", rows, rowsExpected)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(timestamps, timestampsExpected) {
|
|
|
|
t.Fatalf("unexpected timestamps;\ngot\n%d\nwant\n%d", timestamps, timestampsExpected)
|
|
|
|
}
|
|
|
|
if result != resultExpected {
|
|
|
|
t.Fatalf("unexpected result;\ngot\n%s\nwant\n%s", result, resultExpected)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the request with compression
|
|
|
|
timestamps = nil
|
|
|
|
result = ""
|
|
|
|
compressedData := compressData(data)
|
|
|
|
r = bytes.NewBufferString(compressedData)
|
|
|
|
rows, err = readBulkRequest(r, true, timeField, msgField, processLogMessage)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error: %s", err)
|
|
|
|
}
|
|
|
|
if rows != rowsExpected {
|
|
|
|
t.Fatalf("unexpected rows read; got %d; want %d", rows, rowsExpected)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(timestamps, timestampsExpected) {
|
|
|
|
t.Fatalf("unexpected timestamps;\ngot\n%d\nwant\n%d", timestamps, timestampsExpected)
|
|
|
|
}
|
|
|
|
if result != resultExpected {
|
|
|
|
t.Fatalf("unexpected result;\ngot\n%s\nwant\n%s", result, resultExpected)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-21 04:16:11 +00:00
|
|
|
// Verify an empty data
|
|
|
|
f("", "_time", "_msg", 0, nil, "")
|
2023-06-21 04:23:36 +00:00
|
|
|
f("\n", "_time", "_msg", 0, nil, "")
|
|
|
|
f("\n\n", "_time", "_msg", 0, nil, "")
|
2023-06-21 04:16:11 +00:00
|
|
|
|
|
|
|
// Verify non-empty data
|
2023-06-20 05:55:12 +00:00
|
|
|
data := `{"create":{"_index":"filebeat-8.8.0"}}
|
|
|
|
{"@timestamp":"2023-06-06T04:48:11.735Z","log":{"offset":71770,"file":{"path":"/var/log/auth.log"}},"message":"foobar"}
|
|
|
|
{"create":{"_index":"filebeat-8.8.0"}}
|
|
|
|
{"@timestamp":"2023-06-06T04:48:12.735Z","message":"baz"}
|
2023-06-21 04:16:11 +00:00
|
|
|
{"index":{"_index":"filebeat-8.8.0"}}
|
2023-06-20 05:55:12 +00:00
|
|
|
{"message":"xyz","@timestamp":"2023-06-06T04:48:13.735Z","x":"y"}
|
|
|
|
`
|
|
|
|
timeField := "@timestamp"
|
|
|
|
msgField := "message"
|
|
|
|
rowsExpected := 3
|
|
|
|
timestampsExpected := []int64{1686026891735000000, 1686026892735000000, 1686026893735000000}
|
|
|
|
resultExpected := `{"@timestamp":"","log.offset":"71770","log.file.path":"/var/log/auth.log","_msg":"foobar"}
|
|
|
|
{"@timestamp":"","_msg":"baz"}
|
|
|
|
{"_msg":"xyz","@timestamp":"","x":"y"}
|
|
|
|
`
|
|
|
|
f(data, timeField, msgField, rowsExpected, timestampsExpected, resultExpected)
|
|
|
|
}
|
|
|
|
|
|
|
|
func compressData(s string) string {
|
|
|
|
var bb bytes.Buffer
|
|
|
|
zw := gzip.NewWriter(&bb)
|
|
|
|
if _, err := zw.Write([]byte(s)); err != nil {
|
2023-10-25 19:24:01 +00:00
|
|
|
panic(fmt.Errorf("unexpected error when compressing data: %w", err))
|
2023-06-20 05:55:12 +00:00
|
|
|
}
|
|
|
|
if err := zw.Close(); err != nil {
|
2023-10-25 19:24:01 +00:00
|
|
|
panic(fmt.Errorf("unexpected error when closing gzip writer: %w", err))
|
2023-06-20 05:55:12 +00:00
|
|
|
}
|
|
|
|
return bb.String()
|
|
|
|
}
|