parent
635abc6524
commit
8a27cd4389
|
@ -17,6 +17,7 @@ Information about release notes of INFINI Console is provided here.
|
||||||
|
|
||||||
### Bug fix
|
### Bug fix
|
||||||
- Fixed query thread pool metrics when cluster uuid is empty
|
- Fixed query thread pool metrics when cluster uuid is empty
|
||||||
|
- Fixed unit tests
|
||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
- Optimize UI of agent list when its columns are overflow.
|
- Optimize UI of agent list when its columns are overflow.
|
||||||
|
|
|
@ -102,7 +102,7 @@ func TestCreateRule( t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
Channels: NotificationConfig{
|
Channels: &NotificationConfig{
|
||||||
Normal: []Channel{
|
Normal: []Channel{
|
||||||
{Name: "钉钉", Type: ChannelWebhook, Webhook: &CustomWebhook{
|
{Name: "钉钉", Type: ChannelWebhook, Webhook: &CustomWebhook{
|
||||||
HeaderParams: map[string]string{
|
HeaderParams: map[string]string{
|
||||||
|
|
|
@ -34,8 +34,11 @@ import (
|
||||||
|
|
||||||
func TestGetMetricParams(t *testing.T) {
|
func TestGetMetricParams(t *testing.T) {
|
||||||
handler:=APIHandler{}
|
handler:=APIHandler{}
|
||||||
req:=http.Request{}
|
req, err :=http.NewRequest("GET","https://infinilabs.com/api/?bucket_size=1m",nil)
|
||||||
bucketSize, min, max, err:=handler.getMetricRangeAndBucketSize(&req,60,15)
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
bucketSize, min, max, err:=handler.GetMetricRangeAndBucketSize(req,"", "",15)
|
||||||
|
|
||||||
fmt.Println(bucketSize)
|
fmt.Println(bucketSize)
|
||||||
fmt.Println(util.FormatUnixTimestamp(min/1000))//2022-01-27 15:28:57
|
fmt.Println(util.FormatUnixTimestamp(min/1000))//2022-01-27 15:28:57
|
||||||
|
|
|
@ -1,115 +0,0 @@
|
||||||
// Copyright (C) INFINI Labs & INFINI LIMITED.
|
|
||||||
//
|
|
||||||
// The INFINI Console is offered under the GNU Affero General Public License v3.0
|
|
||||||
// and as commercial software.
|
|
||||||
//
|
|
||||||
// For commercial licensing, contact us at:
|
|
||||||
// - Website: infinilabs.com
|
|
||||||
// - Email: hello@infini.ltd
|
|
||||||
//
|
|
||||||
// Open Source licensed under AGPL V3:
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package v1
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"infini.sh/framework/core/util"
|
|
||||||
"infini.sh/framework/modules/elastic/common"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetMetricParams(t *testing.T) {
|
|
||||||
handler:=APIHandler{}
|
|
||||||
req:=http.Request{}
|
|
||||||
bucketSize, min, max, err:=handler.getMetricRangeAndBucketSize(&req,60,15)
|
|
||||||
|
|
||||||
fmt.Println(bucketSize)
|
|
||||||
fmt.Println(util.FormatUnixTimestamp(min/1000))//2022-01-27 15:28:57
|
|
||||||
fmt.Println(util.FormatUnixTimestamp(max/1000))//2022-01-27 15:28:57
|
|
||||||
fmt.Println(time.Now())//2022-01-27 15:28:57
|
|
||||||
|
|
||||||
fmt.Println(bucketSize, min, max, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConvertBucketItemsToAggQueryParams(t *testing.T) {
|
|
||||||
bucketItem:=common.BucketItem{}
|
|
||||||
bucketItem.Key="key1"
|
|
||||||
bucketItem.Type=common.TermsBucket
|
|
||||||
bucketItem.Parameters=map[string]interface{}{}
|
|
||||||
bucketItem.Parameters["field"]="metadata.labels.cluster_id"
|
|
||||||
bucketItem.Parameters["size"]=2
|
|
||||||
|
|
||||||
|
|
||||||
nestBucket:=common.BucketItem{}
|
|
||||||
nestBucket.Key="key2"
|
|
||||||
nestBucket.Type=common.DateHistogramBucket
|
|
||||||
nestBucket.Parameters=map[string]interface{}{}
|
|
||||||
nestBucket.Parameters["field"]="timestamp"
|
|
||||||
nestBucket.Parameters["calendar_interval"]="1d"
|
|
||||||
nestBucket.Parameters["time_zone"]="+08:00"
|
|
||||||
|
|
||||||
leafBucket:=common.NewBucketItem(common.TermsBucket,util.MapStr{
|
|
||||||
"size":5,
|
|
||||||
"field":"payload.elasticsearch.cluster_health.status",
|
|
||||||
})
|
|
||||||
|
|
||||||
leafBucket.Key="key3"
|
|
||||||
|
|
||||||
metricItems:=[]*common.MetricItem{}
|
|
||||||
var bucketSizeStr ="10s"
|
|
||||||
metricItem:=newMetricItem("cluster_summary", 2, "cluster")
|
|
||||||
metricItem.Key="key4"
|
|
||||||
metricItem.AddLine("Indexing","Total Indexing","Number of documents being indexed for primary and replica shards.","group1",
|
|
||||||
"payload.elasticsearch.index_stats.total.indexing.index_total","max",bucketSizeStr,"doc/s","num","0,0.[00]","0,0.[00]",false,true)
|
|
||||||
metricItem.AddLine("Search","Total Search","Number of search requests being executed across primary and replica shards. A single search can run against multiple shards!","group1",
|
|
||||||
"payload.elasticsearch.index_stats.total.search.query_total","max",bucketSizeStr,"query/s","num","0,0.[00]","0,0.[00]",false,true)
|
|
||||||
metricItems=append(metricItems,metricItem)
|
|
||||||
|
|
||||||
nestBucket.AddNestBucket(leafBucket)
|
|
||||||
nestBucket.Metrics=metricItems
|
|
||||||
|
|
||||||
bucketItem.Buckets=[]*common.BucketItem{}
|
|
||||||
bucketItem.Buckets=append(bucketItem.Buckets,&nestBucket)
|
|
||||||
|
|
||||||
|
|
||||||
aggs:=ConvertBucketItemsToAggQuery([]*common.BucketItem{&bucketItem},nil)
|
|
||||||
fmt.Println(util.MustToJSON(aggs))
|
|
||||||
|
|
||||||
response:="{ \"took\": 37, \"timed_out\": false, \"_shards\": { \"total\": 1, \"successful\": 1, \"skipped\": 0, \"failed\": 0 }, \"hits\": { \"total\": { \"value\": 10000, \"relation\": \"gte\" }, \"max_score\": null, \"hits\": [] }, \"aggregations\": { \"key1\": { \"doc_count_error_upper_bound\": 0, \"sum_other_doc_count\": 0, \"buckets\": [ { \"key\": \"c7pqhptj69a0sg3rn05g\", \"doc_count\": 80482, \"key2\": { \"buckets\": [ { \"key_as_string\": \"2022-01-28T00:00:00.000+08:00\", \"key\": 1643299200000, \"doc_count\": 14310, \"c7qi5hii4h935v9bs91g\": { \"value\": 15680 }, \"key3\": { \"doc_count_error_upper_bound\": 0, \"sum_other_doc_count\": 0, \"buckets\": [] }, \"c7qi5hii4h935v9bs920\": { \"value\": 2985 } }, { \"key_as_string\": \"2022-01-29T00:00:00.000+08:00\", \"key\": 1643385600000, \"doc_count\": 66172, \"c7qi5hii4h935v9bs91g\": { \"value\": 106206 }, \"key3\": { \"doc_count_error_upper_bound\": 0, \"sum_other_doc_count\": 0, \"buckets\": [] }, \"c7qi5hii4h935v9bs920\": { \"value\": 20204 }, \"c7qi5hii4h935v9bs91g_deriv\": { \"value\": 90526 }, \"c7qi5hii4h935v9bs920_deriv\": { \"value\": 17219 } } ] } }, { \"key\": \"c7qi42ai4h92sksk979g\", \"doc_count\": 660, \"key2\": { \"buckets\": [ { \"key_as_string\": \"2022-01-29T00:00:00.000+08:00\", \"key\": 1643385600000, \"doc_count\": 660, \"c7qi5hii4h935v9bs91g\": { \"value\": 106206 }, \"key3\": { \"doc_count_error_upper_bound\": 0, \"sum_other_doc_count\": 0, \"buckets\": [] }, \"c7qi5hii4h935v9bs920\": { \"value\": 20204 } } ] } } ] } } }"
|
|
||||||
res:=SearchResponse{}
|
|
||||||
util.FromJSONBytes([]byte(response),&res)
|
|
||||||
fmt.Println(response)
|
|
||||||
groupKey:="key1"
|
|
||||||
metricLabelKey:="key2"
|
|
||||||
metricValueKey:="c7qi5hii4h935v9bs920"
|
|
||||||
data:=ParseAggregationResult(int(10),res.Aggregations,groupKey,metricLabelKey,metricValueKey)
|
|
||||||
fmt.Println(data)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConvertBucketItems(t *testing.T) {
|
|
||||||
response:="{ \"took\": 8, \"timed_out\": false, \"_shards\": { \"total\": 1, \"successful\": 1, \"skipped\": 0, \"failed\": 0 }, \"hits\": { \"total\": { \"value\": 81, \"relation\": \"eq\" }, \"max_score\": null, \"hits\": [] }, \"aggregations\": { \"c7v2gm3i7638vvo4pv80\": { \"doc_count_error_upper_bound\": 0, \"sum_other_doc_count\": 0, \"buckets\": [ { \"key\": \"c7uv7p3i76360kgdmpb0\", \"doc_count\": 81, \"c7v2gm3i7638vvo4pv8g\": { \"buckets\": [ { \"key_as_string\": \"2022-02-05T00:00:00.000+08:00\", \"key\": 1643990400000, \"doc_count\": 81, \"c7v2gm3i7638vvo4pv90\": { \"doc_count_error_upper_bound\": 0, \"sum_other_doc_count\": 0, \"buckets\": [ { \"key\": \"yellow\", \"doc_count\": 81 } ] } } ] } } ] } } }"
|
|
||||||
res:=SearchResponse{}
|
|
||||||
util.FromJSONBytes([]byte(response),&res)
|
|
||||||
|
|
||||||
data:=ParseAggregationBucketResult(int(10),res.Aggregations,"c7v2gm3i7638vvo4pv80","c7v2gm3i7638vvo4pv8g","c7v2gm3i7638vvo4pv90", func() {
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
fmt.Println(data)
|
|
||||||
|
|
||||||
}
|
|
|
@ -30,7 +30,10 @@ package elasticsearch
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"infini.sh/console/model/alerting"
|
"infini.sh/console/model/alerting"
|
||||||
|
"infini.sh/console/model/insight"
|
||||||
|
"infini.sh/framework/core/elastic"
|
||||||
"infini.sh/framework/core/util"
|
"infini.sh/framework/core/util"
|
||||||
|
"infini.sh/framework/modules/elastic/adapter/elasticsearch"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -77,12 +80,15 @@ func TestEngine( t *testing.T) {
|
||||||
},
|
},
|
||||||
|
|
||||||
Metrics: alerting.Metric{
|
Metrics: alerting.Metric{
|
||||||
PeriodInterval: "1m",
|
Metric: insight.Metric{
|
||||||
Items: []alerting.MetricItem{
|
BucketSize: "1m",
|
||||||
{Name: "a", Field: "payload.elasticsearch.node_stats.fs.total.free_in_bytes", Statistic: "min", Group: []string{"metadata.labels.cluster_id", "metadata.labels.node_id"}},
|
Items: []insight.MetricItem{
|
||||||
{Name: "b", Field: "payload.elasticsearch.node_stats.fs.total.total_in_bytes", Statistic: "max", Group: []string{"metadata.labels.cluster_id", "metadata.labels.node_id"}},
|
{Name: "a", Field: "payload.elasticsearch.node_stats.fs.total.free_in_bytes", Statistic: "min"},
|
||||||
|
{Name: "b", Field: "payload.elasticsearch.node_stats.fs.total.total_in_bytes", Statistic: "max"},
|
||||||
},
|
},
|
||||||
Formula: "a/b*100",
|
Formula: "a/b*100",
|
||||||
|
},
|
||||||
|
|
||||||
//Expression: "min(fs.free_in_bytes)/max(fs.total_in_bytes)*100",
|
//Expression: "min(fs.free_in_bytes)/max(fs.total_in_bytes)*100",
|
||||||
},
|
},
|
||||||
Conditions: alerting.Condition{
|
Conditions: alerting.Condition{
|
||||||
|
@ -93,7 +99,7 @@ func TestEngine( t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
Channels: alerting.NotificationConfig{
|
Channels: &alerting.NotificationConfig{
|
||||||
Normal: []alerting.Channel{
|
Normal: []alerting.Channel{
|
||||||
{Name: "钉钉", Type: alerting.ChannelWebhook, Webhook: &alerting.CustomWebhook{
|
{Name: "钉钉", Type: alerting.ChannelWebhook, Webhook: &alerting.CustomWebhook{
|
||||||
HeaderParams: map[string]string{
|
HeaderParams: map[string]string{
|
||||||
|
@ -139,7 +145,7 @@ func TestEngine( t *testing.T) {
|
||||||
|
|
||||||
func TestGenerateAgg(t *testing.T) {
|
func TestGenerateAgg(t *testing.T) {
|
||||||
eng := &Engine{}
|
eng := &Engine{}
|
||||||
agg := eng.generateAgg(&alerting.MetricItem{
|
agg := eng.generateAgg(&insight.MetricItem{
|
||||||
Name: "a",
|
Name: "a",
|
||||||
Field: "cpu.percent",
|
Field: "cpu.percent",
|
||||||
Statistic: "p99",
|
Statistic: "p99",
|
||||||
|
@ -199,13 +205,23 @@ func TestGeneratePercentilesAggQuery(t *testing.T) {
|
||||||
// EscalationThrottlePeriod: "30m",
|
// EscalationThrottlePeriod: "30m",
|
||||||
// },
|
// },
|
||||||
//}
|
//}
|
||||||
|
cfg := elastic.ElasticsearchConfig{}
|
||||||
|
cfg.ID = "test"
|
||||||
|
esClient := elasticsearch.ESAPIV7{}
|
||||||
|
esClient.Elasticsearch = cfg.ID
|
||||||
|
esClient.Version = elastic.Version{
|
||||||
|
Number: "7.10.2",
|
||||||
|
Major: 7,
|
||||||
|
Distribution: elastic.Elasticsearch,
|
||||||
|
}
|
||||||
|
elastic.UpdateClient(cfg, &esClient)
|
||||||
rule := alerting.Rule{
|
rule := alerting.Rule{
|
||||||
ID: util.GetUUID(),
|
ID: util.GetUUID(),
|
||||||
Created: time.Now(),
|
Created: time.Now(),
|
||||||
Updated: time.Now(),
|
Updated: time.Now(),
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Resource: alerting.Resource{
|
Resource: alerting.Resource{
|
||||||
ID: "c8i18llath2blrusdjng",
|
ID: cfg.ID,
|
||||||
Type: "elasticsearch",
|
Type: "elasticsearch",
|
||||||
Objects: []string{".infini_metrics*"},
|
Objects: []string{".infini_metrics*"},
|
||||||
TimeField: "timestamp",
|
TimeField: "timestamp",
|
||||||
|
@ -225,13 +241,15 @@ func TestGeneratePercentilesAggQuery(t *testing.T) {
|
||||||
},
|
},
|
||||||
|
|
||||||
Metrics: alerting.Metric{
|
Metrics: alerting.Metric{
|
||||||
PeriodInterval: "1m",
|
Metric: insight.Metric{
|
||||||
Items: []alerting.MetricItem{
|
BucketSize: "1m",
|
||||||
{Name: "a", Field: "payload.elasticsearch.index_stats.total.search.query_total", Statistic: "rate", Group: []string{"metadata.labels.cluster_id"}},
|
Items: []insight.MetricItem{
|
||||||
{Name: "b", Field: "payload.elasticsearch.index_stats.total.search.query_time_in_millis", Statistic: "rate", Group: []string{"metadata.labels.cluster_id"}},
|
{Name: "a", Field: "payload.elasticsearch.index_stats.total.search.query_total", Statistic: "rate"},
|
||||||
|
{Name: "b", Field: "payload.elasticsearch.index_stats.total.search.query_time_in_millis", Statistic: "rate"},
|
||||||
},
|
},
|
||||||
Formula: "b/a",
|
Formula: "b/a",
|
||||||
},
|
},
|
||||||
|
},
|
||||||
Conditions: alerting.Condition{
|
Conditions: alerting.Condition{
|
||||||
Operator: "any",
|
Operator: "any",
|
||||||
Items: []alerting.ConditionItem{
|
Items: []alerting.ConditionItem{
|
||||||
|
@ -239,7 +257,7 @@ func TestGeneratePercentilesAggQuery(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
Channels: alerting.NotificationConfig{
|
Channels: &alerting.NotificationConfig{
|
||||||
Normal: []alerting.Channel{
|
Normal: []alerting.Channel{
|
||||||
{Name: "钉钉", Type: alerting.ChannelWebhook, Webhook: &alerting.CustomWebhook{
|
{Name: "钉钉", Type: alerting.ChannelWebhook, Webhook: &alerting.CustomWebhook{
|
||||||
HeaderParams: map[string]string{
|
HeaderParams: map[string]string{
|
||||||
|
|
Loading…
Reference in New Issue