mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-01 10:12:02 +08:00
184 lines
7.1 KiB
Go
184 lines
7.1 KiB
Go
package inframetrics
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/SigNoz/signoz/pkg/query-service/constants"
|
|
"github.com/SigNoz/signoz/pkg/query-service/model"
|
|
)
|
|
|
|
var (
|
|
// TODO(srikanthccv): import metadata yaml from receivers and use generated files to check the metrics
|
|
podMetricNamesToCheck = []string{
|
|
"k8s_pod_cpu_utilization",
|
|
"k8s_pod_memory_usage",
|
|
"k8s_pod_cpu_request_utilization",
|
|
"k8s_pod_memory_request_utilization",
|
|
"k8s_pod_cpu_limit_utilization",
|
|
"k8s_pod_memory_limit_utilization",
|
|
"k8s_container_restarts",
|
|
"k8s_pod_phase",
|
|
}
|
|
nodeMetricNamesToCheck = []string{
|
|
"k8s_node_cpu_utilization",
|
|
"k8s_node_allocatable_cpu",
|
|
"k8s_node_memory_usage",
|
|
"k8s_node_allocatable_memory",
|
|
"k8s_node_condition_ready",
|
|
}
|
|
clusterMetricNamesToCheck = []string{
|
|
"k8s_daemonset_desired_scheduled_nodes",
|
|
"k8s_daemonset_current_scheduled_nodes",
|
|
"k8s_deployment_desired",
|
|
"k8s_deployment_available",
|
|
"k8s_job_desired_successful_pods",
|
|
"k8s_job_active_pods",
|
|
"k8s_job_failed_pods",
|
|
"k8s_job_successful_pods",
|
|
"k8s_statefulset_desired_pods",
|
|
"k8s_statefulset_current_pods",
|
|
}
|
|
optionalPodMetricNamesToCheck = []string{
|
|
"k8s_pod_cpu_request_utilization",
|
|
"k8s_pod_memory_request_utilization",
|
|
"k8s_pod_cpu_limit_utilization",
|
|
"k8s_pod_memory_limit_utilization",
|
|
}
|
|
|
|
// did they ever send _any_ pod metrics?
|
|
didSendPodMetricsQuery = `
|
|
SELECT count() FROM %s.%s WHERE metric_name IN (%s)
|
|
`
|
|
|
|
// did they ever send any node metrics?
|
|
didSendNodeMetricsQuery = `
|
|
SELECT count() FROM %s.%s WHERE metric_name IN (%s)
|
|
`
|
|
|
|
// did they ever send any cluster metrics?
|
|
didSendClusterMetricsQuery = `
|
|
SELECT count() FROM %s.%s WHERE metric_name IN (%s)
|
|
`
|
|
|
|
// if they ever sent _any_ pod metrics, we assume they know how to send pod metrics
|
|
// now, are they sending optional pod metrics such request/limit metrics?
|
|
isSendingOptionalPodMetricsQuery = `
|
|
SELECT count() FROM %s.%s WHERE metric_name IN (%s)
|
|
`
|
|
|
|
// there should be [cluster, node, namespace, one of (deployment, statefulset, daemonset, cronjob, job)] for each pod
|
|
isSendingRequiredMetadataQuery = `
|
|
SELECT any(JSONExtractString(labels, 'k8s_cluster_name')) as k8s_cluster_name,
|
|
any(JSONExtractString(labels, 'k8s_node_name')) as k8s_node_name,
|
|
any(JSONExtractString(labels, 'k8s_namespace_name')) as k8s_namespace_name,
|
|
any(JSONExtractString(labels, 'k8s_deployment_name')) as k8s_deployment_name,
|
|
any(JSONExtractString(labels, 'k8s_statefulset_name')) as k8s_statefulset_name,
|
|
any(JSONExtractString(labels, 'k8s_daemonset_name')) as k8s_daemonset_name,
|
|
any(JSONExtractString(labels, 'k8s_cronjob_name')) as k8s_cronjob_name,
|
|
any(JSONExtractString(labels, 'k8s_job_name')) as k8s_job_name,
|
|
JSONExtractString(labels, 'k8s_pod_name') as k8s_pod_name
|
|
FROM %s.%s WHERE metric_name IN (%s)
|
|
AND (unix_milli >= (toUnixTimestamp(now() - toIntervalMinute(60)) * 1000))
|
|
AND JSONExtractString(labels, 'k8s_namespace_name') NOT IN ('kube-system', 'kube-public', 'kube-node-lease', 'metallb-system')
|
|
GROUP BY k8s_pod_name
|
|
LIMIT 1 BY k8s_cluster_name, k8s_node_name, k8s_namespace_name
|
|
`
|
|
)
|
|
|
|
// getParamsForTopItems returns the step, time series table name and samples table name
|
|
// for the top items query. what are we doing here?
|
|
// we want to identify the top hosts/pods/nodes quickly, so we use pre-aggregated data
|
|
// for samples and time series tables to speed up the query
|
|
// the speed of the query depends on the number of values in group by clause, the higher
|
|
// the step interval, the faster the query will be as number of rows to group by is reduced
|
|
// here we are using the averaged value of the time series data to get the top items
|
|
func getParamsForTopItems(start, end int64) (int64, string, string) {
|
|
var step int64
|
|
var timeSeriesTableName string
|
|
var samplesTableName string
|
|
|
|
if end-start < time.Hour.Milliseconds() {
|
|
// 5 minute aggregation for any query less than 1 hour
|
|
step = 5 * 60
|
|
timeSeriesTableName = constants.SIGNOZ_TIMESERIES_v4_LOCAL_TABLENAME
|
|
samplesTableName = constants.SIGNOZ_SAMPLES_V4_AGG_5M_TABLENAME
|
|
} else if end-start < time.Hour.Milliseconds()*6 {
|
|
// 15 minute aggregation for any query less than 6 hours
|
|
step = 15 * 60
|
|
timeSeriesTableName = constants.SIGNOZ_TIMESERIES_v4_6HRS_LOCAL_TABLENAME
|
|
samplesTableName = constants.SIGNOZ_SAMPLES_V4_AGG_5M_TABLENAME
|
|
} else if end-start < time.Hour.Milliseconds()*24 {
|
|
// 1 hour aggregation for any query less than 1 day
|
|
step = 60 * 60
|
|
timeSeriesTableName = constants.SIGNOZ_TIMESERIES_v4_1DAY_LOCAL_TABLENAME
|
|
samplesTableName = constants.SIGNOZ_SAMPLES_V4_AGG_30M_TABLENAME
|
|
} else if end-start < time.Hour.Milliseconds()*7 {
|
|
// 6 hours aggregation for any query less than 1 week
|
|
step = 6 * 60 * 60
|
|
timeSeriesTableName = constants.SIGNOZ_TIMESERIES_v4_1WEEK_LOCAL_TABLENAME
|
|
samplesTableName = constants.SIGNOZ_SAMPLES_V4_AGG_30M_TABLENAME
|
|
} else {
|
|
// 12 hours aggregation for any query greater than 1 week
|
|
step = 12 * 60 * 60
|
|
timeSeriesTableName = constants.SIGNOZ_TIMESERIES_v4_1WEEK_LOCAL_TABLENAME
|
|
samplesTableName = constants.SIGNOZ_SAMPLES_V4_AGG_30M_TABLENAME
|
|
}
|
|
return step, timeSeriesTableName, samplesTableName
|
|
}
|
|
|
|
func getParamsForTopHosts(req model.HostListRequest) (int64, string, string) {
|
|
return getParamsForTopItems(req.Start, req.End)
|
|
}
|
|
|
|
func getParamsForTopProcesses(req model.ProcessListRequest) (int64, string, string) {
|
|
return getParamsForTopItems(req.Start, req.End)
|
|
}
|
|
|
|
func getParamsForTopPods(req model.PodListRequest) (int64, string, string) {
|
|
return getParamsForTopItems(req.Start, req.End)
|
|
}
|
|
|
|
func getParamsForTopNodes(req model.NodeListRequest) (int64, string, string) {
|
|
return getParamsForTopItems(req.Start, req.End)
|
|
}
|
|
|
|
func getParamsForTopNamespaces(req model.NamespaceListRequest) (int64, string, string) {
|
|
return getParamsForTopItems(req.Start, req.End)
|
|
}
|
|
|
|
func getParamsForTopClusters(req model.ClusterListRequest) (int64, string, string) {
|
|
return getParamsForTopItems(req.Start, req.End)
|
|
}
|
|
|
|
func getParamsForTopDeployments(req model.DeploymentListRequest) (int64, string, string) {
|
|
return getParamsForTopItems(req.Start, req.End)
|
|
}
|
|
|
|
func getParamsForTopDaemonSets(req model.DaemonSetListRequest) (int64, string, string) {
|
|
return getParamsForTopItems(req.Start, req.End)
|
|
}
|
|
|
|
func getParamsForTopStatefulSets(req model.StatefulSetListRequest) (int64, string, string) {
|
|
return getParamsForTopItems(req.Start, req.End)
|
|
}
|
|
|
|
func getParamsForTopJobs(req model.JobListRequest) (int64, string, string) {
|
|
return getParamsForTopItems(req.Start, req.End)
|
|
}
|
|
|
|
func getParamsForTopVolumes(req model.VolumeListRequest) (int64, string, string) {
|
|
return getParamsForTopItems(req.Start, req.End)
|
|
}
|
|
|
|
// TODO(srikanthccv): remove this
|
|
// What is happening here?
|
|
// The `PrepareTimeseriesFilterQuery` uses the local time series table for sub-query because each fingerprint
|
|
// goes to same shard.
|
|
// However, in this case, we are interested in the attributes values across all the shards.
|
|
// So, we replace the local time series table with the distributed time series table.
|
|
// See `PrepareTimeseriesFilterQuery` for more details.
|
|
func localQueryToDistributedQuery(query string) string {
|
|
return strings.Replace(query, ".time_series_v4", ".distributed_time_series_v4", 1)
|
|
}
|