mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-07-02 01:14:27 +08:00
226 lines
5.0 KiB
Go
226 lines
5.0 KiB
Go
// Copyright 2019 Yunion
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package tsdb
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"yunion.io/x/pkg/util/sets"
|
|
|
|
api "yunion.io/x/onecloud/pkg/apis/monitor"
|
|
)
|
|
|
|
type TsdbQuery struct {
|
|
TimeRange *TimeRange
|
|
Queries []*Query
|
|
Debug bool
|
|
}
|
|
|
|
type Query struct {
|
|
RefId string
|
|
api.MetricQuery
|
|
DataSource DataSource
|
|
MaxDataPoints int64
|
|
IntervalMs int64
|
|
}
|
|
|
|
type Response struct {
|
|
Results map[string]*QueryResult `json:"results"`
|
|
Message string `json:"message,omitempty"`
|
|
}
|
|
|
|
type QueryResultMeta struct {
|
|
RawQuery string `json:"raw_query"`
|
|
}
|
|
|
|
type QueryResult struct {
|
|
Error error `json:"-"`
|
|
ErrorString string `json:"error,omitempty"`
|
|
RefId string `json:"ref_id"`
|
|
Meta QueryResultMeta `json:"meta"`
|
|
Series TimeSeriesSlice `json:"series"`
|
|
Tables []*Table `json:"tables"`
|
|
Dataframes [][]byte `json:"dataframes"`
|
|
}
|
|
|
|
type TimeSeries struct {
|
|
// RawName is used to frontend displaying the curve name
|
|
RawName string `json:"raw_name"`
|
|
Columns []string `json:"columns"`
|
|
Name string `json:"name"`
|
|
Points TimeSeriesPoints `json:"points"`
|
|
Tags map[string]string `json:"tags,omitempty"`
|
|
}
|
|
|
|
func NewTimeSeries(
|
|
name string,
|
|
rawName string,
|
|
columns []string,
|
|
points TimeSeriesPoints,
|
|
tags map[string]string,
|
|
) *TimeSeries {
|
|
return &TimeSeries{
|
|
RawName: rawName,
|
|
Columns: columns,
|
|
Name: name,
|
|
Points: points,
|
|
Tags: tags,
|
|
}
|
|
}
|
|
|
|
type Table struct {
|
|
Columns []TableColumn `json:"columns"`
|
|
Rows []RowValues `json:"rows"`
|
|
}
|
|
|
|
type TableColumn struct {
|
|
Text string `json:"text"`
|
|
}
|
|
|
|
type RowValues []interface{}
|
|
type TimePoint []interface{}
|
|
type TimeSeriesPoints []TimePoint
|
|
type TimeSeriesSlice []*TimeSeries
|
|
|
|
func NewQueryResult() *QueryResult {
|
|
return &QueryResult{
|
|
Series: make(TimeSeriesSlice, 0),
|
|
}
|
|
}
|
|
|
|
func NewTimePoint(value *float64, timestamp float64) TimePoint {
|
|
return TimePoint{value, timestamp}
|
|
}
|
|
|
|
func NewTimePointByVal(value float64, timestamp float64) TimePoint {
|
|
return NewTimePoint(&value, timestamp)
|
|
}
|
|
|
|
func (p TimePoint) IsValid() bool {
|
|
if val, ok := p[0].(*float64); ok && val != nil {
|
|
return true
|
|
}
|
|
return false
|
|
//return p[0].(*float64) != nil
|
|
}
|
|
|
|
func (p TimePoint) IsValids() bool {
|
|
for i := 0; i < len(p)-1; i++ {
|
|
if p[i] == nil {
|
|
return false
|
|
}
|
|
if p[i].(*float64) == nil {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (p TimePoint) Value() float64 {
|
|
return *(p[0].(*float64))
|
|
}
|
|
|
|
func (p TimePoint) Timestamp() float64 {
|
|
return p[len(p)-1].(float64)
|
|
}
|
|
|
|
func (p TimePoint) Values() []float64 {
|
|
values := make([]float64, 0)
|
|
for i := 0; i < len(p)-1; i++ {
|
|
values = append(values, *(p[i].(*float64)))
|
|
}
|
|
return values
|
|
}
|
|
|
|
func (p TimePoint) PointValueStr() []string {
|
|
arrStr := make([]string, 0)
|
|
for i := 0; i < len(p)-1; i++ {
|
|
if p[i] == nil {
|
|
arrStr = append(arrStr, "")
|
|
}
|
|
if fval, ok := p[i].(*float64); ok {
|
|
arrStr = append(arrStr, strconv.FormatFloat((*fval), 'f', -1, 64))
|
|
continue
|
|
}
|
|
if ival, ok := p[i].(*int64); ok {
|
|
arrStr = append(arrStr, strconv.FormatInt((*ival), 64))
|
|
continue
|
|
}
|
|
arrStr = append(arrStr, p[i].(string))
|
|
}
|
|
return arrStr
|
|
}
|
|
|
|
func NewTimeSeriesPointsFromArgs(values ...float64) TimeSeriesPoints {
|
|
points := make(TimeSeriesPoints, 0)
|
|
|
|
for i := 0; i < len(values); i += 2 {
|
|
points = append(points, NewTimePoint(&values[i], values[i+1]))
|
|
}
|
|
|
|
return points
|
|
}
|
|
|
|
func FormatRawName(idx int, name string, groupByTags []string, tags map[string]string) string {
|
|
// when group by tag specified
|
|
if len(groupByTags) != 0 {
|
|
for key, val := range tags {
|
|
if strings.Contains(strings.Join(groupByTags, ","), key) {
|
|
return val
|
|
}
|
|
}
|
|
}
|
|
|
|
genHint := func(k, v string) string {
|
|
return fmt.Sprintf("%s=%s", k, v)
|
|
}
|
|
|
|
hintNames := sets.NewString()
|
|
hints := sets.NewString()
|
|
for _, tagKey := range api.MEASUREMENT_TAG_KEYWORD {
|
|
if tagV, ok := tags[tagKey]; ok {
|
|
gHint := genHint(tagKey, tagV)
|
|
if strings.Contains(tagKey, "name") {
|
|
hintNames.Insert(gHint)
|
|
} else {
|
|
hints.Insert(gHint)
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(hints) == 0 {
|
|
// try id
|
|
for key, val := range tags {
|
|
if strings.Contains(key, "id") && len(val) != 0 {
|
|
hints.Insert(genHint(key, val))
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(hints) == 0 {
|
|
// if hints is empty at last, return index hint
|
|
return fmt.Sprintf("unknown-%d-%s", idx, name)
|
|
}
|
|
sortNL := hintNames.List()
|
|
sort.Strings(sortNL)
|
|
sortL := hints.List()
|
|
sort.Strings(sortL)
|
|
sortNL = append(sortNL, sortL...)
|
|
return fmt.Sprintf("{%s}", strings.Join(sortNL, ","))
|
|
}
|