Elasticsearch: Add log highlight processing on backend (#63924)

* Elasticsearch: Add highlight for logs

* Fix running of queries trough backend only when shouldRunTroughBackend

* Fix incorrect json in test string

* Address feedback

* Keep order of words same
This commit is contained in:
Ivana Huckova
2023-03-09 13:34:53 +01:00
committed by GitHub
parent cb8e01214d
commit bd0fa79542
6 changed files with 206 additions and 24 deletions

View File

@@ -3,6 +3,7 @@ package elasticsearch
import (
"encoding/json"
"errors"
"fmt"
"regexp"
"sort"
"strconv"
@@ -36,6 +37,8 @@ const (
logsType = "logs"
)
var searchWordsRegex = regexp.MustCompile(regexp.QuoteMeta(es.HighlightPreTagsString) + `(.*?)` + regexp.QuoteMeta(es.HighlightPostTagsString))
func parseResponse(responses []*es.SearchResponse, targets []*Query, configuredFields es.ConfiguredFields) (*backend.QueryDataResponse, error) {
result := backend.QueryDataResponse{
Responses: backend.Responses{},
@@ -94,6 +97,7 @@ func parseResponse(responses []*es.SearchResponse, targets []*Query, configuredF
func processLogsResponse(res *es.SearchResponse, target *Query, configuredFields es.ConfiguredFields, queryRes *backend.DataResponse) error {
propNames := make(map[string]bool)
docs := make([]map[string]interface{}, len(res.Hits.Hits))
searchWords := make(map[string]bool)
for hitIdx, hit := range res.Hits.Hits {
var flattened map[string]interface{}
@@ -121,7 +125,22 @@ func processLogsResponse(res *es.SearchResponse, target *Query, configuredFields
for key := range doc {
propNames[key] = true
}
// TODO: Implement highlighting
// Process highlight to searchWords
if highlights, ok := doc["highlight"].(map[string]interface{}); ok {
for _, highlight := range highlights {
if highlightList, ok := highlight.([]interface{}); ok {
for _, highlightValue := range highlightList {
str := fmt.Sprintf("%v", highlightValue)
matches := searchWordsRegex.FindAllStringSubmatch(str, -1)
for _, v := range matches {
searchWords[v[1]] = true
}
}
}
}
}
docs[hitIdx] = doc
}
@@ -132,6 +151,7 @@ func processLogsResponse(res *es.SearchResponse, target *Query, configuredFields
frames := data.Frames{}
frame := data.NewFrame("", fields...)
setPreferredVisType(frame, "logs")
setSearchWords(frame, searchWords)
frames = append(frames, frame)
queryRes.Frames = frames
@@ -1073,3 +1093,25 @@ func setPreferredVisType(frame *data.Frame, visType data.VisType) {
frame.Meta.PreferredVisualization = visType
}
func setSearchWords(frame *data.Frame, searchWords map[string]bool) {
i := 0
searchWordsList := make([]string, len(searchWords))
for searchWord := range searchWords {
searchWordsList[i] = searchWord
i++
}
sort.Strings(searchWordsList)
if frame.Meta == nil {
frame.Meta = &data.FrameMeta{}
}
if frame.Meta.Custom == nil {
frame.Meta.Custom = map[string]interface{}{}
}
frame.Meta.Custom = map[string]interface{}{
"searchWords": searchWordsList,
}
}