reformat monitoring apis
This commit is contained in:
993
pkg/models/metrics/metrics.go
Normal file
993
pkg/models/metrics/metrics.go
Normal file
@@ -0,0 +1,993 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
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 metrics
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/api/core/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
"kubesphere.io/kubesphere/pkg/models/workspaces"
|
||||
)
|
||||
|
||||
var nodeStatusDelLables = []string{"endpoint", "instance", "job", "namespace", "pod", "service"}
|
||||
|
||||
const (
|
||||
ChannelMaxCapacityWorkspaceMetric = 400
|
||||
ChannelMaxCapacity = 100
|
||||
)
|
||||
|
||||
type PagedFormatedLevelMetric struct {
|
||||
CurrentPage int `json:"page"`
|
||||
TotalPage int `json:"total_page"`
|
||||
Message string `json:"msg"`
|
||||
Metric FormatedLevelMetric `json:"metrics"`
|
||||
}
|
||||
|
||||
type FormatedLevelMetric struct {
|
||||
MetricsLevel string `json:"metrics_level"`
|
||||
Results []FormatedMetric `json:"results"`
|
||||
}
|
||||
|
||||
type FormatedMetric struct {
|
||||
MetricName string `json:"metric_name, omitempty"`
|
||||
Status string `json:"status"`
|
||||
Data FormatedMetricData `json:"data, omitempty"`
|
||||
}
|
||||
|
||||
type FormatedMetricData struct {
|
||||
Result []map[string]interface{} `json:"result"`
|
||||
ResultType string `json:"resultType"`
|
||||
}
|
||||
|
||||
type MetricResultValues []MetricResultValue
|
||||
|
||||
type MetricResultValue struct {
|
||||
timestamp float64
|
||||
value string
|
||||
}
|
||||
|
||||
type MetricItem struct {
|
||||
MetricLabel map[string]string `json:"metric"`
|
||||
Value []interface{} `json:"value"`
|
||||
}
|
||||
|
||||
type CommonMetricsResult struct {
|
||||
Status string `json:"status"`
|
||||
Data CommonMetricsData `json:"data"`
|
||||
}
|
||||
|
||||
type CommonMetricsData struct {
|
||||
Result []CommonResultItem `json:"result"`
|
||||
ResultType string `json:"resultType"`
|
||||
}
|
||||
|
||||
type CommonResultItem struct {
|
||||
KubePodMetric KubePodMetric `json:"metric"`
|
||||
Value interface{} `json:"value"`
|
||||
}
|
||||
|
||||
type KubePodMetric struct {
|
||||
CreatedByKind string `json:"created_by_kind"`
|
||||
CreatedByName string `json:"created_by_name"`
|
||||
Namespace string `json:"namespace"`
|
||||
Pod string `json:"pod"`
|
||||
}
|
||||
|
||||
type ComponentStatus struct {
|
||||
Name string `json:"metric_name,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
ComponentStatus []OneComponentStatus `json:"component"`
|
||||
}
|
||||
|
||||
type OneComponentStatus struct {
|
||||
// Valid value: "Healthy"
|
||||
Type string `json:"type"`
|
||||
// Valid values for "Healthy": "True", "False", or "Unknown".
|
||||
Status string `json:"status"`
|
||||
// Message about the condition for a component.
|
||||
Message string `json:"message,omitempty"`
|
||||
// Condition error code for a component.
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
func getPodNameRegexInWorkload(res string) string {
|
||||
|
||||
data := []byte(res)
|
||||
var dat CommonMetricsResult
|
||||
jsonErr := json.Unmarshal(data, &dat)
|
||||
if jsonErr != nil {
|
||||
glog.Errorln("json parse failed", jsonErr)
|
||||
}
|
||||
var podNames []string
|
||||
for _, item := range dat.Data.Result {
|
||||
podName := item.KubePodMetric.Pod
|
||||
podNames = append(podNames, podName)
|
||||
}
|
||||
podNamesFilter := "^(" + strings.Join(podNames, "|") + ")$"
|
||||
return podNamesFilter
|
||||
}
|
||||
|
||||
func AssembleWorkloadMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, metricName string) (string, string) {
|
||||
rule := MakeWorkloadRule(monitoringRequest.WorkloadKind, monitoringRequest.WorkloadName, monitoringRequest.NsName)
|
||||
paramValues := monitoringRequest.Params
|
||||
params := makeRequestParamString(rule, paramValues)
|
||||
|
||||
res := client.SendMonitoringRequest(client.DefaultQueryType, params)
|
||||
|
||||
podNamesFilter := getPodNameRegexInWorkload(res)
|
||||
|
||||
queryType := monitoringRequest.QueryType
|
||||
rule = MakePodPromQL(metricName, monitoringRequest.NsName, "", "", podNamesFilter)
|
||||
params = makeRequestParamString(rule, paramValues)
|
||||
|
||||
return queryType, params
|
||||
}
|
||||
|
||||
func AssemblePodMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, metricName string) (string, string, bool) {
|
||||
queryType := monitoringRequest.QueryType
|
||||
|
||||
paramValues := monitoringRequest.Params
|
||||
|
||||
rule := MakePodPromQL(metricName, monitoringRequest.NsName, monitoringRequest.NodeId, monitoringRequest.PodName, monitoringRequest.PodsFilter)
|
||||
params := makeRequestParamString(rule, paramValues)
|
||||
return queryType, params, rule == ""
|
||||
}
|
||||
|
||||
func GetMetric(queryType, params, metricName string) *FormatedMetric {
|
||||
res := client.SendMonitoringRequest(queryType, params)
|
||||
formatedMetric := ReformatJson(res, metricName)
|
||||
return formatedMetric
|
||||
}
|
||||
|
||||
func GetNodeAddressInfo() *map[string][]v1.NodeAddress {
|
||||
nodeList, _ := client.NewK8sClient().CoreV1().Nodes().List(metaV1.ListOptions{})
|
||||
var nodeAddress = make(map[string][]v1.NodeAddress)
|
||||
for _, node := range nodeList.Items {
|
||||
nodeAddress[node.Name] = node.Status.Addresses
|
||||
}
|
||||
return &nodeAddress
|
||||
}
|
||||
|
||||
func AddNodeAddressMetric(nodeMetric *FormatedMetric, nodeAddress *map[string][]v1.NodeAddress) {
|
||||
|
||||
for i := 0; i < len(nodeMetric.Data.Result); i++ {
|
||||
metricDesc := nodeMetric.Data.Result[i][ResultItemMetric]
|
||||
metricDescMap := metricDesc.(map[string]interface{})
|
||||
if nodeId, exist := metricDescMap["node"]; exist {
|
||||
addr, exist := (*nodeAddress)[nodeId.(string)]
|
||||
if exist {
|
||||
metricDescMap["address"] = addr
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func MonitorContainer(monitoringRequest *client.MonitoringRequestParams) *FormatedMetric {
|
||||
queryType := monitoringRequest.QueryType
|
||||
|
||||
paramValues := monitoringRequest.Params
|
||||
rule := MakeContainerPromQL(monitoringRequest.NsName, monitoringRequest.PodName, monitoringRequest.ContainerName, monitoringRequest.MetricsName, monitoringRequest.ContainersFilter)
|
||||
params := makeRequestParamString(rule, paramValues)
|
||||
|
||||
res := GetMetric(queryType, params, monitoringRequest.MetricsName)
|
||||
return res
|
||||
}
|
||||
|
||||
func AssembleNamespaceMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, metricName string) (string, string) {
|
||||
queryType := monitoringRequest.QueryType
|
||||
|
||||
paramValues := monitoringRequest.Params
|
||||
rule := MakeNamespacePromQL(monitoringRequest.NsName, monitoringRequest.NsFilter, metricName)
|
||||
params := makeRequestParamString(rule, paramValues)
|
||||
|
||||
return queryType, params
|
||||
}
|
||||
|
||||
func AssembleWorkspaceMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, namespaceList []string, metricName string) (string, string) {
|
||||
nsFilter := "^(" + strings.Join(namespaceList, "|") + ")$"
|
||||
|
||||
queryType := monitoringRequest.QueryType
|
||||
|
||||
rule := MakeWorkspacePromQL(metricName, nsFilter)
|
||||
paramValues := monitoringRequest.Params
|
||||
params := makeRequestParamString(rule, paramValues)
|
||||
return queryType, params
|
||||
}
|
||||
|
||||
func makeRequestParamString(rule string, paramValues url.Values) string {
|
||||
|
||||
var values = make(url.Values)
|
||||
for key, v := range paramValues {
|
||||
values.Set(key, v[0])
|
||||
}
|
||||
|
||||
values.Set("query", rule)
|
||||
|
||||
params := values.Encode()
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
func filterNamespace(nsFilter string, namespaceList []string) []string {
|
||||
var newNSlist []string
|
||||
if nsFilter == "" {
|
||||
nsFilter = ".*"
|
||||
}
|
||||
for _, ns := range namespaceList {
|
||||
bol, _ := regexp.MatchString(nsFilter, ns)
|
||||
if bol {
|
||||
newNSlist = append(newNSlist, ns)
|
||||
}
|
||||
}
|
||||
return newNSlist
|
||||
}
|
||||
|
||||
func MonitorAllWorkspaces(monitoringRequest *client.MonitoringRequestParams) *FormatedLevelMetric {
|
||||
metricsFilter := monitoringRequest.MetricsFilter
|
||||
if strings.Trim(metricsFilter, " ") == "" {
|
||||
metricsFilter = ".*"
|
||||
}
|
||||
var filterMetricsName []string
|
||||
for _, metricName := range WorkspaceMetricsNames {
|
||||
bol, err := regexp.MatchString(metricsFilter, metricName)
|
||||
if err == nil && bol {
|
||||
filterMetricsName = append(filterMetricsName, metricName)
|
||||
}
|
||||
}
|
||||
|
||||
var wgAll sync.WaitGroup
|
||||
var wsAllch = make(chan *[]FormatedMetric, ChannelMaxCapacityWorkspaceMetric)
|
||||
|
||||
workspaceNamespaceMap, _, _ := workspaces.GetAllOrgAndProjList()
|
||||
for ws, _ := range workspaceNamespaceMap {
|
||||
bol, err := regexp.MatchString(monitoringRequest.WsFilter, ws)
|
||||
if err == nil && bol {
|
||||
// a workspace
|
||||
wgAll.Add(1)
|
||||
go collectWorkspaceMetric(monitoringRequest, ws, filterMetricsName, &wgAll, wsAllch)
|
||||
}
|
||||
}
|
||||
|
||||
wgAll.Wait()
|
||||
close(wsAllch)
|
||||
|
||||
fmtMetricMap := make(map[string]FormatedMetric)
|
||||
for oneWsMetric := range wsAllch {
|
||||
if oneWsMetric != nil {
|
||||
// aggregate workspace metric
|
||||
for _, metric := range *oneWsMetric {
|
||||
fm, exist := fmtMetricMap[metric.MetricName]
|
||||
if exist {
|
||||
if metric.Status == "error" {
|
||||
fm.Status = metric.Status
|
||||
}
|
||||
fm.Data.Result = append(fm.Data.Result, metric.Data.Result...)
|
||||
fmtMetricMap[metric.MetricName] = fm
|
||||
} else {
|
||||
fmtMetricMap[metric.MetricName] = metric
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var metricArray = make([]FormatedMetric, 0)
|
||||
for _, metric := range fmtMetricMap {
|
||||
metricArray = append(metricArray, metric)
|
||||
}
|
||||
|
||||
return &FormatedLevelMetric{
|
||||
MetricsLevel: MetricLevelClusterWorkspace,
|
||||
Results: metricArray,
|
||||
}
|
||||
}
|
||||
|
||||
func collectWorkspaceMetric(monitoringRequest *client.MonitoringRequestParams, ws string, filterMetricsName []string, wgAll *sync.WaitGroup, wsAllch chan *[]FormatedMetric) {
|
||||
defer wgAll.Done()
|
||||
var wg sync.WaitGroup
|
||||
var ch = make(chan *FormatedMetric, ChannelMaxCapacity)
|
||||
namespaceArray, err := workspaces.WorkspaceNamespaces(ws)
|
||||
if err != nil {
|
||||
glog.Errorln(err.Error())
|
||||
}
|
||||
// add by namespace
|
||||
for _, metricName := range filterMetricsName {
|
||||
wg.Add(1)
|
||||
go func(metricName string) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
}()
|
||||
|
||||
queryType, params := AssembleWorkspaceMetricRequestInfo(monitoringRequest, namespaceArray, metricName)
|
||||
ch <- GetMetric(queryType, params, metricName)
|
||||
|
||||
wg.Done()
|
||||
}(metricName)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
var metricsArray []FormatedMetric
|
||||
for oneMetric := range ch {
|
||||
if oneMetric != nil {
|
||||
// add "workspace" filed to oneMetric `metric` field
|
||||
for i := 0; i < len(oneMetric.Data.Result); i++ {
|
||||
tmap := oneMetric.Data.Result[i]["metric"].(map[string]interface{})
|
||||
tmap[MetricLevelWorkspace] = ws
|
||||
oneMetric.Data.Result[i]["metric"] = tmap
|
||||
}
|
||||
metricsArray = append(metricsArray, *oneMetric)
|
||||
}
|
||||
}
|
||||
|
||||
wsAllch <- &metricsArray
|
||||
}
|
||||
|
||||
func MonitorAllMetrics(monitoringRequest *client.MonitoringRequestParams, resourceType string) *FormatedLevelMetric {
|
||||
metricsFilter := monitoringRequest.MetricsFilter
|
||||
if metricsFilter == "" {
|
||||
metricsFilter = ".*"
|
||||
}
|
||||
|
||||
var ch = make(chan *FormatedMetric, ChannelMaxCapacity)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
switch resourceType {
|
||||
case MetricLevelCluster:
|
||||
{
|
||||
for _, metricName := range ClusterMetricsNames {
|
||||
bol, err := regexp.MatchString(metricsFilter, metricName)
|
||||
if err == nil && bol {
|
||||
wg.Add(1)
|
||||
go func(metricName string) {
|
||||
queryType, params := AssembleClusterMetricRequestInfo(monitoringRequest, metricName)
|
||||
clusterMetrics := GetMetric(queryType, params, metricName)
|
||||
|
||||
// for this special case, get namespace history which in a workspace by determining namespace label
|
||||
if metricName == MetricNameWorkspaceAllProjectCount {
|
||||
clusterMetrics = MonitorWorkspaceNamespaceHistory(clusterMetrics)
|
||||
}
|
||||
|
||||
ch <- clusterMetrics
|
||||
|
||||
wg.Done()
|
||||
}(metricName)
|
||||
}
|
||||
}
|
||||
}
|
||||
case MetricLevelNode:
|
||||
{
|
||||
for _, metricName := range NodeMetricsNames {
|
||||
bol, err := regexp.MatchString(metricsFilter, metricName)
|
||||
if err == nil && bol {
|
||||
wg.Add(1)
|
||||
go func(metricName string) {
|
||||
queryType, params := AssembleNodeMetricRequestInfo(monitoringRequest, metricName)
|
||||
ch <- GetMetric(queryType, params, metricName)
|
||||
wg.Done()
|
||||
}(metricName)
|
||||
}
|
||||
}
|
||||
}
|
||||
case MetricLevelWorkspace:
|
||||
{
|
||||
namespaceArray, err := workspaces.WorkspaceNamespaces(monitoringRequest.WsName)
|
||||
if err != nil {
|
||||
glog.Errorln(err.Error())
|
||||
}
|
||||
namespaceArray = filterNamespace(monitoringRequest.NsFilter, namespaceArray)
|
||||
|
||||
if monitoringRequest.Tp == "" {
|
||||
for _, metricName := range WorkspaceMetricsNames {
|
||||
bol, err := regexp.MatchString(metricsFilter, metricName)
|
||||
if err == nil && bol {
|
||||
wg.Add(1)
|
||||
go func(metricName string) {
|
||||
queryType, params := AssembleWorkspaceMetricRequestInfo(monitoringRequest, namespaceArray, metricName)
|
||||
ch <- GetMetric(queryType, params, metricName)
|
||||
wg.Done()
|
||||
}(metricName)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, metricName := range NamespaceMetricsNames {
|
||||
bol, err := regexp.MatchString(metricsFilter, metricName)
|
||||
ns := "^(" + strings.Join(namespaceArray, "|") + ")$"
|
||||
monitoringRequest.NsFilter = ns
|
||||
if err == nil && bol {
|
||||
wg.Add(1)
|
||||
go func(metricName string) {
|
||||
queryType, params := AssembleNamespaceMetricRequestInfo(monitoringRequest, metricName)
|
||||
ch <- GetMetric(queryType, params, metricName)
|
||||
wg.Done()
|
||||
}(metricName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case MetricLevelNamespace:
|
||||
{
|
||||
for _, metricName := range NamespaceMetricsNames {
|
||||
bol, err := regexp.MatchString(metricsFilter, metricName)
|
||||
if err == nil && bol {
|
||||
wg.Add(1)
|
||||
go func(metricName string) {
|
||||
queryType, params := AssembleNamespaceMetricRequestInfo(monitoringRequest, metricName)
|
||||
ch <- GetMetric(queryType, params, metricName)
|
||||
wg.Done()
|
||||
}(metricName)
|
||||
}
|
||||
}
|
||||
}
|
||||
case MetricLevelWorkload:
|
||||
{
|
||||
for _, metricName := range WorkloadMetricsNames {
|
||||
bol, err := regexp.MatchString(metricsFilter, metricName)
|
||||
if err == nil && bol {
|
||||
wg.Add(1)
|
||||
go func(metricName string) {
|
||||
metricName = strings.TrimLeft(metricName, "workload_")
|
||||
queryType, params := AssembleWorkloadMetricRequestInfo(monitoringRequest, metricName)
|
||||
ch <- GetMetric(queryType, params, metricName)
|
||||
wg.Done()
|
||||
}(metricName)
|
||||
}
|
||||
}
|
||||
}
|
||||
case MetricLevelPod:
|
||||
{
|
||||
for _, metricName := range PodMetricsNames {
|
||||
bol, err := regexp.MatchString(metricsFilter, metricName)
|
||||
if err == nil && bol {
|
||||
wg.Add(1)
|
||||
go func(metricName string) {
|
||||
queryType, params, nullRule := AssemblePodMetricRequestInfo(monitoringRequest, metricName)
|
||||
if !nullRule {
|
||||
ch <- GetMetric(queryType, params, metricName)
|
||||
} else {
|
||||
ch <- nil
|
||||
}
|
||||
wg.Done()
|
||||
}(metricName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
var metricsArray []FormatedMetric
|
||||
|
||||
for oneMetric := range ch {
|
||||
if oneMetric != nil {
|
||||
metricsArray = append(metricsArray, *oneMetric)
|
||||
}
|
||||
}
|
||||
|
||||
return &FormatedLevelMetric{
|
||||
MetricsLevel: resourceType,
|
||||
Results: metricsArray,
|
||||
}
|
||||
}
|
||||
|
||||
func MonitorWorkspaceNamespaceHistory(metric *FormatedMetric) *FormatedMetric {
|
||||
resultType := metric.Data.ResultType
|
||||
//metric.Status
|
||||
metricName := metric.MetricName
|
||||
|
||||
for i := 0; i < len(metric.Data.Result); i++ {
|
||||
metricItem := metric.Data.Result[i]
|
||||
|
||||
if resultType == ResultTypeVector {
|
||||
timeAndValue, sure := metricItem[ResultItemValue].([]interface{})
|
||||
if !sure {
|
||||
return metric
|
||||
}
|
||||
metric := getNamespaceHistoryMetric(timeAndValue[0].(float64), metricName)
|
||||
|
||||
workspaceNamespaceCount := calcWorkspaceNamespace(metric)
|
||||
|
||||
timeAndValue[1] = fmt.Sprintf("%d", workspaceNamespaceCount)
|
||||
|
||||
} else if resultType == ResultTypeMatrix {
|
||||
|
||||
values, sure := metricItem[ResultItemValues].([]interface{})
|
||||
if !sure {
|
||||
return metric
|
||||
}
|
||||
|
||||
for _, valueItem := range values {
|
||||
timeAndValue, sure := valueItem.([]interface{})
|
||||
if !sure {
|
||||
return metric
|
||||
}
|
||||
|
||||
metric := getNamespaceHistoryMetric(timeAndValue[0].(float64), metricName)
|
||||
|
||||
workspaceNamespaceCount := calcWorkspaceNamespace(metric)
|
||||
|
||||
timeAndValue[1] = fmt.Sprintf("%d", workspaceNamespaceCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return metric
|
||||
}
|
||||
|
||||
func getNamespaceHistoryMetric(timestamp float64, metricName string) *FormatedMetric {
|
||||
var timeRelatedParams = make(url.Values)
|
||||
timeRelatedParams.Set("time", fmt.Sprintf("%f", timestamp))
|
||||
timeRelatedParams.Set("query", NamespaceLabelRule)
|
||||
params := timeRelatedParams.Encode()
|
||||
metric := GetMetric(client.DefaultQueryType, params, metricName)
|
||||
return metric
|
||||
}
|
||||
|
||||
// calculate all namespace which belong to workspaces
|
||||
func calcWorkspaceNamespace(metric *FormatedMetric) int {
|
||||
if metric.Status == "error" {
|
||||
glog.Errorf("failed when retrive namespace history, the metric is %v", metric.Data.Result)
|
||||
return 0
|
||||
}
|
||||
|
||||
var workspaceNamespaceCount = 0
|
||||
|
||||
for _, result := range metric.Data.Result {
|
||||
tmpMap := result[ResultItemMetric].(map[string]interface{})
|
||||
wsName, exist := tmpMap[WorkspaceJoinedKey]
|
||||
|
||||
if exist && wsName != "" {
|
||||
workspaceNamespaceCount += 1
|
||||
}
|
||||
}
|
||||
|
||||
return workspaceNamespaceCount
|
||||
}
|
||||
|
||||
func MonitorAllWorkspacesStatistics() *FormatedLevelMetric {
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
var metricsArray []FormatedMetric
|
||||
timestamp := time.Now().Unix()
|
||||
|
||||
var orgResultItem *FormatedMetric
|
||||
var devopsResultItem *FormatedMetric
|
||||
var clusterProjResultItem *FormatedMetric
|
||||
var workspaceProjResultItem *FormatedMetric
|
||||
var accountResultItem *FormatedMetric
|
||||
|
||||
wsMap, projs, errProj := workspaces.GetAllOrgAndProjList()
|
||||
|
||||
wg.Add(5)
|
||||
|
||||
go func() {
|
||||
orgNums, errOrg := workspaces.GetAllOrgNums()
|
||||
if errOrg != nil {
|
||||
glog.Errorln(errOrg.Error())
|
||||
}
|
||||
orgResultItem = getSpecificMetricItem(timestamp, MetricNameWorkspaceAllOrganizationCount, WorkspaceResourceKindOrganization, orgNums, errOrg)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
devOpsProjectNums, errDevops := workspaces.GetAllDevOpsProjectsNums()
|
||||
if errDevops != nil {
|
||||
glog.Errorln(errDevops.Error())
|
||||
}
|
||||
devopsResultItem = getSpecificMetricItem(timestamp, MetricNameWorkspaceAllDevopsCount, WorkspaceResourceKindDevops, devOpsProjectNums, errDevops)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
var projNums = 0
|
||||
for _, v := range wsMap {
|
||||
projNums += len(v)
|
||||
}
|
||||
if errProj != nil {
|
||||
glog.Errorln(errProj.Error())
|
||||
}
|
||||
workspaceProjResultItem = getSpecificMetricItem(timestamp, MetricNameWorkspaceAllProjectCount, WorkspaceResourceKindNamespace, projNums, errProj)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
projNums := len(projs)
|
||||
if errProj != nil {
|
||||
glog.Errorln(errProj.Error())
|
||||
}
|
||||
clusterProjResultItem = getSpecificMetricItem(timestamp, MetricNameClusterAllProjectCount, WorkspaceResourceKindNamespace, projNums, errProj)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
actNums, errAct := workspaces.GetAllAccountNums()
|
||||
if errAct != nil {
|
||||
glog.Errorln(errAct.Error())
|
||||
}
|
||||
accountResultItem = getSpecificMetricItem(timestamp, MetricNameWorkspaceAllAccountCount, WorkspaceResourceKindAccount, actNums, errAct)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
|
||||
metricsArray = append(metricsArray, *orgResultItem, *devopsResultItem, *workspaceProjResultItem, *accountResultItem, *clusterProjResultItem)
|
||||
|
||||
return &FormatedLevelMetric{
|
||||
MetricsLevel: MetricLevelWorkspace,
|
||||
Results: metricsArray,
|
||||
}
|
||||
}
|
||||
|
||||
func MonitorOneWorkspaceStatistics(wsName string) *FormatedLevelMetric {
|
||||
|
||||
var nsMetrics *FormatedMetric
|
||||
var devopsMetrics *FormatedMetric
|
||||
var memberMetrics *FormatedMetric
|
||||
var roleMetrics *FormatedMetric
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(4)
|
||||
|
||||
var fMetricsArray []FormatedMetric
|
||||
timestamp := int64(time.Now().Unix())
|
||||
|
||||
go func() {
|
||||
// add namespaces(project) metric
|
||||
namespaces, errNs := workspaces.WorkspaceNamespaces(wsName)
|
||||
namespaces, noneExistentNs := getExistingNamespace(namespaces)
|
||||
if len(noneExistentNs) != 0 {
|
||||
nsStr := strings.Join(noneExistentNs, "|")
|
||||
errStr := "the namespaces " + nsStr + " do not exist"
|
||||
if errNs == nil {
|
||||
errNs = errors.New(errStr)
|
||||
} else {
|
||||
errNs = errors.New(errNs.Error() + "\t" + errStr)
|
||||
}
|
||||
}
|
||||
if errNs != nil {
|
||||
glog.Errorln(errNs.Error())
|
||||
}
|
||||
nsMetrics = getSpecificMetricItem(timestamp, MetricNameWorkspaceNamespaceCount, WorkspaceResourceKindNamespace, len(namespaces), errNs)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
devOpsProjects, errDevOps := workspaces.GetDevOpsProjects(wsName)
|
||||
if errDevOps != nil {
|
||||
glog.Errorln(errDevOps.Error())
|
||||
}
|
||||
// add devops metric
|
||||
devopsMetrics = getSpecificMetricItem(timestamp, MetricNameWorkspaceDevopsCount, WorkspaceResourceKindDevops, len(devOpsProjects), errDevOps)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
members, errMemb := workspaces.GetOrgMembers(wsName)
|
||||
if errMemb != nil {
|
||||
glog.Errorln(errMemb.Error())
|
||||
}
|
||||
// add member metric
|
||||
memberMetrics = getSpecificMetricItem(timestamp, MetricNameWorkspaceMemberCount, WorkspaceResourceKindMember, len(members), errMemb)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
roles, errRole := workspaces.GetOrgRoles(wsName)
|
||||
if errRole != nil {
|
||||
glog.Errorln(errRole.Error())
|
||||
}
|
||||
// add role metric
|
||||
roleMetrics = getSpecificMetricItem(timestamp, MetricNameWorkspaceRoleCount, WorkspaceResourceKindRole, len(roles), errRole)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
|
||||
fMetricsArray = append(fMetricsArray, *nsMetrics, *devopsMetrics, *memberMetrics, *roleMetrics)
|
||||
|
||||
return &FormatedLevelMetric{
|
||||
MetricsLevel: MetricLevelWorkspace,
|
||||
Results: fMetricsArray,
|
||||
}
|
||||
}
|
||||
|
||||
func getSpecificMetricItem(timestamp int64, metricName string, resource string, count int, err error, resourceType ...string) *FormatedMetric {
|
||||
var nsMetrics FormatedMetric
|
||||
nsMetrics.MetricName = metricName
|
||||
nsMetrics.Data.ResultType = ResultTypeVector
|
||||
resultItem := make(map[string]interface{})
|
||||
tmp := make(map[string]string)
|
||||
|
||||
if len(resourceType) > 0 {
|
||||
tmp[resourceType[0]] = resource
|
||||
} else {
|
||||
tmp[ResultItemMetricResource] = resource
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
nsMetrics.Status = MetricStatusSuccess
|
||||
} else {
|
||||
nsMetrics.Status = MetricStatusError
|
||||
resultItem["errormsg"] = err.Error()
|
||||
}
|
||||
|
||||
resultItem[ResultItemMetric] = tmp
|
||||
resultItem[ResultItemValue] = []interface{}{timestamp, count}
|
||||
nsMetrics.Data.Result = make([]map[string]interface{}, 1)
|
||||
nsMetrics.Data.Result[0] = resultItem
|
||||
return &nsMetrics
|
||||
}
|
||||
|
||||
// k8s component(controller, scheduler, etcd) status
|
||||
func MonitorComponentStatus(monitoringRequest *client.MonitoringRequestParams) *[]interface{} {
|
||||
componentList, err := client.NewK8sClient().CoreV1().ComponentStatuses().List(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Errorln(err.Error())
|
||||
}
|
||||
|
||||
var componentStatusList []*ComponentStatus
|
||||
for _, item := range componentList.Items {
|
||||
var status []OneComponentStatus
|
||||
for _, cond := range item.Conditions {
|
||||
status = append(status, OneComponentStatus{
|
||||
Type: string(cond.Type),
|
||||
Status: string(cond.Status),
|
||||
Message: cond.Message,
|
||||
Error: cond.Error,
|
||||
})
|
||||
}
|
||||
|
||||
componentStatusList = append(componentStatusList, &ComponentStatus{
|
||||
Name: item.Name,
|
||||
Namespace: item.Namespace,
|
||||
Labels: item.Labels,
|
||||
ComponentStatus: status,
|
||||
})
|
||||
}
|
||||
|
||||
// node status
|
||||
queryType := monitoringRequest.QueryType
|
||||
paramValues := monitoringRequest.Params
|
||||
paramValues.Set("query", NodeStatusRule)
|
||||
params := paramValues.Encode()
|
||||
res := client.SendMonitoringRequest(queryType, params)
|
||||
|
||||
nodeStatusMetric := ReformatJson(res, "node_status", nodeStatusDelLables...)
|
||||
nodeStatusMetric = ReformatNodeStatusField(nodeStatusMetric)
|
||||
|
||||
var normalNodes []string
|
||||
var abnormalNodes []string
|
||||
for _, result := range nodeStatusMetric.Data.Result {
|
||||
tmap := result[ResultItemMetric].(map[string]interface{})
|
||||
if tmap[MetricStatus].(string) == "false" {
|
||||
abnormalNodes = append(abnormalNodes, tmap[MetricLevelNode].(string))
|
||||
} else {
|
||||
normalNodes = append(normalNodes, tmap[MetricLevelNode].(string))
|
||||
}
|
||||
}
|
||||
|
||||
Components, err := models.GetAllComponentsStatus()
|
||||
|
||||
if err != nil {
|
||||
glog.Error(err.Error())
|
||||
}
|
||||
|
||||
var namspaceComponentHealthyMap = make(map[string]int)
|
||||
var namspaceComponentTotalMap = make(map[string]int)
|
||||
|
||||
for _, ns := range models.SYSTEM_NAMESPACES {
|
||||
nsStatus, exist := Components[ns]
|
||||
if exist {
|
||||
for _, nsStatusItem := range nsStatus.(map[string]interface{}) {
|
||||
component := nsStatusItem.(models.Component)
|
||||
namspaceComponentTotalMap[ns] += 1
|
||||
if component.HealthyBackends == component.TotalBackends {
|
||||
namspaceComponentHealthyMap[ns] += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
timestamp := int64(time.Now().Unix())
|
||||
|
||||
onlineMetricItems := makeMetricItems(timestamp, namspaceComponentHealthyMap, MetricLevelNamespace)
|
||||
metricItems := makeMetricItems(timestamp, namspaceComponentTotalMap, MetricLevelNamespace)
|
||||
|
||||
var assembleList []interface{}
|
||||
assembleList = append(assembleList, nodeStatusMetric)
|
||||
|
||||
for _, statusItem := range componentStatusList {
|
||||
assembleList = append(assembleList, statusItem)
|
||||
}
|
||||
|
||||
assembleList = append(assembleList, FormatedMetric{
|
||||
Data: FormatedMetricData{
|
||||
Result: *onlineMetricItems,
|
||||
ResultType: ResultTypeVector,
|
||||
},
|
||||
MetricName: MetricNameComponentOnLine,
|
||||
Status: MetricStatusSuccess,
|
||||
})
|
||||
|
||||
assembleList = append(assembleList, FormatedMetric{
|
||||
Data: FormatedMetricData{
|
||||
Result: *metricItems,
|
||||
ResultType: ResultTypeVector,
|
||||
},
|
||||
MetricName: MetricNameComponentLine,
|
||||
Status: MetricStatusSuccess,
|
||||
})
|
||||
|
||||
return &assembleList
|
||||
}
|
||||
|
||||
func makeMetricItems(timestamp int64, statusMap map[string]int, resourceType string) *[]map[string]interface{} {
|
||||
var metricItems []map[string]interface{}
|
||||
|
||||
for ns, count := range statusMap {
|
||||
metricItems = append(metricItems, map[string]interface{}{
|
||||
ResultItemMetric: map[string]string{resourceType: ns},
|
||||
ResultItemValue: []interface{}{timestamp, fmt.Sprintf("%d", count)},
|
||||
})
|
||||
}
|
||||
return &metricItems
|
||||
}
|
||||
|
||||
// monitor k8s event, there are two status: Normal, Warning
|
||||
func MonitorEvents(nsFilter string) *[]v1.Event {
|
||||
namespaceMap, err := getAllNamespace()
|
||||
if err != nil {
|
||||
glog.Errorln(err.Error())
|
||||
}
|
||||
var nsList = make([]string, 0)
|
||||
for ns, _ := range namespaceMap {
|
||||
nsList = append(nsList, ns)
|
||||
}
|
||||
|
||||
filterNS := filterNamespace(nsFilter, nsList)
|
||||
var eventsList = make([]v1.Event, 0)
|
||||
|
||||
for _, ns := range filterNS {
|
||||
events, err := client.NewK8sClient().CoreV1().Events(ns).List(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Errorln(err.Error())
|
||||
} else {
|
||||
for _, item := range events.Items {
|
||||
eventsList = append(eventsList, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
return &eventsList
|
||||
}
|
||||
|
||||
func AssembleClusterMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, metricName string) (string, string) {
|
||||
queryType := monitoringRequest.QueryType
|
||||
paramValues := monitoringRequest.Params
|
||||
rule := MakeClusterRule(metricName)
|
||||
params := makeRequestParamString(rule, paramValues)
|
||||
|
||||
return queryType, params
|
||||
}
|
||||
|
||||
func AssembleNodeMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, metricName string) (string, string) {
|
||||
queryType := monitoringRequest.QueryType
|
||||
paramValues := monitoringRequest.Params
|
||||
rule := MakeNodeRule(monitoringRequest.NodeId, monitoringRequest.NodesFilter, metricName)
|
||||
params := makeRequestParamString(rule, paramValues)
|
||||
|
||||
return queryType, params
|
||||
}
|
||||
|
||||
func getExistingNamespace(namespaces []string) ([]string, []string) {
|
||||
namespaceMap, err := getAllNamespace()
|
||||
var existedNS []string
|
||||
var noneExistedNS []string
|
||||
if err != nil {
|
||||
return namespaces, nil
|
||||
}
|
||||
for _, ns := range namespaces {
|
||||
if _, exist := namespaceMap[ns]; exist {
|
||||
existedNS = append(existedNS, ns)
|
||||
} else {
|
||||
noneExistedNS = append(noneExistedNS, ns)
|
||||
}
|
||||
}
|
||||
return existedNS, noneExistedNS
|
||||
}
|
||||
|
||||
func getAllNamespace() (map[string]int, error) {
|
||||
k8sClient := client.NewK8sClient()
|
||||
nsList, err := k8sClient.CoreV1().Namespaces().List(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Errorln(err.Error())
|
||||
return nil, err
|
||||
}
|
||||
namespaceMap := make(map[string]int)
|
||||
for _, item := range nsList.Items {
|
||||
namespaceMap[item.Name] = 0
|
||||
}
|
||||
return namespaceMap, nil
|
||||
}
|
||||
|
||||
func MonitorWorkloadCount(namespace string) *FormatedMetric {
|
||||
quotaMetric, err := models.GetNamespaceQuota(namespace)
|
||||
fMetric := convertQuota2MetricStruct(quotaMetric)
|
||||
|
||||
// whether the namespace in request parameters exists?
|
||||
namespaceMap, err := getAllNamespace()
|
||||
|
||||
_, exist := namespaceMap[namespace]
|
||||
if err != nil {
|
||||
exist = true
|
||||
}
|
||||
|
||||
if !exist || err != nil {
|
||||
fMetric.Status = MetricStatusError
|
||||
fMetric.Data.ResultType = ""
|
||||
errInfo := make(map[string]interface{})
|
||||
if err != nil {
|
||||
errInfo["errormsg"] = err.Error()
|
||||
} else {
|
||||
errInfo["errormsg"] = "namespace " + namespace + " does not exist"
|
||||
}
|
||||
fMetric.Data.Result = []map[string]interface{}{errInfo}
|
||||
}
|
||||
|
||||
return fMetric
|
||||
}
|
||||
|
||||
func convertQuota2MetricStruct(quotaMetric *models.ResourceQuota) *FormatedMetric {
|
||||
var fMetric FormatedMetric
|
||||
fMetric.MetricName = MetricNameWorkloadCount
|
||||
fMetric.Status = MetricStatusSuccess
|
||||
fMetric.Data.ResultType = ResultTypeVector
|
||||
timestamp := int64(time.Now().Unix())
|
||||
var resultItems []map[string]interface{}
|
||||
|
||||
hardMap := make(map[string]string)
|
||||
for resourceName, v := range quotaMetric.Data.Hard {
|
||||
hardMap[resourceName.String()] = v.String()
|
||||
}
|
||||
|
||||
for resourceName, v := range quotaMetric.Data.Used {
|
||||
resultItem := make(map[string]interface{})
|
||||
tmp := make(map[string]string)
|
||||
tmp[ResultItemMetricResource] = resourceName.String()
|
||||
resultItem[ResultItemMetric] = tmp
|
||||
resultItem[ResultItemValue] = []interface{}{timestamp, hardMap[resourceName.String()], v.String()}
|
||||
resultItems = append(resultItems, resultItem)
|
||||
}
|
||||
|
||||
fMetric.Data.Result = resultItems
|
||||
return &fMetric
|
||||
}
|
||||
@@ -1,539 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
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 metrics
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/golang/glog"
|
||||
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/api/core/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"sync"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
v12 "k8s.io/client-go/listers/core/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
"kubesphere.io/kubesphere/pkg/models/controllers"
|
||||
"kubesphere.io/kubesphere/pkg/models/workspaces"
|
||||
)
|
||||
|
||||
func getPodNameRegexInWorkload(request *restful.Request) string {
|
||||
promql := MakeWorkloadRule(request)
|
||||
res := client.SendPrometheusRequest(request, promql)
|
||||
data := []byte(res)
|
||||
var dat CommonMetricsResult
|
||||
jsonErr := json.Unmarshal(data, &dat)
|
||||
if jsonErr != nil {
|
||||
glog.Errorln("json parse failed", jsonErr)
|
||||
}
|
||||
var podNames []string
|
||||
for _, x := range dat.Data.Result {
|
||||
podName := x.KubePodMetric.Pod
|
||||
podNames = append(podNames, podName)
|
||||
}
|
||||
podNamesFilter := "^(" + strings.Join(podNames, "|") + ")$"
|
||||
return podNamesFilter
|
||||
}
|
||||
|
||||
func MonitorWorkloadSingleMetric(request *restful.Request, metricsName string) *FormatedMetric {
|
||||
nsName := strings.Trim(request.PathParameter("ns_name"), " ")
|
||||
podNamesFilter := getPodNameRegexInWorkload(request)
|
||||
newPromql := MakePodPromQL(request, []string{metricsName, nsName, "", "", podNamesFilter})
|
||||
podMetrics := client.SendPrometheusRequest(request, newPromql)
|
||||
cleanedJson := ReformatJson(podMetrics, metricsName)
|
||||
return cleanedJson
|
||||
}
|
||||
|
||||
func MonitorPodSingleMetric(request *restful.Request, metricsName string) *FormatedMetric {
|
||||
nsName := strings.Trim(request.PathParameter("ns_name"), " ")
|
||||
nodeID := strings.Trim(request.PathParameter("node_id"), " ")
|
||||
podName := strings.Trim(request.PathParameter("pod_name"), " ")
|
||||
podFilter := strings.Trim(request.QueryParameter("pods_filter"), " ")
|
||||
params := []string{metricsName, nsName, nodeID, podName, podFilter}
|
||||
promql := MakePodPromQL(request, params)
|
||||
if promql != "" {
|
||||
res := client.SendPrometheusRequest(request, promql)
|
||||
cleanedJson := ReformatJson(res, metricsName)
|
||||
return cleanedJson
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func MonitorNamespaceSingleMetric(request *restful.Request, metricsName string) *FormatedMetric {
|
||||
recordingRule := MakeNamespacePromQL(request, metricsName)
|
||||
res := client.SendPrometheusRequest(request, recordingRule)
|
||||
cleanedJson := ReformatJson(res, metricsName)
|
||||
return cleanedJson
|
||||
}
|
||||
|
||||
// maybe this function is time consuming
|
||||
func ReformatJson(metric string, metricsName string) *FormatedMetric {
|
||||
var formatMetric FormatedMetric
|
||||
err := json.Unmarshal([]byte(metric), &formatMetric)
|
||||
if err != nil {
|
||||
glog.Errorln("Unmarshal metric json failed", err)
|
||||
}
|
||||
if formatMetric.MetricName == "" {
|
||||
formatMetric.MetricName = metricsName
|
||||
}
|
||||
// retrive metrics success
|
||||
if formatMetric.Status == MetricStatusSuccess {
|
||||
result := formatMetric.Data.Result
|
||||
for _, res := range result {
|
||||
metric, ok := res[ResultItemMetric]
|
||||
me := metric.(map[string]interface{})
|
||||
if ok {
|
||||
delete(me, "__name__")
|
||||
}
|
||||
}
|
||||
}
|
||||
return &formatMetric
|
||||
}
|
||||
|
||||
func collectNodeorClusterMetrics(request *restful.Request, metricsName string, ch chan<- *FormatedMetric) {
|
||||
metric := MonitorNodeorClusterSingleMetric(request, metricsName)
|
||||
ch <- metric
|
||||
}
|
||||
|
||||
func collectNamespaceMetrics(request *restful.Request, metricsName string, ch chan<- *FormatedMetric) {
|
||||
metric := MonitorNamespaceSingleMetric(request, metricsName)
|
||||
ch <- metric
|
||||
}
|
||||
|
||||
func collectWorkloadMetrics(request *restful.Request, metricsName string, ch chan<- *FormatedMetric) {
|
||||
metricsName = strings.TrimLeft(metricsName, "workload_")
|
||||
metric := MonitorWorkloadSingleMetric(request, metricsName)
|
||||
ch <- metric
|
||||
}
|
||||
|
||||
func collectWorkspaceMetrics(request *restful.Request, metricsName string, namespaceList []string, ch chan<- *FormatedMetric) {
|
||||
mertic := monitorWorkspaceSingleMertic(request, metricsName, namespaceList)
|
||||
ch <- mertic
|
||||
}
|
||||
|
||||
func collectPodMetrics(request *restful.Request, metricsName string, ch chan<- *FormatedMetric) {
|
||||
metric := MonitorPodSingleMetric(request, metricsName)
|
||||
ch <- metric
|
||||
}
|
||||
|
||||
func monitorWorkspaceSingleMertic(request *restful.Request, metricsName string, namespaceList []string) *FormatedMetric {
|
||||
namespaceRe2 := "^(" + strings.Join(namespaceList, "|") + ")$"
|
||||
newpromql := MakeWorkspacePromQL(metricsName, namespaceRe2)
|
||||
podMetrics := client.SendPrometheusRequest(request, newpromql)
|
||||
cleanedJson := ReformatJson(podMetrics, metricsName)
|
||||
return cleanedJson
|
||||
}
|
||||
|
||||
func filterNamespace(request *restful.Request, namespaceList []string) []string {
|
||||
var newNSlist []string
|
||||
nsFilter := strings.Trim(request.QueryParameter("namespaces_filter"), " ")
|
||||
if nsFilter == "" {
|
||||
nsFilter = ".*"
|
||||
}
|
||||
for _, ns := range namespaceList {
|
||||
bol, _ := regexp.MatchString(nsFilter, ns)
|
||||
if bol {
|
||||
newNSlist = append(newNSlist, ns)
|
||||
}
|
||||
}
|
||||
return newNSlist
|
||||
}
|
||||
|
||||
func MonitorAllMetrics(request *restful.Request) FormatedLevelMetric {
|
||||
metricsName := strings.Trim(request.QueryParameter("metrics_filter"), " ")
|
||||
if metricsName == "" {
|
||||
metricsName = ".*"
|
||||
}
|
||||
path := request.SelectedRoutePath()
|
||||
sourceType := path[strings.LastIndex(path, "/")+1 : len(path)-1]
|
||||
if strings.Contains(path, MetricLevelWorkload) {
|
||||
sourceType = MetricLevelWorkload
|
||||
} else if strings.Contains(path, MetricLevelWorkspace) {
|
||||
sourceType = MetricLevelWorkspace
|
||||
}
|
||||
var ch = make(chan *FormatedMetric, 10)
|
||||
for _, metricName := range MetricsNames {
|
||||
bol, err := regexp.MatchString(metricsName, metricName)
|
||||
if !bol {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
glog.Errorln("regex match failed", err)
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(metricName, sourceType) {
|
||||
if sourceType == MetricLevelCluster || sourceType == MetricLevelNode {
|
||||
go collectNodeorClusterMetrics(request, metricName, ch)
|
||||
} else if sourceType == MetricLevelNamespace {
|
||||
go collectNamespaceMetrics(request, metricName, ch)
|
||||
} else if sourceType == MetricLevelPod {
|
||||
go collectPodMetrics(request, metricName, ch)
|
||||
} else if sourceType == MetricLevelWorkload {
|
||||
go collectWorkloadMetrics(request, metricName, ch)
|
||||
} else if sourceType == MetricLevelWorkspace {
|
||||
name := request.PathParameter("workspace_name")
|
||||
namespaces, err := workspaces.WorkspaceNamespaces(name)
|
||||
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
}
|
||||
namespaces = filterNamespace(request, namespaces)
|
||||
go collectWorkspaceMetrics(request, metricName, namespaces, ch)
|
||||
}
|
||||
}
|
||||
}
|
||||
var metricsArray []FormatedMetric
|
||||
var tempJson *FormatedMetric
|
||||
for _, k := range MetricsNames {
|
||||
bol, err := regexp.MatchString(metricsName, k)
|
||||
if !bol {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
glog.Errorln("regex match failed")
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(k, sourceType) {
|
||||
tempJson = <-ch
|
||||
if tempJson != nil {
|
||||
metricsArray = append(metricsArray, *tempJson)
|
||||
}
|
||||
}
|
||||
}
|
||||
return FormatedLevelMetric{
|
||||
MetricsLevel: sourceType,
|
||||
Results: metricsArray,
|
||||
}
|
||||
}
|
||||
|
||||
func MonitorWorkspaceUserInfo(req *restful.Request) FormatedLevelMetric {
|
||||
|
||||
var metricsArray []FormatedMetric
|
||||
timestamp := time.Now().Unix()
|
||||
|
||||
wg := sync.WaitGroup{}
|
||||
var orgResultItem FormatedMetric
|
||||
var dvpResultItem FormatedMetric
|
||||
var projResultItem FormatedMetric
|
||||
var actResultItem FormatedMetric
|
||||
|
||||
wg.Add(4)
|
||||
|
||||
go func() {
|
||||
orgNums, errOrg := workspaces.GetAllOrgNums()
|
||||
orgResultItem = getSpecificMetricItem(timestamp, MetricNameWorkspaceAllOrganizationCount, WorkspaceResourceKindOrganization, orgNums, errOrg)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
devOpsProjectNums, errDevops := workspaces.GetAllDevOpsProjectsNums()
|
||||
dvpResultItem = getSpecificMetricItem(timestamp, MetricNameWorkspaceAllDevopsCount, WorkspaceResourceKindDevops, devOpsProjectNums, errDevops)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
projNums, errProj := workspaces.GetAllProjectNums()
|
||||
projResultItem = getSpecificMetricItem(timestamp, MetricNameWorkspaceAllProjectCount, WorkspaceResourceKindNamespace, projNums, errProj)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
actNums, errAct := workspaces.GetAllAccountNums()
|
||||
actResultItem = getSpecificMetricItem(timestamp, MetricNameWorkspaceAllAccountCount, WorkspaceResourceKindAccount, actNums, errAct)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
metricsArray = append(metricsArray, orgResultItem, dvpResultItem, projResultItem, actResultItem)
|
||||
|
||||
return FormatedLevelMetric{
|
||||
MetricsLevel: MetricLevelWorkspace,
|
||||
Results: metricsArray,
|
||||
}
|
||||
}
|
||||
|
||||
//func getWorkspaceMetricItem(timestamp int64, namespaceNums int64, resourceName string, err error) FormatedMetric {
|
||||
// var fMetric FormatedMetric
|
||||
// fMetric.Data.ResultType = ResultTypeVector
|
||||
// fMetric.MetricName = MetricNameWorkspaceInfoCount
|
||||
// fMetric.Status = MetricStatusSuccess
|
||||
// if err != nil {
|
||||
// fMetric.Status = MetricStatusError
|
||||
// }
|
||||
// resultItem := make(map[string]interface{})
|
||||
// tmp := make(map[string]string)
|
||||
// tmp[ResultItemMetricResource] = resourceName
|
||||
// resultItem[ResultItemMetric] = tmp
|
||||
// resultItem[ResultItemValue] = []interface{}{timestamp, strconv.FormatInt(namespaceNums, 10)}
|
||||
// return fMetric
|
||||
//}
|
||||
|
||||
func MonitorWorkspaceResourceLevelMetrics(request *restful.Request) FormatedLevelMetric {
|
||||
wsName := request.PathParameter("workspace_name")
|
||||
namspaces, errNs := workspaces.WorkspaceNamespaces(wsName)
|
||||
|
||||
devOpsProjects, errDevOps := workspaces.GetDevOpsProjects(wsName)
|
||||
members, errMemb := workspaces.GetOrgMembers(wsName)
|
||||
roles, errRole := workspaces.GetOrgRoles(wsName)
|
||||
|
||||
var fMetricsArray []FormatedMetric
|
||||
timestamp := int64(time.Now().Unix())
|
||||
namespaces, noneExistentNs := getExistingNamespace(namspaces)
|
||||
if len(noneExistentNs) != 0 {
|
||||
nsStr := strings.Join(noneExistentNs, "|")
|
||||
errStr := "the namespaces " + nsStr + " do not exist"
|
||||
if errNs == nil {
|
||||
errNs = errors.New(errStr)
|
||||
} else {
|
||||
errNs = errors.New(errNs.Error() + "\t" + errStr)
|
||||
}
|
||||
}
|
||||
|
||||
// add namespaces(project) metric
|
||||
nsMetrics := getSpecificMetricItem(timestamp, MetricNameWorkspaceNamespaceCount, WorkspaceResourceKindNamespace, len(namespaces), errNs)
|
||||
// add devops metric
|
||||
devopsMetrics := getSpecificMetricItem(timestamp, MetricNameWorkspaceDevopsCount, WorkspaceResourceKindDevops, len(devOpsProjects), errDevOps)
|
||||
// add member metric
|
||||
memberMetrics := getSpecificMetricItem(timestamp, MetricNameWorkspaceMemberCount, WorkspaceResourceKindMember, len(members), errMemb)
|
||||
// add role metric
|
||||
roleMetrics := getSpecificMetricItem(timestamp, MetricNameWorkspaceRoleCount, WorkspaceResourceKindRole, len(roles), errRole)
|
||||
// add workloads count metric
|
||||
wlMetrics := getWorkspaceWorkloadCountMetrics(namespaces)
|
||||
// add pods count metric
|
||||
podsCountMetrics := getWorkspacePodsCountMetrics(request, namespaces)
|
||||
fMetricsArray = append(fMetricsArray, nsMetrics, devopsMetrics, memberMetrics, roleMetrics, wlMetrics, *podsCountMetrics)
|
||||
|
||||
return FormatedLevelMetric{
|
||||
MetricsLevel: MetricLevelWorkspace,
|
||||
Results: fMetricsArray,
|
||||
}
|
||||
}
|
||||
|
||||
func getWorkspacePodsCountMetrics(request *restful.Request, namespaces []string) *FormatedMetric {
|
||||
metricName := MetricNameNamespacePodCount
|
||||
var recordingRule = RulePromQLTmplMap[metricName]
|
||||
nsFilter := "^(" + strings.Join(namespaces, "|") + ")$"
|
||||
recordingRule = strings.Replace(recordingRule, "$1", nsFilter, -1)
|
||||
res := client.SendPrometheusRequest(request, recordingRule)
|
||||
cleanedJson := ReformatJson(res, metricName)
|
||||
return cleanedJson
|
||||
}
|
||||
|
||||
func getWorkspaceWorkloadCountMetrics(namespaces []string) FormatedMetric {
|
||||
var wlQuotaMetrics models.ResourceQuota
|
||||
wlQuotaMetrics.NameSpace = strings.Join(namespaces, "|")
|
||||
wlQuotaMetrics.Data.Used = make(v1.ResourceList, 1)
|
||||
wlQuotaMetrics.Data.Hard = make(v1.ResourceList, 1)
|
||||
for _, ns := range namespaces {
|
||||
quotaMetric, err := models.GetNamespaceQuota(ns)
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
continue
|
||||
}
|
||||
// sum all resources used along namespaces
|
||||
quotaUsed := quotaMetric.Data.Used
|
||||
for resourceName, quantity := range quotaUsed {
|
||||
if _, ok := wlQuotaMetrics.Data.Used[resourceName]; ok {
|
||||
tmpQuantity := wlQuotaMetrics.Data.Used[v1.ResourceName(resourceName)]
|
||||
tmpQuantity.Add(quantity)
|
||||
wlQuotaMetrics.Data.Used[v1.ResourceName(resourceName)] = tmpQuantity
|
||||
} else {
|
||||
wlQuotaMetrics.Data.Used[v1.ResourceName(resourceName)] = quantity.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
// sum all resources hard along namespaces
|
||||
quotaHard := quotaMetric.Data.Hard
|
||||
for resourceName, quantity := range quotaHard {
|
||||
if _, ok := wlQuotaMetrics.Data.Hard[resourceName]; ok {
|
||||
tmpQuantity := wlQuotaMetrics.Data.Hard[v1.ResourceName(resourceName)]
|
||||
tmpQuantity.Add(quantity)
|
||||
wlQuotaMetrics.Data.Hard[v1.ResourceName(resourceName)] = tmpQuantity
|
||||
} else {
|
||||
wlQuotaMetrics.Data.Hard[v1.ResourceName(resourceName)] = quantity.DeepCopy()
|
||||
}
|
||||
}
|
||||
}
|
||||
wlMetrics := convertQuota2MetricStruct(&wlQuotaMetrics)
|
||||
return wlMetrics
|
||||
}
|
||||
|
||||
func getSpecificMetricItem(timestamp int64, metricName string, kind string, count int, err error) FormatedMetric {
|
||||
var nsMetrics FormatedMetric
|
||||
nsMetrics.MetricName = metricName
|
||||
nsMetrics.Data.ResultType = ResultTypeVector
|
||||
resultItem := make(map[string]interface{})
|
||||
tmp := make(map[string]string)
|
||||
tmp[ResultItemMetricResource] = kind
|
||||
if err == nil {
|
||||
nsMetrics.Status = MetricStatusSuccess
|
||||
} else {
|
||||
nsMetrics.Status = MetricStatusError
|
||||
resultItem["errorinfo"] = err.Error()
|
||||
}
|
||||
|
||||
resultItem[ResultItemMetric] = tmp
|
||||
resultItem[ResultItemValue] = []interface{}{timestamp, count}
|
||||
nsMetrics.Data.Result = make([]map[string]interface{}, 1)
|
||||
nsMetrics.Data.Result[0] = resultItem
|
||||
return nsMetrics
|
||||
}
|
||||
|
||||
func MonitorNodeorClusterSingleMetric(request *restful.Request, metricsName string) *FormatedMetric {
|
||||
// support cluster node statistic, include healthy nodes and unhealthy nodes
|
||||
var res string
|
||||
var fMetric FormatedMetric
|
||||
timestamp := int64(time.Now().Unix())
|
||||
|
||||
if metricsName == "cluster_node_online" {
|
||||
onlineNodes, _ := getNodeHealthyConditionMetric()
|
||||
fMetric = getSpecificMetricItem(timestamp, MetricNameClusterHealthyNodeCount, "node_count", len(onlineNodes), nil)
|
||||
} else if metricsName == "cluster_node_offline" {
|
||||
_, offlineNodes := getNodeHealthyConditionMetric()
|
||||
fMetric = getSpecificMetricItem(timestamp, MetricNameClusterUnhealthyNodeCount, "node_count", len(offlineNodes), nil)
|
||||
} else if metricsName == "cluster_node_total" {
|
||||
onlineNodes, offlineNodes := getNodeHealthyConditionMetric()
|
||||
fMetric = getSpecificMetricItem(timestamp, MetricNameClusterNodeCount, "node_count", len(onlineNodes)+len(offlineNodes), nil)
|
||||
} else {
|
||||
recordingRule := MakeNodeorClusterRule(request, metricsName)
|
||||
res = client.SendPrometheusRequest(request, recordingRule)
|
||||
fMetric = *ReformatJson(res, metricsName)
|
||||
}
|
||||
return &fMetric
|
||||
}
|
||||
|
||||
func getNodeHealthyConditionMetric() ([]string, []string) {
|
||||
nodeList, err := client.NewK8sClient().CoreV1().Nodes().List(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
return nil, nil
|
||||
}
|
||||
var onlineNodes []string
|
||||
var offlineNodes []string
|
||||
for _, node := range nodeList.Items {
|
||||
nodeName := node.Labels["kubernetes.io/hostname"]
|
||||
nodeRole := node.Labels["role"]
|
||||
bol := true
|
||||
for _, cond := range node.Status.Conditions {
|
||||
if cond.Type == "Ready" && cond.Status == "Unknown" {
|
||||
bol = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if nodeRole != "log" {
|
||||
if bol {
|
||||
// reachable node
|
||||
onlineNodes = append(onlineNodes, nodeName)
|
||||
} else {
|
||||
// unreachable node
|
||||
offlineNodes = append(offlineNodes, nodeName)
|
||||
}
|
||||
}
|
||||
}
|
||||
return onlineNodes, offlineNodes
|
||||
}
|
||||
|
||||
func getExistingNamespace(namespaces []string) ([]string, []string) {
|
||||
namespaceMap, err := getAllNamespace()
|
||||
var existedNs []string
|
||||
var noneExistedNs []string
|
||||
if err != nil {
|
||||
return namespaces, nil
|
||||
}
|
||||
for _, ns := range namespaces {
|
||||
if _, ok := namespaceMap[ns]; ok {
|
||||
existedNs = append(existedNs, ns)
|
||||
} else {
|
||||
noneExistedNs = append(noneExistedNs, ns)
|
||||
}
|
||||
}
|
||||
return existedNs, noneExistedNs
|
||||
}
|
||||
|
||||
func getAllNamespace() (map[string]int, error) {
|
||||
lister := controllers.ResourceControllers.Controllers[controllers.Namespaces].Lister().(v12.NamespaceLister)
|
||||
nsList, err := lister.List(labels.Everything())
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
namespaceMap := make(map[string]int)
|
||||
for _, item := range nsList {
|
||||
namespaceMap[item.Name] = 0
|
||||
}
|
||||
return namespaceMap, nil
|
||||
}
|
||||
|
||||
func MonitorWorkloadCount(request *restful.Request) FormatedMetric {
|
||||
namespace := strings.Trim(request.PathParameter("ns_name"), " ")
|
||||
|
||||
quotaMetric, err := models.GetNamespaceQuota(namespace)
|
||||
fMetric := convertQuota2MetricStruct(quotaMetric)
|
||||
|
||||
// whether the namespace in request parameters exists?
|
||||
namespaceMap, e := getAllNamespace()
|
||||
_, ok := namespaceMap[namespace]
|
||||
if e != nil {
|
||||
ok = true
|
||||
}
|
||||
if !ok || err != nil {
|
||||
fMetric.Status = MetricStatusError
|
||||
fMetric.Data.ResultType = ""
|
||||
errInfo := make(map[string]interface{})
|
||||
if err != nil {
|
||||
errInfo["errormsg"] = err.Error()
|
||||
} else {
|
||||
errInfo["errormsg"] = "namespace " + namespace + " does not exist"
|
||||
}
|
||||
fMetric.Data.Result = []map[string]interface{}{errInfo}
|
||||
}
|
||||
|
||||
return fMetric
|
||||
}
|
||||
|
||||
func convertQuota2MetricStruct(quotaMetric *models.ResourceQuota) FormatedMetric {
|
||||
var fMetric FormatedMetric
|
||||
fMetric.MetricName = MetricNameWorkloadCount
|
||||
fMetric.Status = MetricStatusSuccess
|
||||
fMetric.Data.ResultType = ResultTypeVector
|
||||
timestamp := int64(time.Now().Unix())
|
||||
var resultItems []map[string]interface{}
|
||||
|
||||
hardMap := make(map[string]string)
|
||||
for resourceName, v := range quotaMetric.Data.Hard {
|
||||
hardMap[resourceName.String()] = v.String()
|
||||
}
|
||||
|
||||
for resourceName, v := range quotaMetric.Data.Used {
|
||||
resultItem := make(map[string]interface{})
|
||||
tmp := make(map[string]string)
|
||||
tmp[ResultItemMetricResource] = resourceName.String()
|
||||
resultItem[ResultItemMetric] = tmp
|
||||
resultItem[ResultItemValue] = []interface{}{timestamp, hardMap[resourceName.String()], v.String()}
|
||||
resultItems = append(resultItems, resultItem)
|
||||
}
|
||||
|
||||
fMetric.Data.Result = resultItems
|
||||
return fMetric
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
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 metrics
|
||||
|
||||
const (
|
||||
ResultTypeVector = "vector"
|
||||
ResultTypeMatrix = "matrix"
|
||||
MetricStatusError = "error"
|
||||
MetricStatusSuccess = "success"
|
||||
ResultItemMetric = "metric"
|
||||
ResultItemMetricResource = "resource"
|
||||
ResultItemValue = "value"
|
||||
)
|
||||
|
||||
const (
|
||||
MetricNameWorkloadCount = "workload_count"
|
||||
MetricNameNamespacePodCount = "namespace_pod_count"
|
||||
|
||||
MetricNameWorkspaceAllOrganizationCount = "workspace_all_organization_count"
|
||||
MetricNameWorkspaceAllAccountCount = "workspace_all_account_count"
|
||||
MetricNameWorkspaceAllProjectCount = "workspace_all_project_count"
|
||||
MetricNameWorkspaceAllDevopsCount = "workspace_all_devops_project_count"
|
||||
|
||||
MetricNameWorkspaceNamespaceCount = "workspace_namespace_count"
|
||||
MetricNameWorkspaceDevopsCount = "workspace_devops_project_count"
|
||||
MetricNameWorkspaceMemberCount = "workspace_member_count"
|
||||
MetricNameWorkspaceRoleCount = "workspace_role_count"
|
||||
|
||||
MetricNameClusterHealthyNodeCount = "cluster_node_online"
|
||||
MetricNameClusterUnhealthyNodeCount = "cluster_node_offline"
|
||||
MetricNameClusterNodeCount = "cluster_node_total"
|
||||
)
|
||||
|
||||
const (
|
||||
WorkspaceResourceKindOrganization = "organization"
|
||||
WorkspaceResourceKindAccount = "account"
|
||||
WorkspaceResourceKindNamespace = "namespace"
|
||||
WorkspaceResourceKindDevops = "devops"
|
||||
WorkspaceResourceKindMember = "member"
|
||||
WorkspaceResourceKindRole = "role"
|
||||
)
|
||||
|
||||
const (
|
||||
MetricLevelCluster = "cluster"
|
||||
MetricLevelNode = "node"
|
||||
MetricLevelWorkspace = "workspace"
|
||||
MetricLevelNamespace = "namespace"
|
||||
MetricLevelPod = "pod"
|
||||
MetricLevelContainer = "container"
|
||||
MetricLevelWorkload = "workload"
|
||||
)
|
||||
|
||||
type MetricMap map[string]string
|
||||
|
||||
var MetricsNames = []string{
|
||||
"cluster_cpu_utilisation",
|
||||
"cluster_cpu_usage",
|
||||
"cluster_cpu_total",
|
||||
"cluster_memory_utilisation",
|
||||
"cluster_pod_count",
|
||||
"cluster_memory_bytes_available",
|
||||
"cluster_memory_bytes_total",
|
||||
"cluster_memory_bytes_usage",
|
||||
"cluster_net_utilisation",
|
||||
"cluster_net_bytes_transmitted",
|
||||
"cluster_net_bytes_received",
|
||||
"cluster_disk_read_iops",
|
||||
"cluster_disk_write_iops",
|
||||
"cluster_disk_read_throughput",
|
||||
"cluster_disk_write_throughput",
|
||||
"cluster_disk_size_usage",
|
||||
"cluster_disk_size_utilisation",
|
||||
"cluster_disk_size_capacity",
|
||||
"cluster_disk_size_available",
|
||||
"cluster_node_online",
|
||||
"cluster_node_offline",
|
||||
"cluster_node_total",
|
||||
|
||||
"node_cpu_utilisation",
|
||||
"node_cpu_total",
|
||||
"node_cpu_usage",
|
||||
"node_memory_utilisation",
|
||||
"node_memory_bytes_usage",
|
||||
"node_memory_bytes_available",
|
||||
"node_memory_bytes_total",
|
||||
"node_net_utilisation",
|
||||
"node_net_bytes_transmitted",
|
||||
"node_net_bytes_received",
|
||||
"node_disk_read_iops",
|
||||
"node_disk_write_iops",
|
||||
"node_disk_read_throughput",
|
||||
"node_disk_write_throughput",
|
||||
"node_disk_size_capacity",
|
||||
"node_disk_size_available",
|
||||
"node_disk_size_usage",
|
||||
"node_disk_size_utilisation",
|
||||
"node_pod_count",
|
||||
"node_pod_quota",
|
||||
|
||||
"namespace_cpu_usage",
|
||||
"namespace_memory_usage",
|
||||
"namespace_memory_usage_wo_cache",
|
||||
"namespace_net_bytes_transmitted",
|
||||
"namespace_net_bytes_received",
|
||||
"namespace_pod_count",
|
||||
|
||||
"pod_cpu_usage",
|
||||
"pod_memory_usage",
|
||||
"pod_memory_usage_wo_cache",
|
||||
"pod_net_bytes_transmitted",
|
||||
"pod_net_bytes_received",
|
||||
|
||||
"workload_pod_cpu_usage",
|
||||
"workload_pod_memory_usage",
|
||||
"workload_pod_memory_usage_wo_cache",
|
||||
"workload_pod_net_bytes_transmitted",
|
||||
"workload_pod_net_bytes_received",
|
||||
//"container_cpu_usage",
|
||||
//"container_memory_usage_wo_cache",
|
||||
//"container_memory_usage",
|
||||
|
||||
"workspace_cpu_usage",
|
||||
"workspace_memory_usage",
|
||||
"workspace_memory_usage_wo_cache",
|
||||
"workspace_net_bytes_transmitted",
|
||||
"workspace_net_bytes_received",
|
||||
"workspace_pod_count",
|
||||
}
|
||||
|
||||
var RulePromQLTmplMap = MetricMap{
|
||||
//cluster
|
||||
"cluster_cpu_utilisation": ":node_cpu_utilisation:avg1m",
|
||||
"cluster_cpu_usage": `sum (irate(container_cpu_usage_seconds_total{job="kubelet", image!=""}[5m]))`,
|
||||
"cluster_cpu_total": "sum(node:node_num_cpu:sum)",
|
||||
"cluster_memory_utilisation": ":node_memory_utilisation:",
|
||||
"cluster_pod_count": `count(kube_pod_info unless on(pod) kube_pod_completion_time unless on(node) kube_node_labels{label_role="log"})`,
|
||||
"cluster_memory_bytes_available": "sum(node:node_memory_bytes_available:sum)",
|
||||
"cluster_memory_bytes_total": "sum(node:node_memory_bytes_total:sum)",
|
||||
"cluster_memory_bytes_usage": "sum(node:node_memory_bytes_total:sum) - sum(node:node_memory_bytes_available:sum)",
|
||||
"cluster_net_utilisation": ":node_net_utilisation:sum_irate",
|
||||
"cluster_net_bytes_transmitted": "sum(node:node_net_bytes_transmitted:sum_irate)",
|
||||
"cluster_net_bytes_received": "sum(node:node_net_bytes_received:sum_irate)",
|
||||
"cluster_disk_read_iops": "sum(node:data_volume_iops_reads:sum)",
|
||||
"cluster_disk_write_iops": "sum(node:data_volume_iops_writes:sum)",
|
||||
"cluster_disk_read_throughput": "sum(node:data_volume_throughput_bytes_read:sum)",
|
||||
"cluster_disk_write_throughput": "sum(node:data_volume_throughput_bytes_written:sum)",
|
||||
"cluster_disk_size_usage": `sum(sum by (node) ((node_filesystem_size{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:)) - sum(sum by (node) ((node_filesystem_avail{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:))`,
|
||||
"cluster_disk_size_utilisation": `(sum(sum by (node) ((node_filesystem_size{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:)) - sum(sum by (node) ((node_filesystem_avail{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:))) / sum(sum by (node) ((node_filesystem_size{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:))`,
|
||||
"cluster_disk_size_capacity": `sum(sum by (node) ((node_filesystem_size{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:))`,
|
||||
"cluster_disk_size_available": `sum(sum by (node) ((node_filesystem_avail{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:))`,
|
||||
|
||||
//node
|
||||
"node_cpu_utilisation": "node:node_cpu_utilisation:avg1m",
|
||||
"node_cpu_total": "node:node_num_cpu:sum",
|
||||
"node_memory_utilisation": "node:node_memory_utilisation:",
|
||||
"node_memory_bytes_available": "node:node_memory_bytes_available:sum",
|
||||
"node_memory_bytes_total": "node:node_memory_bytes_total:sum",
|
||||
// Node network utilisation (bytes received + bytes transmitted per second)
|
||||
"node_net_utilisation": "node:node_net_utilisation:sum_irate",
|
||||
// Node network bytes transmitted per second
|
||||
"node_net_bytes_transmitted": "node:node_net_bytes_transmitted:sum_irate",
|
||||
// Node network bytes received per second
|
||||
"node_net_bytes_received": "node:node_net_bytes_received:sum_irate",
|
||||
|
||||
// node:data_volume_iops_reads:sum{node=~"i-5xcldxos|i-6soe9zl1"}
|
||||
"node_disk_read_iops": "node:data_volume_iops_reads:sum",
|
||||
// node:data_volume_iops_writes:sum{node=~"i-5xcldxos|i-6soe9zl1"}
|
||||
"node_disk_write_iops": "node:data_volume_iops_writes:sum",
|
||||
// node:data_volume_throughput_bytes_read:sum{node=~"i-5xcldxos|i-6soe9zl1"}
|
||||
"node_disk_read_throughput": "node:data_volume_throughput_bytes_read:sum",
|
||||
// node:data_volume_throughput_bytes_written:sum{node=~"i-5xcldxos|i-6soe9zl1"}
|
||||
"node_disk_write_throughput": "node:data_volume_throughput_bytes_written:sum",
|
||||
|
||||
"node_disk_size_capacity": `sum by (node) ((node_filesystem_size{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1)`,
|
||||
"node_disk_size_available": `sum by (node) ((node_filesystem_avail{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1)`,
|
||||
"node_disk_size_usage": `sum by (node) ((node_filesystem_size{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1) -sum by (node) ((node_filesystem_avail{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1)`,
|
||||
"node_disk_size_utilisation": `sum by (node) (((node_filesystem_size{mountpoint="/", job="node-exporter"} - node_filesystem_avail{mountpoint="/", job="node-exporter"}) / node_filesystem_size{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1)`,
|
||||
"node_pod_count": `count(kube_pod_info$1 unless on(pod) kube_pod_completion_time) by (node)`,
|
||||
// without log node: unless on(node) kube_node_labels{label_role="log"}
|
||||
"node_pod_quota": `sum(kube_node_status_capacity_pods$1) by (node)`,
|
||||
"node_cpu_usage": `sum by (node) (label_join(irate(container_cpu_usage_seconds_total{job="kubelet", image!=""}[5m]), "pod", " ", "pod_name") * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1)`,
|
||||
"node_memory_bytes_usage": "node:node_memory_bytes_total:sum$1 - node:node_memory_bytes_available:sum$1",
|
||||
|
||||
//namespace
|
||||
"namespace_cpu_usage": `namespace:container_cpu_usage_seconds_total:sum_rate{namespace=~"$1"}`,
|
||||
"namespace_memory_usage": `namespace:container_memory_usage_bytes:sum{namespace=~"$1"}`,
|
||||
"namespace_memory_usage_wo_cache": `namespace:container_memory_usage_bytes_wo_cache:sum{namespace=~"$1"}`,
|
||||
"namespace_net_bytes_transmitted": `sum by (namespace) (irate(container_network_transmit_bytes_total{namespace=~"$1", pod_name!="", interface="eth0", job="kubelet"}[5m]))`,
|
||||
"namespace_net_bytes_received": `sum by (namespace) (irate(container_network_receive_bytes_total{namespace=~"$1", pod_name!="", interface="eth0", job="kubelet"}[5m]))`,
|
||||
"namespace_pod_count": `count(kube_pod_info{namespace=~"$1"} unless on(pod) kube_pod_completion_time) by (namespace)`,
|
||||
|
||||
// pod
|
||||
"pod_cpu_usage": `sum(irate(container_cpu_usage_seconds_total{job="kubelet", namespace="$1", pod_name="$2", image!=""}[5m])) by (namespace, pod_name)`,
|
||||
"pod_memory_usage": `sum(container_memory_usage_bytes{job="kubelet", namespace="$1", pod_name="$2", image!=""}) by (namespace, pod_name)`,
|
||||
"pod_memory_usage_wo_cache": `sum(container_memory_usage_bytes{job="kubelet", namespace="$1", pod_name="$2", image!=""} - container_memory_cache{job="kubelet", namespace="$1", pod_name="$2",image!=""}) by (namespace, pod_name)`,
|
||||
"pod_net_bytes_transmitted": `sum by (namespace, pod_name) (irate(container_network_transmit_bytes_total{namespace="$1", pod_name!="", pod_name="$2", interface="eth0", job="kubelet"}[5m]))`,
|
||||
"pod_net_bytes_received": `sum by (namespace, pod_name) (irate(container_network_receive_bytes_total{namespace="$1", pod_name!="", pod_name="$2", interface="eth0", job="kubelet"}[5m]))`,
|
||||
|
||||
"pod_cpu_usage_all": `sum(irate(container_cpu_usage_seconds_total{job="kubelet", namespace="$1", pod_name=~"$2", image!=""}[5m])) by (namespace, pod_name)`,
|
||||
"pod_memory_usage_all": `sum(container_memory_usage_bytes{job="kubelet", namespace="$1", pod_name=~"$2", image!=""}) by (namespace, pod_name)`,
|
||||
"pod_memory_usage_wo_cache_all": `sum(container_memory_usage_bytes{job="kubelet", namespace="$1", pod_name=~"$2", image!=""} - container_memory_cache{job="kubelet", namespace="$1", pod_name=~"$2", image!=""}) by (namespace, pod_name)`,
|
||||
"pod_net_bytes_transmitted_all": `sum by (namespace, pod_name) (irate(container_network_transmit_bytes_total{namespace="$1", pod_name!="", pod_name=~"$2", interface="eth0", job="kubelet"}[5m]))`,
|
||||
"pod_net_bytes_received_all": `sum by (namespace, pod_name) (irate(container_network_receive_bytes_total{namespace="$1", pod_name!="", pod_name=~"$2", interface="eth0", job="kubelet"}[5m]))`,
|
||||
|
||||
"pod_cpu_usage_node": `sum by (node, pod) (label_join(irate(container_cpu_usage_seconds_total{job="kubelet",pod_name=~"$2", image!=""}[5m]), "pod", " ", "pod_name") * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:{node=~"$3"})`,
|
||||
"pod_memory_usage_node": `sum by (node, pod) (label_join(container_memory_usage_bytes{job="kubelet",pod_name=~"$2", image!=""}, "pod", " ", "pod_name") * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:{node=~"$3"})`,
|
||||
"pod_memory_usage_wo_cache_node": `sum by (node, pod) ((label_join(container_memory_usage_bytes{job="kubelet",pod_name=~"$2", image!=""}, "pod", " ", "pod_name") - label_join(container_memory_cache{job="kubelet",pod_name=~"$2", image!=""}, "pod", " ", "pod_name")) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:{node=~"$3"})`,
|
||||
|
||||
// container
|
||||
"container_cpu_usage": `sum(irate(container_cpu_usage_seconds_total{namespace="$1", pod_name="$2", container_name="$3"}[5m])) by (namespace, pod_name, container_name)`,
|
||||
"container_cpu_usage_all": `sum(irate(container_cpu_usage_seconds_total{namespace="$1", pod_name="$2", container_name=~"$3", container_name!="POD"}[5m])) by (namespace, pod_name, container_name)`,
|
||||
|
||||
"container_memory_usage_wo_cache": `container_memory_usage_bytes{namespace="$1", pod_name="$2", container_name="$3"} - ignoring(id, image, endpoint, instance, job, name, service) container_memory_cache{namespace="$1", pod_name="$2", container_name="$3"}`,
|
||||
"container_memory_usage_wo_cache_all": `container_memory_usage_bytes{namespace="$1", pod_name="$2", container_name=~"$3", container_name!="POD"} - ignoring(id, image, endpoint, instance, job, name, service) container_memory_cache{namespace="$1", pod_name="$2", container_name=~"$3", container_name!="POD"}`,
|
||||
"container_memory_usage": `container_memory_usage_bytes{namespace="$1", pod_name="$2", container_name="$3"}`,
|
||||
"container_memory_usage_all": `container_memory_usage_bytes{namespace="$1", pod_name="$2", container_name=~"$3", container_name!="POD"}`,
|
||||
|
||||
// enterprise
|
||||
"workspace_cpu_usage": `sum(namespace:container_cpu_usage_seconds_total:sum_rate{namespace =~"$1"})`,
|
||||
"workspace_memory_usage": `sum(namespace:container_memory_usage_bytes:sum{namespace =~"$1"})`,
|
||||
"workspace_memory_usage_wo_cache": `sum(namespace:container_memory_usage_bytes_wo_cache:sum{namespace =~"$1"})`,
|
||||
"workspace_net_bytes_transmitted": `sum(sum by (namespace) (irate(container_network_transmit_bytes_total{namespace=~"$1", pod_name!="", interface="eth0", job="kubelet"}[5m])))`,
|
||||
"workspace_net_bytes_received": `sum(sum by (namespace) (irate(container_network_receive_bytes_total{namespace=~"$1", pod_name!="", interface="eth0", job="kubelet"}[5m])))`,
|
||||
"workspace_pod_count": `sum(count(kube_pod_info{namespace=~"$1"} unless on(pod) kube_pod_completion_time) by (namespace))`,
|
||||
}
|
||||
@@ -15,142 +15,119 @@ package metrics
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
)
|
||||
|
||||
func MakeWorkloadRule(request *restful.Request) string {
|
||||
// kube_pod_info{created_by_kind="DaemonSet",created_by_name="fluent-bit",endpoint="https-main",
|
||||
// host_ip="192.168.0.14",instance="10.244.114.187:8443",job="kube-state-metrics",
|
||||
// namespace="kube-system",node="i-k89a62il",pod="fluent-bit-l5vxr",
|
||||
// pod_ip="10.244.114.175",service="kube-state-metrics"}
|
||||
rule := `kube_pod_info{created_by_kind="$1",created_by_name=$2,namespace="$3"}`
|
||||
kind := strings.Trim(request.PathParameter("workload_kind"), " ")
|
||||
name := strings.Trim(request.QueryParameter("workload_name"), " ")
|
||||
namespace := strings.Trim(request.PathParameter("ns_name"), " ")
|
||||
func MakeWorkloadRule(wkKind, wkName, namespace string) string {
|
||||
var rule = PodInfoRule
|
||||
if namespace == "" {
|
||||
namespace = ".*"
|
||||
}
|
||||
// alertnatives values: Deployment StatefulSet ReplicaSet DaemonSet
|
||||
wkKind = strings.ToLower(wkKind)
|
||||
|
||||
// kind alertnatives values: Deployment StatefulSet ReplicaSet DaemonSet
|
||||
kind = strings.ToLower(kind)
|
||||
|
||||
switch kind {
|
||||
switch wkKind {
|
||||
case "deployment":
|
||||
kind = "ReplicaSet"
|
||||
if name != "" {
|
||||
name = "~\"" + name + ".*\""
|
||||
wkKind = ReplicaSet
|
||||
if wkName != "" {
|
||||
wkName = "~\"" + wkName + ".*\""
|
||||
} else {
|
||||
name = "~\".*\""
|
||||
wkName = "~\".*\""
|
||||
}
|
||||
rule = strings.Replace(rule, "$1", kind, -1)
|
||||
rule = strings.Replace(rule, "$2", name, -1)
|
||||
rule = strings.Replace(rule, "$1", wkKind, -1)
|
||||
rule = strings.Replace(rule, "$2", wkName, -1)
|
||||
rule = strings.Replace(rule, "$3", namespace, -1)
|
||||
return rule
|
||||
case "replicaset":
|
||||
kind = "ReplicaSet"
|
||||
wkKind = ReplicaSet
|
||||
case "statefulset":
|
||||
kind = "StatefulSet"
|
||||
wkKind = StatefulSet
|
||||
case "daemonset":
|
||||
kind = "DaemonSet"
|
||||
wkKind = DaemonSet
|
||||
}
|
||||
|
||||
if name == "" {
|
||||
name = "~\".*\""
|
||||
if wkName == "" {
|
||||
wkName = "~\".*\""
|
||||
} else {
|
||||
name = "\"" + name + "\""
|
||||
wkName = "\"" + wkName + "\""
|
||||
}
|
||||
|
||||
rule = strings.Replace(rule, "$1", kind, -1)
|
||||
rule = strings.Replace(rule, "$2", name, -1)
|
||||
rule = strings.Replace(rule, "$1", wkKind, -1)
|
||||
rule = strings.Replace(rule, "$2", wkName, -1)
|
||||
rule = strings.Replace(rule, "$3", namespace, -1)
|
||||
return rule
|
||||
}
|
||||
|
||||
func MakeWorkspacePromQL(metricsName string, namespaceRe2 string) string {
|
||||
func MakeWorkspacePromQL(metricsName string, nsFilter string) string {
|
||||
promql := RulePromQLTmplMap[metricsName]
|
||||
promql = strings.Replace(promql, "$1", namespaceRe2, -1)
|
||||
promql = strings.Replace(promql, "$1", nsFilter, -1)
|
||||
return promql
|
||||
}
|
||||
|
||||
func MakeContainerPromQL(request *restful.Request) string {
|
||||
nsName := strings.Trim(request.PathParameter("ns_name"), " ")
|
||||
poName := strings.Trim(request.PathParameter("pod_name"), " ")
|
||||
containerName := strings.Trim(request.PathParameter("container_name"), " ")
|
||||
// metricType container_cpu_utilisation container_memory_utilisation container_memory_utilisation_wo_cache
|
||||
metricType := strings.Trim(request.QueryParameter("metrics_name"), " ")
|
||||
func MakeContainerPromQL(nsName, podName, containerName, metricName, containerFilter string) string {
|
||||
var promql = ""
|
||||
if containerName == "" {
|
||||
// all containers maybe use filter
|
||||
metricType += "_all"
|
||||
promql = RulePromQLTmplMap[metricType]
|
||||
metricName += "_all"
|
||||
promql = RulePromQLTmplMap[metricName]
|
||||
promql = strings.Replace(promql, "$1", nsName, -1)
|
||||
promql = strings.Replace(promql, "$2", poName, -1)
|
||||
containerFilter := strings.Trim(request.QueryParameter("containers_filter"), " ")
|
||||
promql = strings.Replace(promql, "$2", podName, -1)
|
||||
|
||||
if containerFilter == "" {
|
||||
containerFilter = ".*"
|
||||
}
|
||||
|
||||
promql = strings.Replace(promql, "$3", containerFilter, -1)
|
||||
return promql
|
||||
}
|
||||
promql = RulePromQLTmplMap[metricType]
|
||||
promql = RulePromQLTmplMap[metricName]
|
||||
|
||||
promql = strings.Replace(promql, "$1", nsName, -1)
|
||||
promql = strings.Replace(promql, "$2", poName, -1)
|
||||
promql = strings.Replace(promql, "$2", podName, -1)
|
||||
promql = strings.Replace(promql, "$3", containerName, -1)
|
||||
return promql
|
||||
}
|
||||
|
||||
func MakePodPromQL(request *restful.Request, params []string) string {
|
||||
metricType := params[0]
|
||||
nsName := params[1]
|
||||
nodeID := params[2]
|
||||
podName := params[3]
|
||||
podFilter := params[4]
|
||||
func MakePodPromQL(metricName, nsName, nodeID, podName, podFilter string) string {
|
||||
|
||||
if podFilter == "" {
|
||||
podFilter = ".*"
|
||||
}
|
||||
|
||||
var promql = ""
|
||||
if nsName != "" {
|
||||
// get pod metrics by namespace
|
||||
if podName != "" {
|
||||
// specific pod
|
||||
promql = RulePromQLTmplMap[metricType]
|
||||
promql = RulePromQLTmplMap[metricName]
|
||||
promql = strings.Replace(promql, "$1", nsName, -1)
|
||||
promql = strings.Replace(promql, "$2", podName, -1)
|
||||
|
||||
} else {
|
||||
// all pods
|
||||
metricType += "_all"
|
||||
promql = RulePromQLTmplMap[metricType]
|
||||
if podFilter == "" {
|
||||
podFilter = ".*"
|
||||
}
|
||||
metricName += "_all"
|
||||
promql = RulePromQLTmplMap[metricName]
|
||||
|
||||
promql = strings.Replace(promql, "$1", nsName, -1)
|
||||
promql = strings.Replace(promql, "$2", podFilter, -1)
|
||||
}
|
||||
} else if nodeID != "" {
|
||||
// get pod metrics by nodeid
|
||||
metricType += "_node"
|
||||
promql = RulePromQLTmplMap[metricType]
|
||||
metricName += "_node"
|
||||
promql = RulePromQLTmplMap[metricName]
|
||||
promql = strings.Replace(promql, "$3", nodeID, -1)
|
||||
if podName != "" {
|
||||
// specific pod
|
||||
promql = strings.Replace(promql, "$2", podName, -1)
|
||||
} else {
|
||||
// choose pod use re2 expression
|
||||
podFilter := strings.Trim(request.QueryParameter("pods_filter"), " ")
|
||||
if podFilter == "" {
|
||||
podFilter = ".*"
|
||||
}
|
||||
promql = strings.Replace(promql, "$2", podFilter, -1)
|
||||
}
|
||||
}
|
||||
return promql
|
||||
}
|
||||
|
||||
func MakeNamespacePromQL(request *restful.Request, metricsName string) string {
|
||||
nsName := strings.Trim(request.PathParameter("ns_name"), " ")
|
||||
metricType := metricsName
|
||||
var recordingRule = RulePromQLTmplMap[metricType]
|
||||
nsFilter := strings.Trim(request.QueryParameter("namespaces_filter"), " ")
|
||||
func MakeNamespacePromQL(nsName string, nsFilter string, metricsName string) string {
|
||||
var recordingRule = RulePromQLTmplMap[metricsName]
|
||||
|
||||
if nsName != "" {
|
||||
nsFilter = nsName
|
||||
} else {
|
||||
@@ -162,37 +139,37 @@ func MakeNamespacePromQL(request *restful.Request, metricsName string) string {
|
||||
return recordingRule
|
||||
}
|
||||
|
||||
func MakeNodeorClusterRule(request *restful.Request, metricsName string) string {
|
||||
nodeID := request.PathParameter("node_id")
|
||||
// cluster rule
|
||||
func MakeClusterRule(metricsName string) string {
|
||||
var rule = RulePromQLTmplMap[metricsName]
|
||||
|
||||
if strings.Contains(request.SelectedRoutePath(), "monitoring/cluster") {
|
||||
// cluster
|
||||
return rule
|
||||
} else {
|
||||
// node
|
||||
nodesFilter := strings.Trim(request.QueryParameter("nodes_filter"), " ")
|
||||
if nodesFilter == "" {
|
||||
nodesFilter = ".*"
|
||||
}
|
||||
if strings.Contains(metricsName, "disk_size") || strings.Contains(metricsName, "pod") || strings.Contains(metricsName, "usage") {
|
||||
// disk size promql
|
||||
if nodeID != "" {
|
||||
nodesFilter = "{" + "node" + "=" + "\"" + nodeID + "\"" + "}"
|
||||
} else {
|
||||
nodesFilter = "{" + "node" + "=~" + "\"" + nodesFilter + "\"" + "}"
|
||||
}
|
||||
rule = strings.Replace(rule, "$1", nodesFilter, -1)
|
||||
} else {
|
||||
// cpu, memory, network, disk_iops rules
|
||||
if nodeID != "" {
|
||||
// specific node
|
||||
rule = rule + "{" + "node" + "=" + "\"" + nodeID + "\"" + "}"
|
||||
} else {
|
||||
// all nodes or specific nodes filted with re2 syntax
|
||||
rule = rule + "{" + "node" + "=~" + "\"" + nodesFilter + "\"" + "}"
|
||||
}
|
||||
}
|
||||
}
|
||||
return rule
|
||||
}
|
||||
|
||||
// node rule
|
||||
func MakeNodeRule(nodeID string, nodesFilter string, metricsName string) string {
|
||||
var rule = RulePromQLTmplMap[metricsName]
|
||||
|
||||
if nodesFilter == "" {
|
||||
nodesFilter = ".*"
|
||||
}
|
||||
if strings.Contains(metricsName, "disk_size") || strings.Contains(metricsName, "pod") || strings.Contains(metricsName, "usage") || strings.Contains(metricsName, "inode") {
|
||||
// disk size promql
|
||||
if nodeID != "" {
|
||||
nodesFilter = "{" + "node" + "=" + "\"" + nodeID + "\"" + "}"
|
||||
} else {
|
||||
nodesFilter = "{" + "node" + "=~" + "\"" + nodesFilter + "\"" + "}"
|
||||
}
|
||||
rule = strings.Replace(rule, "$1", nodesFilter, -1)
|
||||
} else {
|
||||
// cpu, memory, network, disk_iops rules
|
||||
if nodeID != "" {
|
||||
// specific node
|
||||
rule = rule + "{" + "node" + "=" + "\"" + nodeID + "\"" + "}"
|
||||
} else {
|
||||
// all nodes or specific nodes filted with re2 syntax
|
||||
rule = rule + "{" + "node" + "=~" + "\"" + nodesFilter + "\"" + "}"
|
||||
}
|
||||
}
|
||||
|
||||
return rule
|
||||
}
|
||||
|
||||
560
pkg/models/metrics/metricsruleconst.go
Normal file
560
pkg/models/metrics/metricsruleconst.go
Normal file
@@ -0,0 +1,560 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
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 metrics
|
||||
|
||||
const (
|
||||
ResultTypeVector = "vector"
|
||||
ResultTypeMatrix = "matrix"
|
||||
MetricStatus = "status"
|
||||
MetricStatusError = "error"
|
||||
MetricStatusSuccess = "success"
|
||||
ResultItemMetric = "metric"
|
||||
ResultItemMetricResource = "resource"
|
||||
ResultItemValue = "value"
|
||||
ResultItemValues = "values"
|
||||
ResultSortTypeDesc = "desc"
|
||||
ResultSortTypeAsce = "asce"
|
||||
)
|
||||
|
||||
const (
|
||||
MetricNameWorkloadCount = "workload_count"
|
||||
MetricNameNamespacePodCount = "namespace_pod_count"
|
||||
|
||||
MetricNameWorkspaceAllOrganizationCount = "workspace_all_organization_count"
|
||||
MetricNameWorkspaceAllAccountCount = "workspace_all_account_count"
|
||||
MetricNameWorkspaceAllProjectCount = "workspace_all_project_count"
|
||||
MetricNameWorkspaceAllDevopsCount = "workspace_all_devops_project_count"
|
||||
MetricNameClusterAllProjectCount = "cluster_namespace_count"
|
||||
|
||||
MetricNameWorkspaceNamespaceCount = "workspace_namespace_count"
|
||||
MetricNameWorkspaceDevopsCount = "workspace_devops_project_count"
|
||||
MetricNameWorkspaceMemberCount = "workspace_member_count"
|
||||
MetricNameWorkspaceRoleCount = "workspace_role_count"
|
||||
MetricNameComponentOnLine = "component_online_count"
|
||||
MetricNameComponentLine = "component_count"
|
||||
)
|
||||
|
||||
const (
|
||||
WorkspaceResourceKindOrganization = "organization"
|
||||
WorkspaceResourceKindAccount = "account"
|
||||
WorkspaceResourceKindNamespace = "namespace"
|
||||
WorkspaceResourceKindDevops = "devops"
|
||||
WorkspaceResourceKindMember = "member"
|
||||
WorkspaceResourceKindRole = "role"
|
||||
)
|
||||
|
||||
const (
|
||||
MetricLevelCluster = "cluster"
|
||||
MetricLevelClusterWorkspace = "cluster_workspace"
|
||||
MetricLevelNode = "node"
|
||||
MetricLevelWorkspace = "workspace"
|
||||
MetricLevelNamespace = "namespace"
|
||||
MetricLevelPod = "pod"
|
||||
MetricLevelPodName = "pod_name"
|
||||
MetricLevelContainer = "container"
|
||||
MetricLevelWorkload = "workload"
|
||||
)
|
||||
|
||||
const (
|
||||
ReplicaSet = "ReplicaSet"
|
||||
StatefulSet = "StatefulSet"
|
||||
DaemonSet = "DaemonSet"
|
||||
)
|
||||
|
||||
const (
|
||||
NodeStatusRule = `kube_node_status_condition{condition="Ready"} > 0`
|
||||
PodInfoRule = `kube_pod_info{created_by_kind="$1",created_by_name=$2,namespace="$3"}`
|
||||
NamespaceLabelRule = `kube_namespace_labels`
|
||||
)
|
||||
|
||||
const (
|
||||
WorkspaceJoinedKey = "label_kubesphere_io_workspace"
|
||||
)
|
||||
|
||||
type MetricMap map[string]string
|
||||
|
||||
var ClusterMetricsNames = []string{
|
||||
"cluster_cpu_utilisation",
|
||||
"cluster_cpu_usage",
|
||||
"cluster_cpu_total",
|
||||
"cluster_memory_utilisation",
|
||||
"cluster_memory_bytes_available",
|
||||
"cluster_memory_bytes_total",
|
||||
"cluster_memory_bytes_usage",
|
||||
"cluster_net_utilisation",
|
||||
"cluster_net_bytes_transmitted",
|
||||
"cluster_net_bytes_received",
|
||||
"cluster_disk_read_iops",
|
||||
"cluster_disk_write_iops",
|
||||
"cluster_disk_read_throughput",
|
||||
"cluster_disk_write_throughput",
|
||||
"cluster_disk_size_usage",
|
||||
"cluster_disk_size_utilisation",
|
||||
"cluster_disk_size_capacity",
|
||||
"cluster_disk_size_available",
|
||||
"cluster_disk_inode_total",
|
||||
"cluster_disk_inode_usage",
|
||||
"cluster_disk_inode_utilisation",
|
||||
|
||||
"cluster_node_online",
|
||||
"cluster_node_offline",
|
||||
"cluster_node_total",
|
||||
|
||||
"cluster_pod_count",
|
||||
"cluster_pod_quota",
|
||||
"cluster_pod_utilisation",
|
||||
"cluster_pod_running_count",
|
||||
"cluster_pod_succeeded_count",
|
||||
"cluster_pod_abnormal_count",
|
||||
"cluster_ingresses_extensions_count",
|
||||
"cluster_cronjob_count",
|
||||
"cluster_pvc_count",
|
||||
"cluster_daemonset_count",
|
||||
"cluster_deployment_count",
|
||||
"cluster_endpoint_count",
|
||||
"cluster_hpa_count",
|
||||
"cluster_job_count",
|
||||
"cluster_statefulset_count",
|
||||
"cluster_replicaset_count",
|
||||
"cluster_service_count",
|
||||
"cluster_secret_count",
|
||||
|
||||
"cluster_namespace_count",
|
||||
"workspace_all_project_count",
|
||||
}
|
||||
var NodeMetricsNames = []string{
|
||||
"node_cpu_utilisation",
|
||||
"node_cpu_total",
|
||||
"node_cpu_usage",
|
||||
"node_memory_utilisation",
|
||||
"node_memory_bytes_usage",
|
||||
"node_memory_bytes_available",
|
||||
"node_memory_bytes_total",
|
||||
"node_net_utilisation",
|
||||
"node_net_bytes_transmitted",
|
||||
"node_net_bytes_received",
|
||||
"node_disk_read_iops",
|
||||
"node_disk_write_iops",
|
||||
"node_disk_read_throughput",
|
||||
"node_disk_write_throughput",
|
||||
"node_disk_size_capacity",
|
||||
"node_disk_size_available",
|
||||
"node_disk_size_usage",
|
||||
"node_disk_size_utilisation",
|
||||
|
||||
"node_disk_inode_total",
|
||||
"node_disk_inode_usage",
|
||||
"node_disk_inode_utilisation",
|
||||
|
||||
"node_pod_count",
|
||||
"node_pod_quota",
|
||||
"node_pod_utilisation",
|
||||
"node_pod_running_count",
|
||||
"node_pod_succeeded_count",
|
||||
"node_pod_abnormal_count",
|
||||
}
|
||||
var WorkspaceMetricsNames = []string{
|
||||
"workspace_cpu_usage",
|
||||
"workspace_memory_usage",
|
||||
"workspace_memory_usage_wo_cache",
|
||||
"workspace_net_bytes_transmitted",
|
||||
"workspace_net_bytes_received",
|
||||
"workspace_pod_count",
|
||||
"workspace_pod_running_count",
|
||||
"workspace_pod_succeeded_count",
|
||||
"workspace_pod_abnormal_count",
|
||||
"workspace_ingresses_extensions_count",
|
||||
|
||||
"workspace_cronjob_count",
|
||||
"workspace_pvc_count",
|
||||
"workspace_daemonset_count",
|
||||
"workspace_deployment_count",
|
||||
"workspace_endpoint_count",
|
||||
"workspace_hpa_count",
|
||||
"workspace_job_count",
|
||||
"workspace_statefulset_count",
|
||||
"workspace_replicaset_count",
|
||||
"workspace_service_count",
|
||||
"workspace_secret_count",
|
||||
}
|
||||
var NamespaceMetricsNames = []string{
|
||||
"namespace_cpu_usage",
|
||||
"namespace_memory_usage",
|
||||
"namespace_memory_usage_wo_cache",
|
||||
"namespace_net_bytes_transmitted",
|
||||
"namespace_net_bytes_received",
|
||||
"namespace_pod_count",
|
||||
"namespace_pod_running_count",
|
||||
"namespace_pod_succeeded_count",
|
||||
"namespace_pod_abnormal_count",
|
||||
|
||||
"namespace_configmap_count_used",
|
||||
"namespace_jobs_batch_count_used",
|
||||
"namespace_roles_count_used",
|
||||
"namespace_memory_limit_used",
|
||||
"namespace_pvc_used",
|
||||
"namespace_memory_request_used",
|
||||
"namespace_pvc_count_used",
|
||||
"namespace_cronjobs_batch_count_used",
|
||||
"namespace_ingresses_extensions_count_used",
|
||||
"namespace_cpu_limit_used",
|
||||
"namespace_storage_request_used",
|
||||
"namespace_deployment_count_used",
|
||||
"namespace_pod_count_used",
|
||||
"namespace_statefulset_count_used",
|
||||
"namespace_daemonset_count_used",
|
||||
"namespace_secret_count_used",
|
||||
"namespace_service_count_used",
|
||||
"namespace_cpu_request_used",
|
||||
"namespace_service_loadbalancer_used",
|
||||
|
||||
"namespace_configmap_count_hard",
|
||||
"namespace_jobs_batch_count_hard",
|
||||
"namespace_roles_count_hard",
|
||||
"namespace_memory_limit_hard",
|
||||
"namespace_pvc_hard",
|
||||
"namespace_memory_request_hard",
|
||||
"namespace_pvc_count_hard",
|
||||
"namespace_cronjobs_batch_count_hard",
|
||||
"namespace_ingresses_extensions_count_hard",
|
||||
"namespace_cpu_limit_hard",
|
||||
"namespace_storage_request_hard",
|
||||
"namespace_deployment_count_hard",
|
||||
"namespace_pod_count_hard",
|
||||
"namespace_statefulset_count_hard",
|
||||
"namespace_daemonset_count_hard",
|
||||
"namespace_secret_count_hard",
|
||||
"namespace_service_count_hard",
|
||||
"namespace_cpu_request_hard",
|
||||
"namespace_service_loadbalancer_hard",
|
||||
|
||||
"namespace_cronjob_count",
|
||||
"namespace_pvc_count",
|
||||
"namespace_daemonset_count",
|
||||
"namespace_deployment_count",
|
||||
"namespace_endpoint_count",
|
||||
"namespace_hpa_count",
|
||||
"namespace_job_count",
|
||||
"namespace_statefulset_count",
|
||||
"namespace_replicaset_count",
|
||||
"namespace_service_count",
|
||||
"namespace_secret_count",
|
||||
}
|
||||
|
||||
var PodMetricsNames = []string{
|
||||
"pod_cpu_usage",
|
||||
"pod_memory_usage",
|
||||
"pod_memory_usage_wo_cache",
|
||||
"pod_net_bytes_transmitted",
|
||||
"pod_net_bytes_received",
|
||||
}
|
||||
|
||||
var WorkloadMetricsNames = []string{
|
||||
"workload_pod_cpu_usage",
|
||||
"workload_pod_memory_usage",
|
||||
"workload_pod_memory_usage_wo_cache",
|
||||
"workload_pod_net_bytes_transmitted",
|
||||
"workload_pod_net_bytes_received",
|
||||
}
|
||||
|
||||
var RulePromQLTmplMap = MetricMap{
|
||||
//cluster
|
||||
"cluster_cpu_utilisation": ":node_cpu_utilisation:avg1m",
|
||||
"cluster_cpu_usage": `:node_cpu_utilisation:avg1m * sum(node:node_num_cpu:sum)`,
|
||||
"cluster_cpu_total": "sum(node:node_num_cpu:sum)",
|
||||
"cluster_memory_utilisation": ":node_memory_utilisation:",
|
||||
"cluster_memory_bytes_available": "sum(node:node_memory_bytes_available:sum)",
|
||||
"cluster_memory_bytes_total": "sum(node:node_memory_bytes_total:sum)",
|
||||
"cluster_memory_bytes_usage": "sum(node:node_memory_bytes_total:sum) - sum(node:node_memory_bytes_available:sum)",
|
||||
"cluster_net_utilisation": ":node_net_utilisation:sum_irate",
|
||||
"cluster_net_bytes_transmitted": "sum(node:node_net_bytes_transmitted:sum_irate)",
|
||||
"cluster_net_bytes_received": "sum(node:node_net_bytes_received:sum_irate)",
|
||||
"cluster_disk_read_iops": "sum(node:data_volume_iops_reads:sum)",
|
||||
"cluster_disk_write_iops": "sum(node:data_volume_iops_writes:sum)",
|
||||
"cluster_disk_read_throughput": "sum(node:data_volume_throughput_bytes_read:sum)",
|
||||
"cluster_disk_write_throughput": "sum(node:data_volume_throughput_bytes_written:sum)",
|
||||
"cluster_disk_size_usage": `sum(sum by (node) ((node_filesystem_size{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:)) - sum(sum by (node) ((node_filesystem_avail{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:))`,
|
||||
"cluster_disk_size_utilisation": `(sum(sum by (node) ((node_filesystem_size{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:)) - sum(sum by (node) ((node_filesystem_avail{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:))) / sum(sum by (node) ((node_filesystem_size{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:))`,
|
||||
"cluster_disk_size_capacity": `sum(sum by (node) ((node_filesystem_size{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:))`,
|
||||
"cluster_disk_size_available": `sum(sum by (node) ((node_filesystem_avail{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:))`,
|
||||
|
||||
"cluster_disk_inode_total": `sum(node:disk_inodes_total:)`,
|
||||
"cluster_disk_inode_usage": `sum(node:disk_inodes_total:) - sum(node:disk_inodes_free:)`,
|
||||
"cluster_disk_inode_utilisation": `1 - sum(node:disk_inodes_free:) / sum(node:disk_inodes_total:)`,
|
||||
|
||||
"cluster_namespace_count": `count(kube_namespace_annotations)`,
|
||||
"workspace_all_project_count": `count(kube_namespace_annotations)`,
|
||||
|
||||
// cluster_pod_count = cluster_pod_running_count + cluster_pod_succeeded_count + cluster_pod_abnormal_count
|
||||
"cluster_pod_count": `sum(kube_pod_status_phase)`,
|
||||
"cluster_pod_utilisation": `sum(kube_pod_status_phase) / sum(kube_node_status_capacity_pods)`,
|
||||
"cluster_pod_running_count": `sum(kube_pod_status_phase{phase="Running"})`,
|
||||
"cluster_pod_succeeded_count": `sum(kube_pod_status_phase{phase="Succeeded"})`,
|
||||
"cluster_pod_abnormal_count": `sum(kube_pod_status_phase{phase=~"Failed|Pending|Unknown"})`,
|
||||
|
||||
"cluster_node_online": `sum(kube_node_status_condition{condition="Ready",status="true"})`,
|
||||
"cluster_node_offline": `sum(kube_node_status_condition{condition="Ready",status=~"unknown|false"})`,
|
||||
"cluster_node_total": `sum(kube_node_status_condition{condition="Ready"})`,
|
||||
"cluster_pod_quota": `sum(kube_node_status_capacity_pods)`,
|
||||
"cluster_ingresses_extensions_count": `sum(kube_resourcequota{type="used", resource="count/ingresses.extensions"}) by (resource, type)`,
|
||||
|
||||
"cluster_configmap_count_used": `sum(kube_resourcequota{type="used", resource="count/configmaps"}) by (resource, type)`,
|
||||
"cluster_jobs_batch_count_used": `sum(kube_resourcequota{type="used", resource="count/jobs.batch"}) by (resource, type)`,
|
||||
"cluster_roles_count_used": `sum(kube_resourcequota{type="used", resource="count/roles.rbac.authorization.k8s.io"}) by (resource, type)`,
|
||||
"cluster_memory_limit_used": `sum(kube_resourcequota{type="used", resource="limits.memory"}) by (resource, type)`,
|
||||
"cluster_pvc_used": `sum(kube_resourcequota{type="used", resource="persistentvolumeclaims"}) by (resource, type)`,
|
||||
"cluster_memory_request_used": `sum(kube_resourcequota{type="used", resource="requests.memory"}) by (resource, type)`,
|
||||
"cluster_pvc_count_used": `sum(kube_resourcequota{type="used", resource="count/persistentvolumeclaims"}) by (resource, type)`,
|
||||
"cluster_cronjobs_batch_count_used": `sum(kube_resourcequota{type="used", resource="count/cronjobs.batch"}) by (resource, type)`,
|
||||
"cluster_ingresses_extensions_count_used": `sum(kube_resourcequota{type="used", resource="count/ingresses.extensions"}) by (resource, type)`,
|
||||
"cluster_cpu_limit_used": `sum(kube_resourcequota{type="used", resource="limits.cpu"}) by (resource, type)`,
|
||||
"cluster_storage_request_used": `sum(kube_resourcequota{type="used", resource="requests.storage"}) by (resource, type)`,
|
||||
"cluster_deployment_count_used": `sum(kube_resourcequota{type="used", resource="count/deployments.apps"}) by (resource, type)`,
|
||||
"cluster_pod_count_used": `sum(kube_resourcequota{type="used", resource="count/pods"}) by (resource, type)`,
|
||||
"cluster_statefulset_count_used": `sum(kube_resourcequota{type="used", resource="count/statefulsets.apps"}) by (resource, type)`,
|
||||
"cluster_daemonset_count_used": `sum(kube_resourcequota{type="used", resource="count/daemonsets.apps"}) by (resource, type)`,
|
||||
"cluster_secret_count_used": `sum(kube_resourcequota{type="used", resource="count/secrets"}) by (resource, type)`,
|
||||
"cluster_service_count_used": `sum(kube_resourcequota{type="used", resource="count/services"}) by (resource, type)`,
|
||||
"cluster_cpu_request_used": `sum(kube_resourcequota{type="used", resource="requests.cpu"}) by (resource, type)`,
|
||||
"cluster_service_loadbalancer_used": `sum(kube_resourcequota{type="used", resource="services.loadbalancers"}) by (resource, type)`,
|
||||
|
||||
"cluster_configmap_count_hard": `sum(kube_resourcequota{type="hard", resource="count/configmaps"}) by (resource, type)`,
|
||||
"cluster_jobs_batch_count_hard": `sum(kube_resourcequota{type="hard", resource="count/jobs.batch"}) by (resource, type)`,
|
||||
"cluster_roles_count_hard": `sum(kube_resourcequota{type="hard", resource="count/roles.rbac.authorization.k8s.io"}) by (resource, type)`,
|
||||
"cluster_memory_limit_hard": `sum(kube_resourcequota{type="hard", resource="limits.memory"}) by (resource, type)`,
|
||||
"cluster_pvc_hard": `sum(kube_resourcequota{type="hard", resource="persistentvolumeclaims"}) by (resource, type)`,
|
||||
"cluster_memory_request_hard": `sum(kube_resourcequota{type="hard", resource="requests.memory"}) by (resource, type)`,
|
||||
"cluster_pvc_count_hard": `sum(kube_resourcequota{type="hard", resource="count/persistentvolumeclaims"}) by (resource, type)`,
|
||||
"cluster_cronjobs_batch_count_hard": `sum(kube_resourcequota{type="hard", resource="count/cronjobs.batch"}) by (resource, type)`,
|
||||
"cluster_ingresses_extensions_count_hard": `sum(kube_resourcequota{type="hard", resource="count/ingresses.extensions"}) by (resource, type)`,
|
||||
"cluster_cpu_limit_hard": `sum(kube_resourcequota{type="hard", resource="limits.cpu"}) by (resource, type)`,
|
||||
"cluster_storage_request_hard": `sum(kube_resourcequota{type="hard", resource="requests.storage"}) by (resource, type)`,
|
||||
"cluster_deployment_count_hard": `sum(kube_resourcequota{type="hard", resource="count/deployments.apps"}) by (resource, type)`,
|
||||
"cluster_pod_count_hard": `sum(kube_resourcequota{type="hard", resource="count/pods"}) by (resource, type)`,
|
||||
"cluster_statefulset_count_hard": `sum(kube_resourcequota{type="hard", resource="count/statefulsets.apps"}) by (resource, type)`,
|
||||
"cluster_daemonset_count_hard": `sum(kube_resourcequota{type="hard", resource="count/daemonsets.apps"}) by (resource, type)`,
|
||||
"cluster_secret_count_hard": `sum(kube_resourcequota{type="hard", resource="count/secrets"}) by (resource, type)`,
|
||||
"cluster_service_count_hard": `sum(kube_resourcequota{type="hard", resource="count/services"}) by (resource, type)`,
|
||||
"cluster_cpu_request_hard": `sum(kube_resourcequota{type="hard", resource="requests.cpu"}) by (resource, type)`,
|
||||
"cluster_service_loadbalancer_hard": `sum(kube_resourcequota{type="hard", resource="services.loadbalancers"}) by (resource, type)`,
|
||||
|
||||
"cluster_cronjob_count": `sum(kube_cronjob_labels)`,
|
||||
"cluster_pvc_count": `sum(kube_persistentvolumeclaim_info)`,
|
||||
"cluster_daemonset_count": `sum(kube_daemonset_labels)`,
|
||||
"cluster_deployment_count": `sum(kube_deployment_labels)`,
|
||||
"cluster_endpoint_count": `sum(kube_endpoint_labels)`,
|
||||
"cluster_hpa_count": `sum(kube_hpa_labels)`,
|
||||
"cluster_job_count": `sum(kube_job_labels)`,
|
||||
"cluster_statefulset_count": `sum(kube_statefulset_labels)`,
|
||||
"cluster_replicaset_count": `count(kube_replicaset_created)`,
|
||||
"cluster_service_count": `sum(kube_service_info)`,
|
||||
"cluster_secret_count": `sum(kube_secret_info)`,
|
||||
"cluster_pv_count": `sum(kube_persistentvolume_labels)`,
|
||||
|
||||
//node
|
||||
"node_cpu_utilisation": "node:node_cpu_utilisation:avg1m",
|
||||
"node_cpu_total": "node:node_num_cpu:sum",
|
||||
"node_memory_utilisation": "node:node_memory_utilisation:",
|
||||
"node_memory_bytes_available": "node:node_memory_bytes_available:sum",
|
||||
"node_memory_bytes_total": "node:node_memory_bytes_total:sum",
|
||||
// Node network utilisation (bytes received + bytes transmitted per second)
|
||||
"node_net_utilisation": "node:node_net_utilisation:sum_irate",
|
||||
// Node network bytes transmitted per second
|
||||
"node_net_bytes_transmitted": "node:node_net_bytes_transmitted:sum_irate",
|
||||
// Node network bytes received per second
|
||||
"node_net_bytes_received": "node:node_net_bytes_received:sum_irate",
|
||||
|
||||
// node:data_volume_iops_reads:sum{node=~"i-5xcldxos|i-6soe9zl1"}
|
||||
"node_disk_read_iops": "node:data_volume_iops_reads:sum",
|
||||
// node:data_volume_iops_writes:sum{node=~"i-5xcldxos|i-6soe9zl1"}
|
||||
"node_disk_write_iops": "node:data_volume_iops_writes:sum",
|
||||
// node:data_volume_throughput_bytes_read:sum{node=~"i-5xcldxos|i-6soe9zl1"}
|
||||
"node_disk_read_throughput": "node:data_volume_throughput_bytes_read:sum",
|
||||
// node:data_volume_throughput_bytes_written:sum{node=~"i-5xcldxos|i-6soe9zl1"}
|
||||
"node_disk_write_throughput": "node:data_volume_throughput_bytes_written:sum",
|
||||
|
||||
"node_disk_size_capacity": `sum by (node) ((node_filesystem_size{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1)`,
|
||||
"node_disk_size_available": `sum by (node) ((node_filesystem_avail{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1)`,
|
||||
"node_disk_size_usage": `sum by (node) ((node_filesystem_size{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1) -sum by (node) ((node_filesystem_avail{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1)`,
|
||||
"node_disk_size_utilisation": `sum by (node) (((node_filesystem_size{mountpoint="/", job="node-exporter"} - node_filesystem_avail{mountpoint="/", job="node-exporter"}) / node_filesystem_size{mountpoint="/", job="node-exporter"}) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:$1)`,
|
||||
|
||||
"node_disk_inode_total": `node:disk_inodes_total:$1`,
|
||||
"node_disk_inode_usage": `node:disk_inodes_total:$1 - node:disk_inodes_free:$1`,
|
||||
"node_disk_inode_utilisation": `(1 - (node:disk_inodes_free:$1 / node:disk_inodes_total:$1))`,
|
||||
|
||||
"node_pod_count": `count(kube_pod_info$1) by (node)`,
|
||||
"node_pod_quota": `sum(kube_node_status_capacity_pods$1) by (node)`,
|
||||
"node_pod_utilisation": `sum(kube_pod_info$1) by (node) / sum(kube_node_status_capacity_pods$1) by (node)`,
|
||||
"node_pod_running_count": `count(kube_pod_info$1 unless on (pod) (kube_pod_status_phase{phase=~"Failed|Pending|Unknown|Succeeded"} > 0)) by (node)`,
|
||||
"node_pod_succeeded_count": `count(kube_pod_info$1 unless on (pod) (kube_pod_status_phase{phase=~"Failed|Pending|Unknown|Running"} > 0)) by (node)`,
|
||||
"node_pod_abnormal_count": `count(kube_pod_info$1 unless on (pod) (kube_pod_status_phase{phase=~"Succeeded|Running"} > 0)) by (node)`,
|
||||
|
||||
// without log node: unless on(node) kube_node_labels{label_role="log"}
|
||||
"node_cpu_usage": `node:node_cpu_utilisation:avg1m$1 * node:node_num_cpu:sum$1`,
|
||||
"node_memory_bytes_usage": "node:node_memory_bytes_total:sum$1 - node:node_memory_bytes_available:sum$1",
|
||||
|
||||
//namespace
|
||||
"namespace_cpu_usage": `namespace:container_cpu_usage_seconds_total:sum_rate{namespace=~"$1"}`,
|
||||
"namespace_memory_usage": `namespace:container_memory_usage_bytes:sum{namespace=~"$1"}`,
|
||||
"namespace_memory_usage_wo_cache": `namespace:container_memory_usage_bytes_wo_cache:sum{namespace=~"$1"}`,
|
||||
"namespace_net_bytes_transmitted": `sum by (namespace) (irate(container_network_transmit_bytes_total{namespace=~"$1", pod_name!="", interface="eth0", job="kubelet"}[5m]))`,
|
||||
"namespace_net_bytes_received": `sum by (namespace) (irate(container_network_receive_bytes_total{namespace=~"$1", pod_name!="", interface="eth0", job="kubelet"}[5m]))`,
|
||||
"namespace_pod_count": `sum(kube_pod_status_phase{namespace=~"$1"}) by (namespace)`,
|
||||
"namespace_pod_running_count": `sum(kube_pod_status_phase{phase="Running", namespace=~"$1"}) by (namespace)`,
|
||||
"namespace_pod_succeeded_count": `sum(kube_pod_status_phase{phase="Succeeded", namespace=~"$1"}) by (namespace)`,
|
||||
"namespace_pod_abnormal_count": `sum(kube_pod_status_phase{phase=~"Failed|Pending|Unknown", namespace=~"$1"}) by (namespace)`,
|
||||
|
||||
"namespace_configmap_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/configmaps"}) by (namespace, resource, type)`,
|
||||
"namespace_jobs_batch_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/jobs.batch"}) by (namespace, resource, type)`,
|
||||
"namespace_roles_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/roles.rbac.authorization.k8s.io"}) by (namespace, resource, type)`,
|
||||
"namespace_memory_limit_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="limits.memory"}) by (namespace, resource, type)`,
|
||||
"namespace_pvc_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="persistentvolumeclaims"}) by (namespace, resource, type)`,
|
||||
"namespace_memory_request_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="requests.memory"}) by (namespace, resource, type)`,
|
||||
"namespace_pvc_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/persistentvolumeclaims"}) by (namespace, resource, type)`,
|
||||
"namespace_cronjobs_batch_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/cronjobs.batch"}) by (namespace, resource, type)`,
|
||||
"namespace_ingresses_extensions_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/ingresses.extensions"}) by (namespace, resource, type)`,
|
||||
"namespace_cpu_limit_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="limits.cpu"}) by (namespace, resource, type)`,
|
||||
"namespace_storage_request_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="requests.storage"}) by (namespace, resource, type)`,
|
||||
"namespace_deployment_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/deployments.apps"}) by (namespace, resource, type)`,
|
||||
"namespace_pod_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/pods"}) by (namespace, resource, type)`,
|
||||
"namespace_statefulset_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/statefulsets.apps"}) by (namespace, resource, type)`,
|
||||
"namespace_daemonset_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/daemonsets.apps"}) by (namespace, resource, type)`,
|
||||
"namespace_secret_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/secrets"}) by (namespace, resource, type)`,
|
||||
"namespace_service_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/services"}) by (namespace, resource, type)`,
|
||||
"namespace_cpu_request_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="requests.cpu"}) by (namespace, resource, type)`,
|
||||
"namespace_service_loadbalancer_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="services.loadbalancers"}) by (namespace, resource, type)`,
|
||||
|
||||
"namespace_configmap_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/configmaps"}) by (namespace, resource, type)`,
|
||||
"namespace_jobs_batch_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/jobs.batch"}) by (namespace, resource, type)`,
|
||||
"namespace_roles_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/roles.rbac.authorization.k8s.io"}) by (namespace, resource, type)`,
|
||||
"namespace_memory_limit_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="limits.memory"}) by (namespace, resource, type)`,
|
||||
"namespace_pvc_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="persistentvolumeclaims"}) by (namespace, resource, type)`,
|
||||
"namespace_memory_request_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="requests.memory"}) by (namespace, resource, type)`,
|
||||
"namespace_pvc_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/persistentvolumeclaims"}) by (namespace, resource, type)`,
|
||||
"namespace_cronjobs_batch_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/cronjobs.batch"}) by (namespace, resource, type)`,
|
||||
"namespace_ingresses_extensions_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/ingresses.extensions"}) by (namespace, resource, type)`,
|
||||
"namespace_cpu_limit_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="limits.cpu"}) by (namespace, resource, type)`,
|
||||
"namespace_storage_request_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="requests.storage"}) by (namespace, resource, type)`,
|
||||
"namespace_deployment_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/deployments.apps"}) by (namespace, resource, type)`,
|
||||
"namespace_pod_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/pods"}) by (namespace, resource, type)`,
|
||||
"namespace_statefulset_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/statefulsets.apps"}) by (namespace, resource, type)`,
|
||||
"namespace_daemonset_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/daemonsets.apps"}) by (namespace, resource, type)`,
|
||||
"namespace_secret_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/secrets"}) by (namespace, resource, type)`,
|
||||
"namespace_service_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/services"}) by (namespace, resource, type)`,
|
||||
"namespace_cpu_request_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="requests.cpu"}) by (namespace, resource, type)`,
|
||||
"namespace_service_loadbalancer_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="services.loadbalancers"}) by (namespace, resource, type)`,
|
||||
|
||||
"namespace_cronjob_count": `sum(kube_cronjob_labels{namespace=~"$1"}) by (namespace)`,
|
||||
"namespace_pvc_count": `sum(kube_persistentvolumeclaim_info{namespace=~"$1"}) by (namespace)`,
|
||||
"namespace_daemonset_count": `sum(kube_daemonset_labels{namespace=~"$1"}) by (namespace)`,
|
||||
"namespace_deployment_count": `sum(kube_deployment_labels{namespace=~"$1"}) by (namespace)`,
|
||||
"namespace_endpoint_count": `sum(kube_endpoint_labels{namespace=~"$1"}) by (namespace)`,
|
||||
"namespace_hpa_count": `sum(kube_hpa_labels{namespace=~"$1"}) by (namespace)`,
|
||||
"namespace_job_count": `sum(kube_job_labels{namespace=~"$1"}) by (namespace)`,
|
||||
"namespace_statefulset_count": `sum(kube_statefulset_labels{namespace=~"$1"}) by (namespace)`,
|
||||
"namespace_replicaset_count": `count(kube_replicaset_created{namespace=~"$1"}) by (namespace)`,
|
||||
"namespace_service_count": `sum(kube_service_info{namespace=~"$1"}) by (namespace)`,
|
||||
"namespace_secret_count": `sum(kube_secret_info{namespace=~"$1"}) by (namespace)`,
|
||||
|
||||
// pod
|
||||
"pod_cpu_usage": `sum(irate(container_cpu_usage_seconds_total{job="kubelet", namespace="$1", pod_name="$2", image!=""}[5m])) by (namespace, pod_name)`,
|
||||
"pod_memory_usage": `sum(container_memory_usage_bytes{job="kubelet", namespace="$1", pod_name="$2", image!=""}) by (namespace, pod_name)`,
|
||||
"pod_memory_usage_wo_cache": `sum(container_memory_usage_bytes{job="kubelet", namespace="$1", pod_name="$2", image!=""} - container_memory_cache{job="kubelet", namespace="$1", pod_name="$2",image!=""}) by (namespace, pod_name)`,
|
||||
"pod_net_bytes_transmitted": `sum by (namespace, pod_name) (irate(container_network_transmit_bytes_total{namespace="$1", pod_name!="", pod_name="$2", interface="eth0", job="kubelet"}[5m]))`,
|
||||
"pod_net_bytes_received": `sum by (namespace, pod_name) (irate(container_network_receive_bytes_total{namespace="$1", pod_name!="", pod_name="$2", interface="eth0", job="kubelet"}[5m]))`,
|
||||
|
||||
"pod_cpu_usage_all": `sum(irate(container_cpu_usage_seconds_total{job="kubelet", namespace="$1", pod_name=~"$2", image!=""}[5m])) by (namespace, pod_name)`,
|
||||
"pod_memory_usage_all": `sum(container_memory_usage_bytes{job="kubelet", namespace="$1", pod_name=~"$2", image!=""}) by (namespace, pod_name)`,
|
||||
"pod_memory_usage_wo_cache_all": `sum(container_memory_usage_bytes{job="kubelet", namespace="$1", pod_name=~"$2", image!=""} - container_memory_cache{job="kubelet", namespace="$1", pod_name=~"$2", image!=""}) by (namespace, pod_name)`,
|
||||
"pod_net_bytes_transmitted_all": `sum by (namespace, pod_name) (irate(container_network_transmit_bytes_total{namespace="$1", pod_name!="", pod_name=~"$2", interface="eth0", job="kubelet"}[5m]))`,
|
||||
"pod_net_bytes_received_all": `sum by (namespace, pod_name) (irate(container_network_receive_bytes_total{namespace="$1", pod_name!="", pod_name=~"$2", interface="eth0", job="kubelet"}[5m]))`,
|
||||
|
||||
"pod_cpu_usage_node": `sum by (node, pod) (label_join(irate(container_cpu_usage_seconds_total{job="kubelet",pod_name=~"$2", image!=""}[5m]), "pod", " ", "pod_name") * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:{node=~"$3"})`,
|
||||
"pod_memory_usage_node": `sum by (node, pod) (label_join(container_memory_usage_bytes{job="kubelet",pod_name=~"$2", image!=""}, "pod", " ", "pod_name") * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:{node=~"$3"})`,
|
||||
"pod_memory_usage_wo_cache_node": `sum by (node, pod) ((label_join(container_memory_usage_bytes{job="kubelet",pod_name=~"$2", image!=""}, "pod", " ", "pod_name") - label_join(container_memory_cache{job="kubelet",pod_name=~"$2", image!=""}, "pod", " ", "pod_name")) * on (namespace, pod) group_left(node) node_namespace_pod:kube_pod_info:{node=~"$3"})`,
|
||||
|
||||
// container
|
||||
"container_cpu_usage": `sum(irate(container_cpu_usage_seconds_total{namespace="$1", pod_name="$2", container_name="$3"}[5m])) by (namespace, pod_name, container_name)`,
|
||||
"container_cpu_usage_all": `sum(irate(container_cpu_usage_seconds_total{namespace="$1", pod_name="$2", container_name=~"$3", container_name!="POD"}[5m])) by (namespace, pod_name, container_name)`,
|
||||
|
||||
"container_memory_usage_wo_cache": `container_memory_usage_bytes{namespace="$1", pod_name="$2", container_name="$3"} - ignoring(id, image, endpoint, instance, job, name, service) container_memory_cache{namespace="$1", pod_name="$2", container_name="$3"}`,
|
||||
"container_memory_usage_wo_cache_all": `container_memory_usage_bytes{namespace="$1", pod_name="$2", container_name=~"$3", container_name!="POD"} - ignoring(id, image, endpoint, instance, job, name, service) container_memory_cache{namespace="$1", pod_name="$2", container_name=~"$3", container_name!="POD"}`,
|
||||
|
||||
"container_memory_usage": `container_memory_usage_bytes{namespace="$1", pod_name="$2", container_name="$3"}`,
|
||||
"container_memory_usage_all": `container_memory_usage_bytes{namespace="$1", pod_name="$2", container_name=~"$3", container_name!="POD"}`,
|
||||
|
||||
// workspace
|
||||
"workspace_cpu_usage": `sum(namespace:container_cpu_usage_seconds_total:sum_rate{namespace =~"$1"})`,
|
||||
"workspace_memory_usage": `sum(namespace:container_memory_usage_bytes:sum{namespace =~"$1"})`,
|
||||
"workspace_memory_usage_wo_cache": `sum(namespace:container_memory_usage_bytes_wo_cache:sum{namespace =~"$1"})`,
|
||||
"workspace_net_bytes_transmitted": `sum(sum by (namespace) (irate(container_network_transmit_bytes_total{namespace=~"$1", pod_name!="", interface="eth0", job="kubelet"}[5m])))`,
|
||||
"workspace_net_bytes_received": `sum(sum by (namespace) (irate(container_network_receive_bytes_total{namespace=~"$1", pod_name!="", interface="eth0", job="kubelet"}[5m])))`,
|
||||
"workspace_pod_count": `sum(kube_pod_status_phase{namespace=~"$1"})`,
|
||||
"workspace_pod_running_count": `sum(kube_pod_status_phase{phase="Running", namespace=~"$1"})`,
|
||||
"workspace_pod_succeeded_count": `sum(kube_pod_status_phase{phase="Succeeded", namespace=~"$1"})`,
|
||||
"workspace_pod_abnormal_count": `sum(kube_pod_status_phase{phase=~"Failed|Pending|Unknown", namespace=~"$1"})`,
|
||||
|
||||
"workspace_configmap_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/configmaps"}) by (resource, type)`,
|
||||
"workspace_jobs_batch_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/jobs.batch"}) by (resource, type)`,
|
||||
"workspace_roles_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/roles.rbac.authorization.k8s.io"}) by (resource, type)`,
|
||||
"workspace_memory_limit_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="limits.memory"}) by (resource, type)`,
|
||||
"workspace_pvc_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="persistentvolumeclaims"}) by (resource, type)`,
|
||||
"workspace_memory_request_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="requests.memory"}) by (resource, type)`,
|
||||
"workspace_pvc_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/persistentvolumeclaims"}) by (resource, type)`,
|
||||
"workspace_cronjobs_batch_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/cronjobs.batch"}) by (resource, type)`,
|
||||
"workspace_ingresses_extensions_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/ingresses.extensions"}) by (resource, type)`,
|
||||
"workspace_cpu_limit_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="limits.cpu"}) by (resource, type)`,
|
||||
"workspace_storage_request_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="requests.storage"}) by (resource, type)`,
|
||||
"workspace_deployment_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/deployments.apps"}) by (resource, type)`,
|
||||
"workspace_pod_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/pods"}) by (resource, type)`,
|
||||
"workspace_statefulset_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/statefulsets.apps"}) by (resource, type)`,
|
||||
"workspace_daemonset_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/daemonsets.apps"}) by (resource, type)`,
|
||||
"workspace_secret_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/secrets"}) by (resource, type)`,
|
||||
"workspace_service_count_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/services"}) by (resource, type)`,
|
||||
"workspace_cpu_request_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="requests.cpu"}) by (resource, type)`,
|
||||
"workspace_service_loadbalancer_used": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="services.loadbalancers"}) by (resource, type)`,
|
||||
|
||||
"workspace_configmap_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/configmaps"}) by (resource, type)`,
|
||||
"workspace_jobs_batch_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/jobs.batch"}) by (resource, type)`,
|
||||
"workspace_roles_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/roles.rbac.authorization.k8s.io"}) by (resource, type)`,
|
||||
"workspace_memory_limit_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="limits.memory"}) by (resource, type)`,
|
||||
"workspace_pvc_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="persistentvolumeclaims"}) by (resource, type)`,
|
||||
"workspace_memory_request_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="requests.memory"}) by (resource, type)`,
|
||||
"workspace_pvc_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/persistentvolumeclaims"}) by (resource, type)`,
|
||||
"workspace_cronjobs_batch_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/cronjobs.batch"}) by (resource, type)`,
|
||||
"workspace_ingresses_extensions_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/ingresses.extensions"}) by (resource, type)`,
|
||||
"workspace_cpu_limit_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="limits.cpu"}) by (resource, type)`,
|
||||
"workspace_storage_request_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="requests.storage"}) by (resource, type)`,
|
||||
"workspace_deployment_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/deployments.apps"}) by (resource, type)`,
|
||||
"workspace_pod_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/pods"}) by (resource, type)`,
|
||||
"workspace_statefulset_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/statefulsets.apps"}) by (resource, type)`,
|
||||
"workspace_daemonset_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/daemonsets.apps"}) by (resource, type)`,
|
||||
"workspace_secret_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/secrets"}) by (resource, type)`,
|
||||
"workspace_service_count_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="count/services"}) by (resource, type)`,
|
||||
"workspace_cpu_request_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="requests.cpu"}) by (resource, type)`,
|
||||
"workspace_service_loadbalancer_hard": `sum(kube_resourcequota{type="hard", namespace=~"$1", resource="services.loadbalancers"}) by (resource, type)`,
|
||||
"workspace_ingresses_extensions_count": `sum(kube_resourcequota{type="used", namespace=~"$1", resource="count/ingresses.extensions"}) by (resource, type)`,
|
||||
|
||||
"workspace_cronjob_count": `sum(kube_cronjob_labels{namespace=~"$1"})`,
|
||||
"workspace_pvc_count": `sum(kube_persistentvolumeclaim_info{namespace=~"$1"})`,
|
||||
"workspace_daemonset_count": `sum(kube_daemonset_labels{namespace=~"$1"})`,
|
||||
"workspace_deployment_count": `sum(kube_deployment_labels{namespace=~"$1"})`,
|
||||
"workspace_endpoint_count": `sum(kube_endpoint_labels{namespace=~"$1"})`,
|
||||
"workspace_hpa_count": `sum(kube_hpa_labels{namespace=~"$1"})`,
|
||||
"workspace_job_count": `sum(kube_job_labels{namespace=~"$1"})`,
|
||||
"workspace_statefulset_count": `sum(kube_statefulset_labels{namespace=~"$1"})`,
|
||||
"workspace_replicaset_count": `count(kube_replicaset_created{namespace=~"$1"})`,
|
||||
"workspace_service_count": `sum(kube_service_info{namespace=~"$1"})`,
|
||||
"workspace_secret_count": `sum(kube_secret_info{namespace=~"$1"})`,
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
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 metrics
|
||||
|
||||
type FormatedLevelMetric struct {
|
||||
MetricsLevel string `json:"metrics_level"`
|
||||
Results []FormatedMetric `json:"results"`
|
||||
}
|
||||
|
||||
type FormatedMetric struct {
|
||||
MetricName string `json:"metric_name, omitempty"`
|
||||
Status string `json:"status"`
|
||||
Data FormatedMetricData `json:"data, omitempty"`
|
||||
}
|
||||
|
||||
type FormatedMetricData struct {
|
||||
Result []map[string]interface{} `json:"result"`
|
||||
ResultType string `json:"resultType"`
|
||||
}
|
||||
|
||||
type CommonMetricsResult struct {
|
||||
Status string `json:"status"`
|
||||
Data CommonMetricsData `json:"data"`
|
||||
}
|
||||
|
||||
type CommonMetricsData struct {
|
||||
Result []CommonResultItem `json:"result"`
|
||||
ResultType string `json:"resultType"`
|
||||
}
|
||||
|
||||
type CommonResultItem struct {
|
||||
KubePodMetric KubePodMetric `json:"metric"`
|
||||
Value interface{} `json:"value"`
|
||||
}
|
||||
|
||||
/**
|
||||
"__name__": "kube_pod_info",
|
||||
"created_by_kind": "\\u003cnone\\u003e",
|
||||
"created_by_name": "\\u003cnone\\u003e",
|
||||
"endpoint": "https-main",
|
||||
"host_ip": "192.168.0.13",
|
||||
"instance": "10.244.114.187:8443",
|
||||
"job": "kube-state-metrics",
|
||||
"namespace": "kube-system",
|
||||
"node": "i-39p7faw6",
|
||||
"pod": "cloud-controller-manager-i-39p7faw6",
|
||||
"pod_ip": "192.168.0.13",
|
||||
"service": "kube-state-metrics"
|
||||
*/
|
||||
type KubePodMetric struct {
|
||||
CreatedByKind string `json:"created_by_kind"`
|
||||
CreatedByName string `json:"created_by_name"`
|
||||
Namespace string `json:"namespace"`
|
||||
Pod string `json:"pod"`
|
||||
}
|
||||
268
pkg/models/metrics/util.go
Normal file
268
pkg/models/metrics/util.go
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
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 metrics
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math"
|
||||
"sort"
|
||||
"strconv"
|
||||
"unicode"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultPageLimit = 5
|
||||
DefaultPage = 1
|
||||
)
|
||||
|
||||
type FormatedMetricDataWrapper struct {
|
||||
fmtMetricData FormatedMetricData
|
||||
by func(p, q *map[string]interface{}) bool
|
||||
}
|
||||
|
||||
func (wrapper FormatedMetricDataWrapper) Len() int {
|
||||
return len(wrapper.fmtMetricData.Result)
|
||||
}
|
||||
|
||||
func (wrapper FormatedMetricDataWrapper) Less(i, j int) bool {
|
||||
return wrapper.by(&wrapper.fmtMetricData.Result[i], &wrapper.fmtMetricData.Result[j])
|
||||
}
|
||||
|
||||
func (wrapper FormatedMetricDataWrapper) Swap(i, j int) {
|
||||
wrapper.fmtMetricData.Result[i], wrapper.fmtMetricData.Result[j] = wrapper.fmtMetricData.Result[j], wrapper.fmtMetricData.Result[i]
|
||||
}
|
||||
|
||||
// sorted metric by ascending or descending order
|
||||
func Sort(sortMetricName string, sortType string, fmtLevelMetric *FormatedLevelMetric, resourceType string) (*FormatedLevelMetric, int) {
|
||||
var maxLength = 0
|
||||
for _, metricItem := range fmtLevelMetric.Results {
|
||||
if metricItem.Data.ResultType == ResultTypeVector && metricItem.Status == MetricStatusSuccess {
|
||||
if maxLength < len(metricItem.Data.Result) {
|
||||
maxLength = len(metricItem.Data.Result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if sortMetricName == "" {
|
||||
return fmtLevelMetric, maxLength
|
||||
}
|
||||
|
||||
// default sort type is descending order
|
||||
if sortType == "" {
|
||||
sortType = ResultSortTypeDesc
|
||||
}
|
||||
|
||||
var currentResourceMap = make(map[string]int)
|
||||
|
||||
// indexMap store sorted index for each node/namespace/pod
|
||||
var indexMap = make(map[string]int)
|
||||
for _, metricItem := range fmtLevelMetric.Results {
|
||||
if metricItem.Data.ResultType == ResultTypeVector && metricItem.Status == MetricStatusSuccess {
|
||||
if metricItem.MetricName == sortMetricName {
|
||||
if sortType == ResultSortTypeAsce {
|
||||
// desc
|
||||
sort.Sort(FormatedMetricDataWrapper{metricItem.Data, func(p, q *map[string]interface{}) bool {
|
||||
value1 := (*p)[ResultItemValue].([]interface{})
|
||||
value2 := (*q)[ResultItemValue].([]interface{})
|
||||
v1, _ := strconv.ParseFloat(value1[len(value1)-1].(string), 64)
|
||||
v2, _ := strconv.ParseFloat(value2[len(value2)-1].(string), 64)
|
||||
return v1 < v2
|
||||
}})
|
||||
} else {
|
||||
// desc
|
||||
sort.Sort(FormatedMetricDataWrapper{metricItem.Data, func(p, q *map[string]interface{}) bool {
|
||||
value1 := (*p)[ResultItemValue].([]interface{})
|
||||
value2 := (*q)[ResultItemValue].([]interface{})
|
||||
v1, _ := strconv.ParseFloat(value1[len(value1)-1].(string), 64)
|
||||
v2, _ := strconv.ParseFloat(value2[len(value2)-1].(string), 64)
|
||||
return v1 > v2
|
||||
}})
|
||||
}
|
||||
|
||||
i := 0
|
||||
for _, r := range metricItem.Data.Result {
|
||||
// for some reasons, 'metric' may not contain `resourceType` field
|
||||
// example: {"metric":{},"value":[1541142931.731,"3"]}
|
||||
k, exist := r[ResultItemMetric].(map[string]interface{})[resourceType]
|
||||
if exist {
|
||||
indexMap[k.(string)] = i
|
||||
i = i + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iterator all metric to find max metricItems length
|
||||
for _, r := range metricItem.Data.Result {
|
||||
k, ok := r[ResultItemMetric].(map[string]interface{})[resourceType]
|
||||
if ok {
|
||||
currentResourceMap[k.(string)] = 1
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// sort other metric
|
||||
for i := 0; i < len(fmtLevelMetric.Results); i++ {
|
||||
re := fmtLevelMetric.Results[i]
|
||||
if re.MetricName != sortMetricName && re.Data.ResultType == ResultTypeVector && re.Status == MetricStatusSuccess {
|
||||
sortedMetric := make([]map[string]interface{}, len(indexMap))
|
||||
noneSortedMetric := make([]map[string]interface{}, 0)
|
||||
for j := 0; j < len(re.Data.Result); j++ {
|
||||
r := re.Data.Result[j]
|
||||
k, ok := r[ResultItemMetric].(map[string]interface{})[resourceType]
|
||||
if ok {
|
||||
index, exist := indexMap[k.(string)]
|
||||
if exist {
|
||||
sortedMetric[index] = r
|
||||
} else {
|
||||
noneSortedMetric = append(noneSortedMetric, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sortedMetric = append(sortedMetric, noneSortedMetric...)
|
||||
fmtLevelMetric.Results[i].Data.Result = sortedMetric
|
||||
}
|
||||
}
|
||||
|
||||
return fmtLevelMetric, maxLength
|
||||
}
|
||||
|
||||
func Page(pageNum string, limitNum string, fmtLevelMetric *FormatedLevelMetric, maxLength int) interface{} {
|
||||
// matrix type can not be sorted
|
||||
for _, metricItem := range fmtLevelMetric.Results {
|
||||
if metricItem.Data.ResultType != ResultTypeVector {
|
||||
return fmtLevelMetric
|
||||
}
|
||||
}
|
||||
|
||||
var page = DefaultPage
|
||||
|
||||
if pageNum != "" {
|
||||
p, err := strconv.Atoi(pageNum)
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
} else {
|
||||
if p > 0 {
|
||||
page = p
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// the default mode is none paging
|
||||
return fmtLevelMetric
|
||||
}
|
||||
|
||||
var limit = DefaultPageLimit
|
||||
|
||||
if limitNum != "" {
|
||||
l, err := strconv.Atoi(limitNum)
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
} else {
|
||||
if l > 0 {
|
||||
limit = l
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the i page: [(page-1) * limit, (page) * limit - 1]
|
||||
start := (page - 1) * limit
|
||||
end := (page)*limit - 1
|
||||
|
||||
for i := 0; i < len(fmtLevelMetric.Results); i++ {
|
||||
// only pageing when result type is `vector` and result status is `success`
|
||||
if fmtLevelMetric.Results[i].Data.ResultType != ResultTypeVector || fmtLevelMetric.Results[i].Status != MetricStatusSuccess {
|
||||
continue
|
||||
}
|
||||
resultLen := len(fmtLevelMetric.Results[i].Data.Result)
|
||||
if start >= resultLen {
|
||||
fmtLevelMetric.Results[i].Data.Result = nil
|
||||
continue
|
||||
}
|
||||
if end >= resultLen {
|
||||
end = resultLen - 1
|
||||
}
|
||||
slice := fmtLevelMetric.Results[i].Data.Result[start : end+1]
|
||||
fmtLevelMetric.Results[i].Data.Result = slice
|
||||
}
|
||||
|
||||
allPage := int(math.Ceil(float64(maxLength) / float64(limit)))
|
||||
|
||||
return &PagedFormatedLevelMetric{
|
||||
Message: "paged",
|
||||
TotalPage: allPage,
|
||||
CurrentPage: page,
|
||||
Metric: *fmtLevelMetric,
|
||||
}
|
||||
}
|
||||
|
||||
// maybe this function is time consuming
|
||||
func ReformatJson(metric string, metricsName string, needDelParams ...string) *FormatedMetric {
|
||||
var formatMetric FormatedMetric
|
||||
err := json.Unmarshal([]byte(metric), &formatMetric)
|
||||
if err != nil {
|
||||
glog.Errorln("Unmarshal metric json failed", err)
|
||||
}
|
||||
if formatMetric.MetricName == "" {
|
||||
if metricsName != "" {
|
||||
formatMetric.MetricName = metricsName
|
||||
}
|
||||
}
|
||||
// retrive metrics success
|
||||
if formatMetric.Status == MetricStatusSuccess {
|
||||
result := formatMetric.Data.Result
|
||||
for _, res := range result {
|
||||
metric, exist := res[ResultItemMetric]
|
||||
metricMap := metric.(map[string]interface{})
|
||||
if exist {
|
||||
delete(metricMap, "__name__")
|
||||
}
|
||||
if len(needDelParams) > 0 {
|
||||
for _, p := range needDelParams {
|
||||
delete(metricMap, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &formatMetric
|
||||
}
|
||||
|
||||
func ReformatNodeStatusField(nodeMetric *FormatedMetric) *FormatedMetric {
|
||||
metricCount := len(nodeMetric.Data.Result)
|
||||
for i := 0; i < metricCount; i++ {
|
||||
metric, exist := nodeMetric.Data.Result[i][ResultItemMetric]
|
||||
if exist {
|
||||
status, exist := metric.(map[string]interface{})[MetricStatus]
|
||||
if exist {
|
||||
status = UpperFirstLetter(status.(string))
|
||||
metric.(map[string]interface{})[MetricStatus] = status
|
||||
}
|
||||
}
|
||||
}
|
||||
return nodeMetric
|
||||
}
|
||||
|
||||
func UpperFirstLetter(str string) string {
|
||||
for i, ch := range str {
|
||||
return string(unicode.ToUpper(ch)) + str[i+1:]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in New Issue
Block a user