[plugin][api] visualization/data supports top_hits

This commit is contained in:
Kassian Sun 2023-03-22 10:10:30 +08:00
parent 157fc43ee8
commit 17abd00e20
1 changed files with 104 additions and 66 deletions

View File

@ -6,14 +6,15 @@ package insight
import ( import (
"fmt" "fmt"
"strconv"
"strings"
"infini.sh/framework/core/elastic" "infini.sh/framework/core/elastic"
"infini.sh/framework/core/insight" "infini.sh/framework/core/insight"
"infini.sh/framework/core/util" "infini.sh/framework/core/util"
"strconv"
"strings"
) )
func generateAgg(metricItem *insight.MetricItem) map[string]interface{}{ func generateAgg(metricItem *insight.MetricItem, timeField string) map[string]interface{} {
var ( var (
aggType = "value_count" aggType = "value_count"
field = metricItem.Field field = metricItem.Field
@ -37,9 +38,24 @@ func generateAgg(metricItem *insight.MetricItem) map[string]interface{}{
aggType = "percentiles" aggType = "percentiles"
percentStr := strings.TrimPrefix(metricItem.Statistic, "p") percentStr := strings.TrimPrefix(metricItem.Statistic, "p")
percent, _ = strconv.ParseFloat(percentStr, 32) percent, _ = strconv.ParseFloat(percentStr, 32)
case "latest":
aggType = "top_hits"
} }
aggValue := util.MapStr{ aggValue := util.MapStr{}
"field": field, if aggType != "top_hits" {
aggValue["field"] = field
} else {
aggValue["_source"] = util.MapStr{
"includes": []string{field},
}
aggValue["sort"] = []util.MapStr{
util.MapStr{
timeField: util.MapStr{
"order": "desc",
},
},
}
aggValue["size"] = 1
} }
if aggType == "percentiles" { if aggType == "percentiles" {
aggValue["percents"] = []interface{}{percent} aggValue["percents"] = []interface{}{percent}
@ -70,7 +86,7 @@ func GenerateQuery(metric *insight.Metric) (interface{}, error) {
if metricItem.Name == "" { if metricItem.Name == "" {
metricItem.Name = string('a' + i) metricItem.Name = string('a' + i)
} }
metricAggs := generateAgg(&metricItem) metricAggs := generateAgg(&metricItem, metric.TimeField)
if err := util.MergeFields(basicAggs, metricAggs, true); err != nil { if err := util.MergeFields(basicAggs, metricAggs, true); err != nil {
return nil, err return nil, err
} }
@ -85,7 +101,7 @@ func GenerateQuery(metric *insight.Metric) (interface{}, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("get interval field error: %w", err) return nil, fmt.Errorf("get interval field error: %w", err)
} }
if metric.TimeField != "" && !timeBeforeGroup{ if metric.BucketSize != "" && !timeBeforeGroup {
basicAggs = util.MapStr{ basicAggs = util.MapStr{
"time_buckets": util.MapStr{ "time_buckets": util.MapStr{
"date_histogram": util.MapStr{ "date_histogram": util.MapStr{
@ -97,7 +113,6 @@ func GenerateQuery(metric *insight.Metric) (interface{}, error) {
} }
} }
var rootAggs util.MapStr var rootAggs util.MapStr
groups := metric.Groups groups := metric.Groups
@ -126,7 +141,7 @@ func GenerateQuery(metric *insight.Metric) (interface{}, error) {
} }
lastGroupAgg = groupAgg lastGroupAgg = groupAgg
} }
if metric.TimeField == "" || (metric.TimeField != "" && !timeBeforeGroup) { if metric.BucketSize == "" || (metric.BucketSize != "" && !timeBeforeGroup) {
rootAggs = util.MapStr{ rootAggs = util.MapStr{
util.GetUUID(): lastGroupAgg, util.GetUUID(): lastGroupAgg,
} }
@ -145,7 +160,7 @@ func GenerateQuery(metric *insight.Metric) (interface{}, error) {
} }
} else { } else {
if metric.TimeField != "" && timeBeforeGroup{ if metric.BucketSize != "" && timeBeforeGroup {
basicAggs = util.MapStr{ basicAggs = util.MapStr{
"time_buckets": util.MapStr{ "time_buckets": util.MapStr{
"date_histogram": util.MapStr{ "date_histogram": util.MapStr{
@ -318,13 +333,28 @@ func collectMetricDataOther(agg interface{}, groupValues string, metricData *[]i
} }
} }
func collectMetricDataItem(key string, vm map[string]interface{}, metricData *insight.MetricData, timeKey interface{}) { func collectMetricDataItem(key string, vm map[string]interface{}, metricData *insight.MetricData, timeKey interface{}) {
if val, ok := vm["value"]; ok { if val, ok := vm["value"]; ok {
metricData.Data[key] = append(metricData.Data[key], insight.MetricDataItem{ metricData.Data[key] = append(metricData.Data[key], insight.MetricDataItem{
Value: val, Value: val,
Timestamp: timeKey, Timestamp: timeKey,
}) })
} else if hits, ok := vm["hits"]; ok {
if hits, ok := hits.(map[string]interface{}); ok {
// statistic: top_hits
if hits, ok := hits["hits"]; ok {
if hits, ok := hits.([]interface{}); ok {
for _, hit := range hits {
if hit, ok := hit.(map[string]interface{}); ok {
metricData.Data[key] = append(metricData.Data[key], insight.MetricDataItem{
Value: extractSomeValue(hit["_source"]),
Timestamp: timeKey,
})
}
}
}
}
}
} else { } else {
//percentiles agg type //percentiles agg type
switch vm["values"].(type) { switch vm["values"].(type) {
@ -350,3 +380,11 @@ func collectMetricDataItem(key string, vm map[string]interface{}, metricData *in
} }
} }
func extractSomeValue(v interface{}) interface{} {
if vm, ok := v.(map[string]interface{}); ok {
for _, v := range vm {
return extractSomeValue(v)
}
}
return v
}