chore: support for non-normalized metrics behind a feature flag (#7919)

feat(7294-services): added dot metrics boolean for services tab
This commit is contained in:
aniketio-ctrl 2025-05-30 15:57:29 +05:30 committed by GitHub
parent c08d1bccaf
commit 68effaf232
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
121 changed files with 17187 additions and 14622 deletions

View File

@ -3,6 +3,7 @@ package httplicensing
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"github.com/SigNoz/signoz/ee/query-service/constants"
"time" "time"
"github.com/SigNoz/signoz/ee/licensing/licensingstore/sqllicensingstore" "github.com/SigNoz/signoz/ee/licensing/licensingstore/sqllicensingstore"
@ -251,6 +252,13 @@ func (provider *provider) GetFeatureFlags(ctx context.Context) ([]*featuretypes.
} }
} }
if constants.IsDotMetricsEnabled {
gettableFeatures = append(gettableFeatures, &featuretypes.GettableFeature{
Name: featuretypes.DotMetricsEnabled,
Active: true,
})
}
return gettableFeatures, nil return gettableFeatures, nil
} }

View File

@ -4,6 +4,10 @@ import (
"os" "os"
) )
const (
DefaultSiteURL = "https://localhost:8080"
)
var LicenseSignozIo = "https://license.signoz.io/api/v1" var LicenseSignozIo = "https://license.signoz.io/api/v1"
var LicenseAPIKey = GetOrDefaultEnv("SIGNOZ_LICENSE_API_KEY", "") var LicenseAPIKey = GetOrDefaultEnv("SIGNOZ_LICENSE_API_KEY", "")
var SaasSegmentKey = GetOrDefaultEnv("SIGNOZ_SAAS_SEGMENT_KEY", "") var SaasSegmentKey = GetOrDefaultEnv("SIGNOZ_SAAS_SEGMENT_KEY", "")
@ -20,3 +24,22 @@ func GetOrDefaultEnv(key string, fallback string) string {
} }
return v return v
} }
// constant functions that override env vars
// GetDefaultSiteURL returns default site url, primarily
// used to send saml request and allowing backend to
// handle http redirect
func GetDefaultSiteURL() string {
return GetOrDefaultEnv("SIGNOZ_SITE_URL", DefaultSiteURL)
}
const DotMetricsEnabled = "DOT_METRICS_ENABLED"
var IsDotMetricsEnabled = false
func init() {
if GetOrDefaultEnv(DotMetricsEnabled, "false") == "true" {
IsDotMetricsEnabled = true
}
}

View File

@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData'; import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
import { UnderscoreToDotMap } from '../utils';
export interface K8sClustersListPayload { export interface K8sClustersListPayload {
filters: TagFilter; filters: TagFilter;
groupBy?: BaseAutocompleteData[]; groupBy?: BaseAutocompleteData[];
@ -40,23 +42,80 @@ export interface K8sClustersListResponse {
}; };
} }
export const clustersMetaMap = [
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
{ dot: 'k8s.cluster.uid', under: 'k8s_cluster_uid' },
] as const;
export function mapClustersMeta(
raw: Record<string, unknown>,
): K8sClustersData['meta'] {
const out: Record<string, unknown> = { ...raw };
clustersMetaMap.forEach(({ dot, under }) => {
if (dot in raw) {
const v = raw[dot];
out[under] = typeof v === 'string' ? v : raw[under];
}
});
return out as K8sClustersData['meta'];
}
export const getK8sClustersList = async ( export const getK8sClustersList = async (
props: K8sClustersListPayload, props: K8sClustersListPayload,
signal?: AbortSignal, signal?: AbortSignal,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled = false,
): Promise<SuccessResponse<K8sClustersListResponse> | ErrorResponse> => { ): Promise<SuccessResponse<K8sClustersListResponse> | ErrorResponse> => {
try { try {
const response = await axios.post('/clusters/list', props, { const requestProps =
dotMetricsEnabled && Array.isArray(props.filters?.items)
? {
...props,
filters: {
...props.filters,
items: props.filters.items.reduce<typeof props.filters.items>(
(acc, item) => {
if (item.value === undefined) return acc;
if (
item.key &&
typeof item.key === 'object' &&
'key' in item.key &&
typeof item.key.key === 'string'
) {
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
acc.push({
...item,
key: { ...item.key, key: mappedKey },
});
} else {
acc.push(item);
}
return acc;
},
[] as typeof props.filters.items,
),
},
}
: props;
const response = await axios.post('/clusters/list', requestProps, {
signal, signal,
headers, headers,
}); });
const payload: K8sClustersListResponse = response.data;
// one-liner meta mapping
payload.data.records = payload.data.records.map((record) => ({
...record,
meta: mapClustersMeta(record.meta as Record<string, unknown>),
}));
return { return {
statusCode: 200, statusCode: 200,
error: null, error: null,
message: 'Success', message: 'Success',
payload: response.data, payload,
params: props, params: requestProps,
}; };
} catch (error) { } catch (error) {
return ErrorResponseHandler(error as AxiosError); return ErrorResponseHandler(error as AxiosError);

View File

@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData'; import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
import { UnderscoreToDotMap } from '../utils';
export interface K8sDaemonSetsListPayload { export interface K8sDaemonSetsListPayload {
filters: TagFilter; filters: TagFilter;
groupBy?: BaseAutocompleteData[]; groupBy?: BaseAutocompleteData[];
@ -46,23 +48,82 @@ export interface K8sDaemonSetsListResponse {
}; };
} }
export const daemonSetsMetaMap = [
{ dot: 'k8s.namespace.name', under: 'k8s_namespace_name' },
{ dot: 'k8s.daemonset.name', under: 'k8s_daemonset_name' },
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
] as const;
export function mapDaemonSetsMeta(
raw: Record<string, unknown>,
): K8sDaemonSetsData['meta'] {
const out: Record<string, unknown> = { ...raw };
daemonSetsMetaMap.forEach(({ dot, under }) => {
if (dot in raw) {
const v = raw[dot];
out[under] = typeof v === 'string' ? v : raw[under];
}
});
return out as K8sDaemonSetsData['meta'];
}
export const getK8sDaemonSetsList = async ( export const getK8sDaemonSetsList = async (
props: K8sDaemonSetsListPayload, props: K8sDaemonSetsListPayload,
signal?: AbortSignal, signal?: AbortSignal,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled = false,
): Promise<SuccessResponse<K8sDaemonSetsListResponse> | ErrorResponse> => { ): Promise<SuccessResponse<K8sDaemonSetsListResponse> | ErrorResponse> => {
try { try {
const response = await axios.post('/daemonsets/list', props, { // filter prep (unchanged)…
const requestProps =
dotMetricsEnabled && Array.isArray(props.filters?.items)
? {
...props,
filters: {
...props.filters,
items: props.filters.items.reduce<typeof props.filters.items>(
(acc, item) => {
if (item.value === undefined) return acc;
if (
item.key &&
typeof item.key === 'object' &&
'key' in item.key &&
typeof item.key.key === 'string'
) {
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
acc.push({
...item,
key: { ...item.key, key: mappedKey },
});
} else {
acc.push(item);
}
return acc;
},
[] as typeof props.filters.items,
),
},
}
: props;
const response = await axios.post('/daemonsets/list', requestProps, {
signal, signal,
headers, headers,
}); });
const payload: K8sDaemonSetsListResponse = response.data;
// single-line meta mapping
payload.data.records = payload.data.records.map((record) => ({
...record,
meta: mapDaemonSetsMeta(record.meta as Record<string, unknown>),
}));
return { return {
statusCode: 200, statusCode: 200,
error: null, error: null,
message: 'Success', message: 'Success',
payload: response.data, payload,
params: props, params: requestProps,
}; };
} catch (error) { } catch (error) {
return ErrorResponseHandler(error as AxiosError); return ErrorResponseHandler(error as AxiosError);

View File

@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData'; import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
import { UnderscoreToDotMap } from '../utils';
export interface K8sDeploymentsListPayload { export interface K8sDeploymentsListPayload {
filters: TagFilter; filters: TagFilter;
groupBy?: BaseAutocompleteData[]; groupBy?: BaseAutocompleteData[];
@ -46,23 +48,81 @@ export interface K8sDeploymentsListResponse {
}; };
} }
export const deploymentsMetaMap = [
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
{ dot: 'k8s.deployment.name', under: 'k8s_deployment_name' },
{ dot: 'k8s.namespace.name', under: 'k8s_namespace_name' },
] as const;
export function mapDeploymentsMeta(
raw: Record<string, unknown>,
): K8sDeploymentsData['meta'] {
const out: Record<string, unknown> = { ...raw };
deploymentsMetaMap.forEach(({ dot, under }) => {
if (dot in raw) {
const v = raw[dot];
out[under] = typeof v === 'string' ? v : raw[under];
}
});
return out as K8sDeploymentsData['meta'];
}
export const getK8sDeploymentsList = async ( export const getK8sDeploymentsList = async (
props: K8sDeploymentsListPayload, props: K8sDeploymentsListPayload,
signal?: AbortSignal, signal?: AbortSignal,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled = false,
): Promise<SuccessResponse<K8sDeploymentsListResponse> | ErrorResponse> => { ): Promise<SuccessResponse<K8sDeploymentsListResponse> | ErrorResponse> => {
try { try {
const response = await axios.post('/deployments/list', props, { const requestProps =
dotMetricsEnabled && Array.isArray(props.filters?.items)
? {
...props,
filters: {
...props.filters,
items: props.filters.items.reduce<typeof props.filters.items>(
(acc, item) => {
if (item.value === undefined) return acc;
if (
item.key &&
typeof item.key === 'object' &&
'key' in item.key &&
typeof item.key.key === 'string'
) {
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
acc.push({
...item,
key: { ...item.key, key: mappedKey },
});
} else {
acc.push(item);
}
return acc;
},
[] as typeof props.filters.items,
),
},
}
: props;
const response = await axios.post('/deployments/list', requestProps, {
signal, signal,
headers, headers,
}); });
const payload: K8sDeploymentsListResponse = response.data;
// single-line mapping
payload.data.records = payload.data.records.map((record) => ({
...record,
meta: mapDeploymentsMeta(record.meta as Record<string, unknown>),
}));
return { return {
statusCode: 200, statusCode: 200,
error: null, error: null,
message: 'Success', message: 'Success',
payload: response.data, payload,
params: props, params: requestProps,
}; };
} catch (error) { } catch (error) {
return ErrorResponseHandler(error as AxiosError); return ErrorResponseHandler(error as AxiosError);

View File

@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData'; import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
import { UnderscoreToDotMap } from '../utils';
export interface K8sJobsListPayload { export interface K8sJobsListPayload {
filters: TagFilter; filters: TagFilter;
groupBy?: BaseAutocompleteData[]; groupBy?: BaseAutocompleteData[];
@ -48,23 +50,79 @@ export interface K8sJobsListResponse {
}; };
} }
export const jobsMetaMap = [
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
{ dot: 'k8s.job.name', under: 'k8s_job_name' },
{ dot: 'k8s.namespace.name', under: 'k8s_namespace_name' },
] as const;
export function mapJobsMeta(raw: Record<string, unknown>): K8sJobsData['meta'] {
const out: Record<string, unknown> = { ...raw };
jobsMetaMap.forEach(({ dot, under }) => {
if (dot in raw) {
const v = raw[dot];
out[under] = typeof v === 'string' ? v : raw[under];
}
});
return out as K8sJobsData['meta'];
}
export const getK8sJobsList = async ( export const getK8sJobsList = async (
props: K8sJobsListPayload, props: K8sJobsListPayload,
signal?: AbortSignal, signal?: AbortSignal,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled = false,
): Promise<SuccessResponse<K8sJobsListResponse> | ErrorResponse> => { ): Promise<SuccessResponse<K8sJobsListResponse> | ErrorResponse> => {
try { try {
const response = await axios.post('/jobs/list', props, { const requestProps =
dotMetricsEnabled && Array.isArray(props.filters?.items)
? {
...props,
filters: {
...props.filters,
items: props.filters.items.reduce<typeof props.filters.items>(
(acc, item) => {
if (item.value === undefined) return acc;
if (
item.key &&
typeof item.key === 'object' &&
'key' in item.key &&
typeof item.key.key === 'string'
) {
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
acc.push({
...item,
key: { ...item.key, key: mappedKey },
});
} else {
acc.push(item);
}
return acc;
},
[] as typeof props.filters.items,
),
},
}
: props;
const response = await axios.post('/jobs/list', requestProps, {
signal, signal,
headers, headers,
}); });
const payload: K8sJobsListResponse = response.data;
// one-liner meta mapping
payload.data.records = payload.data.records.map((record) => ({
...record,
meta: mapJobsMeta(record.meta as Record<string, unknown>),
}));
return { return {
statusCode: 200, statusCode: 200,
error: null, error: null,
message: 'Success', message: 'Success',
payload: response.data, payload,
params: props, params: requestProps,
}; };
} catch (error) { } catch (error) {
return ErrorResponseHandler(error as AxiosError); return ErrorResponseHandler(error as AxiosError);

View File

@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData'; import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
import { UnderscoreToDotMap } from '../utils';
export interface K8sNamespacesListPayload { export interface K8sNamespacesListPayload {
filters: TagFilter; filters: TagFilter;
groupBy?: BaseAutocompleteData[]; groupBy?: BaseAutocompleteData[];
@ -38,23 +40,79 @@ export interface K8sNamespacesListResponse {
}; };
} }
export const namespacesMetaMap = [
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
{ dot: 'k8s.namespace.name', under: 'k8s_namespace_name' },
] as const;
export function mapNamespacesMeta(
raw: Record<string, unknown>,
): K8sNamespacesData['meta'] {
const out: Record<string, unknown> = { ...raw };
namespacesMetaMap.forEach(({ dot, under }) => {
if (dot in raw) {
const v = raw[dot];
out[under] = typeof v === 'string' ? v : raw[under];
}
});
return out as K8sNamespacesData['meta'];
}
export const getK8sNamespacesList = async ( export const getK8sNamespacesList = async (
props: K8sNamespacesListPayload, props: K8sNamespacesListPayload,
signal?: AbortSignal, signal?: AbortSignal,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled = false,
): Promise<SuccessResponse<K8sNamespacesListResponse> | ErrorResponse> => { ): Promise<SuccessResponse<K8sNamespacesListResponse> | ErrorResponse> => {
try { try {
const response = await axios.post('/namespaces/list', props, { const requestProps =
dotMetricsEnabled && Array.isArray(props.filters?.items)
? {
...props,
filters: {
...props.filters,
items: props.filters.items.reduce<typeof props.filters.items>(
(acc, item) => {
if (item.value === undefined) return acc;
if (
item.key &&
typeof item.key === 'object' &&
'key' in item.key &&
typeof item.key.key === 'string'
) {
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
acc.push({
...item,
key: { ...item.key, key: mappedKey },
});
} else {
acc.push(item);
}
return acc;
},
[] as typeof props.filters.items,
),
},
}
: props;
const response = await axios.post('/namespaces/list', requestProps, {
signal, signal,
headers, headers,
}); });
const payload: K8sNamespacesListResponse = response.data;
payload.data.records = payload.data.records.map((record) => ({
...record,
meta: mapNamespacesMeta(record.meta as Record<string, unknown>),
}));
return { return {
statusCode: 200, statusCode: 200,
error: null, error: null,
message: 'Success', message: 'Success',
payload: response.data, payload,
params: props, params: requestProps,
}; };
} catch (error) { } catch (error) {
return ErrorResponseHandler(error as AxiosError); return ErrorResponseHandler(error as AxiosError);

View File

@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData'; import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
import { UnderscoreToDotMap } from '../utils';
export interface K8sNodesListPayload { export interface K8sNodesListPayload {
filters: TagFilter; filters: TagFilter;
groupBy?: BaseAutocompleteData[]; groupBy?: BaseAutocompleteData[];
@ -41,23 +43,81 @@ export interface K8sNodesListResponse {
}; };
} }
export const nodesMetaMap = [
{ dot: 'k8s.node.name', under: 'k8s_node_name' },
{ dot: 'k8s.node.uid', under: 'k8s_node_uid' },
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
] as const;
export function mapNodesMeta(
raw: Record<string, unknown>,
): K8sNodesData['meta'] {
const out: Record<string, unknown> = { ...raw };
nodesMetaMap.forEach(({ dot, under }) => {
if (dot in raw) {
const v = raw[dot];
out[under] = typeof v === 'string' ? v : raw[under];
}
});
return out as K8sNodesData['meta'];
}
export const getK8sNodesList = async ( export const getK8sNodesList = async (
props: K8sNodesListPayload, props: K8sNodesListPayload,
signal?: AbortSignal, signal?: AbortSignal,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled = false,
): Promise<SuccessResponse<K8sNodesListResponse> | ErrorResponse> => { ): Promise<SuccessResponse<K8sNodesListResponse> | ErrorResponse> => {
try { try {
const response = await axios.post('/nodes/list', props, { const requestProps =
dotMetricsEnabled && Array.isArray(props.filters?.items)
? {
...props,
filters: {
...props.filters,
items: props.filters.items.reduce<typeof props.filters.items>(
(acc, item) => {
if (item.value === undefined) return acc;
if (
item.key &&
typeof item.key === 'object' &&
'key' in item.key &&
typeof item.key.key === 'string'
) {
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
acc.push({
...item,
key: { ...item.key, key: mappedKey },
});
} else {
acc.push(item);
}
return acc;
},
[] as typeof props.filters.items,
),
},
}
: props;
const response = await axios.post('/nodes/list', requestProps, {
signal, signal,
headers, headers,
}); });
const payload: K8sNodesListResponse = response.data;
// one-liner to map dot→underscore
payload.data.records = payload.data.records.map((record) => ({
...record,
meta: mapNodesMeta(record.meta as Record<string, unknown>),
}));
return { return {
statusCode: 200, statusCode: 200,
error: null, error: null,
message: 'Success', message: 'Success',
payload: response.data, payload,
params: props, params: requestProps,
}; };
} catch (error) { } catch (error) {
return ErrorResponseHandler(error as AxiosError); return ErrorResponseHandler(error as AxiosError);

View File

@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData'; import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
import { UnderscoreToDotMap } from '../utils';
export interface K8sPodsListPayload { export interface K8sPodsListPayload {
filters: TagFilter; filters: TagFilter;
groupBy?: BaseAutocompleteData[]; groupBy?: BaseAutocompleteData[];
@ -69,23 +71,87 @@ export interface K8sPodsListResponse {
}; };
} }
export const podsMetaMap = [
{ dot: 'k8s.cronjob.name', under: 'k8s_cronjob_name' },
{ dot: 'k8s.daemonset.name', under: 'k8s_daemonset_name' },
{ dot: 'k8s.deployment.name', under: 'k8s_deployment_name' },
{ dot: 'k8s.job.name', under: 'k8s_job_name' },
{ dot: 'k8s.namespace.name', under: 'k8s_namespace_name' },
{ dot: 'k8s.node.name', under: 'k8s_node_name' },
{ dot: 'k8s.pod.name', under: 'k8s_pod_name' },
{ dot: 'k8s.pod.uid', under: 'k8s_pod_uid' },
{ dot: 'k8s.statefulset.name', under: 'k8s_statefulset_name' },
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
] as const;
export function mapPodsMeta(raw: Record<string, unknown>): K8sPodsData['meta'] {
// clone everything
const out: Record<string, unknown> = { ...raw };
// overlay only the dot→under mappings
podsMetaMap.forEach(({ dot, under }) => {
if (dot in raw) {
const v = raw[dot];
out[under] = typeof v === 'string' ? v : raw[under];
}
});
return out as K8sPodsData['meta'];
}
// getK8sPodsList
export const getK8sPodsList = async ( export const getK8sPodsList = async (
props: K8sPodsListPayload, props: K8sPodsListPayload,
signal?: AbortSignal, signal?: AbortSignal,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled = false,
): Promise<SuccessResponse<K8sPodsListResponse> | ErrorResponse> => { ): Promise<SuccessResponse<K8sPodsListResponse> | ErrorResponse> => {
try { try {
const response = await axios.post('/pods/list', props, { const requestProps =
dotMetricsEnabled && Array.isArray(props.filters?.items)
? {
...props,
filters: {
...props.filters,
items: props.filters.items.reduce<typeof props.filters.items>(
(acc, item) => {
if (item.value === undefined) return acc;
if (
item.key &&
typeof item.key === 'object' &&
'key' in item.key &&
typeof item.key.key === 'string'
) {
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
acc.push({
...item,
key: { ...item.key, key: mappedKey },
});
} else {
acc.push(item);
}
return acc;
},
[] as typeof props.filters.items,
),
},
}
: props;
const response = await axios.post('/pods/list', requestProps, {
signal, signal,
headers, headers,
}); });
const payload: K8sPodsListResponse = response.data;
payload.data.records = payload.data.records.map((record) => ({
...record,
meta: mapPodsMeta(record.meta as Record<string, unknown>),
}));
return { return {
statusCode: 200, statusCode: 200,
error: null, error: null,
message: 'Success', message: 'Success',
payload: response.data, payload,
params: props, params: requestProps,
}; };
} catch (error) { } catch (error) {
return ErrorResponseHandler(error as AxiosError); return ErrorResponseHandler(error as AxiosError);

View File

@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData'; import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
import { UnderscoreToDotMap } from '../utils';
export interface K8sVolumesListPayload { export interface K8sVolumesListPayload {
filters: TagFilter; filters: TagFilter;
groupBy?: BaseAutocompleteData[]; groupBy?: BaseAutocompleteData[];
@ -47,23 +49,92 @@ export interface K8sVolumesListResponse {
}; };
} }
export const volumesMetaMap: Array<{
dot: keyof Record<string, unknown>;
under: keyof K8sVolumesData['meta'];
}> = [
{ dot: 'k8s.cluster.name', under: 'k8s_cluster_name' },
{ dot: 'k8s.namespace.name', under: 'k8s_namespace_name' },
{ dot: 'k8s.node.name', under: 'k8s_node_name' },
{
dot: 'k8s.persistentvolumeclaim.name',
under: 'k8s_persistentvolumeclaim_name',
},
{ dot: 'k8s.pod.name', under: 'k8s_pod_name' },
{ dot: 'k8s.pod.uid', under: 'k8s_pod_uid' },
{ dot: 'k8s.statefulset.name', under: 'k8s_statefulset_name' },
];
export function mapVolumesMeta(
rawMeta: Record<string, unknown>,
): K8sVolumesData['meta'] {
// start with everything that was already there
const out: Record<string, unknown> = { ...rawMeta };
// for each dot→under rule, if the raw has the dot, overwrite the underscore
volumesMetaMap.forEach(({ dot, under }) => {
if (dot in rawMeta) {
const val = rawMeta[dot];
out[under] = typeof val === 'string' ? val : rawMeta[under];
}
});
return out as K8sVolumesData['meta'];
}
export const getK8sVolumesList = async ( export const getK8sVolumesList = async (
props: K8sVolumesListPayload, props: K8sVolumesListPayload,
signal?: AbortSignal, signal?: AbortSignal,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled = false,
): Promise<SuccessResponse<K8sVolumesListResponse> | ErrorResponse> => { ): Promise<SuccessResponse<K8sVolumesListResponse> | ErrorResponse> => {
try { try {
const response = await axios.post('/pvcs/list', props, { // Prepare filters
const requestProps =
dotMetricsEnabled && Array.isArray(props.filters?.items)
? {
...props,
filters: {
...props.filters,
items: props.filters.items.reduce<typeof props.filters.items>(
(acc, item) => {
if (item.value === undefined) return acc;
if (
item.key &&
typeof item.key === 'object' &&
'key' in item.key &&
typeof item.key.key === 'string'
) {
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
acc.push({ ...item, key: { ...item.key, key: mappedKey } });
} else {
acc.push(item);
}
return acc;
},
[] as typeof props.filters.items,
),
},
}
: props;
const response = await axios.post('/pvcs/list', requestProps, {
signal, signal,
headers, headers,
}); });
const payload: K8sVolumesListResponse = response.data;
payload.data.records = payload.data.records.map((record) => ({
...record,
meta: mapVolumesMeta(record.meta as Record<string, unknown>),
}));
return { return {
statusCode: 200, statusCode: 200,
error: null, error: null,
message: 'Success', message: 'Success',
payload: response.data, payload,
params: props, params: requestProps,
}; };
} catch (error) { } catch (error) {
return ErrorResponseHandler(error as AxiosError); return ErrorResponseHandler(error as AxiosError);

View File

@ -5,6 +5,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData'; import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
import { UnderscoreToDotMap } from '../utils';
export interface K8sStatefulSetsListPayload { export interface K8sStatefulSetsListPayload {
filters: TagFilter; filters: TagFilter;
groupBy?: BaseAutocompleteData[]; groupBy?: BaseAutocompleteData[];
@ -45,23 +47,78 @@ export interface K8sStatefulSetsListResponse {
}; };
} }
export const statefulSetsMetaMap = [
{ dot: 'k8s.statefulset.name', under: 'k8s_statefulset_name' },
{ dot: 'k8s.namespace.name', under: 'k8s_namespace_name' },
] as const;
export function mapStatefulSetsMeta(
raw: Record<string, unknown>,
): K8sStatefulSetsData['meta'] {
const out: Record<string, unknown> = { ...raw };
statefulSetsMetaMap.forEach(({ dot, under }) => {
if (dot in raw) {
const v = raw[dot];
out[under] = typeof v === 'string' ? v : raw[under];
}
});
return out as K8sStatefulSetsData['meta'];
}
export const getK8sStatefulSetsList = async ( export const getK8sStatefulSetsList = async (
props: K8sStatefulSetsListPayload, props: K8sStatefulSetsListPayload,
signal?: AbortSignal, signal?: AbortSignal,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled = false,
): Promise<SuccessResponse<K8sStatefulSetsListResponse> | ErrorResponse> => { ): Promise<SuccessResponse<K8sStatefulSetsListResponse> | ErrorResponse> => {
try { try {
const response = await axios.post('/statefulsets/list', props, { // Prepare filters
const requestProps =
dotMetricsEnabled && Array.isArray(props.filters?.items)
? {
...props,
filters: {
...props.filters,
items: props.filters.items.reduce<typeof props.filters.items>(
(acc, item) => {
if (item.value === undefined) return acc;
if (
item.key &&
typeof item.key === 'object' &&
'key' in item.key &&
typeof item.key.key === 'string'
) {
const mappedKey = UnderscoreToDotMap[item.key.key] ?? item.key.key;
acc.push({ ...item, key: { ...item.key, key: mappedKey } });
} else {
acc.push(item);
}
return acc;
},
[] as typeof props.filters.items,
),
},
}
: props;
const response = await axios.post('/statefulsets/list', requestProps, {
signal, signal,
headers, headers,
}); });
const payload: K8sStatefulSetsListResponse = response.data;
// apply our helper
payload.data.records = payload.data.records.map((record) => ({
...record,
meta: mapStatefulSetsMeta(record.meta as Record<string, unknown>),
}));
return { return {
statusCode: 200, statusCode: 200,
error: null, error: null,
message: 'Success', message: 'Success',
payload: response.data, payload,
params: props, params: requestProps,
}; };
} catch (error) { } catch (error) {
return ErrorResponseHandler(error as AxiosError); return ErrorResponseHandler(error as AxiosError);

View File

@ -17,3 +17,19 @@ export const Logout = (): void => {
history.push(ROUTES.LOGIN); history.push(ROUTES.LOGIN);
}; };
export const UnderscoreToDotMap: Record<string, string> = {
k8s_cluster_name: 'k8s.cluster.name',
k8s_cluster_uid: 'k8s.cluster.uid',
k8s_namespace_name: 'k8s.namespace.name',
k8s_node_name: 'k8s.node.name',
k8s_node_uid: 'k8s.node.uid',
k8s_pod_name: 'k8s.pod.name',
k8s_pod_uid: 'k8s.pod.uid',
k8s_deployment_name: 'k8s.deployment.name',
k8s_daemonset_name: 'k8s.daemonset.name',
k8s_statefulset_name: 'k8s.statefulset.name',
k8s_cronjob_name: 'k8s.cronjob.name',
k8s_job_name: 'k8s.job.name',
k8s_persistentvolumeclaim_name: 'k8s.persistentvolumeclaim.name',
};

View File

@ -23,6 +23,9 @@ import { useQueries, UseQueryResult } from 'react-query';
import { SuccessResponse } from 'types/api'; import { SuccessResponse } from 'types/api';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange'; import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
interface MetricsTabProps { interface MetricsTabProps {
timeRange: { timeRange: {
startTime: number; startTime: number;
@ -45,9 +48,20 @@ function Metrics({
handleTimeChange, handleTimeChange,
isModalTimeSelection, isModalTimeSelection,
}: MetricsTabProps): JSX.Element { }: MetricsTabProps): JSX.Element {
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const queryPayloads = useMemo( const queryPayloads = useMemo(
() => getHostQueryPayload(hostName, timeRange.startTime, timeRange.endTime), () =>
[hostName, timeRange.startTime, timeRange.endTime], getHostQueryPayload(
hostName,
timeRange.startTime,
timeRange.endTime,
dotMetricsEnabled,
),
[hostName, timeRange.startTime, timeRange.endTime, dotMetricsEnabled],
); );
const queries = useQueries( const queries = useQueries(

View File

@ -10,4 +10,5 @@ export enum FeatureKeys {
ONBOARDING_V3 = 'ONBOARDING_V3', ONBOARDING_V3 = 'ONBOARDING_V3',
THIRD_PARTY_API = 'THIRD_PARTY_API', THIRD_PARTY_API = 'THIRD_PARTY_API',
TRACE_FUNNELS = 'TRACE_FUNNELS', TRACE_FUNNELS = 'TRACE_FUNNELS',
DOT_METRICS_ENABLED = 'DOT_METRICS_ENABLED',
} }

View File

@ -21,7 +21,10 @@ import ROUTES from 'constants/routes';
import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam'; import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import useResourceAttribute from 'hooks/useResourceAttribute'; import useResourceAttribute from 'hooks/useResourceAttribute';
import { convertCompositeQueryToTraceSelectedTags } from 'hooks/useResourceAttribute/utils'; import {
convertCompositeQueryToTraceSelectedTags,
getResourceDeploymentKeys,
} from 'hooks/useResourceAttribute/utils';
import { TimestampInput } from 'hooks/useTimezoneFormatter/useTimezoneFormatter'; import { TimestampInput } from 'hooks/useTimezoneFormatter/useTimezoneFormatter';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import createQueryParams from 'lib/createQueryParams'; import createQueryParams from 'lib/createQueryParams';
@ -38,6 +41,8 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
import { Exception, PayloadProps } from 'types/api/errors/getAll'; import { Exception, PayloadProps } from 'types/api/errors/getAll';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { FeatureKeys } from '../../constants/features';
import { useAppContext } from '../../providers/App/App';
import { FilterDropdownExtendsProps } from './types'; import { FilterDropdownExtendsProps } from './types';
import { import {
extractFilterValues, extractFilterValues,
@ -405,6 +410,11 @@ function AllErrors(): JSX.Element {
}, },
]; ];
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const onChangeHandler: TableProps<Exception>['onChange'] = useCallback( const onChangeHandler: TableProps<Exception>['onChange'] = useCallback(
( (
paginations: TablePaginationConfig, paginations: TablePaginationConfig,
@ -438,7 +448,7 @@ function AllErrors(): JSX.Element {
useEffect(() => { useEffect(() => {
if (!isUndefined(errorCountResponse.data?.payload)) { if (!isUndefined(errorCountResponse.data?.payload)) {
const selectedEnvironments = queries.find( const selectedEnvironments = queries.find(
(val) => val.tagKey === 'resource_deployment_environment', (val) => val.tagKey === getResourceDeploymentKeys(dotMetricsEnabled),
)?.tagValue; )?.tagValue;
logEvent('Exception: List page visited', { logEvent('Exception: List page visited', {

View File

@ -10,6 +10,8 @@ import { Provider, useSelector } from 'react-redux';
import { MemoryRouter } from 'react-router-dom'; import { MemoryRouter } from 'react-router-dom';
import store from 'store'; import store from 'store';
import * as appContextHooks from '../../../providers/App/App';
import { LicenseEvent } from '../../../types/api/licensesV3/getActive';
import AllErrors from '../index'; import AllErrors from '../index';
import { import {
INIT_URL_WITH_COMMON_QUERY, INIT_URL_WITH_COMMON_QUERY,
@ -28,6 +30,30 @@ jest.mock('react-redux', () => ({
useSelector: jest.fn(), useSelector: jest.fn(),
})); }));
jest.spyOn(appContextHooks, 'useAppContext').mockReturnValue({
user: {
role: 'admin',
},
activeLicenseV3: {
event_queue: {
created_at: '0',
event: LicenseEvent.NO_EVENT,
scheduled_at: '0',
status: '',
updated_at: '0',
},
license: {
license_key: 'test-license-key',
license_type: 'trial',
org_id: 'test-org-id',
plan_id: 'test-plan-id',
plan_name: 'test-plan-name',
plan_type: 'trial',
plan_version: 'test-plan-version',
},
},
} as any);
function Exceptions({ initUrl }: { initUrl?: string[] }): JSX.Element { function Exceptions({ initUrl }: { initUrl?: string[] }): JSX.Element {
return ( return (
<MemoryRouter initialEntries={initUrl ?? ['/exceptions']}> <MemoryRouter initialEntries={initUrl ?? ['/exceptions']}>

View File

@ -10,6 +10,7 @@ import getAllUserPreferences from 'api/preferences/getAllUserPreference';
import updateUserPreferenceAPI from 'api/preferences/updateUserPreference'; import updateUserPreferenceAPI from 'api/preferences/updateUserPreference';
import Header from 'components/Header/Header'; import Header from 'components/Header/Header';
import { DEFAULT_ENTITY_VERSION } from 'constants/app'; import { DEFAULT_ENTITY_VERSION } from 'constants/app';
import { FeatureKeys } from 'constants/features';
import { LOCALSTORAGE } from 'constants/localStorage'; import { LOCALSTORAGE } from 'constants/localStorage';
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder'; import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys'; import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
@ -161,10 +162,20 @@ export default function Home(): JSX.Element {
enabled: !!query, enabled: !!query,
}); });
const { data: k8sPodsData } = useGetK8sPodsList(query as K8sPodsListPayload, { const { featureFlags } = useAppContext();
queryKey: ['K8sPodsList', query], const dotMetricsEnabled =
enabled: !!query, featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
}); ?.active || false;
const { data: k8sPodsData } = useGetK8sPodsList(
query as K8sPodsListPayload,
{
queryKey: ['K8sPodsList', query],
enabled: !!query,
},
undefined,
dotMetricsEnabled,
);
const [isLogsIngestionActive, setIsLogsIngestionActive] = useState(false); const [isLogsIngestionActive, setIsLogsIngestionActive] = useState(false);
const [isTracesIngestionActive, setIsTracesIngestionActive] = useState(false); const [isTracesIngestionActive, setIsTracesIngestionActive] = useState(false);

View File

@ -30,6 +30,7 @@ import { GlobalReducer } from 'types/reducer/globalTime';
import { Tags } from 'types/reducer/trace'; import { Tags } from 'types/reducer/trace';
import { USER_ROLES } from 'types/roles'; import { USER_ROLES } from 'types/roles';
import { FeatureKeys } from '../../../constants/features';
import { DOCS_LINKS } from '../constants'; import { DOCS_LINKS } from '../constants';
import { columns, TIME_PICKER_OPTIONS } from './constants'; import { columns, TIME_PICKER_OPTIONS } from './constants';
@ -210,6 +211,11 @@ function ServiceMetrics({
const topLevelOperations = useMemo(() => Object.entries(data || {}), [data]); const topLevelOperations = useMemo(() => Object.entries(data || {}), [data]);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const queryRangeRequestData = useMemo( const queryRangeRequestData = useMemo(
() => () =>
getQueryRangeRequestData({ getQueryRangeRequestData({
@ -217,12 +223,14 @@ function ServiceMetrics({
minTime: timeRange.startTime * 1e6, minTime: timeRange.startTime * 1e6,
maxTime: timeRange.endTime * 1e6, maxTime: timeRange.endTime * 1e6,
globalSelectedInterval, globalSelectedInterval,
dotMetricsEnabled,
}), }),
[ [
globalSelectedInterval, globalSelectedInterval,
timeRange.endTime, timeRange.endTime,
timeRange.startTime, timeRange.startTime,
topLevelOperations, topLevelOperations,
dotMetricsEnabled,
], ],
); );

View File

@ -25,9 +25,11 @@ import { AppState } from 'store/reducers';
import { IBuilderQuery, Query } from 'types/api/queryBuilder/queryBuilderData'; import { IBuilderQuery, Query } from 'types/api/queryBuilder/queryBuilderData';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { FeatureKeys } from '../../constants/features';
import { useAppContext } from '../../providers/App/App';
import HostsListControls from './HostsListControls'; import HostsListControls from './HostsListControls';
import HostsListTable from './HostsListTable'; import HostsListTable from './HostsListTable';
import { getHostListsQuery, HostsQuickFiltersConfig } from './utils'; import { getHostListsQuery, GetHostsQuickFiltersConfig } from './utils';
// eslint-disable-next-line sonarjs/cognitive-complexity // eslint-disable-next-line sonarjs/cognitive-complexity
function HostsList(): JSX.Element { function HostsList(): JSX.Element {
const { maxTime, minTime } = useSelector<AppState, GlobalReducer>( const { maxTime, minTime } = useSelector<AppState, GlobalReducer>(
@ -114,6 +116,11 @@ function HostsList(): JSX.Element {
entityVersion: '', entityVersion: '',
}); });
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const handleFiltersChange = useCallback( const handleFiltersChange = useCallback(
(value: IBuilderQuery['filters']): void => { (value: IBuilderQuery['filters']): void => {
const isNewFilterAdded = value.items.length !== filters.items.length; const isNewFilterAdded = value.items.length !== filters.items.length;
@ -182,7 +189,7 @@ function HostsList(): JSX.Element {
</div> </div>
<QuickFilters <QuickFilters
source={QuickFiltersSource.INFRA_MONITORING} source={QuickFiltersSource.INFRA_MONITORING}
config={HostsQuickFiltersConfig} config={GetHostsQuickFiltersConfig(dotMetricsEnabled)}
handleFilterVisibilityChange={handleFilterVisibilityChange} handleFilterVisibilityChange={handleFilterVisibilityChange}
onFilterChange={handleQuickFiltersChange} onFilterChange={handleQuickFiltersChange}
/> />

View File

@ -198,3 +198,48 @@ export const HostsQuickFiltersConfig: IQuickFiltersConfig[] = [
defaultOpen: true, defaultOpen: true,
}, },
]; ];
export function GetHostsQuickFiltersConfig(
dotMetricsEnabled: boolean,
): IQuickFiltersConfig[] {
// These keys dont change with dotMetricsEnabled
const hostNameKey = dotMetricsEnabled ? 'host.name' : 'host_name';
const osTypeKey = dotMetricsEnabled ? 'os.type' : 'os_type';
// This metric stays the same regardless of notation
const metricName = dotMetricsEnabled
? 'system.cpu.load_average.15m'
: 'system_cpu_load_average_15m';
return [
{
type: FiltersType.CHECKBOX,
title: 'Host Name',
attributeKey: {
key: hostNameKey,
dataType: DataTypes.String,
type: 'resource',
isColumn: false,
isJSON: false,
},
aggregateOperator: 'noop',
aggregateAttribute: metricName,
dataSource: DataSource.METRICS,
defaultOpen: true,
},
{
type: FiltersType.CHECKBOX,
title: 'OS Type',
attributeKey: {
key: osTypeKey,
dataType: DataTypes.String,
type: 'resource',
isColumn: false,
isJSON: false,
},
aggregateOperator: 'noop',
aggregateAttribute: metricName,
dataSource: DataSource.METRICS,
defaultOpen: true,
},
];
}

View File

@ -28,11 +28,13 @@ import { AppState } from 'store/reducers';
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData'; import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { getOrderByFromParams } from '../commonUtils'; import { getOrderByFromParams } from '../commonUtils';
import { import {
GetK8sEntityToAggregateAttribute,
INFRA_MONITORING_K8S_PARAMS_KEYS, INFRA_MONITORING_K8S_PARAMS_KEYS,
K8sCategory, K8sCategory,
K8sEntityToAggregateAttributeMapping,
} from '../constants'; } from '../constants';
import K8sHeader from '../K8sHeader'; import K8sHeader from '../K8sHeader';
import LoadingContainer from '../LoadingContainer'; import LoadingContainer from '../LoadingContainer';
@ -135,6 +137,11 @@ function K8sClustersList({
} }
}, [quickFiltersLastUpdated]); }, [quickFiltersLastUpdated]);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const createFiltersForSelectedRowData = ( const createFiltersForSelectedRowData = (
selectedRowData: K8sClustersRowData, selectedRowData: K8sClustersRowData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -194,6 +201,8 @@ function K8sClustersList({
queryKey: ['clusterList', fetchGroupedByRowDataQuery], queryKey: ['clusterList', fetchGroupedByRowDataQuery],
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData, enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
}, },
undefined,
dotMetricsEnabled,
); );
const { const {
@ -202,8 +211,10 @@ function K8sClustersList({
} = useGetAggregateKeys( } = useGetAggregateKeys(
{ {
dataSource: currentQuery.builder.queryData[0].dataSource, dataSource: currentQuery.builder.queryData[0].dataSource,
aggregateAttribute: aggregateAttribute: GetK8sEntityToAggregateAttribute(
K8sEntityToAggregateAttributeMapping[K8sCategory.CLUSTERS], K8sCategory.CLUSTERS,
dotMetricsEnabled,
),
aggregateOperator: 'noop', aggregateOperator: 'noop',
searchText: '', searchText: '',
tagType: '', tagType: '',
@ -249,6 +260,8 @@ function K8sClustersList({
queryKey: ['clusterList', query], queryKey: ['clusterList', query],
enabled: !!query, enabled: !!query,
}, },
undefined,
dotMetricsEnabled,
); );
const clustersData = useMemo(() => data?.payload?.data?.records || [], [data]); const clustersData = useMemo(() => data?.payload?.data?.records || [], [data]);

View File

@ -136,6 +136,11 @@ export const getK8sClustersListColumns = (
return columnsConfig as ColumnType<K8sClustersRowData>[]; return columnsConfig as ColumnType<K8sClustersRowData>[];
}; };
const dotToUnder: Record<string, keyof K8sClustersData['meta']> = {
'k8s.cluster.name': 'k8s_cluster_name',
'k8s.cluster.uid': 'k8s_cluster_uid',
};
const getGroupByEle = ( const getGroupByEle = (
cluster: K8sClustersData, cluster: K8sClustersData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -143,7 +148,13 @@ const getGroupByEle = (
const groupByValues: string[] = []; const groupByValues: string[] = [];
groupBy.forEach((group) => { groupBy.forEach((group) => {
groupByValues.push(cluster.meta[group.key as keyof typeof cluster.meta]); const rawKey = group.key as string;
// Choose mapped key if present, otherwise use rawKey
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof cluster.meta;
const value = cluster.meta[metaKey];
groupByValues.push(value);
}); });
return ( return (

View File

@ -29,11 +29,13 @@ import { AppState } from 'store/reducers';
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData'; import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { getOrderByFromParams } from '../commonUtils'; import { getOrderByFromParams } from '../commonUtils';
import { import {
GetK8sEntityToAggregateAttribute,
INFRA_MONITORING_K8S_PARAMS_KEYS, INFRA_MONITORING_K8S_PARAMS_KEYS,
K8sCategory, K8sCategory,
K8sEntityToAggregateAttributeMapping,
} from '../constants'; } from '../constants';
import K8sHeader from '../K8sHeader'; import K8sHeader from '../K8sHeader';
import LoadingContainer from '../LoadingContainer'; import LoadingContainer from '../LoadingContainer';
@ -137,6 +139,11 @@ function K8sDaemonSetsList({
} }
}, [quickFiltersLastUpdated]); }, [quickFiltersLastUpdated]);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const createFiltersForSelectedRowData = ( const createFiltersForSelectedRowData = (
selectedRowData: K8sDaemonSetsRowData, selectedRowData: K8sDaemonSetsRowData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -196,6 +203,8 @@ function K8sDaemonSetsList({
queryKey: ['daemonSetList', fetchGroupedByRowDataQuery], queryKey: ['daemonSetList', fetchGroupedByRowDataQuery],
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData, enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
}, },
undefined,
dotMetricsEnabled,
); );
const { const {
@ -204,8 +213,10 @@ function K8sDaemonSetsList({
} = useGetAggregateKeys( } = useGetAggregateKeys(
{ {
dataSource: currentQuery.builder.queryData[0].dataSource, dataSource: currentQuery.builder.queryData[0].dataSource,
aggregateAttribute: aggregateAttribute: GetK8sEntityToAggregateAttribute(
K8sEntityToAggregateAttributeMapping[K8sCategory.DAEMONSETS], K8sCategory.DAEMONSETS,
dotMetricsEnabled,
),
aggregateOperator: 'noop', aggregateOperator: 'noop',
searchText: '', searchText: '',
tagType: '', tagType: '',
@ -246,6 +257,8 @@ function K8sDaemonSetsList({
queryKey: ['daemonSetList', query], queryKey: ['daemonSetList', query],
enabled: !!query, enabled: !!query,
}, },
undefined,
dotMetricsEnabled,
); );
const daemonSetsData = useMemo(() => data?.payload?.data?.records || [], [ const daemonSetsData = useMemo(() => data?.payload?.data?.records || [], [

View File

@ -236,6 +236,12 @@ export const getK8sDaemonSetsListColumns = (
return columnsConfig as ColumnType<K8sDaemonSetsRowData>[]; return columnsConfig as ColumnType<K8sDaemonSetsRowData>[];
}; };
const dotToUnder: Record<string, keyof K8sDaemonSetsData['meta']> = {
'k8s.daemonset.name': 'k8s_daemonset_name',
'k8s.namespace.name': 'k8s_namespace_name',
'k8s.cluster.name': 'k8s_cluster_name',
};
const getGroupByEle = ( const getGroupByEle = (
daemonSet: K8sDaemonSetsData, daemonSet: K8sDaemonSetsData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -243,7 +249,13 @@ const getGroupByEle = (
const groupByValues: string[] = []; const groupByValues: string[] = [];
groupBy.forEach((group) => { groupBy.forEach((group) => {
groupByValues.push(daemonSet.meta[group.key as keyof typeof daemonSet.meta]); const rawKey = group.key as string;
// Choose mapped key if present, otherwise use rawKey
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof daemonSet.meta;
const value = daemonSet.meta[metaKey];
groupByValues.push(value);
}); });
return ( return (

View File

@ -29,11 +29,13 @@ import { AppState } from 'store/reducers';
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData'; import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { getOrderByFromParams } from '../commonUtils'; import { getOrderByFromParams } from '../commonUtils';
import { import {
GetK8sEntityToAggregateAttribute,
INFRA_MONITORING_K8S_PARAMS_KEYS, INFRA_MONITORING_K8S_PARAMS_KEYS,
K8sCategory, K8sCategory,
K8sEntityToAggregateAttributeMapping,
} from '../constants'; } from '../constants';
import K8sHeader from '../K8sHeader'; import K8sHeader from '../K8sHeader';
import LoadingContainer from '../LoadingContainer'; import LoadingContainer from '../LoadingContainer';
@ -138,6 +140,11 @@ function K8sDeploymentsList({
} }
}, [quickFiltersLastUpdated]); }, [quickFiltersLastUpdated]);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const createFiltersForSelectedRowData = ( const createFiltersForSelectedRowData = (
selectedRowData: K8sDeploymentsRowData, selectedRowData: K8sDeploymentsRowData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -197,6 +204,8 @@ function K8sDeploymentsList({
queryKey: ['deploymentList', fetchGroupedByRowDataQuery], queryKey: ['deploymentList', fetchGroupedByRowDataQuery],
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData, enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
}, },
undefined,
dotMetricsEnabled,
); );
const { const {
@ -205,8 +214,10 @@ function K8sDeploymentsList({
} = useGetAggregateKeys( } = useGetAggregateKeys(
{ {
dataSource: currentQuery.builder.queryData[0].dataSource, dataSource: currentQuery.builder.queryData[0].dataSource,
aggregateAttribute: aggregateAttribute: GetK8sEntityToAggregateAttribute(
K8sEntityToAggregateAttributeMapping[K8sCategory.DEPLOYMENTS], K8sCategory.DEPLOYMENTS,
dotMetricsEnabled,
),
aggregateOperator: 'noop', aggregateOperator: 'noop',
searchText: '', searchText: '',
tagType: '', tagType: '',
@ -247,6 +258,8 @@ function K8sDeploymentsList({
queryKey: ['deploymentList', query], queryKey: ['deploymentList', query],
enabled: !!query, enabled: !!query,
}, },
undefined,
dotMetricsEnabled,
); );
const deploymentsData = useMemo(() => data?.payload?.data?.records || [], [ const deploymentsData = useMemo(() => data?.payload?.data?.records || [], [

View File

@ -226,6 +226,12 @@ export const getK8sDeploymentsListColumns = (
return columnsConfig as ColumnType<K8sDeploymentsRowData>[]; return columnsConfig as ColumnType<K8sDeploymentsRowData>[];
}; };
const dotToUnder: Record<string, keyof K8sDeploymentsData['meta']> = {
'k8s.deployment.name': 'k8s_deployment_name',
'k8s.namespace.name': 'k8s_namespace_name',
'k8s.cluster.name': 'k8s_cluster_name',
};
const getGroupByEle = ( const getGroupByEle = (
deployment: K8sDeploymentsData, deployment: K8sDeploymentsData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -233,9 +239,14 @@ const getGroupByEle = (
const groupByValues: string[] = []; const groupByValues: string[] = [];
groupBy.forEach((group) => { groupBy.forEach((group) => {
groupByValues.push( const rawKey = group.key as string;
deployment.meta[group.key as keyof typeof deployment.meta],
); // Choose mapped key if present, otherwise use rawKey
const metaKey = (dotToUnder[rawKey] ??
rawKey) as keyof typeof deployment.meta;
const value = deployment.meta[metaKey];
groupByValues.push(value);
}); });
return ( return (

View File

@ -29,6 +29,9 @@ import { SuccessResponse } from 'types/api';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange'; import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { Options } from 'uplot'; import { Options } from 'uplot';
import { FeatureKeys } from '../../../../constants/features';
import { useAppContext } from '../../../../providers/App/App';
interface EntityMetricsProps<T> { interface EntityMetricsProps<T> {
timeRange: { timeRange: {
startTime: number; startTime: number;
@ -49,6 +52,7 @@ interface EntityMetricsProps<T> {
node: T, node: T,
start: number, start: number,
end: number, end: number,
dotMetricsEnabled: boolean,
) => GetQueryResultsProps[]; ) => GetQueryResultsProps[];
queryKey: string; queryKey: string;
category: K8sCategory; category: K8sCategory;
@ -65,9 +69,25 @@ function EntityMetrics<T>({
queryKey, queryKey,
category, category,
}: EntityMetricsProps<T>): JSX.Element { }: EntityMetricsProps<T>): JSX.Element {
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const queryPayloads = useMemo( const queryPayloads = useMemo(
() => getEntityQueryPayload(entity, timeRange.startTime, timeRange.endTime), () =>
[getEntityQueryPayload, entity, timeRange.startTime, timeRange.endTime], getEntityQueryPayload(
entity,
timeRange.startTime,
timeRange.endTime,
dotMetricsEnabled,
),
[
getEntityQueryPayload,
entity,
timeRange.startTime,
timeRange.endTime,
dotMetricsEnabled,
],
); );
const queries = useQueries( const queries = useQueries(

View File

@ -26,19 +26,21 @@ import { useState } from 'react';
import { useSearchParams } from 'react-router-dom-v5-compat'; import { useSearchParams } from 'react-router-dom-v5-compat';
import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { FeatureKeys } from '../../constants/features';
import { useAppContext } from '../../providers/App/App';
import K8sClustersList from './Clusters/K8sClustersList'; import K8sClustersList from './Clusters/K8sClustersList';
import { import {
ClustersQuickFiltersConfig, GetClustersQuickFiltersConfig,
DaemonSetsQuickFiltersConfig, GetDaemonsetsQuickFiltersConfig,
DeploymentsQuickFiltersConfig, GetDeploymentsQuickFiltersConfig,
GetJobsQuickFiltersConfig,
GetNamespaceQuickFiltersConfig,
GetNodesQuickFiltersConfig,
GetPodsQuickFiltersConfig,
GetStatefulsetsQuickFiltersConfig,
GetVolumesQuickFiltersConfig,
INFRA_MONITORING_K8S_PARAMS_KEYS, INFRA_MONITORING_K8S_PARAMS_KEYS,
JobsQuickFiltersConfig,
K8sCategories, K8sCategories,
NamespaceQuickFiltersConfig,
NodesQuickFiltersConfig,
PodsQuickFiltersConfig,
StatefulsetsQuickFiltersConfig,
VolumesQuickFiltersConfig,
} from './constants'; } from './constants';
import K8sDaemonSetsList from './DaemonSets/K8sDaemonSetsList'; import K8sDaemonSetsList from './DaemonSets/K8sDaemonSetsList';
import K8sDeploymentsList from './Deployments/K8sDeploymentsList'; import K8sDeploymentsList from './Deployments/K8sDeploymentsList';
@ -74,6 +76,11 @@ export default function InfraMonitoringK8s(): JSX.Element {
entityVersion: '', entityVersion: '',
}); });
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const handleFilterChange = (query: Query): void => { const handleFilterChange = (query: Query): void => {
// update the current query with the new filters // update the current query with the new filters
// in infra monitoring k8s, we are using only one query, hence updating the 0th index of queryData // in infra monitoring k8s, we are using only one query, hence updating the 0th index of queryData
@ -109,7 +116,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
children: ( children: (
<QuickFilters <QuickFilters
source={QuickFiltersSource.INFRA_MONITORING} source={QuickFiltersSource.INFRA_MONITORING}
config={PodsQuickFiltersConfig} config={GetPodsQuickFiltersConfig(dotMetricsEnabled)}
handleFilterVisibilityChange={handleFilterVisibilityChange} handleFilterVisibilityChange={handleFilterVisibilityChange}
onFilterChange={handleFilterChange} onFilterChange={handleFilterChange}
/> />
@ -129,7 +136,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
children: ( children: (
<QuickFilters <QuickFilters
source={QuickFiltersSource.INFRA_MONITORING} source={QuickFiltersSource.INFRA_MONITORING}
config={NodesQuickFiltersConfig} config={GetNodesQuickFiltersConfig(dotMetricsEnabled)}
handleFilterVisibilityChange={handleFilterVisibilityChange} handleFilterVisibilityChange={handleFilterVisibilityChange}
onFilterChange={handleFilterChange} onFilterChange={handleFilterChange}
/> />
@ -152,7 +159,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
children: ( children: (
<QuickFilters <QuickFilters
source={QuickFiltersSource.INFRA_MONITORING} source={QuickFiltersSource.INFRA_MONITORING}
config={NamespaceQuickFiltersConfig} config={GetNamespaceQuickFiltersConfig(dotMetricsEnabled)}
handleFilterVisibilityChange={handleFilterVisibilityChange} handleFilterVisibilityChange={handleFilterVisibilityChange}
onFilterChange={handleFilterChange} onFilterChange={handleFilterChange}
/> />
@ -172,7 +179,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
children: ( children: (
<QuickFilters <QuickFilters
source={QuickFiltersSource.INFRA_MONITORING} source={QuickFiltersSource.INFRA_MONITORING}
config={ClustersQuickFiltersConfig} config={GetClustersQuickFiltersConfig(dotMetricsEnabled)}
handleFilterVisibilityChange={handleFilterVisibilityChange} handleFilterVisibilityChange={handleFilterVisibilityChange}
onFilterChange={handleFilterChange} onFilterChange={handleFilterChange}
/> />
@ -192,7 +199,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
children: ( children: (
<QuickFilters <QuickFilters
source={QuickFiltersSource.INFRA_MONITORING} source={QuickFiltersSource.INFRA_MONITORING}
config={DeploymentsQuickFiltersConfig} config={GetDeploymentsQuickFiltersConfig(dotMetricsEnabled)}
handleFilterVisibilityChange={handleFilterVisibilityChange} handleFilterVisibilityChange={handleFilterVisibilityChange}
onFilterChange={handleFilterChange} onFilterChange={handleFilterChange}
/> />
@ -212,7 +219,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
children: ( children: (
<QuickFilters <QuickFilters
source={QuickFiltersSource.INFRA_MONITORING} source={QuickFiltersSource.INFRA_MONITORING}
config={JobsQuickFiltersConfig} config={GetJobsQuickFiltersConfig(dotMetricsEnabled)}
handleFilterVisibilityChange={handleFilterVisibilityChange} handleFilterVisibilityChange={handleFilterVisibilityChange}
onFilterChange={handleFilterChange} onFilterChange={handleFilterChange}
/> />
@ -232,7 +239,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
children: ( children: (
<QuickFilters <QuickFilters
source={QuickFiltersSource.INFRA_MONITORING} source={QuickFiltersSource.INFRA_MONITORING}
config={DaemonSetsQuickFiltersConfig} config={GetDaemonsetsQuickFiltersConfig(dotMetricsEnabled)}
handleFilterVisibilityChange={handleFilterVisibilityChange} handleFilterVisibilityChange={handleFilterVisibilityChange}
onFilterChange={handleFilterChange} onFilterChange={handleFilterChange}
/> />
@ -255,7 +262,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
children: ( children: (
<QuickFilters <QuickFilters
source={QuickFiltersSource.INFRA_MONITORING} source={QuickFiltersSource.INFRA_MONITORING}
config={StatefulsetsQuickFiltersConfig} config={GetStatefulsetsQuickFiltersConfig(dotMetricsEnabled)}
handleFilterVisibilityChange={handleFilterVisibilityChange} handleFilterVisibilityChange={handleFilterVisibilityChange}
onFilterChange={handleFilterChange} onFilterChange={handleFilterChange}
/> />
@ -275,7 +282,7 @@ export default function InfraMonitoringK8s(): JSX.Element {
children: ( children: (
<QuickFilters <QuickFilters
source={QuickFiltersSource.INFRA_MONITORING} source={QuickFiltersSource.INFRA_MONITORING}
config={VolumesQuickFiltersConfig} config={GetVolumesQuickFiltersConfig(dotMetricsEnabled)}
handleFilterVisibilityChange={handleFilterVisibilityChange} handleFilterVisibilityChange={handleFilterVisibilityChange}
onFilterChange={handleFilterChange} onFilterChange={handleFilterChange}
/> />

View File

@ -30,395 +30,415 @@ export const getJobMetricsQueryPayload = (
job: K8sJobsData, job: K8sJobsData,
start: number, start: number,
end: number, end: number,
): GetQueryResultsProps[] => [ dotMetricsEnabled: boolean,
{ ): GetQueryResultsProps[] => {
selectedTime: 'GLOBAL_TIME', const k8sPodCpuUtilizationKey = dotMetricsEnabled
graphType: PANEL_TYPES.TIME_SERIES, ? 'k8s.pod.cpu.utilization'
query: { : 'k8s_pod_cpu_utilization';
builder: { const k8sPodMemoryUsageKey = dotMetricsEnabled
queryData: [ ? 'k8s.pod.memory.usage'
: 'k8s_pod_memory_usage';
const k8sPodNetworkIoKey = dotMetricsEnabled
? 'k8s.pod.network.io'
: 'k8s_pod_network_io';
const k8sPodNetworkErrorsKey = dotMetricsEnabled
? 'k8s.pod.network.errors'
: 'k8s_pod_network_errors';
const k8sJobNameKey = dotMetricsEnabled ? 'k8s.job.name' : 'k8s_job_name';
const k8sNamespaceNameKey = dotMetricsEnabled
? 'k8s.namespace.name'
: 'k8s_namespace_name';
return [
{
selectedTime: 'GLOBAL_TIME',
graphType: PANEL_TYPES.TIME_SERIES,
query: {
builder: {
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
id: 'k8s_pod_cpu_utilization--float64--Gauge--true',
isColumn: true,
isJSON: false,
key: k8sPodCpuUtilizationKey,
type: 'Gauge',
},
aggregateOperator: 'avg',
dataSource: DataSource.METRICS,
disabled: false,
expression: 'A',
filters: {
items: [
{
id: '6b59b690',
key: {
dataType: DataTypes.String,
id: 'k8s_job_name--string--tag--false',
isColumn: false,
isJSON: false,
key: k8sJobNameKey,
type: 'tag',
},
op: '=',
value: job.jobName,
},
{
id: '47b3adae',
key: {
dataType: DataTypes.String,
id: 'k8s_namespace_name--string--tag--false',
isColumn: false,
isJSON: false,
key: k8sNamespaceNameKey,
type: 'tag',
},
op: '=',
value: job.meta.k8s_namespace_name,
},
],
op: 'AND',
},
functions: [],
groupBy: [],
having: [],
legend: 'usage',
limit: null,
orderBy: [],
queryName: 'A',
reduceTo: 'avg',
spaceAggregation: 'sum',
stepInterval: 60,
timeAggregation: 'avg',
},
],
queryFormulas: [],
},
clickhouse_sql: [
{ {
aggregateAttribute: {
dataType: DataTypes.Float64,
id: 'k8s_pod_cpu_utilization--float64--Gauge--true',
isColumn: true,
isJSON: false,
key: 'k8s_pod_cpu_utilization',
type: 'Gauge',
},
aggregateOperator: 'avg',
dataSource: DataSource.METRICS,
disabled: false, disabled: false,
expression: 'A', legend: '',
filters: { name: 'A',
items: [ query: '',
{
id: '6b59b690',
key: {
dataType: DataTypes.String,
id: 'k8s_job_name--string--tag--false',
isColumn: false,
isJSON: false,
key: 'k8s_job_name',
type: 'tag',
},
op: '=',
value: job.jobName,
},
{
id: '47b3adae',
key: {
dataType: DataTypes.String,
id: 'k8s_namespace_name--string--tag--false',
isColumn: false,
isJSON: false,
key: 'k8s_namespace_name',
type: 'tag',
},
op: '=',
value: job.meta.k8s_namespace_name,
},
],
op: 'AND',
},
functions: [],
groupBy: [],
having: [],
legend: 'usage',
limit: null,
orderBy: [],
queryName: 'A',
reduceTo: 'avg',
spaceAggregation: 'sum',
stepInterval: 60,
timeAggregation: 'avg',
}, },
], ],
queryFormulas: [], id: v4(),
}, promql: [
clickhouse_sql: [
{
disabled: false,
legend: '',
name: 'A',
query: '',
},
],
id: v4(),
promql: [
{
disabled: false,
legend: '',
name: 'A',
query: '',
},
],
queryType: EQueryType.QUERY_BUILDER,
},
variables: {},
formatForWeb: false,
start,
end,
},
{
selectedTime: 'GLOBAL_TIME',
graphType: PANEL_TYPES.TIME_SERIES,
query: {
builder: {
queryData: [
{ {
aggregateAttribute: {
dataType: DataTypes.Float64,
id: 'k8s_pod_memory_usage--float64--Gauge--true',
isColumn: true,
isJSON: false,
key: 'k8s_pod_memory_usage',
type: 'Gauge',
},
aggregateOperator: 'avg',
dataSource: DataSource.METRICS,
disabled: false, disabled: false,
expression: 'A', legend: '',
filters: { name: 'A',
items: [ query: '',
{
id: '8c217f4d',
key: {
dataType: DataTypes.String,
id: 'k8s_job_name--string--tag--false',
isColumn: false,
isJSON: false,
key: 'k8s_job_name',
type: 'tag',
},
op: '=',
value: job.jobName,
},
{
id: '47b3adae',
key: {
dataType: DataTypes.String,
id: 'k8s_namespace_name--string--tag--false',
isColumn: false,
isJSON: false,
key: 'k8s_namespace_name',
type: 'tag',
},
op: '=',
value: job.meta.k8s_namespace_name,
},
],
op: 'AND',
},
functions: [],
groupBy: [],
having: [],
legend: 'usage',
limit: null,
orderBy: [],
queryName: 'A',
reduceTo: 'avg',
spaceAggregation: 'sum',
stepInterval: 60,
timeAggregation: 'avg',
}, },
], ],
queryFormulas: [], queryType: EQueryType.QUERY_BUILDER,
}, },
clickhouse_sql: [ variables: {},
{ formatForWeb: false,
disabled: false, start,
legend: '', end,
name: 'A',
query: '',
},
],
id: v4(),
promql: [
{
disabled: false,
legend: '',
name: 'A',
query: '',
},
],
queryType: EQueryType.QUERY_BUILDER,
}, },
variables: {}, {
formatForWeb: false, selectedTime: 'GLOBAL_TIME',
start, graphType: PANEL_TYPES.TIME_SERIES,
end, query: {
}, builder: {
{ queryData: [
selectedTime: 'GLOBAL_TIME', {
graphType: PANEL_TYPES.TIME_SERIES, aggregateAttribute: {
query: { dataType: DataTypes.Float64,
builder: { id: 'k8s_pod_memory_usage--float64--Gauge--true',
queryData: [ isColumn: true,
isJSON: false,
key: k8sPodMemoryUsageKey,
type: 'Gauge',
},
aggregateOperator: 'avg',
dataSource: DataSource.METRICS,
disabled: false,
expression: 'A',
filters: {
items: [
{
id: '8c217f4d',
key: {
dataType: DataTypes.String,
id: 'k8s_job_name--string--tag--false',
isColumn: false,
isJSON: false,
key: k8sJobNameKey,
type: 'tag',
},
op: '=',
value: job.jobName,
},
{
id: '47b3adae',
key: {
dataType: DataTypes.String,
id: 'k8s_namespace_name--string--tag--false',
isColumn: false,
isJSON: false,
key: k8sNamespaceNameKey,
type: 'tag',
},
op: '=',
value: job.meta.k8s_namespace_name,
},
],
op: 'AND',
},
functions: [],
groupBy: [],
having: [],
legend: 'usage',
limit: null,
orderBy: [],
queryName: 'A',
reduceTo: 'avg',
spaceAggregation: 'sum',
stepInterval: 60,
timeAggregation: 'avg',
},
],
queryFormulas: [],
},
clickhouse_sql: [
{ {
aggregateAttribute: {
dataType: DataTypes.Float64,
id: 'k8s_pod_network_io--float64--Sum--true',
isColumn: true,
isJSON: false,
key: 'k8s_pod_network_io',
type: 'Sum',
},
aggregateOperator: 'rate',
dataSource: DataSource.METRICS,
disabled: false, disabled: false,
expression: 'A', legend: '',
filters: { name: 'A',
items: [ query: '',
{
id: '2bbf9d0c',
key: {
dataType: DataTypes.String,
id: 'k8s_job_name--string--tag--false',
isColumn: false,
isJSON: false,
key: 'k8s_job_name',
type: 'tag',
},
op: '=',
value: job.jobName,
},
{
id: '47b3adae',
key: {
dataType: DataTypes.String,
id: 'k8s_namespace_name--string--tag--false',
isColumn: false,
isJSON: false,
key: 'k8s_namespace_name',
type: 'tag',
},
op: '=',
value: job.meta.k8s_namespace_name,
},
],
op: 'AND',
},
functions: [],
groupBy: [
{
dataType: DataTypes.String,
id: 'direction--string--tag--false',
isColumn: false,
isJSON: false,
key: 'direction',
type: 'tag',
},
{
dataType: DataTypes.String,
id: 'interface--string--tag--false',
isColumn: false,
isJSON: false,
key: 'interface',
type: 'tag',
},
],
having: [],
legend: '{{direction}} :: {{interface}}',
limit: null,
orderBy: [],
queryName: 'A',
reduceTo: 'avg',
spaceAggregation: 'sum',
stepInterval: 60,
timeAggregation: 'rate',
}, },
], ],
queryFormulas: [], id: v4(),
}, promql: [
clickhouse_sql: [
{
disabled: false,
legend: '',
name: 'A',
query: '',
},
],
id: v4(),
promql: [
{
disabled: false,
legend: '',
name: 'A',
query: '',
},
],
queryType: EQueryType.QUERY_BUILDER,
},
variables: {},
formatForWeb: false,
start,
end,
},
{
selectedTime: 'GLOBAL_TIME',
graphType: PANEL_TYPES.TIME_SERIES,
query: {
builder: {
queryData: [
{ {
aggregateAttribute: {
dataType: DataTypes.Float64,
id: 'k8s_pod_network_errors--float64--Sum--true',
isColumn: true,
isJSON: false,
key: 'k8s_pod_network_errors',
type: 'Sum',
},
aggregateOperator: 'increase',
dataSource: DataSource.METRICS,
disabled: false, disabled: false,
expression: 'A', legend: '',
filters: { name: 'A',
items: [ query: '',
{
id: '448e6cf7',
key: {
dataType: DataTypes.String,
id: 'k8s_job_name--string--tag--false',
isColumn: false,
isJSON: false,
key: 'k8s_job_name',
type: 'tag',
},
op: '=',
value: job.jobName,
},
{
id: '47b3adae',
key: {
dataType: DataTypes.String,
id: 'k8s_namespace_name--string--tag--false',
isColumn: false,
isJSON: false,
key: 'k8s_namespace_name',
type: 'tag',
},
op: '=',
value: job.meta.k8s_namespace_name,
},
],
op: 'AND',
},
functions: [],
groupBy: [
{
dataType: DataTypes.String,
id: 'direction--string--tag--false',
isColumn: false,
isJSON: false,
key: 'direction',
type: 'tag',
},
{
dataType: DataTypes.String,
id: 'interface--string--tag--false',
isColumn: false,
isJSON: false,
key: 'interface',
type: 'tag',
},
],
having: [],
legend: '{{direction}} :: {{interface}}',
limit: null,
orderBy: [],
queryName: 'A',
reduceTo: 'avg',
spaceAggregation: 'sum',
stepInterval: 60,
timeAggregation: 'increase',
}, },
], ],
queryFormulas: [], queryType: EQueryType.QUERY_BUILDER,
}, },
clickhouse_sql: [ variables: {},
{ formatForWeb: false,
disabled: false, start,
legend: '', end,
name: 'A',
query: '',
},
],
id: v4(),
promql: [
{
disabled: false,
legend: '',
name: 'A',
query: '',
},
],
queryType: EQueryType.QUERY_BUILDER,
}, },
variables: {}, {
formatForWeb: false, selectedTime: 'GLOBAL_TIME',
start, graphType: PANEL_TYPES.TIME_SERIES,
end, query: {
}, builder: {
]; queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
id: 'k8s_pod_network_io--float64--Sum--true',
isColumn: true,
isJSON: false,
key: k8sPodNetworkIoKey,
type: 'Sum',
},
aggregateOperator: 'rate',
dataSource: DataSource.METRICS,
disabled: false,
expression: 'A',
filters: {
items: [
{
id: '2bbf9d0c',
key: {
dataType: DataTypes.String,
id: 'k8s_job_name--string--tag--false',
isColumn: false,
isJSON: false,
key: k8sJobNameKey,
type: 'tag',
},
op: '=',
value: job.jobName,
},
{
id: '47b3adae',
key: {
dataType: DataTypes.String,
id: 'k8s_namespace_name--string--tag--false',
isColumn: false,
isJSON: false,
key: k8sNamespaceNameKey,
type: 'tag',
},
op: '=',
value: job.meta.k8s_namespace_name,
},
],
op: 'AND',
},
functions: [],
groupBy: [
{
dataType: DataTypes.String,
id: 'direction--string--tag--false',
isColumn: false,
isJSON: false,
key: 'direction',
type: 'tag',
},
{
dataType: DataTypes.String,
id: 'interface--string--tag--false',
isColumn: false,
isJSON: false,
key: 'interface',
type: 'tag',
},
],
having: [],
legend: '{{direction}} :: {{interface}}',
limit: null,
orderBy: [],
queryName: 'A',
reduceTo: 'avg',
spaceAggregation: 'sum',
stepInterval: 60,
timeAggregation: 'rate',
},
],
queryFormulas: [],
},
clickhouse_sql: [
{
disabled: false,
legend: '',
name: 'A',
query: '',
},
],
id: v4(),
promql: [
{
disabled: false,
legend: '',
name: 'A',
query: '',
},
],
queryType: EQueryType.QUERY_BUILDER,
},
variables: {},
formatForWeb: false,
start,
end,
},
{
selectedTime: 'GLOBAL_TIME',
graphType: PANEL_TYPES.TIME_SERIES,
query: {
builder: {
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
id: 'k8s_pod_network_errors--float64--Sum--true',
isColumn: true,
isJSON: false,
key: k8sPodNetworkErrorsKey,
type: 'Sum',
},
aggregateOperator: 'increase',
dataSource: DataSource.METRICS,
disabled: false,
expression: 'A',
filters: {
items: [
{
id: '448e6cf7',
key: {
dataType: DataTypes.String,
id: 'k8s_job_name--string--tag--false',
isColumn: false,
isJSON: false,
key: k8sJobNameKey,
type: 'tag',
},
op: '=',
value: job.jobName,
},
{
id: '47b3adae',
key: {
dataType: DataTypes.String,
id: 'k8s_namespace_name--string--tag--false',
isColumn: false,
isJSON: false,
key: k8sNamespaceNameKey,
type: 'tag',
},
op: '=',
value: job.meta.k8s_namespace_name,
},
],
op: 'AND',
},
functions: [],
groupBy: [
{
dataType: DataTypes.String,
id: 'direction--string--tag--false',
isColumn: false,
isJSON: false,
key: 'direction',
type: 'tag',
},
{
dataType: DataTypes.String,
id: 'interface--string--tag--false',
isColumn: false,
isJSON: false,
key: 'interface',
type: 'tag',
},
],
having: [],
legend: '{{direction}} :: {{interface}}',
limit: null,
orderBy: [],
queryName: 'A',
reduceTo: 'avg',
spaceAggregation: 'sum',
stepInterval: 60,
timeAggregation: 'increase',
},
],
queryFormulas: [],
},
clickhouse_sql: [
{
disabled: false,
legend: '',
name: 'A',
query: '',
},
],
id: v4(),
promql: [
{
disabled: false,
legend: '',
name: 'A',
query: '',
},
],
queryType: EQueryType.QUERY_BUILDER,
},
variables: {},
formatForWeb: false,
start,
end,
},
];
};

View File

@ -29,11 +29,13 @@ import { AppState } from 'store/reducers';
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData'; import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { getOrderByFromParams } from '../commonUtils'; import { getOrderByFromParams } from '../commonUtils';
import { import {
GetK8sEntityToAggregateAttribute,
INFRA_MONITORING_K8S_PARAMS_KEYS, INFRA_MONITORING_K8S_PARAMS_KEYS,
K8sCategory, K8sCategory,
K8sEntityToAggregateAttributeMapping,
} from '../constants'; } from '../constants';
import K8sHeader from '../K8sHeader'; import K8sHeader from '../K8sHeader';
import LoadingContainer from '../LoadingContainer'; import LoadingContainer from '../LoadingContainer';
@ -132,6 +134,11 @@ function K8sJobsList({
} }
}, [quickFiltersLastUpdated]); }, [quickFiltersLastUpdated]);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const createFiltersForSelectedRowData = ( const createFiltersForSelectedRowData = (
selectedRowData: K8sJobsRowData, selectedRowData: K8sJobsRowData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -185,10 +192,15 @@ function K8sJobsList({
isLoading: isLoadingGroupedByRowData, isLoading: isLoadingGroupedByRowData,
isError: isErrorGroupedByRowData, isError: isErrorGroupedByRowData,
refetch: fetchGroupedByRowData, refetch: fetchGroupedByRowData,
} = useGetK8sJobsList(fetchGroupedByRowDataQuery as K8sJobsListPayload, { } = useGetK8sJobsList(
queryKey: ['jobList', fetchGroupedByRowDataQuery], fetchGroupedByRowDataQuery as K8sJobsListPayload,
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData, {
}); queryKey: ['jobList', fetchGroupedByRowDataQuery],
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
},
undefined,
dotMetricsEnabled,
);
const { const {
data: groupByFiltersData, data: groupByFiltersData,
@ -196,7 +208,10 @@ function K8sJobsList({
} = useGetAggregateKeys( } = useGetAggregateKeys(
{ {
dataSource: currentQuery.builder.queryData[0].dataSource, dataSource: currentQuery.builder.queryData[0].dataSource,
aggregateAttribute: K8sEntityToAggregateAttributeMapping[K8sCategory.JOBS], aggregateAttribute: GetK8sEntityToAggregateAttribute(
K8sCategory.JOBS,
dotMetricsEnabled,
),
aggregateOperator: 'noop', aggregateOperator: 'noop',
searchText: '', searchText: '',
tagType: '', tagType: '',
@ -242,6 +257,8 @@ function K8sJobsList({
queryKey: ['jobList', query], queryKey: ['jobList', query],
enabled: !!query, enabled: !!query,
}, },
undefined,
dotMetricsEnabled,
); );
const jobsData = useMemo(() => data?.payload?.data?.records || [], [data]); const jobsData = useMemo(() => data?.payload?.data?.records || [], [data]);

View File

@ -263,6 +263,12 @@ export const getK8sJobsListColumns = (
return columnsConfig as ColumnType<K8sJobsRowData>[]; return columnsConfig as ColumnType<K8sJobsRowData>[];
}; };
const dotToUnder: Record<string, keyof K8sJobsData['meta']> = {
'k8s.job.name': 'k8s_job_name',
'k8s.namespace.name': 'k8s_namespace_name',
'k8s.cluster.name': 'k8s_cluster_name',
};
const getGroupByEle = ( const getGroupByEle = (
job: K8sJobsData, job: K8sJobsData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -270,7 +276,13 @@ const getGroupByEle = (
const groupByValues: string[] = []; const groupByValues: string[] = [];
groupBy.forEach((group) => { groupBy.forEach((group) => {
groupByValues.push(job.meta[group.key as keyof typeof job.meta]); const rawKey = group.key as string;
// Choose mapped key if present, otherwise use rawKey
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof job.meta;
const value = job.meta[metaKey];
groupByValues.push(value);
}); });
return ( return (

View File

@ -28,11 +28,13 @@ import { AppState } from 'store/reducers';
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData'; import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { getOrderByFromParams } from '../commonUtils'; import { getOrderByFromParams } from '../commonUtils';
import { import {
GetK8sEntityToAggregateAttribute,
INFRA_MONITORING_K8S_PARAMS_KEYS, INFRA_MONITORING_K8S_PARAMS_KEYS,
K8sCategory, K8sCategory,
K8sEntityToAggregateAttributeMapping,
} from '../constants'; } from '../constants';
import K8sHeader from '../K8sHeader'; import K8sHeader from '../K8sHeader';
import LoadingContainer from '../LoadingContainer'; import LoadingContainer from '../LoadingContainer';
@ -136,6 +138,11 @@ function K8sNamespacesList({
} }
}, [quickFiltersLastUpdated]); }, [quickFiltersLastUpdated]);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const createFiltersForSelectedRowData = ( const createFiltersForSelectedRowData = (
selectedRowData: K8sNamespacesRowData, selectedRowData: K8sNamespacesRowData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -195,6 +202,8 @@ function K8sNamespacesList({
queryKey: ['namespaceList', fetchGroupedByRowDataQuery], queryKey: ['namespaceList', fetchGroupedByRowDataQuery],
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData, enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
}, },
undefined,
dotMetricsEnabled,
); );
const { const {
@ -203,8 +212,10 @@ function K8sNamespacesList({
} = useGetAggregateKeys( } = useGetAggregateKeys(
{ {
dataSource: currentQuery.builder.queryData[0].dataSource, dataSource: currentQuery.builder.queryData[0].dataSource,
aggregateAttribute: aggregateAttribute: GetK8sEntityToAggregateAttribute(
K8sEntityToAggregateAttributeMapping[K8sCategory.NAMESPACES], K8sCategory.NAMESPACES,
dotMetricsEnabled,
),
aggregateOperator: 'noop', aggregateOperator: 'noop',
searchText: '', searchText: '',
tagType: '', tagType: '',
@ -245,6 +256,8 @@ function K8sNamespacesList({
queryKey: ['namespaceList', query], queryKey: ['namespaceList', query],
enabled: !!query, enabled: !!query,
}, },
undefined,
dotMetricsEnabled,
); );
const namespacesData = useMemo(() => data?.payload?.data?.records || [], [ const namespacesData = useMemo(() => data?.payload?.data?.records || [], [

View File

@ -122,6 +122,11 @@ export const getK8sNamespacesListColumns = (
return columnsConfig as ColumnType<K8sNamespacesRowData>[]; return columnsConfig as ColumnType<K8sNamespacesRowData>[];
}; };
const dotToUnder: Record<string, keyof K8sNamespacesData['meta']> = {
'k8s.namespace.name': 'k8s_namespace_name',
'k8s.cluster.name': 'k8s_cluster_name',
};
const getGroupByEle = ( const getGroupByEle = (
namespace: K8sNamespacesData, namespace: K8sNamespacesData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -129,7 +134,13 @@ const getGroupByEle = (
const groupByValues: string[] = []; const groupByValues: string[] = [];
groupBy.forEach((group) => { groupBy.forEach((group) => {
groupByValues.push(namespace.meta[group.key as keyof typeof namespace.meta]); const rawKey = group.key as string;
// Choose mapped key if present, otherwise use rawKey
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof namespace.meta;
const value = namespace.meta[metaKey];
groupByValues.push(value);
}); });
return ( return (

View File

@ -28,11 +28,13 @@ import { AppState } from 'store/reducers';
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData'; import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { getOrderByFromParams } from '../commonUtils'; import { getOrderByFromParams } from '../commonUtils';
import { import {
GetK8sEntityToAggregateAttribute,
INFRA_MONITORING_K8S_PARAMS_KEYS, INFRA_MONITORING_K8S_PARAMS_KEYS,
K8sCategory, K8sCategory,
K8sEntityToAggregateAttributeMapping,
} from '../constants'; } from '../constants';
import K8sHeader from '../K8sHeader'; import K8sHeader from '../K8sHeader';
import LoadingContainer from '../LoadingContainer'; import LoadingContainer from '../LoadingContainer';
@ -130,6 +132,11 @@ function K8sNodesList({
} }
}, [quickFiltersLastUpdated]); }, [quickFiltersLastUpdated]);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const createFiltersForSelectedRowData = ( const createFiltersForSelectedRowData = (
selectedRowData: K8sNodesRowData, selectedRowData: K8sNodesRowData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -183,10 +190,15 @@ function K8sNodesList({
isLoading: isLoadingGroupedByRowData, isLoading: isLoadingGroupedByRowData,
isError: isErrorGroupedByRowData, isError: isErrorGroupedByRowData,
refetch: fetchGroupedByRowData, refetch: fetchGroupedByRowData,
} = useGetK8sNodesList(fetchGroupedByRowDataQuery as K8sNodesListPayload, { } = useGetK8sNodesList(
queryKey: ['nodeList', fetchGroupedByRowDataQuery], fetchGroupedByRowDataQuery as K8sNodesListPayload,
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData, {
}); queryKey: ['nodeList', fetchGroupedByRowDataQuery],
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
},
undefined,
dotMetricsEnabled,
);
const { const {
data: groupByFiltersData, data: groupByFiltersData,
@ -194,7 +206,10 @@ function K8sNodesList({
} = useGetAggregateKeys( } = useGetAggregateKeys(
{ {
dataSource: currentQuery.builder.queryData[0].dataSource, dataSource: currentQuery.builder.queryData[0].dataSource,
aggregateAttribute: K8sEntityToAggregateAttributeMapping[K8sCategory.NODES], aggregateAttribute: GetK8sEntityToAggregateAttribute(
K8sCategory.NODES,
dotMetricsEnabled,
),
aggregateOperator: 'noop', aggregateOperator: 'noop',
searchText: '', searchText: '',
tagType: '', tagType: '',
@ -240,6 +255,8 @@ function K8sNodesList({
queryKey: ['nodeList', query], queryKey: ['nodeList', query],
enabled: !!query, enabled: !!query,
}, },
undefined,
dotMetricsEnabled,
); );
const nodesData = useMemo(() => data?.payload?.data?.records || [], [data]); const nodesData = useMemo(() => data?.payload?.data?.records || [], [data]);

View File

@ -152,6 +152,12 @@ export const getK8sNodesListColumns = (
return columnsConfig as ColumnType<K8sNodesRowData>[]; return columnsConfig as ColumnType<K8sNodesRowData>[];
}; };
const dotToUnder: Record<string, keyof K8sNodesData['meta']> = {
'k8s.node.name': 'k8s_node_name',
'k8s.cluster.name': 'k8s_cluster_name',
'k8s.node.uid': 'k8s_node_uid',
};
const getGroupByEle = ( const getGroupByEle = (
node: K8sNodesData, node: K8sNodesData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -159,7 +165,14 @@ const getGroupByEle = (
const groupByValues: string[] = []; const groupByValues: string[] = [];
groupBy.forEach((group) => { groupBy.forEach((group) => {
groupByValues.push(node.meta[group.key as keyof typeof node.meta]); const rawKey = group.key as string;
// Choose mapped key if present, otherwise use rawKey
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof node.meta;
const value = node.meta[metaKey];
groupByValues.push(value);
}); });
return ( return (

View File

@ -29,11 +29,13 @@ import { AppState } from 'store/reducers';
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData'; import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { getOrderByFromParams } from '../commonUtils'; import { getOrderByFromParams } from '../commonUtils';
import { import {
GetK8sEntityToAggregateAttribute,
INFRA_MONITORING_K8S_PARAMS_KEYS, INFRA_MONITORING_K8S_PARAMS_KEYS,
K8sCategory, K8sCategory,
K8sEntityToAggregateAttributeMapping,
} from '../constants'; } from '../constants';
import K8sHeader from '../K8sHeader'; import K8sHeader from '../K8sHeader';
import LoadingContainer from '../LoadingContainer'; import LoadingContainer from '../LoadingContainer';
@ -118,13 +120,21 @@ function K8sPodsList({
[currentQuery?.builder?.queryData], [currentQuery?.builder?.queryData],
); );
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const { const {
data: groupByFiltersData, data: groupByFiltersData,
isLoading: isLoadingGroupByFilters, isLoading: isLoadingGroupByFilters,
} = useGetAggregateKeys( } = useGetAggregateKeys(
{ {
dataSource: currentQuery.builder.queryData[0].dataSource, dataSource: currentQuery.builder.queryData[0].dataSource,
aggregateAttribute: K8sEntityToAggregateAttributeMapping[K8sCategory.PODS], aggregateAttribute: GetK8sEntityToAggregateAttribute(
K8sCategory.PODS,
dotMetricsEnabled,
),
aggregateOperator: 'noop', aggregateOperator: 'noop',
searchText: '', searchText: '',
tagType: '', tagType: '',
@ -201,6 +211,8 @@ function K8sPodsList({
queryKey: ['hostList', query], queryKey: ['hostList', query],
enabled: !!query, enabled: !!query,
}, },
undefined,
dotMetricsEnabled,
); );
const createFiltersForSelectedRowData = ( const createFiltersForSelectedRowData = (
@ -255,10 +267,15 @@ function K8sPodsList({
isLoading: isLoadingGroupedByRowData, isLoading: isLoadingGroupedByRowData,
isError: isErrorGroupedByRowData, isError: isErrorGroupedByRowData,
refetch: fetchGroupedByRowData, refetch: fetchGroupedByRowData,
} = useGetK8sPodsList(fetchGroupedByRowDataQuery as K8sPodsListPayload, { } = useGetK8sPodsList(
queryKey: ['hostList', fetchGroupedByRowDataQuery], fetchGroupedByRowDataQuery as K8sPodsListPayload,
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData, {
}); queryKey: ['hostList', fetchGroupedByRowDataQuery],
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
},
undefined,
dotMetricsEnabled,
);
const podsData = useMemo(() => data?.payload?.data?.records || [], [data]); const podsData = useMemo(() => data?.payload?.data?.records || [], [data]);
const totalCount = data?.payload?.data?.total || 0; const totalCount = data?.payload?.data?.total || 0;

File diff suppressed because it is too large Load Diff

View File

@ -29,11 +29,13 @@ import { AppState } from 'store/reducers';
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData'; import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { getOrderByFromParams } from '../commonUtils'; import { getOrderByFromParams } from '../commonUtils';
import { import {
GetK8sEntityToAggregateAttribute,
INFRA_MONITORING_K8S_PARAMS_KEYS, INFRA_MONITORING_K8S_PARAMS_KEYS,
K8sCategory, K8sCategory,
K8sEntityToAggregateAttributeMapping,
} from '../constants'; } from '../constants';
import K8sHeader from '../K8sHeader'; import K8sHeader from '../K8sHeader';
import LoadingContainer from '../LoadingContainer'; import LoadingContainer from '../LoadingContainer';
@ -137,6 +139,11 @@ function K8sStatefulSetsList({
} }
}, [quickFiltersLastUpdated]); }, [quickFiltersLastUpdated]);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const createFiltersForSelectedRowData = ( const createFiltersForSelectedRowData = (
selectedRowData: K8sStatefulSetsRowData, selectedRowData: K8sStatefulSetsRowData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -196,6 +203,8 @@ function K8sStatefulSetsList({
queryKey: ['statefulSetList', fetchGroupedByRowDataQuery], queryKey: ['statefulSetList', fetchGroupedByRowDataQuery],
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData, enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
}, },
undefined,
dotMetricsEnabled,
); );
const { const {
@ -204,8 +213,10 @@ function K8sStatefulSetsList({
} = useGetAggregateKeys( } = useGetAggregateKeys(
{ {
dataSource: currentQuery.builder.queryData[0].dataSource, dataSource: currentQuery.builder.queryData[0].dataSource,
aggregateAttribute: aggregateAttribute: GetK8sEntityToAggregateAttribute(
K8sEntityToAggregateAttributeMapping[K8sCategory.STATEFULSETS], K8sCategory.STATEFULSETS,
dotMetricsEnabled,
),
aggregateOperator: 'noop', aggregateOperator: 'noop',
searchText: '', searchText: '',
tagType: '', tagType: '',
@ -251,6 +262,8 @@ function K8sStatefulSetsList({
queryKey: ['statefulSetList', query], queryKey: ['statefulSetList', query],
enabled: !!query, enabled: !!query,
}, },
undefined,
dotMetricsEnabled,
); );
const statefulSetsData = useMemo(() => data?.payload?.data?.records || [], [ const statefulSetsData = useMemo(() => data?.payload?.data?.records || [], [

View File

@ -236,6 +236,11 @@ export const getK8sStatefulSetsListColumns = (
return columnsConfig as ColumnType<K8sStatefulSetsRowData>[]; return columnsConfig as ColumnType<K8sStatefulSetsRowData>[];
}; };
const dotToUnder: Record<string, keyof K8sStatefulSetsData['meta']> = {
'k8s.namespace.name': 'k8s_namespace_name',
'k8s.statefulset.name': 'k8s_statefulset_name',
};
const getGroupByEle = ( const getGroupByEle = (
statefulSet: K8sStatefulSetsData, statefulSet: K8sStatefulSetsData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -243,9 +248,14 @@ const getGroupByEle = (
const groupByValues: string[] = []; const groupByValues: string[] = [];
groupBy.forEach((group) => { groupBy.forEach((group) => {
groupByValues.push( const rawKey = group.key as string;
statefulSet.meta[group.key as keyof typeof statefulSet.meta],
); // Choose mapped key if present, otherwise use rawKey
const metaKey = (dotToUnder[rawKey] ??
rawKey) as keyof typeof statefulSet.meta;
const value = statefulSet.meta[metaKey];
groupByValues.push(value);
}); });
return ( return (

View File

@ -29,11 +29,13 @@ import { AppState } from 'store/reducers';
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData'; import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { getOrderByFromParams } from '../commonUtils'; import { getOrderByFromParams } from '../commonUtils';
import { import {
GetK8sEntityToAggregateAttribute,
INFRA_MONITORING_K8S_PARAMS_KEYS, INFRA_MONITORING_K8S_PARAMS_KEYS,
K8sCategory, K8sCategory,
K8sEntityToAggregateAttributeMapping,
} from '../constants'; } from '../constants';
import K8sHeader from '../K8sHeader'; import K8sHeader from '../K8sHeader';
import LoadingContainer from '../LoadingContainer'; import LoadingContainer from '../LoadingContainer';
@ -137,6 +139,11 @@ function K8sVolumesList({
} }
}, [quickFiltersLastUpdated]); }, [quickFiltersLastUpdated]);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const createFiltersForSelectedRowData = ( const createFiltersForSelectedRowData = (
selectedRowData: K8sVolumesRowData, selectedRowData: K8sVolumesRowData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -190,10 +197,15 @@ function K8sVolumesList({
isLoading: isLoadingGroupedByRowData, isLoading: isLoadingGroupedByRowData,
isError: isErrorGroupedByRowData, isError: isErrorGroupedByRowData,
refetch: fetchGroupedByRowData, refetch: fetchGroupedByRowData,
} = useGetK8sVolumesList(fetchGroupedByRowDataQuery as K8sVolumesListPayload, { } = useGetK8sVolumesList(
queryKey: ['volumeList', fetchGroupedByRowDataQuery], fetchGroupedByRowDataQuery as K8sVolumesListPayload,
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData, {
}); queryKey: ['volumeList', fetchGroupedByRowDataQuery],
enabled: !!fetchGroupedByRowDataQuery && !!selectedRowData,
},
undefined,
dotMetricsEnabled,
);
const { const {
data: groupByFiltersData, data: groupByFiltersData,
@ -201,7 +213,10 @@ function K8sVolumesList({
} = useGetAggregateKeys( } = useGetAggregateKeys(
{ {
dataSource: currentQuery.builder.queryData[0].dataSource, dataSource: currentQuery.builder.queryData[0].dataSource,
aggregateAttribute: K8sEntityToAggregateAttributeMapping[K8sCategory.NODES], aggregateAttribute: GetK8sEntityToAggregateAttribute(
K8sCategory.NODES,
dotMetricsEnabled,
),
aggregateOperator: 'noop', aggregateOperator: 'noop',
searchText: '', searchText: '',
tagType: '', tagType: '',
@ -247,6 +262,8 @@ function K8sVolumesList({
queryKey: ['volumeList', query], queryKey: ['volumeList', query],
enabled: !!query, enabled: !!query,
}, },
undefined,
dotMetricsEnabled,
); );
const volumesData = useMemo(() => data?.payload?.data?.records || [], [data]); const volumesData = useMemo(() => data?.payload?.data?.records || [], [data]);

View File

@ -142,6 +142,16 @@ export const getK8sVolumesListColumns = (
return columnsConfig as ColumnType<K8sVolumesRowData>[]; return columnsConfig as ColumnType<K8sVolumesRowData>[];
}; };
const dotToUnder: Record<string, keyof K8sVolumesData['meta']> = {
'k8s.namespace.name': 'k8s_namespace_name',
'k8s.node.name': 'k8s_node_name',
'k8s.pod.name': 'k8s_pod_name',
'k8s.pod.uid': 'k8s_pod_uid',
'k8s.statefulset.name': 'k8s_statefulset_name',
'k8s.cluster.name': 'k8s_cluster_name',
'k8s.persistentvolumeclaim.name': 'k8s_persistentvolumeclaim_name',
};
const getGroupByEle = ( const getGroupByEle = (
volume: K8sVolumesData, volume: K8sVolumesData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -149,7 +159,13 @@ const getGroupByEle = (
const groupByValues: string[] = []; const groupByValues: string[] = [];
groupBy.forEach((group) => { groupBy.forEach((group) => {
groupByValues.push(volume.meta[group.key as keyof typeof volume.meta]); const rawKey = group.key as string;
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof volume.meta;
const value = volume.meta[metaKey];
groupByValues.push(value);
}); });
return ( return (

File diff suppressed because it is too large Load Diff

View File

@ -299,6 +299,19 @@ export const getK8sPodsListColumns = (
return updatedColumnsConfig as ColumnType<K8sPodsRowData>[]; return updatedColumnsConfig as ColumnType<K8sPodsRowData>[];
}; };
const dotToUnder: Record<string, keyof K8sPodsData['meta']> = {
'k8s.cronjob.name': 'k8s_cronjob_name',
'k8s.daemonset.name': 'k8s_daemonset_name',
'k8s.deployment.name': 'k8s_deployment_name',
'k8s.job.name': 'k8s_job_name',
'k8s.namespace.name': 'k8s_namespace_name',
'k8s.node.name': 'k8s_node_name',
'k8s.pod.name': 'k8s_pod_name',
'k8s.pod.uid': 'k8s_pod_uid',
'k8s.statefulset.name': 'k8s_statefulset_name',
'k8s.cluster.name': 'k8s_cluster_name',
};
const getGroupByEle = ( const getGroupByEle = (
pod: K8sPodsData, pod: K8sPodsData,
groupBy: IBuilderQuery['groupBy'], groupBy: IBuilderQuery['groupBy'],
@ -306,7 +319,13 @@ const getGroupByEle = (
const groupByValues: string[] = []; const groupByValues: string[] = [];
groupBy.forEach((group) => { groupBy.forEach((group) => {
groupByValues.push(pod.meta[group.key as keyof typeof pod.meta]); const rawKey = group.key as string;
// Choose mapped key if present, otherwise use rawKey
const metaKey = (dotToUnder[rawKey] ?? rawKey) as keyof typeof pod.meta;
const value = pod.meta[metaKey];
groupByValues.push(value);
}); });
return ( return (

View File

@ -15,6 +15,8 @@ import { SuccessResponse } from 'types/api';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange'; import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import uPlot from 'uplot'; import uPlot from 'uplot';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { import {
getHostQueryPayload, getHostQueryPayload,
getNodeQueryPayload, getNodeQueryPayload,
@ -49,12 +51,23 @@ function NodeMetrics({
}; };
}, [logLineTimestamp]); }, [logLineTimestamp]);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const queryPayloads = useMemo(() => { const queryPayloads = useMemo(() => {
if (nodeName) { if (nodeName) {
return getNodeQueryPayload(clusterName, nodeName, start, end); return getNodeQueryPayload(
clusterName,
nodeName,
start,
end,
dotMetricsEnabled,
);
} }
return getHostQueryPayload(hostName, start, end); return getHostQueryPayload(hostName, start, end, dotMetricsEnabled);
}, [nodeName, hostName, clusterName, start, end]); }, [nodeName, hostName, clusterName, start, end, dotMetricsEnabled]);
const widgetInfo = nodeName ? nodeWidgetInfo : hostWidgetInfo; const widgetInfo = nodeName ? nodeWidgetInfo : hostWidgetInfo;
const queries = useQueries( const queries = useQueries(

View File

@ -8,6 +8,7 @@ import { useResizeObserver } from 'hooks/useDimensions';
import { GetMetricQueryRange } from 'lib/dashboard/getQueryResults'; import { GetMetricQueryRange } from 'lib/dashboard/getQueryResults';
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions'; import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData'; import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
import { useAppContext } from 'providers/App/App';
import { useTimezone } from 'providers/Timezone'; import { useTimezone } from 'providers/Timezone';
import { useMemo, useRef } from 'react'; import { useMemo, useRef } from 'react';
import { useQueries, UseQueryResult } from 'react-query'; import { useQueries, UseQueryResult } from 'react-query';
@ -15,6 +16,7 @@ import { SuccessResponse } from 'types/api';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange'; import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import uPlot from 'uplot'; import uPlot from 'uplot';
import { FeatureKeys } from '../../../constants/features';
import { getPodQueryPayload, podWidgetInfo } from './constants'; import { getPodQueryPayload, podWidgetInfo } from './constants';
function PodMetrics({ function PodMetrics({
@ -41,9 +43,15 @@ function PodMetrics({
verticalLineTimestamp: logTimestamp.unix(), verticalLineTimestamp: logTimestamp.unix(),
}; };
}, [logLineTimestamp]); }, [logLineTimestamp]);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const queryPayloads = useMemo( const queryPayloads = useMemo(
() => getPodQueryPayload(clusterName, podName, start, end), () => getPodQueryPayload(clusterName, podName, start, end, dotMetricsEnabled),
[clusterName, end, podName, start], [clusterName, end, podName, start, dotMetricsEnabled],
); );
const queries = useQueries( const queries = useQueries(
queryPayloads.map((payload) => ({ queryPayloads.map((payload) => ({

View File

@ -21,6 +21,7 @@ export const databaseCallsRPS = ({
servicename, servicename,
legend, legend,
tagFilterItems, tagFilterItems,
dotMetricsEnabled,
}: DatabaseCallsRPSProps): QueryBuilderData => { }: DatabaseCallsRPSProps): QueryBuilderData => {
const autocompleteData: BaseAutocompleteData[] = [ const autocompleteData: BaseAutocompleteData[] = [
{ {
@ -34,7 +35,7 @@ export const databaseCallsRPS = ({
{ {
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
key: 'db_system', key: dotMetricsEnabled ? WidgetKeys.Db_system : WidgetKeys.Db_system_norm,
type: 'tag', type: 'tag',
}, },
]; ];
@ -43,7 +44,9 @@ export const databaseCallsRPS = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
type: MetricsType.Resource, type: MetricsType.Resource,
@ -75,6 +78,7 @@ export const databaseCallsRPS = ({
export const databaseCallsAvgDuration = ({ export const databaseCallsAvgDuration = ({
servicename, servicename,
tagFilterItems, tagFilterItems,
dotMetricsEnabled,
}: DatabaseCallProps): QueryBuilderData => { }: DatabaseCallProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = { const autocompleteDataA: BaseAutocompleteData = {
key: WidgetKeys.SignozDbLatencySum, key: WidgetKeys.SignozDbLatencySum,
@ -93,7 +97,9 @@ export const databaseCallsAvgDuration = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
type: MetricsType.Resource, type: MetricsType.Resource,

View File

@ -33,6 +33,7 @@ export const externalCallErrorPercent = ({
servicename, servicename,
legend, legend,
tagFilterItems, tagFilterItems,
dotMetricsEnabled,
}: ExternalCallDurationByAddressProps): QueryBuilderData => { }: ExternalCallDurationByAddressProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = { const autocompleteDataA: BaseAutocompleteData = {
key: WidgetKeys.SignozExternalCallLatencyCount, key: WidgetKeys.SignozExternalCallLatencyCount,
@ -51,7 +52,9 @@ export const externalCallErrorPercent = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
type: MetricsType.Resource, type: MetricsType.Resource,
@ -62,7 +65,7 @@ export const externalCallErrorPercent = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.StatusCode, key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
dataType: DataTypes.Int64, dataType: DataTypes.Int64,
isColumn: false, isColumn: false,
type: MetricsType.Tag, type: MetricsType.Tag,
@ -76,7 +79,9 @@ export const externalCallErrorPercent = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
type: MetricsType.Resource, type: MetricsType.Resource,
@ -121,6 +126,7 @@ export const externalCallErrorPercent = ({
export const externalCallDuration = ({ export const externalCallDuration = ({
servicename, servicename,
tagFilterItems, tagFilterItems,
dotMetricsEnabled,
}: ExternalCallProps): QueryBuilderData => { }: ExternalCallProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = { const autocompleteDataA: BaseAutocompleteData = {
dataType: DataTypes.Float64, dataType: DataTypes.Float64,
@ -144,7 +150,9 @@ export const externalCallDuration = ({
key: { key: {
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
type: MetricsType.Resource, type: MetricsType.Resource,
}, },
op: OPERATORS.IN, op: OPERATORS.IN,
@ -184,6 +192,7 @@ export const externalCallRpsByAddress = ({
servicename, servicename,
legend, legend,
tagFilterItems, tagFilterItems,
dotMetricsEnabled,
}: ExternalCallDurationByAddressProps): QueryBuilderData => { }: ExternalCallDurationByAddressProps): QueryBuilderData => {
const autocompleteData: BaseAutocompleteData[] = [ const autocompleteData: BaseAutocompleteData[] = [
{ {
@ -200,7 +209,9 @@ export const externalCallRpsByAddress = ({
key: { key: {
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
type: MetricsType.Resource, type: MetricsType.Resource,
}, },
op: OPERATORS.IN, op: OPERATORS.IN,
@ -231,6 +242,7 @@ export const externalCallDurationByAddress = ({
servicename, servicename,
legend, legend,
tagFilterItems, tagFilterItems,
dotMetricsEnabled,
}: ExternalCallDurationByAddressProps): QueryBuilderData => { }: ExternalCallDurationByAddressProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = { const autocompleteDataA: BaseAutocompleteData = {
dataType: DataTypes.Float64, dataType: DataTypes.Float64,
@ -253,7 +265,9 @@ export const externalCallDurationByAddress = ({
key: { key: {
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
type: MetricsType.Resource, type: MetricsType.Resource,
}, },
op: OPERATORS.IN, op: OPERATORS.IN,

View File

@ -37,10 +37,18 @@ export const latency = ({
tagFilterItems, tagFilterItems,
isSpanMetricEnable = false, isSpanMetricEnable = false,
topLevelOperationsRoute, topLevelOperationsRoute,
dotMetricsEnabled,
}: LatencyProps): QueryBuilderData => { }: LatencyProps): QueryBuilderData => {
const signozLatencyBucketMetrics = dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm;
const signozMetricsServiceName = dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm;
const newAutoCompleteData: BaseAutocompleteData = { const newAutoCompleteData: BaseAutocompleteData = {
key: isSpanMetricEnable key: isSpanMetricEnable
? WidgetKeys.Signoz_latency_bucket ? signozLatencyBucketMetrics
: WidgetKeys.DurationNano, : WidgetKeys.DurationNano,
dataType: DataTypes.Float64, dataType: DataTypes.Float64,
isColumn: true, isColumn: true,
@ -53,7 +61,7 @@ export const latency = ({
{ {
id: '', id: '',
key: { key: {
key: isSpanMetricEnable ? WidgetKeys.Service_name : WidgetKeys.ServiceName, key: isSpanMetricEnable ? signozMetricsServiceName : WidgetKeys.ServiceName,
dataType: DataTypes.String, dataType: DataTypes.String,
type: isSpanMetricEnable ? MetricsType.Resource : MetricsType.Tag, type: isSpanMetricEnable ? MetricsType.Resource : MetricsType.Tag,
isColumn: !isSpanMetricEnable, isColumn: !isSpanMetricEnable,
@ -295,23 +303,30 @@ export const apDexMetricsQueryBuilderQueries = ({
threashold, threashold,
delta, delta,
metricsBuckets, metricsBuckets,
dotMetricsEnabled,
}: ApDexMetricsQueryBuilderQueriesProps): QueryBuilderData => { }: ApDexMetricsQueryBuilderQueriesProps): QueryBuilderData => {
const autoCompleteDataA: BaseAutocompleteData = { const autoCompleteDataA: BaseAutocompleteData = {
key: WidgetKeys.SignozLatencyCount, key: dotMetricsEnabled
? WidgetKeys.SignozLatencyCount
: WidgetKeys.SignozLatencyCountNorm,
dataType: DataTypes.Float64, dataType: DataTypes.Float64,
isColumn: true, isColumn: true,
type: '', type: '',
}; };
const autoCompleteDataB: BaseAutocompleteData = { const autoCompleteDataB: BaseAutocompleteData = {
key: WidgetKeys.Signoz_latency_bucket, key: dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm,
dataType: DataTypes.Float64, dataType: DataTypes.Float64,
isColumn: true, isColumn: true,
type: '', type: '',
}; };
const autoCompleteDataC: BaseAutocompleteData = { const autoCompleteDataC: BaseAutocompleteData = {
key: WidgetKeys.Signoz_latency_bucket, key: dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm,
dataType: DataTypes.Float64, dataType: DataTypes.Float64,
isColumn: true, isColumn: true,
type: '', type: '',
@ -321,7 +336,9 @@ export const apDexMetricsQueryBuilderQueries = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
type: MetricsType.Tag, type: MetricsType.Tag,
@ -347,7 +364,7 @@ export const apDexMetricsQueryBuilderQueries = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.StatusCode, key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
type: MetricsType.Tag, type: MetricsType.Tag,
@ -369,7 +386,9 @@ export const apDexMetricsQueryBuilderQueries = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
type: MetricsType.Tag, type: MetricsType.Tag,
@ -406,7 +425,7 @@ export const apDexMetricsQueryBuilderQueries = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.StatusCode, key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
type: MetricsType.Tag, type: MetricsType.Tag,
@ -417,7 +436,9 @@ export const apDexMetricsQueryBuilderQueries = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
type: MetricsType.Tag, type: MetricsType.Tag,
@ -482,10 +503,13 @@ export const operationPerSec = ({
servicename, servicename,
tagFilterItems, tagFilterItems,
topLevelOperations, topLevelOperations,
dotMetricsEnabled,
}: OperationPerSecProps): QueryBuilderData => { }: OperationPerSecProps): QueryBuilderData => {
const autocompleteData: BaseAutocompleteData[] = [ const autocompleteData: BaseAutocompleteData[] = [
{ {
key: WidgetKeys.SignozLatencyCount, key: dotMetricsEnabled
? WidgetKeys.SignozLatencyCount
: WidgetKeys.SignozLatencyCountNorm,
dataType: DataTypes.Float64, dataType: DataTypes.Float64,
isColumn: true, isColumn: true,
type: '', type: '',
@ -497,7 +521,9 @@ export const operationPerSec = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
type: MetricsType.Resource, type: MetricsType.Resource,
@ -540,6 +566,7 @@ export const errorPercentage = ({
servicename, servicename,
tagFilterItems, tagFilterItems,
topLevelOperations, topLevelOperations,
dotMetricsEnabled,
}: OperationPerSecProps): QueryBuilderData => { }: OperationPerSecProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = { const autocompleteDataA: BaseAutocompleteData = {
key: WidgetKeys.SignozCallsTotal, key: WidgetKeys.SignozCallsTotal,
@ -560,7 +587,9 @@ export const errorPercentage = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
type: MetricsType.Resource, type: MetricsType.Resource,
@ -582,7 +611,9 @@ export const errorPercentage = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.StatusCode, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.StatusCodeNorm,
dataType: DataTypes.Int64, dataType: DataTypes.Int64,
isColumn: false, isColumn: false,
type: MetricsType.Tag, type: MetricsType.Tag,
@ -597,7 +628,9 @@ export const errorPercentage = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
type: MetricsType.Resource, type: MetricsType.Resource,

View File

@ -21,9 +21,12 @@ import { getQueryBuilderQuerieswithFormula } from './MetricsPageQueriesFactory';
export const topOperationQueries = ({ export const topOperationQueries = ({
servicename, servicename,
dotMetricsEnabled,
}: TopOperationQueryFactoryProps): QueryBuilderData => { }: TopOperationQueryFactoryProps): QueryBuilderData => {
const latencyAutoCompleteData: BaseAutocompleteData = { const latencyAutoCompleteData: BaseAutocompleteData = {
key: WidgetKeys.Signoz_latency_bucket, key: dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm,
dataType: DataTypes.Float64, dataType: DataTypes.Float64,
isColumn: true, isColumn: true,
type: '', type: '',
@ -37,7 +40,9 @@ export const topOperationQueries = ({
}; };
const numOfCallAutoCompleteData: BaseAutocompleteData = { const numOfCallAutoCompleteData: BaseAutocompleteData = {
key: WidgetKeys.SignozLatencyCount, key: dotMetricsEnabled
? WidgetKeys.SignozLatencyCount
: WidgetKeys.SignozLatencyCountNorm,
dataType: DataTypes.Float64, dataType: DataTypes.Float64,
isColumn: true, isColumn: true,
type: '', type: '',
@ -47,7 +52,9 @@ export const topOperationQueries = ({
{ {
id: '', id: '',
key: { key: {
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
type: MetricsType.Resource, type: MetricsType.Resource,
@ -63,7 +70,9 @@ export const topOperationQueries = ({
key: { key: {
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
type: MetricsType.Resource, type: MetricsType.Resource,
}, },
op: OPERATORS.IN, op: OPERATORS.IN,
@ -74,7 +83,7 @@ export const topOperationQueries = ({
key: { key: {
dataType: DataTypes.Int64, dataType: DataTypes.Int64,
isColumn: false, isColumn: false,
key: WidgetKeys.StatusCode, key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
type: MetricsType.Tag, type: MetricsType.Tag,
}, },
op: OPERATORS.IN, op: OPERATORS.IN,

View File

@ -11,6 +11,7 @@ import {
import useResourceAttribute from 'hooks/useResourceAttribute'; import useResourceAttribute from 'hooks/useResourceAttribute';
import { import {
convertRawQueriesToTraceSelectedTags, convertRawQueriesToTraceSelectedTags,
getResourceDeploymentKeys,
resourceAttributesToTagFilterItems, resourceAttributesToTagFilterItems,
} from 'hooks/useResourceAttribute/utils'; } from 'hooks/useResourceAttribute/utils';
import { useSafeNavigate } from 'hooks/useSafeNavigate'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
@ -26,6 +27,8 @@ import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
import { EQueryType } from 'types/common/dashboard'; import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { GraphTitle, MENU_ITEMS, SERVICE_CHART_ID } from '../constant'; import { GraphTitle, MENU_ITEMS, SERVICE_CHART_ID } from '../constant';
import { getWidgetQueryBuilder } from '../MetricsApplication.factory'; import { getWidgetQueryBuilder } from '../MetricsApplication.factory';
import { Card, GraphContainer, Row } from '../styles'; import { Card, GraphContainer, Row } from '../styles';
@ -80,7 +83,12 @@ function DBCall(): JSX.Element {
[queries], [queries],
); );
const legend = '{{db_system}}'; const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const legend = dotMetricsEnabled ? '{{db.system}}' : '{{db_system}}';
const databaseCallsRPSWidget = useMemo( const databaseCallsRPSWidget = useMemo(
() => () =>
@ -92,6 +100,7 @@ function DBCall(): JSX.Element {
servicename, servicename,
legend, legend,
tagFilterItems, tagFilterItems,
dotMetricsEnabled,
}), }),
clickhouse_sql: [], clickhouse_sql: [],
id: uuid(), id: uuid(),
@ -102,7 +111,7 @@ function DBCall(): JSX.Element {
id: SERVICE_CHART_ID.dbCallsRPS, id: SERVICE_CHART_ID.dbCallsRPS,
fillSpans: false, fillSpans: false,
}), }),
[servicename, tagFilterItems], [servicename, tagFilterItems, dotMetricsEnabled, legend],
); );
const databaseCallsAverageDurationWidget = useMemo( const databaseCallsAverageDurationWidget = useMemo(
() => () =>
@ -113,6 +122,7 @@ function DBCall(): JSX.Element {
builder: databaseCallsAvgDuration({ builder: databaseCallsAvgDuration({
servicename, servicename,
tagFilterItems, tagFilterItems,
dotMetricsEnabled,
}), }),
clickhouse_sql: [], clickhouse_sql: [],
id: uuid(), id: uuid(),
@ -123,7 +133,7 @@ function DBCall(): JSX.Element {
id: GraphTitle.DATABASE_CALLS_AVG_DURATION, id: GraphTitle.DATABASE_CALLS_AVG_DURATION,
fillSpans: true, fillSpans: true,
}), }),
[servicename, tagFilterItems], [servicename, tagFilterItems, dotMetricsEnabled],
); );
const stepInterval = useMemo( const stepInterval = useMemo(
@ -141,7 +151,7 @@ function DBCall(): JSX.Element {
useEffect(() => { useEffect(() => {
if (!logEventCalledRef.current) { if (!logEventCalledRef.current) {
const selectedEnvironments = queries.find( const selectedEnvironments = queries.find(
(val) => val.tagKey === 'resource_deployment_environment', (val) => val.tagKey === getResourceDeploymentKeys(dotMetricsEnabled),
)?.tagValue; )?.tagValue;
logEvent('APM: Service detail page visited', { logEvent('APM: Service detail page visited', {

View File

@ -13,6 +13,7 @@ import {
import useResourceAttribute from 'hooks/useResourceAttribute'; import useResourceAttribute from 'hooks/useResourceAttribute';
import { import {
convertRawQueriesToTraceSelectedTags, convertRawQueriesToTraceSelectedTags,
getResourceDeploymentKeys,
resourceAttributesToTagFilterItems, resourceAttributesToTagFilterItems,
} from 'hooks/useResourceAttribute/utils'; } from 'hooks/useResourceAttribute/utils';
import { useSafeNavigate } from 'hooks/useSafeNavigate'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
@ -28,6 +29,8 @@ import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { EQueryType } from 'types/common/dashboard'; import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { GraphTitle, legend, MENU_ITEMS } from '../constant'; import { GraphTitle, legend, MENU_ITEMS } from '../constant';
import { getWidgetQueryBuilder } from '../MetricsApplication.factory'; import { getWidgetQueryBuilder } from '../MetricsApplication.factory';
import { Card, GraphContainer, Row } from '../styles'; import { Card, GraphContainer, Row } from '../styles';
@ -75,6 +78,10 @@ function External(): JSX.Element {
handleNonInQueryRange(resourceAttributesToTagFilterItems(queries)) || [], handleNonInQueryRange(resourceAttributesToTagFilterItems(queries)) || [],
[queries], [queries],
); );
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const externalCallErrorWidget = useMemo( const externalCallErrorWidget = useMemo(
() => () =>
@ -86,6 +93,7 @@ function External(): JSX.Element {
servicename, servicename,
legend: legend.address, legend: legend.address,
tagFilterItems, tagFilterItems,
dotMetricsEnabled,
}), }),
clickhouse_sql: [], clickhouse_sql: [],
id: uuid(), id: uuid(),
@ -95,7 +103,7 @@ function External(): JSX.Element {
yAxisUnit: '%', yAxisUnit: '%',
id: GraphTitle.EXTERNAL_CALL_ERROR_PERCENTAGE, id: GraphTitle.EXTERNAL_CALL_ERROR_PERCENTAGE,
}), }),
[servicename, tagFilterItems], [servicename, tagFilterItems, dotMetricsEnabled],
); );
const selectedTraceTags = useMemo( const selectedTraceTags = useMemo(
@ -112,6 +120,7 @@ function External(): JSX.Element {
builder: externalCallDuration({ builder: externalCallDuration({
servicename, servicename,
tagFilterItems, tagFilterItems,
dotMetricsEnabled,
}), }),
clickhouse_sql: [], clickhouse_sql: [],
id: uuid(), id: uuid(),
@ -122,7 +131,7 @@ function External(): JSX.Element {
id: GraphTitle.EXTERNAL_CALL_DURATION, id: GraphTitle.EXTERNAL_CALL_DURATION,
fillSpans: true, fillSpans: true,
}), }),
[servicename, tagFilterItems], [servicename, tagFilterItems, dotMetricsEnabled],
); );
const errorApmToTraceQuery = useGetAPMToTracesQueries({ const errorApmToTraceQuery = useGetAPMToTracesQueries({
@ -158,7 +167,7 @@ function External(): JSX.Element {
useEffect(() => { useEffect(() => {
if (!logEventCalledRef.current) { if (!logEventCalledRef.current) {
const selectedEnvironments = queries.find( const selectedEnvironments = queries.find(
(val) => val.tagKey === 'resource_deployment_environment', (val) => val.tagKey === getResourceDeploymentKeys(dotMetricsEnabled),
)?.tagValue; )?.tagValue;
logEvent('APM: Service detail page visited', { logEvent('APM: Service detail page visited', {
@ -181,6 +190,7 @@ function External(): JSX.Element {
servicename, servicename,
legend: legend.address, legend: legend.address,
tagFilterItems, tagFilterItems,
dotMetricsEnabled,
}), }),
clickhouse_sql: [], clickhouse_sql: [],
id: uuid(), id: uuid(),
@ -191,7 +201,7 @@ function External(): JSX.Element {
id: GraphTitle.EXTERNAL_CALL_RPS_BY_ADDRESS, id: GraphTitle.EXTERNAL_CALL_RPS_BY_ADDRESS,
fillSpans: true, fillSpans: true,
}), }),
[servicename, tagFilterItems], [servicename, tagFilterItems, dotMetricsEnabled],
); );
const externalCallDurationAddressWidget = useMemo( const externalCallDurationAddressWidget = useMemo(
@ -204,6 +214,7 @@ function External(): JSX.Element {
servicename, servicename,
legend: legend.address, legend: legend.address,
tagFilterItems, tagFilterItems,
dotMetricsEnabled,
}), }),
clickhouse_sql: [], clickhouse_sql: [],
id: uuid(), id: uuid(),
@ -214,7 +225,7 @@ function External(): JSX.Element {
id: GraphTitle.EXTERNAL_CALL_DURATION_BY_ADDRESS, id: GraphTitle.EXTERNAL_CALL_DURATION_BY_ADDRESS,
fillSpans: true, fillSpans: true,
}), }),
[servicename, tagFilterItems], [servicename, tagFilterItems, dotMetricsEnabled],
); );
const apmToTraceQuery = useGetAPMToTracesQueries({ const apmToTraceQuery = useGetAPMToTracesQueries({

View File

@ -11,6 +11,7 @@ import { getQueryString } from 'container/SideNav/helper';
import useResourceAttribute from 'hooks/useResourceAttribute'; import useResourceAttribute from 'hooks/useResourceAttribute';
import { import {
convertRawQueriesToTraceSelectedTags, convertRawQueriesToTraceSelectedTags,
getResourceDeploymentKeys,
resourceAttributesToTagFilterItems, resourceAttributesToTagFilterItems,
} from 'hooks/useResourceAttribute/utils'; } from 'hooks/useResourceAttribute/utils';
import { useSafeNavigate } from 'hooks/useSafeNavigate'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
@ -92,12 +93,15 @@ function Application(): JSX.Element {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
[handleSetTimeStamp], [handleSetTimeStamp],
); );
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const logEventCalledRef = useRef(false); const logEventCalledRef = useRef(false);
useEffect(() => { useEffect(() => {
if (!logEventCalledRef.current) { if (!logEventCalledRef.current) {
const selectedEnvironments = queries.find( const selectedEnvironments = queries.find(
(val) => val.tagKey === 'resource_deployment_environment', (val) => val.tagKey === getResourceDeploymentKeys(dotMetricsEnabled),
)?.tagValue; )?.tagValue;
logEvent('APM: Service detail page visited', { logEvent('APM: Service detail page visited', {
@ -155,6 +159,7 @@ function Application(): JSX.Element {
servicename, servicename,
tagFilterItems, tagFilterItems,
topLevelOperations: topLevelOperationsRoute, topLevelOperations: topLevelOperationsRoute,
dotMetricsEnabled,
}), }),
clickhouse_sql: [], clickhouse_sql: [],
id: uuid(), id: uuid(),
@ -164,7 +169,7 @@ function Application(): JSX.Element {
yAxisUnit: 'ops', yAxisUnit: 'ops',
id: SERVICE_CHART_ID.rps, id: SERVICE_CHART_ID.rps,
}), }),
[servicename, tagFilterItems, topLevelOperationsRoute], [servicename, tagFilterItems, topLevelOperationsRoute, dotMetricsEnabled],
); );
const errorPercentageWidget = useMemo( const errorPercentageWidget = useMemo(
@ -177,6 +182,7 @@ function Application(): JSX.Element {
servicename, servicename,
tagFilterItems, tagFilterItems,
topLevelOperations: topLevelOperationsRoute, topLevelOperations: topLevelOperationsRoute,
dotMetricsEnabled,
}), }),
clickhouse_sql: [], clickhouse_sql: [],
id: uuid(), id: uuid(),
@ -187,7 +193,7 @@ function Application(): JSX.Element {
id: SERVICE_CHART_ID.errorPercentage, id: SERVICE_CHART_ID.errorPercentage,
fillSpans: true, fillSpans: true,
}), }),
[servicename, tagFilterItems, topLevelOperationsRoute], [servicename, tagFilterItems, topLevelOperationsRoute, dotMetricsEnabled],
); );
const stepInterval = useMemo( const stepInterval = useMemo(

View File

@ -20,6 +20,8 @@ import { useParams } from 'react-router-dom';
import { EQueryType } from 'types/common/dashboard'; import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { FeatureKeys } from '../../../../../constants/features';
import { useAppContext } from '../../../../../providers/App/App';
import { IServiceName } from '../../types'; import { IServiceName } from '../../types';
import { ApDexMetricsProps } from './types'; import { ApDexMetricsProps } from './types';
@ -34,7 +36,10 @@ function ApDexMetrics({
}: ApDexMetricsProps): JSX.Element { }: ApDexMetricsProps): JSX.Element {
const { servicename: encodedServiceName } = useParams<IServiceName>(); const { servicename: encodedServiceName } = useParams<IServiceName>();
const servicename = decodeURIComponent(encodedServiceName); const servicename = decodeURIComponent(encodedServiceName);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const apDexMetricsWidget = useMemo( const apDexMetricsWidget = useMemo(
() => () =>
getWidgetQueryBuilder({ getWidgetQueryBuilder({
@ -48,6 +53,7 @@ function ApDexMetrics({
threashold: thresholdValue || 0, threashold: thresholdValue || 0,
delta: delta || false, delta: delta || false,
metricsBuckets: metricsBuckets || [], metricsBuckets: metricsBuckets || [],
dotMetricsEnabled,
}), }),
clickhouse_sql: [], clickhouse_sql: [],
id: uuid(), id: uuid(),
@ -73,6 +79,7 @@ function ApDexMetrics({
tagFilterItems, tagFilterItems,
thresholdValue, thresholdValue,
topLevelOperationsRoute, topLevelOperationsRoute,
dotMetricsEnabled,
], ],
); );

View File

@ -56,6 +56,10 @@ function ServiceOverview({
[isSpanMetricEnable, queries], [isSpanMetricEnable, queries],
); );
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const latencyWidget = useMemo( const latencyWidget = useMemo(
() => () =>
getWidgetQueryBuilder({ getWidgetQueryBuilder({
@ -67,6 +71,7 @@ function ServiceOverview({
tagFilterItems, tagFilterItems,
isSpanMetricEnable, isSpanMetricEnable,
topLevelOperationsRoute, topLevelOperationsRoute,
dotMetricsEnabled,
}), }),
clickhouse_sql: [], clickhouse_sql: [],
id: uuid(), id: uuid(),
@ -76,7 +81,13 @@ function ServiceOverview({
yAxisUnit: 'ns', yAxisUnit: 'ns',
id: SERVICE_CHART_ID.latency, id: SERVICE_CHART_ID.latency,
}), }),
[isSpanMetricEnable, servicename, tagFilterItems, topLevelOperationsRoute], [
isSpanMetricEnable,
servicename,
tagFilterItems,
topLevelOperationsRoute,
dotMetricsEnabled,
],
); );
const isQueryEnabled = const isQueryEnabled =

View File

@ -18,6 +18,8 @@ import { EQueryType } from 'types/common/dashboard';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { FeatureKeys } from '../../../../constants/features';
import { useAppContext } from '../../../../providers/App/App';
import { IServiceName } from '../types'; import { IServiceName } from '../types';
import { title } from './config'; import { title } from './config';
import ColumnWithLink from './TableRenderer/ColumnWithLink'; import ColumnWithLink from './TableRenderer/ColumnWithLink';
@ -40,6 +42,11 @@ function TopOperationMetrics(): JSX.Element {
convertRawQueriesToTraceSelectedTags(queries) || [], convertRawQueriesToTraceSelectedTags(queries) || [],
); );
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const keyOperationWidget = useMemo( const keyOperationWidget = useMemo(
() => () =>
getWidgetQueryBuilder({ getWidgetQueryBuilder({
@ -48,13 +55,14 @@ function TopOperationMetrics(): JSX.Element {
promql: [], promql: [],
builder: topOperationQueries({ builder: topOperationQueries({
servicename, servicename,
dotMetricsEnabled,
}), }),
clickhouse_sql: [], clickhouse_sql: [],
id: uuid(), id: uuid(),
}, },
panelTypes: PANEL_TYPES.TABLE, panelTypes: PANEL_TYPES.TABLE,
}), }),
[servicename], [servicename, dotMetricsEnabled],
); );
const updatedQuery = useStepInterval(keyOperationWidget.query); const updatedQuery = useStepInterval(keyOperationWidget.query);

View File

@ -10,6 +10,7 @@ export interface IServiceName {
export interface TopOperationQueryFactoryProps { export interface TopOperationQueryFactoryProps {
servicename: IServiceName['servicename']; servicename: IServiceName['servicename'];
dotMetricsEnabled: boolean;
} }
export interface ExternalCallDurationByAddressProps extends ExternalCallProps { export interface ExternalCallDurationByAddressProps extends ExternalCallProps {
@ -19,6 +20,7 @@ export interface ExternalCallDurationByAddressProps extends ExternalCallProps {
export interface ExternalCallProps { export interface ExternalCallProps {
servicename: IServiceName['servicename']; servicename: IServiceName['servicename'];
tagFilterItems: TagFilterItem[]; tagFilterItems: TagFilterItem[];
dotMetricsEnabled: boolean;
} }
export interface BuilderQueriesProps { export interface BuilderQueriesProps {
@ -50,6 +52,7 @@ export interface OperationPerSecProps {
servicename: IServiceName['servicename']; servicename: IServiceName['servicename'];
tagFilterItems: TagFilterItem[]; tagFilterItems: TagFilterItem[];
topLevelOperations: string[]; topLevelOperations: string[];
dotMetricsEnabled: boolean;
} }
export interface LatencyProps { export interface LatencyProps {
@ -57,6 +60,7 @@ export interface LatencyProps {
tagFilterItems: TagFilterItem[]; tagFilterItems: TagFilterItem[];
isSpanMetricEnable?: boolean; isSpanMetricEnable?: boolean;
topLevelOperationsRoute: string[]; topLevelOperationsRoute: string[];
dotMetricsEnabled: boolean;
} }
export interface ApDexProps { export interface ApDexProps {
@ -74,4 +78,5 @@ export interface TableRendererProps {
export interface ApDexMetricsQueryBuilderQueriesProps extends ApDexProps { export interface ApDexMetricsQueryBuilderQueriesProps extends ApDexProps {
delta: boolean; delta: boolean;
metricsBuckets: number[]; metricsBuckets: number[];
dotMetricsEnabled: boolean;
} }

View File

@ -85,12 +85,15 @@ export enum WidgetKeys {
HasError = 'hasError', HasError = 'hasError',
Address = 'address', Address = 'address',
DurationNano = 'durationNano', DurationNano = 'durationNano',
StatusCode = 'status_code', StatusCodeNorm = 'status_code',
StatusCode = 'status.code',
Operation = 'operation', Operation = 'operation',
OperationName = 'operationName', OperationName = 'operationName',
Service_name = 'service_name', Service_name_norm = 'service_name',
Service_name = 'service.name',
ServiceName = 'serviceName', ServiceName = 'serviceName',
SignozLatencyCount = 'signoz_latency_count', SignozLatencyCountNorm = 'signoz_latency_count',
SignozLatencyCount = 'signoz_latency.count',
SignozDBLatencyCount = 'signoz_db_latency_count', SignozDBLatencyCount = 'signoz_db_latency_count',
DatabaseCallCount = 'signoz_database_call_count', DatabaseCallCount = 'signoz_database_call_count',
DatabaseCallLatencySum = 'signoz_database_call_latency_sum', DatabaseCallLatencySum = 'signoz_database_call_latency_sum',
@ -98,7 +101,10 @@ export enum WidgetKeys {
SignozCallsTotal = 'signoz_calls_total', SignozCallsTotal = 'signoz_calls_total',
SignozExternalCallLatencyCount = 'signoz_external_call_latency_count', SignozExternalCallLatencyCount = 'signoz_external_call_latency_count',
SignozExternalCallLatencySum = 'signoz_external_call_latency_sum', SignozExternalCallLatencySum = 'signoz_external_call_latency_sum',
Signoz_latency_bucket = 'signoz_latency_bucket', Signoz_latency_bucket_norm = 'signoz_latency_bucket',
Signoz_latency_bucket = 'signoz_latency.bucket',
Db_system = 'db.system',
Db_system_norm = 'db_system',
} }
export const topOperationMetricsDownloadOptions: DownloadOptions = { export const topOperationMetricsDownloadOptions: DownloadOptions = {

View File

@ -25,10 +25,11 @@ export interface NavigateToTraceProps {
} }
export interface DatabaseCallsRPSProps extends DatabaseCallProps { export interface DatabaseCallsRPSProps extends DatabaseCallProps {
legend: '{{db_system}}'; legend: string;
} }
export interface DatabaseCallProps { export interface DatabaseCallProps {
servicename: IServiceName['servicename']; servicename: IServiceName['servicename'];
tagFilterItems: TagFilterItem[]; tagFilterItems: TagFilterItem[];
dotMetricsEnabled: boolean;
} }

View File

@ -5,11 +5,13 @@ import { InspectMetricsSeries } from 'api/metricsExplorer/getInspectMetricsDetai
import { MetricType } from 'api/metricsExplorer/getMetricsList'; import { MetricType } from 'api/metricsExplorer/getMetricsList';
import * as useInspectMetricsHooks from 'hooks/metricsExplorer/useGetInspectMetricsDetails'; import * as useInspectMetricsHooks from 'hooks/metricsExplorer/useGetInspectMetricsDetails';
import * as useGetMetricDetailsHooks from 'hooks/metricsExplorer/useGetMetricDetails'; import * as useGetMetricDetailsHooks from 'hooks/metricsExplorer/useGetMetricDetails';
import * as appContextHooks from 'providers/App/App';
import { QueryClient, QueryClientProvider } from 'react-query'; import { QueryClient, QueryClientProvider } from 'react-query';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import store from 'store'; import store from 'store';
import ROUTES from '../../../../constants/routes'; import ROUTES from '../../../../constants/routes';
import { LicenseEvent } from '../../../../types/api/licensesV3/getActive';
import Inspect from '../Inspect'; import Inspect from '../Inspect';
import { InspectionStep } from '../types'; import { InspectionStep } from '../types';
@ -27,6 +29,30 @@ const mockTimeSeries: InspectMetricsSeries[] = [
}, },
]; ];
jest.spyOn(appContextHooks, 'useAppContext').mockReturnValue({
user: {
role: 'admin',
},
activeLicenseV3: {
event_queue: {
created_at: '0',
event: LicenseEvent.NO_EVENT,
scheduled_at: '0',
status: '',
updated_at: '0',
},
license: {
license_key: 'test-license-key',
license_type: 'trial',
org_id: 'test-org-id',
plan_id: 'test-plan-id',
plan_name: 'test-plan-name',
plan_type: 'trial',
plan_version: 'test-plan-version',
},
},
} as any);
jest.spyOn(useGetMetricDetailsHooks, 'useGetMetricDetails').mockReturnValue({ jest.spyOn(useGetMetricDetailsHooks, 'useGetMetricDetails').mockReturnValue({
data: { data: {
metricDetails: { metricDetails: {

View File

@ -1,11 +1,13 @@
/* eslint-disable react/jsx-props-no-spreading */ /* eslint-disable react/jsx-props-no-spreading */
import { render, screen } from '@testing-library/react'; import { render, screen } from '@testing-library/react';
import { MetricType } from 'api/metricsExplorer/getMetricsList'; import { MetricType } from 'api/metricsExplorer/getMetricsList';
import * as appContextHooks from 'providers/App/App';
import { QueryClient, QueryClientProvider } from 'react-query'; import { QueryClient, QueryClientProvider } from 'react-query';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import store from 'store'; import store from 'store';
import ROUTES from '../../../../constants/routes'; import ROUTES from '../../../../constants/routes';
import { LicenseEvent } from '../../../../types/api/licensesV3/getActive';
import QueryBuilder from '../QueryBuilder'; import QueryBuilder from '../QueryBuilder';
import { import {
InspectionStep, InspectionStep,
@ -20,6 +22,30 @@ jest.mock('react-router-dom', () => ({
}), }),
})); }));
jest.spyOn(appContextHooks, 'useAppContext').mockReturnValue({
user: {
role: 'admin',
},
activeLicenseV3: {
event_queue: {
created_at: '0',
event: LicenseEvent.NO_EVENT,
scheduled_at: '0',
status: '',
updated_at: '0',
},
license: {
license_key: 'test-license-key',
license_type: 'trial',
org_id: 'test-org-id',
plan_id: 'test-plan-id',
plan_name: 'test-plan-name',
plan_type: 'trial',
plan_version: 'test-plan-version',
},
},
} as any);
const queryClient = new QueryClient(); const queryClient = new QueryClient();
describe('QueryBuilder', () => { describe('QueryBuilder', () => {

View File

@ -51,6 +51,8 @@ import { getUserOperatingSystem, UserOperatingSystem } from 'utils/getUserOS';
import { popupContainer } from 'utils/selectPopupContainer'; import { popupContainer } from 'utils/selectPopupContainer';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { FeatureKeys } from '../../../../constants/features';
import { useAppContext } from '../../../../providers/App/App';
import { selectStyle } from './config'; import { selectStyle } from './config';
import { PLACEHOLDER } from './constant'; import { PLACEHOLDER } from './constant';
import ExampleQueriesRendererForLogs from './ExampleQueriesRendererForLogs'; import ExampleQueriesRendererForLogs from './ExampleQueriesRendererForLogs';
@ -85,6 +87,11 @@ function QueryBuilderSearch({
const [isEditingTag, setIsEditingTag] = useState(false); const [isEditingTag, setIsEditingTag] = useState(false);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const { const {
updateTag, updateTag,
handleClearTag, handleClearTag,
@ -104,6 +111,7 @@ function QueryBuilderSearch({
exampleQueries, exampleQueries,
} = useAutoComplete( } = useAutoComplete(
query, query,
dotMetricsEnabled,
whereClauseConfig, whereClauseConfig,
isLogsExplorerPage, isLogsExplorerPage,
isInfraMonitoring, isInfraMonitoring,
@ -121,6 +129,7 @@ function QueryBuilderSearch({
const { sourceKeys, handleRemoveSourceKey } = useFetchKeysAndValues( const { sourceKeys, handleRemoveSourceKey } = useFetchKeysAndValues(
searchValue, searchValue,
query, query,
dotMetricsEnabled,
searchKey, searchKey,
isLogsExplorerPage, isLogsExplorerPage,
isInfraMonitoring, isInfraMonitoring,

View File

@ -9,12 +9,15 @@ import {
convertMetricKeyToTrace, convertMetricKeyToTrace,
getEnvironmentTagKeys, getEnvironmentTagKeys,
getEnvironmentTagValues, getEnvironmentTagValues,
getResourceDeploymentKeys,
} from 'hooks/useResourceAttribute/utils'; } from 'hooks/useResourceAttribute/utils';
import { ReactNode, useEffect, useMemo, useState } from 'react'; import { ReactNode, useEffect, useMemo, useState } from 'react';
import { SelectOption } from 'types/common/select'; import { SelectOption } from 'types/common/select';
import { popupContainer } from 'utils/selectPopupContainer'; import { popupContainer } from 'utils/selectPopupContainer';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { FeatureKeys } from '../../constants/features';
import { useAppContext } from '../../providers/App/App';
import QueryChip from './components/QueryChip'; import QueryChip from './components/QueryChip';
import { QueryChipItem, SearchContainer } from './styles'; import { QueryChipItem, SearchContainer } from './styles';
@ -39,24 +42,27 @@ function ResourceAttributesFilter({
SelectOption<string, string>[] SelectOption<string, string>[]
>([]); >([]);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const resourceDeploymentKey = getResourceDeploymentKeys(dotMetricsEnabled);
const [selectedEnvironments, setSelectedEnvironments] = useState<string[]>([]); const [selectedEnvironments, setSelectedEnvironments] = useState<string[]>([]);
const queriesExcludingEnvironment = useMemo( const queriesExcludingEnvironment = useMemo(
() => () => queries.filter((query) => query.tagKey !== resourceDeploymentKey),
queries.filter( [queries, resourceDeploymentKey],
(query) => query.tagKey !== 'resource_deployment_environment',
),
[queries],
); );
const isEmpty = useMemo( const isEmpty = useMemo(
() => isResourceEmpty(queriesExcludingEnvironment, staging, selectedQuery), () => isResourceEmpty(queriesExcludingEnvironment, staging, selectedQuery),
[queriesExcludingEnvironment, selectedQuery, staging], [queriesExcludingEnvironment, selectedQuery, staging],
); );
useEffect(() => { useEffect(() => {
const resourceDeploymentEnvironmentQuery = queries.filter( const resourceDeploymentEnvironmentQuery = queries.filter(
(query) => query.tagKey === 'resource_deployment_environment', (query) => query.tagKey === resourceDeploymentKey,
); );
if (resourceDeploymentEnvironmentQuery?.length > 0) { if (resourceDeploymentEnvironmentQuery?.length > 0) {
@ -64,17 +70,17 @@ function ResourceAttributesFilter({
} else { } else {
setSelectedEnvironments([]); setSelectedEnvironments([]);
} }
}, [queries]); }, [queries, resourceDeploymentKey]);
useEffect(() => { useEffect(() => {
getEnvironmentTagKeys().then((tagKeys) => { getEnvironmentTagKeys(dotMetricsEnabled).then((tagKeys) => {
if (tagKeys && Array.isArray(tagKeys) && tagKeys.length > 0) { if (tagKeys && Array.isArray(tagKeys) && tagKeys.length > 0) {
getEnvironmentTagValues().then((tagValues) => { getEnvironmentTagValues(dotMetricsEnabled).then((tagValues) => {
setEnvironments(tagValues); setEnvironments(tagValues);
}); });
} }
}); });
}, []); }, [dotMetricsEnabled]);
return ( return (
<div className="resourceAttributesFilter-container"> <div className="resourceAttributesFilter-container">

View File

@ -1,5 +1,10 @@
import { convertMetricKeyToTrace } from 'hooks/useResourceAttribute/utils'; import {
convertMetricKeyToTrace,
getResourceDeploymentKeys,
} from 'hooks/useResourceAttribute/utils';
import { FeatureKeys } from '../../../../constants/features';
import { useAppContext } from '../../../../providers/App/App';
import { QueryChipContainer, QueryChipItem } from '../../styles'; import { QueryChipContainer, QueryChipItem } from '../../styles';
import { IQueryChipProps } from './types'; import { IQueryChipProps } from './types';
@ -8,12 +13,17 @@ function QueryChip({ queryData, onClose }: IQueryChipProps): JSX.Element {
onClose(queryData.id); onClose(queryData.id);
}; };
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
return ( return (
<QueryChipContainer> <QueryChipContainer>
<QueryChipItem>{convertMetricKeyToTrace(queryData.tagKey)}</QueryChipItem> <QueryChipItem>{convertMetricKeyToTrace(queryData.tagKey)}</QueryChipItem>
<QueryChipItem>{queryData.operator}</QueryChipItem> <QueryChipItem>{queryData.operator}</QueryChipItem>
<QueryChipItem <QueryChipItem
closable={queryData.tagKey !== 'resource_deployment_environment'} closable={queryData.tagKey !== getResourceDeploymentKeys(dotMetricsEnabled)}
onClose={onCloseHandler} onClose={onCloseHandler}
> >
{queryData.tagValue.join(', ')} {queryData.tagValue.join(', ')}

View File

@ -3,6 +3,8 @@ import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { ServiceMetricsProps } from '../types'; import { ServiceMetricsProps } from '../types';
import { getQueryRangeRequestData } from '../utils'; import { getQueryRangeRequestData } from '../utils';
import ServiceMetricTable from './ServiceMetricTable'; import ServiceMetricTable from './ServiceMetricTable';
@ -15,6 +17,11 @@ function ServiceMetricsApplication({
GlobalReducer GlobalReducer
>((state) => state.globalTime); >((state) => state.globalTime);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const queryRangeRequestData = useMemo( const queryRangeRequestData = useMemo(
() => () =>
getQueryRangeRequestData({ getQueryRangeRequestData({
@ -22,8 +29,15 @@ function ServiceMetricsApplication({
minTime, minTime,
maxTime, maxTime,
globalSelectedInterval, globalSelectedInterval,
dotMetricsEnabled,
}), }),
[globalSelectedInterval, maxTime, minTime, topLevelOperations], [
globalSelectedInterval,
maxTime,
minTime,
topLevelOperations,
dotMetricsEnabled,
],
); );
return ( return (
<ServiceMetricTable <ServiceMetricTable

View File

@ -19,11 +19,14 @@ import {
export const serviceMetricsQuery = ( export const serviceMetricsQuery = (
topLevelOperation: [keyof ServiceDataProps, string[]], topLevelOperation: [keyof ServiceDataProps, string[]],
dotMetricsEnabled: boolean,
): QueryBuilderData => { ): QueryBuilderData => {
const p99AutoCompleteData: BaseAutocompleteData = { const p99AutoCompleteData: BaseAutocompleteData = {
dataType: DataTypes.Float64, dataType: DataTypes.Float64,
isColumn: true, isColumn: true,
key: WidgetKeys.Signoz_latency_bucket, key: dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm,
type: '', type: '',
}; };
@ -54,7 +57,9 @@ export const serviceMetricsQuery = (
key: { key: {
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
type: MetricsType.Resource, type: MetricsType.Resource,
}, },
op: OPERATORS.IN, op: OPERATORS.IN,
@ -79,7 +84,9 @@ export const serviceMetricsQuery = (
key: { key: {
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
type: MetricsType.Resource, type: MetricsType.Resource,
}, },
op: OPERATORS.IN, op: OPERATORS.IN,
@ -90,7 +97,7 @@ export const serviceMetricsQuery = (
key: { key: {
dataType: DataTypes.Int64, dataType: DataTypes.Int64,
isColumn: false, isColumn: false,
key: WidgetKeys.StatusCode, key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
type: MetricsType.Tag, type: MetricsType.Tag,
}, },
op: OPERATORS.IN, op: OPERATORS.IN,
@ -115,7 +122,9 @@ export const serviceMetricsQuery = (
key: { key: {
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
type: MetricsType.Resource, type: MetricsType.Resource,
}, },
op: OPERATORS.IN, op: OPERATORS.IN,
@ -140,7 +149,9 @@ export const serviceMetricsQuery = (
key: { key: {
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
type: MetricsType.Resource, type: MetricsType.Resource,
}, },
op: OPERATORS.IN, op: OPERATORS.IN,
@ -195,7 +206,9 @@ export const serviceMetricsQuery = (
{ {
dataType: DataTypes.String, dataType: DataTypes.String,
isColumn: false, isColumn: false,
key: WidgetKeys.Service_name, key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
type: MetricsType.Tag, type: MetricsType.Tag,
}, },
]; ];

View File

@ -5,7 +5,10 @@ import { SKIP_ONBOARDING } from 'constants/onboarding';
import useErrorNotification from 'hooks/useErrorNotification'; import useErrorNotification from 'hooks/useErrorNotification';
import { useQueryService } from 'hooks/useQueryService'; import { useQueryService } from 'hooks/useQueryService';
import useResourceAttribute from 'hooks/useResourceAttribute'; import useResourceAttribute from 'hooks/useResourceAttribute';
import { convertRawQueriesToTraceSelectedTags } from 'hooks/useResourceAttribute/utils'; import {
convertRawQueriesToTraceSelectedTags,
getResourceDeploymentKeys,
} from 'hooks/useResourceAttribute/utils';
import { isUndefined } from 'lodash-es'; import { isUndefined } from 'lodash-es';
import { useEffect, useMemo, useRef, useState } from 'react'; import { useEffect, useMemo, useRef, useState } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
@ -13,6 +16,8 @@ import { AppState } from 'store/reducers';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { Tags } from 'types/reducer/trace'; import { Tags } from 'types/reducer/trace';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import SkipOnBoardingModal from '../SkipOnBoardModal'; import SkipOnBoardingModal from '../SkipOnBoardModal';
import ServiceTraceTable from './ServiceTracesTable'; import ServiceTraceTable from './ServiceTracesTable';
@ -34,6 +39,11 @@ function ServiceTraces(): JSX.Element {
selectedTags, selectedTags,
}); });
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
useErrorNotification(error); useErrorNotification(error);
const services = data || []; const services = data || [];
@ -51,7 +61,7 @@ function ServiceTraces(): JSX.Element {
useEffect(() => { useEffect(() => {
if (!logEventCalledRef.current && !isUndefined(data)) { if (!logEventCalledRef.current && !isUndefined(data)) {
const selectedEnvironments = queries.find( const selectedEnvironments = queries.find(
(val) => val.tagKey === 'resource_deployment_environment', (val) => val.tagKey === getResourceDeploymentKeys(dotMetricsEnabled),
)?.tagValue; )?.tagValue;
const rps = data.reduce((total, service) => total + service.callRate, 0); const rps = data.reduce((total, service) => total + service.callRate, 0);

View File

@ -29,6 +29,7 @@ export interface GetQueryRangeRequestDataProps {
maxTime: number; maxTime: number;
minTime: number; minTime: number;
globalSelectedInterval: Time | TimeV2 | CustomTimeType; globalSelectedInterval: Time | TimeV2 | CustomTimeType;
dotMetricsEnabled: boolean;
} }
export interface GetServiceListFromQueryProps { export interface GetServiceListFromQueryProps {

View File

@ -28,6 +28,7 @@ export const getQueryRangeRequestData = ({
maxTime, maxTime,
minTime, minTime,
globalSelectedInterval, globalSelectedInterval,
dotMetricsEnabled,
}: GetQueryRangeRequestDataProps): GetQueryResultsProps[] => { }: GetQueryRangeRequestDataProps): GetQueryResultsProps[] => {
const requestData: GetQueryResultsProps[] = []; const requestData: GetQueryResultsProps[] = [];
topLevelOperations.forEach((operation) => { topLevelOperations.forEach((operation) => {
@ -35,7 +36,7 @@ export const getQueryRangeRequestData = ({
query: { query: {
queryType: EQueryType.QUERY_BUILDER, queryType: EQueryType.QUERY_BUILDER,
promql: [], promql: [],
builder: serviceMetricsQuery(operation), builder: serviceMetricsQuery(operation, dotMetricsEnabled),
clickhouse_sql: [], clickhouse_sql: [],
id: uuid(), id: uuid(),
}, },

View File

@ -17,6 +17,7 @@ type UseGetK8sClustersList = (
>, >,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled?: boolean,
) => UseQueryResult< ) => UseQueryResult<
SuccessResponse<K8sClustersListResponse> | ErrorResponse, SuccessResponse<K8sClustersListResponse> | ErrorResponse,
Error Error
@ -28,6 +29,7 @@ export const useGetK8sClustersList: UseGetK8sClustersList = (
options, options,
headers, headers,
dotMetricsEnabled?: boolean,
) => { ) => {
const queryKey = useMemo(() => { const queryKey = useMemo(() => {
if (options?.queryKey && Array.isArray(options.queryKey)) { if (options?.queryKey && Array.isArray(options.queryKey)) {
@ -45,7 +47,8 @@ export const useGetK8sClustersList: UseGetK8sClustersList = (
SuccessResponse<K8sClustersListResponse> | ErrorResponse, SuccessResponse<K8sClustersListResponse> | ErrorResponse,
Error Error
>({ >({
queryFn: ({ signal }) => getK8sClustersList(requestData, signal, headers), queryFn: ({ signal }) =>
getK8sClustersList(requestData, signal, headers, dotMetricsEnabled),
...options, ...options,

View File

@ -17,6 +17,7 @@ type UseGetK8sDaemonSetsList = (
>, >,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled?: boolean,
) => UseQueryResult< ) => UseQueryResult<
SuccessResponse<K8sDaemonSetsListResponse> | ErrorResponse, SuccessResponse<K8sDaemonSetsListResponse> | ErrorResponse,
Error Error
@ -28,6 +29,7 @@ export const useGetK8sDaemonSetsList: UseGetK8sDaemonSetsList = (
options, options,
headers, headers,
dotMetricsEnabled,
) => { ) => {
const queryKey = useMemo(() => { const queryKey = useMemo(() => {
if (options?.queryKey && Array.isArray(options.queryKey)) { if (options?.queryKey && Array.isArray(options.queryKey)) {
@ -45,7 +47,8 @@ export const useGetK8sDaemonSetsList: UseGetK8sDaemonSetsList = (
SuccessResponse<K8sDaemonSetsListResponse> | ErrorResponse, SuccessResponse<K8sDaemonSetsListResponse> | ErrorResponse,
Error Error
>({ >({
queryFn: ({ signal }) => getK8sDaemonSetsList(requestData, signal, headers), queryFn: ({ signal }) =>
getK8sDaemonSetsList(requestData, signal, headers, dotMetricsEnabled),
...options, ...options,

View File

@ -15,6 +15,7 @@ type UseGetK8sDeploymentsList = (
Error Error
>, >,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled?: boolean,
) => UseQueryResult< ) => UseQueryResult<
SuccessResponse<K8sDeploymentsListResponse> | ErrorResponse, SuccessResponse<K8sDeploymentsListResponse> | ErrorResponse,
Error Error
@ -24,6 +25,7 @@ export const useGetK8sDeploymentsList: UseGetK8sDeploymentsList = (
requestData, requestData,
options, options,
headers, headers,
dotMetricsEnabled,
) => { ) => {
const queryKey = useMemo(() => { const queryKey = useMemo(() => {
if (options?.queryKey && Array.isArray(options.queryKey)) { if (options?.queryKey && Array.isArray(options.queryKey)) {
@ -41,7 +43,8 @@ export const useGetK8sDeploymentsList: UseGetK8sDeploymentsList = (
SuccessResponse<K8sDeploymentsListResponse> | ErrorResponse, SuccessResponse<K8sDeploymentsListResponse> | ErrorResponse,
Error Error
>({ >({
queryFn: ({ signal }) => getK8sDeploymentsList(requestData, signal, headers), queryFn: ({ signal }) =>
getK8sDeploymentsList(requestData, signal, headers, dotMetricsEnabled),
...options, ...options,
queryKey, queryKey,
}); });

View File

@ -17,6 +17,7 @@ type UseGetK8sJobsList = (
>, >,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled?: boolean,
) => UseQueryResult< ) => UseQueryResult<
SuccessResponse<K8sJobsListResponse> | ErrorResponse, SuccessResponse<K8sJobsListResponse> | ErrorResponse,
Error Error
@ -28,6 +29,7 @@ export const useGetK8sJobsList: UseGetK8sJobsList = (
options, options,
headers, headers,
dotMetricsEnabled,
) => { ) => {
const queryKey = useMemo(() => { const queryKey = useMemo(() => {
if (options?.queryKey && Array.isArray(options.queryKey)) { if (options?.queryKey && Array.isArray(options.queryKey)) {
@ -42,7 +44,8 @@ export const useGetK8sJobsList: UseGetK8sJobsList = (
}, [options?.queryKey, requestData]); }, [options?.queryKey, requestData]);
return useQuery<SuccessResponse<K8sJobsListResponse> | ErrorResponse, Error>({ return useQuery<SuccessResponse<K8sJobsListResponse> | ErrorResponse, Error>({
queryFn: ({ signal }) => getK8sJobsList(requestData, signal, headers), queryFn: ({ signal }) =>
getK8sJobsList(requestData, signal, headers, dotMetricsEnabled),
...options, ...options,

View File

@ -15,6 +15,7 @@ type UseGetK8sNamespacesList = (
Error Error
>, >,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled?: boolean,
) => UseQueryResult< ) => UseQueryResult<
SuccessResponse<K8sNamespacesListResponse> | ErrorResponse, SuccessResponse<K8sNamespacesListResponse> | ErrorResponse,
Error Error
@ -24,6 +25,7 @@ export const useGetK8sNamespacesList: UseGetK8sNamespacesList = (
requestData, requestData,
options, options,
headers, headers,
dotMetricsEnabled,
) => { ) => {
const queryKey = useMemo(() => { const queryKey = useMemo(() => {
if (options?.queryKey && Array.isArray(options.queryKey)) { if (options?.queryKey && Array.isArray(options.queryKey)) {
@ -41,7 +43,8 @@ export const useGetK8sNamespacesList: UseGetK8sNamespacesList = (
SuccessResponse<K8sNamespacesListResponse> | ErrorResponse, SuccessResponse<K8sNamespacesListResponse> | ErrorResponse,
Error Error
>({ >({
queryFn: ({ signal }) => getK8sNamespacesList(requestData, signal, headers), queryFn: ({ signal }) =>
getK8sNamespacesList(requestData, signal, headers, dotMetricsEnabled),
...options, ...options,
queryKey, queryKey,
}); });

View File

@ -15,6 +15,7 @@ type UseGetK8sNodesList = (
Error Error
>, >,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled?: boolean,
) => UseQueryResult< ) => UseQueryResult<
SuccessResponse<K8sNodesListResponse> | ErrorResponse, SuccessResponse<K8sNodesListResponse> | ErrorResponse,
Error Error
@ -24,6 +25,7 @@ export const useGetK8sNodesList: UseGetK8sNodesList = (
requestData, requestData,
options, options,
headers, headers,
dotMetricsEnabled,
) => { ) => {
const queryKey = useMemo(() => { const queryKey = useMemo(() => {
if (options?.queryKey && Array.isArray(options.queryKey)) { if (options?.queryKey && Array.isArray(options.queryKey)) {
@ -38,7 +40,8 @@ export const useGetK8sNodesList: UseGetK8sNodesList = (
}, [options?.queryKey, requestData]); }, [options?.queryKey, requestData]);
return useQuery<SuccessResponse<K8sNodesListResponse> | ErrorResponse, Error>({ return useQuery<SuccessResponse<K8sNodesListResponse> | ErrorResponse, Error>({
queryFn: ({ signal }) => getK8sNodesList(requestData, signal, headers), queryFn: ({ signal }) =>
getK8sNodesList(requestData, signal, headers, dotMetricsEnabled),
...options, ...options,
queryKey, queryKey,
}); });

View File

@ -15,6 +15,7 @@ type UseGetK8sPodsList = (
Error Error
>, >,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled?: boolean,
) => UseQueryResult< ) => UseQueryResult<
SuccessResponse<K8sPodsListResponse> | ErrorResponse, SuccessResponse<K8sPodsListResponse> | ErrorResponse,
Error Error
@ -24,6 +25,7 @@ export const useGetK8sPodsList: UseGetK8sPodsList = (
requestData, requestData,
options, options,
headers, headers,
dotMetricsEnabled,
) => { ) => {
const queryKey = useMemo(() => { const queryKey = useMemo(() => {
if (options?.queryKey && Array.isArray(options.queryKey)) { if (options?.queryKey && Array.isArray(options.queryKey)) {
@ -38,7 +40,8 @@ export const useGetK8sPodsList: UseGetK8sPodsList = (
}, [options?.queryKey, requestData]); }, [options?.queryKey, requestData]);
return useQuery<SuccessResponse<K8sPodsListResponse> | ErrorResponse, Error>({ return useQuery<SuccessResponse<K8sPodsListResponse> | ErrorResponse, Error>({
queryFn: ({ signal }) => getK8sPodsList(requestData, signal, headers), queryFn: ({ signal }) =>
getK8sPodsList(requestData, signal, headers, dotMetricsEnabled),
...options, ...options,
queryKey, queryKey,
}); });

View File

@ -17,6 +17,7 @@ type UseGetK8sStatefulSetsList = (
>, >,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled?: boolean,
) => UseQueryResult< ) => UseQueryResult<
SuccessResponse<K8sStatefulSetsListResponse> | ErrorResponse, SuccessResponse<K8sStatefulSetsListResponse> | ErrorResponse,
Error Error
@ -28,6 +29,7 @@ export const useGetK8sStatefulSetsList: UseGetK8sStatefulSetsList = (
options, options,
headers, headers,
dotMetricsEnabled,
) => { ) => {
const queryKey = useMemo(() => { const queryKey = useMemo(() => {
if (options?.queryKey && Array.isArray(options.queryKey)) { if (options?.queryKey && Array.isArray(options.queryKey)) {
@ -45,7 +47,8 @@ export const useGetK8sStatefulSetsList: UseGetK8sStatefulSetsList = (
SuccessResponse<K8sStatefulSetsListResponse> | ErrorResponse, SuccessResponse<K8sStatefulSetsListResponse> | ErrorResponse,
Error Error
>({ >({
queryFn: ({ signal }) => getK8sStatefulSetsList(requestData, signal, headers), queryFn: ({ signal }) =>
getK8sStatefulSetsList(requestData, signal, headers, dotMetricsEnabled),
...options, ...options,

View File

@ -15,6 +15,7 @@ type UseGetK8sVolumesList = (
Error Error
>, >,
headers?: Record<string, string>, headers?: Record<string, string>,
dotMetricsEnabled?: boolean,
) => UseQueryResult< ) => UseQueryResult<
SuccessResponse<K8sVolumesListResponse> | ErrorResponse, SuccessResponse<K8sVolumesListResponse> | ErrorResponse,
Error Error
@ -24,6 +25,7 @@ export const useGetK8sVolumesList: UseGetK8sVolumesList = (
requestData, requestData,
options, options,
headers, headers,
dotMetricsEnabled,
) => { ) => {
const queryKey = useMemo(() => { const queryKey = useMemo(() => {
if (options?.queryKey && Array.isArray(options.queryKey)) { if (options?.queryKey && Array.isArray(options.queryKey)) {
@ -41,7 +43,8 @@ export const useGetK8sVolumesList: UseGetK8sVolumesList = (
SuccessResponse<K8sVolumesListResponse> | ErrorResponse, SuccessResponse<K8sVolumesListResponse> | ErrorResponse,
Error Error
>({ >({
queryFn: ({ signal }) => getK8sVolumesList(requestData, signal, headers), queryFn: ({ signal }) =>
getK8sVolumesList(requestData, signal, headers, dotMetricsEnabled),
...options, ...options,
queryKey, queryKey,
}); });

View File

@ -27,6 +27,7 @@ export type WhereClauseConfig = {
export const useAutoComplete = ( export const useAutoComplete = (
query: IBuilderQuery, query: IBuilderQuery,
dotMetricsEnabled: boolean,
whereClauseConfig?: WhereClauseConfig, whereClauseConfig?: WhereClauseConfig,
shouldUseSuggestions?: boolean, shouldUseSuggestions?: boolean,
isInfraMonitoring?: boolean, isInfraMonitoring?: boolean,
@ -39,6 +40,7 @@ export const useAutoComplete = (
const { keys, results, isFetching, exampleQueries } = useFetchKeysAndValues( const { keys, results, isFetching, exampleQueries } = useFetchKeysAndValues(
searchValue, searchValue,
query, query,
dotMetricsEnabled,
searchKey, searchKey,
shouldUseSuggestions, shouldUseSuggestions,
isInfraMonitoring, isInfraMonitoring,

View File

@ -4,8 +4,8 @@ import { getAttributesValues } from 'api/queryBuilder/getAttributesValues';
import { DATA_TYPE_VS_ATTRIBUTE_VALUES_KEY } from 'constants/queryBuilder'; import { DATA_TYPE_VS_ATTRIBUTE_VALUES_KEY } from 'constants/queryBuilder';
import { DEBOUNCE_DELAY } from 'constants/queryBuilderFilterConfig'; import { DEBOUNCE_DELAY } from 'constants/queryBuilderFilterConfig';
import { import {
GetK8sEntityToAggregateAttribute,
K8sCategory, K8sCategory,
K8sEntityToAggregateAttributeMapping,
} from 'container/InfraMonitoringK8s/constants'; } from 'container/InfraMonitoringK8s/constants';
import { import {
getRemovePrefixFromKey, getRemovePrefixFromKey,
@ -50,6 +50,7 @@ type IuseFetchKeysAndValues = {
export const useFetchKeysAndValues = ( export const useFetchKeysAndValues = (
searchValue: string, searchValue: string,
query: IBuilderQuery, query: IBuilderQuery,
dotMetricsEnabled: boolean,
searchKey: string, searchKey: string,
shouldUseSuggestions?: boolean, shouldUseSuggestions?: boolean,
isInfraMonitoring?: boolean, isInfraMonitoring?: boolean,
@ -123,7 +124,7 @@ export const useFetchKeysAndValues = (
aggregateOperator: query.aggregateOperator, aggregateOperator: query.aggregateOperator,
aggregateAttribute: aggregateAttribute:
isInfraMonitoring && entity isInfraMonitoring && entity
? K8sEntityToAggregateAttributeMapping[entity] ? GetK8sEntityToAggregateAttribute(entity, dotMetricsEnabled)
: query.aggregateAttribute.key, : query.aggregateAttribute.key,
tagType: query.aggregateAttribute.type ?? null, tagType: query.aggregateAttribute.type ?? null,
}, },
@ -219,7 +220,7 @@ export const useFetchKeysAndValues = (
aggregateOperator: 'noop', aggregateOperator: 'noop',
dataSource: query.dataSource, dataSource: query.dataSource,
aggregateAttribute: aggregateAttribute:
K8sEntityToAggregateAttributeMapping[entity] || GetK8sEntityToAggregateAttribute(entity, dotMetricsEnabled) ||
query.aggregateAttribute.key, query.aggregateAttribute.key,
attributeKey: filterAttributeKey?.key ?? tagKey, attributeKey: filterAttributeKey?.key ?? tagKey,
filterAttributeKeyDataType: filterAttributeKeyDataType:

View File

@ -7,6 +7,8 @@ import { encode } from 'js-base64';
import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import { FeatureKeys } from '../../constants/features';
import { useAppContext } from '../../providers/App/App';
import { whilelistedKeys } from './config'; import { whilelistedKeys } from './config';
import { ResourceContext } from './context'; import { ResourceContext } from './context';
import { ResourceAttributesFilterMachine } from './machine'; import { ResourceAttributesFilterMachine } from './machine';
@ -18,6 +20,7 @@ import {
import { import {
createQuery, createQuery,
getResourceAttributeQueriesFromURL, getResourceAttributeQueriesFromURL,
getResourceDeploymentKeys,
GetTagKeys, GetTagKeys,
GetTagValues, GetTagValues,
mappingWithRoutesAndKeys, mappingWithRoutesAndKeys,
@ -53,6 +56,11 @@ function ResourceProvider({ children }: Props): JSX.Element {
} }
}; };
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const dispatchQueries = useCallback( const dispatchQueries = useCallback(
(queries: IResourceAttribute[]): void => { (queries: IResourceAttribute[]): void => {
urlQuery.set( urlQuery.set(
@ -70,7 +78,7 @@ function ResourceProvider({ children }: Props): JSX.Element {
actions: { actions: {
onSelectTagKey: () => { onSelectTagKey: () => {
handleLoading(true); handleLoading(true);
GetTagKeys() GetTagKeys(dotMetricsEnabled)
.then((tagKeys) => { .then((tagKeys) => {
const options = mappingWithRoutesAndKeys(pathname, tagKeys); const options = mappingWithRoutesAndKeys(pathname, tagKeys);
@ -141,10 +149,10 @@ function ResourceProvider({ children }: Props): JSX.Element {
const handleEnvironmentChange = useCallback( const handleEnvironmentChange = useCallback(
(environments: string[]): void => { (environments: string[]): void => {
const staging = ['resource_deployment_environment', 'IN']; const staging = [getResourceDeploymentKeys(dotMetricsEnabled), 'IN'];
const queriesCopy = queries.filter( const queriesCopy = queries.filter(
(query) => query.tagKey !== 'resource_deployment_environment', (query) => query.tagKey !== getResourceDeploymentKeys(dotMetricsEnabled),
); );
if (environments && Array.isArray(environments) && environments.length > 0) { if (environments && Array.isArray(environments) && environments.length > 0) {
@ -159,7 +167,7 @@ function ResourceProvider({ children }: Props): JSX.Element {
send('RESET'); send('RESET');
}, },
[dispatchQueries, queries, send], [dispatchQueries, dotMetricsEnabled, queries, send],
); );
const handleClose = useCallback( const handleClose = useCallback(

View File

@ -1,10 +1,14 @@
import { act, renderHook, waitFor } from '@testing-library/react'; import { act, renderHook, waitFor } from '@testing-library/react';
import { createMemoryHistory } from 'history'; import { createMemoryHistory } from 'history';
import { AppProvider } from 'providers/App/App';
import { QueryClient, QueryClientProvider } from 'react-query';
import { Router } from 'react-router-dom'; import { Router } from 'react-router-dom';
import ResourceProvider from '../ResourceProvider'; import ResourceProvider from '../ResourceProvider';
import useResourceAttribute from '../useResourceAttribute'; import useResourceAttribute from '../useResourceAttribute';
const queryClient = new QueryClient();
jest.mock('hooks/useSafeNavigate', () => ({ jest.mock('hooks/useSafeNavigate', () => ({
useSafeNavigate: (): any => ({ useSafeNavigate: (): any => ({
safeNavigate: jest.fn(), safeNavigate: jest.fn(),
@ -17,9 +21,13 @@ describe('useResourceAttribute component hook', () => {
initialEntries: ['/inital-url?tab=overview'], initialEntries: ['/inital-url?tab=overview'],
}); });
const wrapper = ({ children }: { children: any }): JSX.Element => ( const wrapper = ({ children }: { children: any }): JSX.Element => (
<Router history={history}> <QueryClientProvider client={queryClient}>
<ResourceProvider>{children}</ResourceProvider> <AppProvider>
</Router> <Router history={history}>
<ResourceProvider>{children}</ResourceProvider>
</Router>
</AppProvider>
</QueryClientProvider>
); );
const { result } = renderHook(() => useResourceAttribute(), { wrapper }); const { result } = renderHook(() => useResourceAttribute(), { wrapper });

View File

@ -146,7 +146,17 @@ export const OperatorSchema: IOption[] = OperatorConversions.map(
}), }),
); );
export const GetTagKeys = async (): Promise<IOption[]> => { export const getResourceDeploymentKeys = (
dotMetricsEnabled: boolean,
): string => {
if (dotMetricsEnabled) return 'resource_deployment.environment';
return 'resource_deployment_environment';
};
export const GetTagKeys = async (
dotMetricsEnabled: boolean,
): Promise<IOption[]> => {
const resourceDeploymentKey = getResourceDeploymentKeys(dotMetricsEnabled);
const { payload } = await getResourceAttributesTagKeys({ const { payload } = await getResourceAttributesTagKeys({
metricName: 'signoz_calls_total', metricName: 'signoz_calls_total',
match: 'resource_', match: 'resource_',
@ -159,17 +169,19 @@ export const GetTagKeys = async (): Promise<IOption[]> => {
payload.data.attributeKeys?.map((attributeKey) => attributeKey.key) || []; payload.data.attributeKeys?.map((attributeKey) => attributeKey.key) || [];
return keys return keys
.filter((tagKey: string) => tagKey !== 'resource_deployment_environment') .filter((tagKey: string) => tagKey !== resourceDeploymentKey)
.map((tagKey: string) => ({ .map((tagKey: string) => ({
label: convertMetricKeyToTrace(tagKey), label: convertMetricKeyToTrace(tagKey),
value: tagKey, value: tagKey,
})); }));
}; };
export const getEnvironmentTagKeys = async (): Promise<IOption[]> => { export const getEnvironmentTagKeys = async (
dotMetricsEnabled: boolean,
): Promise<IOption[]> => {
const { payload } = await getResourceAttributesTagKeys({ const { payload } = await getResourceAttributesTagKeys({
metricName: 'signoz_calls_total', metricName: 'signoz_calls_total',
match: 'resource_deployment_environment', match: getResourceDeploymentKeys(dotMetricsEnabled),
}); });
if (!payload || !payload?.data) { if (!payload || !payload?.data) {
return []; return [];
@ -182,9 +194,11 @@ export const getEnvironmentTagKeys = async (): Promise<IOption[]> => {
})); }));
}; };
export const getEnvironmentTagValues = async (): Promise<IOption[]> => { export const getEnvironmentTagValues = async (
dotMetricsEnabled: boolean,
): Promise<IOption[]> => {
const { payload } = await getResourceAttributesTagValues({ const { payload } = await getResourceAttributesTagValues({
tagKey: 'resource_deployment_environment', tagKey: getResourceDeploymentKeys(dotMetricsEnabled),
metricName: 'signoz_calls_total', metricName: 'signoz_calls_total',
}); });

View File

@ -4,22 +4,24 @@ import { useIsDarkMode } from 'hooks/useDarkMode';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Widgets } from 'types/api/dashboard/getAll'; import { Widgets } from 'types/api/dashboard/getAll';
import { FeatureKeys } from '../../../../constants/features';
import { useAppContext } from '../../../../providers/App/App';
import MetricPageGridGraph from './MetricPageGraph'; import MetricPageGridGraph from './MetricPageGraph';
import { import {
averageRequestLatencyWidgetData, getAverageRequestLatencyWidgetData,
brokerCountWidgetData, getBrokerCountWidgetData,
brokerNetworkThroughputWidgetData, getBrokerNetworkThroughputWidgetData,
bytesConsumedWidgetData, getBytesConsumedWidgetData,
consumerFetchRateWidgetData, getConsumerFetchRateWidgetData,
consumerGroupMemberWidgetData, getConsumerGroupMemberWidgetData,
consumerLagByGroupWidgetData, getConsumerLagByGroupWidgetData,
consumerOffsetWidgetData, getConsumerOffsetWidgetData,
ioWaitTimeWidgetData, getIoWaitTimeWidgetData,
kafkaProducerByteRateWidgetData, getKafkaProducerByteRateWidgetData,
messagesConsumedWidgetData, getMessagesConsumedWidgetData,
producerFetchRequestPurgatoryWidgetData, getProducerFetchRequestPurgatoryWidgetData,
requestResponseWidgetData, getRequestResponseWidgetData,
requestTimesWidgetData, getRequestTimesWidgetData,
} from './MetricPageUtil'; } from './MetricPageUtil';
interface MetricSectionProps { interface MetricSectionProps {
@ -71,15 +73,20 @@ function MetricColumnGraphs({
}): JSX.Element { }): JSX.Element {
const { t } = useTranslation('messagingQueues'); const { t } = useTranslation('messagingQueues');
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const metricsData = [ const metricsData = [
{ {
title: t('metricGraphCategory.brokerMetrics.title'), title: t('metricGraphCategory.brokerMetrics.title'),
description: t('metricGraphCategory.brokerMetrics.description'), description: t('metricGraphCategory.brokerMetrics.description'),
graphCount: [ graphCount: [
brokerCountWidgetData, getBrokerCountWidgetData(dotMetricsEnabled),
requestTimesWidgetData, getRequestTimesWidgetData(dotMetricsEnabled),
producerFetchRequestPurgatoryWidgetData, getProducerFetchRequestPurgatoryWidgetData(dotMetricsEnabled),
brokerNetworkThroughputWidgetData, getBrokerNetworkThroughputWidgetData(dotMetricsEnabled),
], ],
id: 'broker-metrics', id: 'broker-metrics',
}, },
@ -87,11 +94,11 @@ function MetricColumnGraphs({
title: t('metricGraphCategory.producerMetrics.title'), title: t('metricGraphCategory.producerMetrics.title'),
description: t('metricGraphCategory.producerMetrics.description'), description: t('metricGraphCategory.producerMetrics.description'),
graphCount: [ graphCount: [
ioWaitTimeWidgetData, getIoWaitTimeWidgetData(dotMetricsEnabled),
requestResponseWidgetData, getRequestResponseWidgetData(dotMetricsEnabled),
averageRequestLatencyWidgetData, getAverageRequestLatencyWidgetData(dotMetricsEnabled),
kafkaProducerByteRateWidgetData, getKafkaProducerByteRateWidgetData(dotMetricsEnabled),
bytesConsumedWidgetData, getBytesConsumedWidgetData(dotMetricsEnabled),
], ],
id: 'producer-metrics', id: 'producer-metrics',
}, },
@ -99,11 +106,11 @@ function MetricColumnGraphs({
title: t('metricGraphCategory.consumerMetrics.title'), title: t('metricGraphCategory.consumerMetrics.title'),
description: t('metricGraphCategory.consumerMetrics.description'), description: t('metricGraphCategory.consumerMetrics.description'),
graphCount: [ graphCount: [
consumerOffsetWidgetData, getConsumerOffsetWidgetData(dotMetricsEnabled),
consumerGroupMemberWidgetData, getConsumerGroupMemberWidgetData(dotMetricsEnabled),
consumerLagByGroupWidgetData, getConsumerLagByGroupWidgetData(dotMetricsEnabled),
consumerFetchRateWidgetData, getConsumerFetchRateWidgetData(dotMetricsEnabled),
messagesConsumedWidgetData, getMessagesConsumedWidgetData(dotMetricsEnabled),
], ],
id: 'consumer-metrics', id: 'consumer-metrics',
}, },

View File

@ -10,17 +10,19 @@ import { useRef, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Widgets } from 'types/api/dashboard/getAll'; import { Widgets } from 'types/api/dashboard/getAll';
import { FeatureKeys } from '../../../../constants/features';
import { useAppContext } from '../../../../providers/App/App';
import MetricColumnGraphs from './MetricColumnGraphs'; import MetricColumnGraphs from './MetricColumnGraphs';
import MetricPageGridGraph from './MetricPageGraph'; import MetricPageGridGraph from './MetricPageGraph';
import { import {
cpuRecentUtilizationWidgetData, getCpuRecentUtilizationWidgetData,
currentOffsetPartitionWidgetData, getCurrentOffsetPartitionWidgetData,
insyncReplicasWidgetData, getInsyncReplicasWidgetData,
jvmGcCollectionsElapsedWidgetData, getJvmGcCollectionsElapsedWidgetData,
jvmGCCountWidgetData, getJvmGCCountWidgetData,
jvmMemoryHeapWidgetData, getJvmMemoryHeapWidgetData,
oldestOffsetWidgetData, getOldestOffsetWidgetData,
partitionCountPerTopicWidgetData, getPartitionCountPerTopicWidgetData,
} from './MetricPageUtil'; } from './MetricPageUtil';
interface CollapsibleMetricSectionProps { interface CollapsibleMetricSectionProps {
@ -95,6 +97,11 @@ function MetricPage(): JSX.Element {
})); }));
}; };
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const { t } = useTranslation('messagingQueues'); const { t } = useTranslation('messagingQueues');
const metricSections = [ const metricSections = [
@ -103,10 +110,10 @@ function MetricPage(): JSX.Element {
title: t('metricGraphCategory.brokerJVMMetrics.title'), title: t('metricGraphCategory.brokerJVMMetrics.title'),
description: t('metricGraphCategory.brokerJVMMetrics.description'), description: t('metricGraphCategory.brokerJVMMetrics.description'),
graphCount: [ graphCount: [
jvmGCCountWidgetData, getJvmGCCountWidgetData(dotMetricsEnabled),
jvmGcCollectionsElapsedWidgetData, getJvmGcCollectionsElapsedWidgetData(dotMetricsEnabled),
cpuRecentUtilizationWidgetData, getCpuRecentUtilizationWidgetData(dotMetricsEnabled),
jvmMemoryHeapWidgetData, getJvmMemoryHeapWidgetData(dotMetricsEnabled),
], ],
}, },
{ {
@ -114,10 +121,10 @@ function MetricPage(): JSX.Element {
title: t('metricGraphCategory.partitionMetrics.title'), title: t('metricGraphCategory.partitionMetrics.title'),
description: t('metricGraphCategory.partitionMetrics.description'), description: t('metricGraphCategory.partitionMetrics.description'),
graphCount: [ graphCount: [
partitionCountPerTopicWidgetData, getPartitionCountPerTopicWidgetData(dotMetricsEnabled),
currentOffsetPartitionWidgetData, getCurrentOffsetPartitionWidgetData(dotMetricsEnabled),
oldestOffsetWidgetData, getOldestOffsetWidgetData(dotMetricsEnabled),
insyncReplicasWidgetData, getInsyncReplicasWidgetData(dotMetricsEnabled),
], ],
}, },
]; ];

View File

@ -13,6 +13,8 @@ import { useState } from 'react';
import { useHistory, useLocation } from 'react-router-dom'; import { useHistory, useLocation } from 'react-router-dom';
import { useCopyToClipboard } from 'react-use'; import { useCopyToClipboard } from 'react-use';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { useGetAllConfigOptions } from './useGetAllConfigOptions'; import { useGetAllConfigOptions } from './useGetAllConfigOptions';
type ConfigOptionType = 'group' | 'topic' | 'partition'; type ConfigOptionType = 'group' | 'topic' | 'partition';
@ -38,11 +40,19 @@ const useConfigOptions = (
isFetching: boolean; isFetching: boolean;
options: DefaultOptionType[]; options: DefaultOptionType[];
} => { } => {
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const [searchText, setSearchText] = useState<string>(''); const [searchText, setSearchText] = useState<string>('');
const { isFetching, options } = useGetAllConfigOptions({ const { isFetching, options } = useGetAllConfigOptions(
attributeKey: type, {
searchText, attributeKey: type,
}); searchText,
},
dotMetricsEnabled,
);
const handleDebouncedSearch = useDebouncedFn((searchText): void => { const handleDebouncedSearch = useDebouncedFn((searchText): void => {
setSearchText(searchText as string); setSearchText(searchText as string);
}, 500); }, 500);

View File

@ -17,16 +17,19 @@ export interface GetAllConfigOptionsResponse {
export function useGetAllConfigOptions( export function useGetAllConfigOptions(
props: ConfigOptions, props: ConfigOptions,
dotMetricsEnabled: boolean,
): GetAllConfigOptionsResponse { ): GetAllConfigOptionsResponse {
const { attributeKey, searchText } = props; const { attributeKey, searchText } = props;
const { data, isLoading } = useQuery( const { data, isLoading } = useQuery(
['attributesValues', attributeKey, searchText], ['attributesValues', attributeKey, searchText],
async () => { async (): Promise<DefaultOptionType[]> => {
const { payload } = await getAttributesValues({ const { payload } = await getAttributesValues({
aggregateOperator: 'avg', aggregateOperator: 'avg',
dataSource: DataSource.METRICS, dataSource: DataSource.METRICS,
aggregateAttribute: 'kafka_consumer_group_lag', aggregateAttribute: dotMetricsEnabled
? 'kafka.consumer_group.lag'
: 'kafka_consumer_group_lag',
attributeKey, attributeKey,
searchText: searchText ?? '', searchText: searchText ?? '',
filterAttributeKeyDataType: DataTypes.String, filterAttributeKeyDataType: DataTypes.String,

View File

@ -243,7 +243,8 @@ export function getAppContextMock(
...appContextOverrides, ...appContextOverrides,
}; };
} }
function AllTheProviders({
export function AllTheProviders({
children, children,
role, // Accept the role as a prop role, // Accept the role as a prop
appContextOverrides, appContextOverrides,
@ -254,20 +255,19 @@ function AllTheProviders({
}): ReactElement { }): ReactElement {
return ( return (
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<ResourceProvider> <Provider store={mockStored(role)}>
<ErrorModalProvider> <AppContext.Provider value={getAppContextMock(role, appContextOverrides)}>
<Provider store={mockStored(role)}> <ResourceProvider>
<AppContext.Provider value={getAppContextMock(role, appContextOverrides)}> <ErrorModalProvider>
<BrowserRouter> <BrowserRouter>
{/* Use the mock store with the provided role */}
<TimezoneProvider> <TimezoneProvider>
<QueryBuilderProvider>{children}</QueryBuilderProvider> <QueryBuilderProvider>{children}</QueryBuilderProvider>
</TimezoneProvider> </TimezoneProvider>
</BrowserRouter> </BrowserRouter>
</AppContext.Provider> </ErrorModalProvider>
</Provider> </ResourceProvider>
</ErrorModalProvider> </AppContext.Provider>
</ResourceProvider> </Provider>
</QueryClientProvider> </QueryClientProvider>
); );
} }

View File

@ -3,6 +3,7 @@ package clickhouseprometheus
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/SigNoz/signoz/pkg/query-service/constants"
"strconv" "strconv"
"strings" "strings"
@ -98,9 +99,15 @@ func (client *client) queryToClickhouseQuery(_ context.Context, query *prompb.Qu
var args []any var args []any
conditions = append(conditions, fmt.Sprintf("metric_name = $%d", argCount+1)) conditions = append(conditions, fmt.Sprintf("metric_name = $%d", argCount+1))
conditions = append(conditions, "temporality IN ['Cumulative', 'Unspecified']") conditions = append(conditions, "temporality IN ['Cumulative', 'Unspecified']")
conditions = append(conditions, "__normalized = true")
conditions = append(conditions, fmt.Sprintf("unix_milli >= %d AND unix_milli < %d", start, end)) conditions = append(conditions, fmt.Sprintf("unix_milli >= %d AND unix_milli < %d", start, end))
normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
conditions = append(conditions, fmt.Sprintf("__normalized = %v", normalized))
args = append(args, metricName) args = append(args, metricName)
for _, m := range query.Matchers { for _, m := range query.Matchers {
switch m.Type { switch m.Type {

View File

@ -3003,18 +3003,22 @@ func (r *ClickHouseReader) QueryDashboardVars(ctx context.Context, query string)
return &result, nil return &result, nil
} }
func (r *ClickHouseReader) GetMetricAggregateAttributes(ctx context.Context, orgID valuer.UUID, req *v3.AggregateAttributeRequest, skipDotNames bool, skipSignozMetrics bool) (*v3.AggregateAttributeResponse, error) { func (r *ClickHouseReader) GetMetricAggregateAttributes(ctx context.Context, orgID valuer.UUID, req *v3.AggregateAttributeRequest, skipSignozMetrics bool) (*v3.AggregateAttributeResponse, error) {
var query string var query string
var err error var err error
var rows driver.Rows var rows driver.Rows
var response v3.AggregateAttributeResponse var response v3.AggregateAttributeResponse
normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
query = fmt.Sprintf("SELECT metric_name, type, is_monotonic, temporality FROM %s.%s WHERE metric_name ILIKE $1 GROUP BY metric_name, type, is_monotonic, temporality", signozMetricDBName, signozTSTableNameV41Day) query = fmt.Sprintf("SELECT metric_name, type, is_monotonic, temporality FROM %s.%s WHERE metric_name ILIKE $1 and __normalized = $2 GROUP BY metric_name, type, is_monotonic, temporality", signozMetricDBName, signozTSTableNameV41Day)
if req.Limit != 0 { if req.Limit != 0 {
query = query + fmt.Sprintf(" LIMIT %d;", req.Limit) query = query + fmt.Sprintf(" LIMIT %d;", req.Limit)
} }
rows, err = r.db.Query(ctx, query, fmt.Sprintf("%%%s%%", req.SearchText)) rows, err = r.db.Query(ctx, query, fmt.Sprintf("%%%s%%", req.SearchText), normalized)
if err != nil { if err != nil {
zap.L().Error("Error while executing query", zap.Error(err)) zap.L().Error("Error while executing query", zap.Error(err))
@ -3030,11 +3034,8 @@ func (r *ClickHouseReader) GetMetricAggregateAttributes(ctx context.Context, org
if err := rows.Scan(&metricName, &typ, &isMonotonic, &temporality); err != nil { if err := rows.Scan(&metricName, &typ, &isMonotonic, &temporality); err != nil {
return nil, fmt.Errorf("error while scanning rows: %s", err.Error()) return nil, fmt.Errorf("error while scanning rows: %s", err.Error())
} }
if skipDotNames && strings.Contains(metricName, ".") {
continue
}
if skipSignozMetrics && strings.HasPrefix(metricName, "signoz_") { if skipSignozMetrics && strings.HasPrefix(metricName, "signoz") {
continue continue
} }
@ -3077,12 +3078,17 @@ func (r *ClickHouseReader) GetMetricAttributeKeys(ctx context.Context, req *v3.F
var rows driver.Rows var rows driver.Rows
var response v3.FilterAttributeKeyResponse var response v3.FilterAttributeKeyResponse
normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
// skips the internal attributes i.e attributes starting with __ // skips the internal attributes i.e attributes starting with __
query = fmt.Sprintf("SELECT arrayJoin(tagKeys) AS distinctTagKey FROM (SELECT JSONExtractKeys(labels) AS tagKeys FROM %s.%s WHERE metric_name=$1 AND unix_milli >= $2 AND __normalized = true GROUP BY tagKeys) WHERE distinctTagKey ILIKE $3 AND distinctTagKey NOT LIKE '\\_\\_%%' GROUP BY distinctTagKey", signozMetricDBName, signozTSTableNameV41Day) query = fmt.Sprintf("SELECT arrayJoin(tagKeys) AS distinctTagKey FROM (SELECT JSONExtractKeys(labels) AS tagKeys FROM %s.%s WHERE metric_name=$1 AND unix_milli >= $2 AND __normalized = $3 GROUP BY tagKeys) WHERE distinctTagKey ILIKE $4 AND distinctTagKey NOT LIKE '\\_\\_%%' GROUP BY distinctTagKey", signozMetricDBName, signozTSTableNameV41Day)
if req.Limit != 0 { if req.Limit != 0 {
query = query + fmt.Sprintf(" LIMIT %d;", req.Limit) query = query + fmt.Sprintf(" LIMIT %d;", req.Limit)
} }
rows, err = r.db.Query(ctx, query, req.AggregateAttribute, common.PastDayRoundOff(), fmt.Sprintf("%%%s%%", req.SearchText)) rows, err = r.db.Query(ctx, query, req.AggregateAttribute, common.PastDayRoundOff(), normalized, fmt.Sprintf("%%%s%%", req.SearchText))
if err != nil { if err != nil {
zap.L().Error("Error while executing query", zap.Error(err)) zap.L().Error("Error while executing query", zap.Error(err))
return nil, fmt.Errorf("error while executing query: %s", err.Error()) return nil, fmt.Errorf("error while executing query: %s", err.Error())
@ -3113,16 +3119,19 @@ func (r *ClickHouseReader) GetMetricAttributeValues(ctx context.Context, req *v3
var rows driver.Rows var rows driver.Rows
var attributeValues v3.FilterAttributeValueResponse var attributeValues v3.FilterAttributeValueResponse
query = fmt.Sprintf("SELECT JSONExtractString(labels, $1) AS tagValue FROM %s.%s WHERE metric_name IN $2 AND JSONExtractString(labels, $3) ILIKE $4 AND unix_milli >= $5 GROUP BY tagValue", signozMetricDBName, signozTSTableNameV41Day) normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
query = fmt.Sprintf("SELECT JSONExtractString(labels, $1) AS tagValue FROM %s.%s WHERE metric_name IN $2 AND JSONExtractString(labels, $3) ILIKE $4 AND unix_milli >= $5 AND __normalized=$6 GROUP BY tagValue", signozMetricDBName, signozTSTableNameV41Day)
if req.Limit != 0 { if req.Limit != 0 {
query = query + fmt.Sprintf(" LIMIT %d;", req.Limit) query = query + fmt.Sprintf(" LIMIT %d;", req.Limit)
} }
names := []string{req.AggregateAttribute} names := []string{req.AggregateAttribute}
if _, ok := metrics.MetricsUnderTransition[req.AggregateAttribute]; ok { names = append(names, metrics.GetTransitionedMetric(req.AggregateAttribute, normalized))
names = append(names, metrics.MetricsUnderTransition[req.AggregateAttribute])
}
rows, err = r.db.Query(ctx, query, req.FilterAttributeKey, names, req.FilterAttributeKey, fmt.Sprintf("%%%s%%", req.SearchText), common.PastDayRoundOff()) rows, err = r.db.Query(ctx, query, req.FilterAttributeKey, names, req.FilterAttributeKey, fmt.Sprintf("%%%s%%", req.SearchText), common.PastDayRoundOff(), normalized)
if err != nil { if err != nil {
zap.L().Error("Error while executing query", zap.Error(err)) zap.L().Error("Error while executing query", zap.Error(err))
@ -4992,15 +5001,19 @@ func (r *ClickHouseReader) SubscribeToQueryProgress(
return r.queryProgressTracker.SubscribeToQueryProgress(queryId) return r.queryProgressTracker.SubscribeToQueryProgress(queryId)
} }
func (r *ClickHouseReader) GetAllMetricFilterAttributeKeys(ctx context.Context, req *metrics_explorer.FilterKeyRequest, skipDotNames bool) (*[]v3.AttributeKey, *model.ApiError) { func (r *ClickHouseReader) GetAllMetricFilterAttributeKeys(ctx context.Context, req *metrics_explorer.FilterKeyRequest) (*[]v3.AttributeKey, *model.ApiError) {
var rows driver.Rows var rows driver.Rows
var response []v3.AttributeKey var response []v3.AttributeKey
query := fmt.Sprintf("SELECT arrayJoin(tagKeys) AS distinctTagKey FROM (SELECT JSONExtractKeys(labels) AS tagKeys FROM %s.%s WHERE unix_milli >= $1 GROUP BY tagKeys) WHERE distinctTagKey ILIKE $2 AND distinctTagKey NOT LIKE '\\_\\_%%' GROUP BY distinctTagKey", signozMetricDBName, signozTSTableNameV41Day) normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
query := fmt.Sprintf("SELECT arrayJoin(tagKeys) AS distinctTagKey FROM (SELECT JSONExtractKeys(labels) AS tagKeys FROM %s.%s WHERE unix_milli >= $1 and __normalized = $2 GROUP BY tagKeys) WHERE distinctTagKey ILIKE $3 AND distinctTagKey NOT LIKE '\\_\\_%%' GROUP BY distinctTagKey", signozMetricDBName, signozTSTableNameV41Day)
if req.Limit != 0 { if req.Limit != 0 {
query = query + fmt.Sprintf(" LIMIT %d;", req.Limit) query = query + fmt.Sprintf(" LIMIT %d;", req.Limit)
} }
valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads) valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads)
rows, err := r.db.Query(valueCtx, query, common.PastDayRoundOff(), fmt.Sprintf("%%%s%%", req.SearchText)) //only showing past day data rows, err := r.db.Query(valueCtx, query, common.PastDayRoundOff(), normalized, fmt.Sprintf("%%%s%%", req.SearchText)) //only showing past day data
if err != nil { if err != nil {
zap.L().Error("Error while executing query", zap.Error(err)) zap.L().Error("Error while executing query", zap.Error(err))
return nil, &model.ApiError{Typ: "ClickHouseError", Err: err} return nil, &model.ApiError{Typ: "ClickHouseError", Err: err}
@ -5011,9 +5024,6 @@ func (r *ClickHouseReader) GetAllMetricFilterAttributeKeys(ctx context.Context,
if err := rows.Scan(&attributeKey); err != nil { if err := rows.Scan(&attributeKey); err != nil {
return nil, &model.ApiError{Typ: "ClickHouseError", Err: err} return nil, &model.ApiError{Typ: "ClickHouseError", Err: err}
} }
if skipDotNames && strings.Contains(attributeKey, ".") {
continue
}
key := v3.AttributeKey{ key := v3.AttributeKey{
Key: attributeKey, Key: attributeKey,
DataType: v3.AttributeKeyDataTypeString, // https://github.com/OpenObservability/OpenMetrics/blob/main/proto/openmetrics_data_model.proto#L64-L72. DataType: v3.AttributeKeyDataTypeString, // https://github.com/OpenObservability/OpenMetrics/blob/main/proto/openmetrics_data_model.proto#L64-L72.
@ -5033,13 +5043,17 @@ func (r *ClickHouseReader) GetAllMetricFilterAttributeValues(ctx context.Context
var err error var err error
var rows driver.Rows var rows driver.Rows
var attributeValues []string var attributeValues []string
normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
query = fmt.Sprintf("SELECT JSONExtractString(labels, $1) AS tagValue FROM %s.%s WHERE JSONExtractString(labels, $2) ILIKE $3 AND unix_milli >= $4 GROUP BY tagValue", signozMetricDBName, signozTSTableNameV41Day) query = fmt.Sprintf("SELECT JSONExtractString(labels, $1) AS tagValue FROM %s.%s WHERE JSONExtractString(labels, $2) ILIKE $3 AND unix_milli >= $4 AND __normalized = $5 GROUP BY tagValue", signozMetricDBName, signozTSTableNameV41Day)
if req.Limit != 0 { if req.Limit != 0 {
query = query + fmt.Sprintf(" LIMIT %d;", req.Limit) query = query + fmt.Sprintf(" LIMIT %d;", req.Limit)
} }
valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads) valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads)
rows, err = r.db.Query(valueCtx, query, req.FilterKey, req.FilterKey, fmt.Sprintf("%%%s%%", req.SearchText), common.PastDayRoundOff()) //only showing past day data rows, err = r.db.Query(valueCtx, query, req.FilterKey, req.FilterKey, fmt.Sprintf("%%%s%%", req.SearchText), common.PastDayRoundOff(), normalized) //only showing past day data
if err != nil { if err != nil {
zap.L().Error("Error while executing query", zap.Error(err)) zap.L().Error("Error while executing query", zap.Error(err))
@ -5176,6 +5190,11 @@ func (r *ClickHouseReader) GetAttributesForMetricName(ctx context.Context, metri
whereClause = "AND " + strings.Join(conditions, " AND ") whereClause = "AND " + strings.Join(conditions, " AND ")
} }
} }
normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
const baseQueryTemplate = ` const baseQueryTemplate = `
SELECT SELECT
kv.1 AS key, kv.1 AS key,
@ -5183,12 +5202,14 @@ SELECT
length(groupUniqArray(10000)(kv.2)) AS valueCount length(groupUniqArray(10000)(kv.2)) AS valueCount
FROM %s.%s FROM %s.%s
ARRAY JOIN arrayFilter(x -> NOT startsWith(x.1, '__'), JSONExtractKeysAndValuesRaw(labels)) AS kv ARRAY JOIN arrayFilter(x -> NOT startsWith(x.1, '__'), JSONExtractKeysAndValuesRaw(labels)) AS kv
WHERE metric_name = ? AND __normalized=true %s` WHERE metric_name = ? AND __normalized=? %s`
var args []interface{} var args []interface{}
args = append(args, metricName) args = append(args, metricName)
tableName := signozTSTableNameV41Week tableName := signozTSTableNameV41Week
args = append(args, normalized)
if start != nil && end != nil { if start != nil && end != nil {
st, en, tsTable, _ := utils.WhichTSTableToUse(*start, *end) st, en, tsTable, _ := utils.WhichTSTableToUse(*start, *end)
*start, *end, tableName = st, en, tsTable *start, *end, tableName = st, en, tsTable
@ -5264,6 +5285,11 @@ func (r *ClickHouseReader) ListSummaryMetrics(ctx context.Context, orgID valuer.
orderByClauseFirstQuery = fmt.Sprintf("ORDER BY %s %s", req.OrderBy.ColumnName, req.OrderBy.Order) orderByClauseFirstQuery = fmt.Sprintf("ORDER BY %s %s", req.OrderBy.ColumnName, req.OrderBy.Order)
} }
normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
// Determine which tables to use // Determine which tables to use
start, end, tsTable, localTsTable := utils.WhichTSTableToUse(req.Start, req.End) start, end, tsTable, localTsTable := utils.WhichTSTableToUse(req.Start, req.End)
sampleTable, countExp := utils.WhichSampleTableToUse(req.Start, req.End) sampleTable, countExp := utils.WhichSampleTableToUse(req.Start, req.End)
@ -5278,8 +5304,8 @@ func (r *ClickHouseReader) ListSummaryMetrics(ctx context.Context, orgID valuer.
uniq(metric_name) OVER() AS total uniq(metric_name) OVER() AS total
FROM %s.%s AS t FROM %s.%s AS t
WHERE unix_milli BETWEEN ? AND ? WHERE unix_milli BETWEEN ? AND ?
AND NOT startsWith(metric_name, 'signoz_') AND NOT startsWith(metric_name, 'signoz')
AND __normalized = true AND __normalized = ?
%s %s
GROUP BY t.metric_name GROUP BY t.metric_name
%s %s
@ -5287,6 +5313,7 @@ func (r *ClickHouseReader) ListSummaryMetrics(ctx context.Context, orgID valuer.
signozMetricDBName, tsTable, whereClause, orderByClauseFirstQuery, firstQueryLimit, req.Offset) signozMetricDBName, tsTable, whereClause, orderByClauseFirstQuery, firstQueryLimit, req.Offset)
args = append(args, start, end) args = append(args, start, end)
args = append(args, normalized)
valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads) valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads)
begin := time.Now() begin := time.Now()
rows, err := r.db.Query(valueCtx, metricsQuery, args...) rows, err := r.db.Query(valueCtx, metricsQuery, args...)
@ -5346,7 +5373,7 @@ func (r *ClickHouseReader) ListSummaryMetrics(ctx context.Context, orgID valuer.
SELECT fingerprint SELECT fingerprint
FROM %s.%s FROM %s.%s
WHERE metric_name IN (%s) WHERE metric_name IN (%s)
AND __normalized = true AND __normalized = ?
AND unix_milli BETWEEN ? AND ? AND unix_milli BETWEEN ? AND ?
%s %s
GROUP BY fingerprint GROUP BY fingerprint
@ -5361,6 +5388,7 @@ func (r *ClickHouseReader) ListSummaryMetrics(ctx context.Context, orgID valuer.
metricsList, metricsList,
whereClause, whereClause,
)) ))
args = append(args, normalized)
args = append(args, start, end) args = append(args, start, end)
args = append(args, req.Start, req.End) args = append(args, req.Start, req.End)
} else { } else {
@ -5455,6 +5483,11 @@ func (r *ClickHouseReader) ListSummaryMetrics(ctx context.Context, orgID valuer.
func (r *ClickHouseReader) GetMetricsTimeSeriesPercentage(ctx context.Context, req *metrics_explorer.TreeMapMetricsRequest) (*[]metrics_explorer.TreeMapResponseItem, *model.ApiError) { func (r *ClickHouseReader) GetMetricsTimeSeriesPercentage(ctx context.Context, req *metrics_explorer.TreeMapMetricsRequest) (*[]metrics_explorer.TreeMapResponseItem, *model.ApiError) {
var args []interface{} var args []interface{}
normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
// Build filters dynamically // Build filters dynamically
conditions, _ := utils.BuildFilterConditions(&req.Filters, "") conditions, _ := utils.BuildFilterConditions(&req.Filters, "")
whereClause := "" whereClause := ""
@ -5475,9 +5508,9 @@ func (r *ClickHouseReader) GetMetricsTimeSeriesPercentage(ctx context.Context, r
uniq(fingerprint) AS total_value, uniq(fingerprint) AS total_value,
(SELECT uniq(fingerprint) (SELECT uniq(fingerprint)
FROM %s.%s FROM %s.%s
WHERE unix_milli BETWEEN ? AND ? AND __normalized = true) AS total_time_series WHERE unix_milli BETWEEN ? AND ? AND __normalized = ?) AS total_time_series
FROM %s.%s FROM %s.%s
WHERE unix_milli BETWEEN ? AND ? AND NOT startsWith(metric_name, 'signoz_') AND __normalized = true %s WHERE unix_milli BETWEEN ? AND ? AND NOT startsWith(metric_name, 'signoz') AND __normalized = ? %s
GROUP BY metric_name GROUP BY metric_name
) )
ORDER BY percentage DESC ORDER BY percentage DESC
@ -5491,8 +5524,10 @@ func (r *ClickHouseReader) GetMetricsTimeSeriesPercentage(ctx context.Context, r
) )
args = append(args, args = append(args,
start, end, // For total_time_series subquery start, end,
normalized, // For total_time_series subquery
start, end, // For main query start, end, // For main query
normalized,
) )
valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads) valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads)
@ -5532,6 +5567,11 @@ func (r *ClickHouseReader) GetMetricsSamplesPercentage(ctx context.Context, req
whereClause = "AND " + strings.Join(conditions, " AND ") whereClause = "AND " + strings.Join(conditions, " AND ")
} }
normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
// Determine time range and tables to use // Determine time range and tables to use
start, end, tsTable, localTsTable := utils.WhichTSTableToUse(req.Start, req.End) start, end, tsTable, localTsTable := utils.WhichTSTableToUse(req.Start, req.End)
sampleTable, countExp := utils.WhichSampleTableToUse(req.Start, req.End) sampleTable, countExp := utils.WhichSampleTableToUse(req.Start, req.End)
@ -5543,7 +5583,7 @@ func (r *ClickHouseReader) GetMetricsSamplesPercentage(ctx context.Context, req
uniq(ts.fingerprint) AS timeSeries uniq(ts.fingerprint) AS timeSeries
FROM %s.%s AS ts FROM %s.%s AS ts
WHERE NOT startsWith(ts.metric_name, 'signoz_') WHERE NOT startsWith(ts.metric_name, 'signoz_')
AND __normalized = true AND __normalized = ?
AND unix_milli BETWEEN ? AND ? AND unix_milli BETWEEN ? AND ?
%s %s
GROUP BY ts.metric_name GROUP BY ts.metric_name
@ -5554,7 +5594,7 @@ func (r *ClickHouseReader) GetMetricsSamplesPercentage(ctx context.Context, req
valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads) valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads)
begin := time.Now() begin := time.Now()
rows, err := r.db.Query(valueCtx, metricsQuery, start, end) rows, err := r.db.Query(valueCtx, metricsQuery, normalized, start, end)
duration := time.Since(begin) duration := time.Since(begin)
zap.L().Info("Time taken to execute samples percentage metric name query to reduce search space", zap.String("query", metricsQuery), zap.Any("start", start), zap.Any("end", end), zap.Duration("duration", duration)) zap.L().Info("Time taken to execute samples percentage metric name query to reduce search space", zap.String("query", metricsQuery), zap.Any("start", start), zap.Any("end", end), zap.Duration("duration", duration))
if err != nil { if err != nil {
@ -5626,13 +5666,13 @@ func (r *ClickHouseReader) GetMetricsSamplesPercentage(ctx context.Context, req
FROM %s.%s AS ts FROM %s.%s AS ts
WHERE ts.metric_name IN (%s) WHERE ts.metric_name IN (%s)
AND unix_milli BETWEEN ? AND ? AND unix_milli BETWEEN ? AND ?
AND __normalized = true AND __normalized = ?
%s %s
GROUP BY ts.fingerprint GROUP BY ts.fingerprint
)`, )`,
signozMetricDBName, localTsTable, metricsList, whereClause, signozMetricDBName, localTsTable, metricsList, whereClause,
)) ))
args = append(args, start, end) args = append(args, start, end, normalized)
} }
// Apply metric filtering after all conditions // Apply metric filtering after all conditions
@ -5682,6 +5722,11 @@ func (r *ClickHouseReader) GetMetricsSamplesPercentage(ctx context.Context, req
func (r *ClickHouseReader) GetNameSimilarity(ctx context.Context, req *metrics_explorer.RelatedMetricsRequest) (map[string]metrics_explorer.RelatedMetricsScore, *model.ApiError) { func (r *ClickHouseReader) GetNameSimilarity(ctx context.Context, req *metrics_explorer.RelatedMetricsRequest) (map[string]metrics_explorer.RelatedMetricsScore, *model.ApiError) {
start, end, tsTable, _ := utils.WhichTSTableToUse(req.Start, req.End) start, end, tsTable, _ := utils.WhichTSTableToUse(req.Start, req.End)
normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
query := fmt.Sprintf(` query := fmt.Sprintf(`
SELECT SELECT
metric_name, metric_name,
@ -5692,15 +5737,15 @@ func (r *ClickHouseReader) GetNameSimilarity(ctx context.Context, req *metrics_e
FROM %s.%s FROM %s.%s
WHERE metric_name != ? WHERE metric_name != ?
AND unix_milli BETWEEN ? AND ? AND unix_milli BETWEEN ? AND ?
AND NOT startsWith(metric_name, 'signoz_') AND NOT startsWith(metric_name, 'signoz')
AND __normalized = true AND __normalized = ?
GROUP BY metric_name GROUP BY metric_name
ORDER BY name_similarity DESC ORDER BY name_similarity DESC
LIMIT 30;`, LIMIT 30;`,
signozMetricDBName, tsTable) signozMetricDBName, tsTable)
valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads) valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads)
rows, err := r.db.Query(valueCtx, query, req.CurrentMetricName, req.CurrentMetricName, req.CurrentMetricName, start, end) rows, err := r.db.Query(valueCtx, query, req.CurrentMetricName, req.CurrentMetricName, req.CurrentMetricName, start, end, normalized)
if err != nil { if err != nil {
return nil, &model.ApiError{Typ: "ClickHouseError", Err: err} return nil, &model.ApiError{Typ: "ClickHouseError", Err: err}
} }
@ -5730,6 +5775,11 @@ func (r *ClickHouseReader) GetNameSimilarity(ctx context.Context, req *metrics_e
func (r *ClickHouseReader) GetAttributeSimilarity(ctx context.Context, req *metrics_explorer.RelatedMetricsRequest) (map[string]metrics_explorer.RelatedMetricsScore, *model.ApiError) { func (r *ClickHouseReader) GetAttributeSimilarity(ctx context.Context, req *metrics_explorer.RelatedMetricsRequest) (map[string]metrics_explorer.RelatedMetricsScore, *model.ApiError) {
start, end, tsTable, _ := utils.WhichTSTableToUse(req.Start, req.End) start, end, tsTable, _ := utils.WhichTSTableToUse(req.Start, req.End)
normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
// Get target labels // Get target labels
extractedLabelsQuery := fmt.Sprintf(` extractedLabelsQuery := fmt.Sprintf(`
SELECT SELECT
@ -5741,12 +5791,12 @@ func (r *ClickHouseReader) GetAttributeSimilarity(ctx context.Context, req *metr
AND unix_milli between ? and ? AND unix_milli between ? and ?
AND NOT startsWith(kv.1, '__') AND NOT startsWith(kv.1, '__')
AND NOT startsWith(metric_name, 'signoz_') AND NOT startsWith(metric_name, 'signoz_')
AND __normalized = true AND __normalized = ?
GROUP BY label_key GROUP BY label_key
LIMIT 50`, signozMetricDBName, tsTable) LIMIT 50`, signozMetricDBName, tsTable)
valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads) valueCtx := context.WithValue(ctx, "clickhouse_max_threads", constants.MetricsExplorerClickhouseThreads)
rows, err := r.db.Query(valueCtx, extractedLabelsQuery, req.CurrentMetricName, start, end) rows, err := r.db.Query(valueCtx, extractedLabelsQuery, req.CurrentMetricName, start, end, normalized)
if err != nil { if err != nil {
return nil, &model.ApiError{Typ: "ClickHouseError", Err: err} return nil, &model.ApiError{Typ: "ClickHouseError", Err: err}
} }
@ -5819,7 +5869,7 @@ func (r *ClickHouseReader) GetAttributeSimilarity(ctx context.Context, req *metr
WHERE rand() %% 100 < 10 WHERE rand() %% 100 < 10
AND unix_milli between ? and ? AND unix_milli between ? and ?
AND NOT startsWith(metric_name, 'signoz_') AND NOT startsWith(metric_name, 'signoz_')
AND __normalized = true AND __normalized = ?
GROUP BY metric_name GROUP BY metric_name
ORDER BY weighted_match_count DESC, raw_match_count DESC ORDER BY weighted_match_count DESC, raw_match_count DESC
LIMIT 30 LIMIT 30
@ -5827,7 +5877,7 @@ func (r *ClickHouseReader) GetAttributeSimilarity(ctx context.Context, req *metr
targetKeysList, targetValuesList, priorityListString, 2, targetKeysList, targetValuesList, priorityListString, 2,
signozMetricDBName, tsTable) signozMetricDBName, tsTable)
rows, err = r.db.Query(valueCtx, candidateLabelsQuery, start, end) rows, err = r.db.Query(valueCtx, candidateLabelsQuery, start, end, normalized)
if err != nil { if err != nil {
return nil, &model.ApiError{Typ: "ClickHouseError", Err: err} return nil, &model.ApiError{Typ: "ClickHouseError", Err: err}
} }

View File

@ -7,6 +7,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/SigNoz/signoz/pkg/query-service/constants"
"io" "io"
"math" "math"
"net/http" "net/http"
@ -29,7 +30,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/app/cloudintegrations/services" "github.com/SigNoz/signoz/pkg/query-service/app/cloudintegrations/services"
"github.com/SigNoz/signoz/pkg/query-service/app/integrations" "github.com/SigNoz/signoz/pkg/query-service/app/integrations"
"github.com/SigNoz/signoz/pkg/query-service/app/metricsexplorer" "github.com/SigNoz/signoz/pkg/query-service/app/metricsexplorer"
"github.com/SigNoz/signoz/pkg/query-service/constants"
"github.com/SigNoz/signoz/pkg/signoz" "github.com/SigNoz/signoz/pkg/signoz"
"github.com/SigNoz/signoz/pkg/valuer" "github.com/SigNoz/signoz/pkg/valuer"
"github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/promql"
@ -1198,7 +1198,31 @@ func prepareQuery(r *http.Request) (string, error) {
if tmplErr != nil { if tmplErr != nil {
return "", tmplErr return "", tmplErr
} }
return queryBuf.String(), nil
if !constants.IsDotMetricsEnabled {
return queryBuf.String(), nil
}
query = queryBuf.String()
// Now handle $var replacements (simple string replace)
keys := make([]string, 0, len(vars))
for k := range vars {
keys = append(keys, k)
}
sort.Slice(keys, func(i, j int) bool {
return len(keys[i]) > len(keys[j])
})
newQuery := query
for _, k := range keys {
placeholder := "$" + k
v := vars[k]
newQuery = strings.ReplaceAll(newQuery, placeholder, v)
}
return newQuery, nil
} }
func (aH *APIHandler) queryDashboardVarsV2(w http.ResponseWriter, r *http.Request) { func (aH *APIHandler) queryDashboardVarsV2(w http.ResponseWriter, r *http.Request) {
@ -1996,6 +2020,12 @@ func (aH *APIHandler) getFeatureFlags(w http.ResponseWriter, r *http.Request) {
} }
} }
} }
if constants.IsDotMetricsEnabled {
featureSet = append(featureSet, &featuretypes.GettableFeature{
Name: featuretypes.DotMetricsEnabled,
Active: true,
})
}
aH.Respond(w, featureSet) aH.Respond(w, featureSet)
} }
@ -2503,6 +2533,12 @@ func (aH *APIHandler) onboardKafka(w http.ResponseWriter, r *http.Request) {
} }
} }
} }
var kafkaConsumerFetchLatencyAvg string = "kafka_consumer_fetch_latency_avg"
var kafkaConsumerLag string = "kafka_consumer_group_lag"
if constants.IsDotMetricsEnabled {
kafkaConsumerLag = "kafka.consumer_group.lag"
kafkaConsumerFetchLatencyAvg = "kafka.consumer.fetch_latency_avg"
}
if !fetchLatencyState && !consumerLagState { if !fetchLatencyState && !consumerLagState {
entries = append(entries, kafka.OnboardingResponse{ entries = append(entries, kafka.OnboardingResponse{
@ -2513,27 +2549,28 @@ func (aH *APIHandler) onboardKafka(w http.ResponseWriter, r *http.Request) {
} }
if !fetchLatencyState { if !fetchLatencyState {
entries = append(entries, kafka.OnboardingResponse{ entries = append(entries, kafka.OnboardingResponse{
Attribute: "kafka_consumer_fetch_latency_avg", Attribute: kafkaConsumerFetchLatencyAvg,
Message: "Metric kafka_consumer_fetch_latency_avg is not present in the given time range.", Message: "Metric kafka_consumer_fetch_latency_avg is not present in the given time range.",
Status: "0", Status: "0",
}) })
} else { } else {
entries = append(entries, kafka.OnboardingResponse{ entries = append(entries, kafka.OnboardingResponse{
Attribute: "kafka_consumer_fetch_latency_avg", Attribute: kafkaConsumerFetchLatencyAvg,
Status: "1", Status: "1",
}) })
} }
if !consumerLagState { if !consumerLagState {
entries = append(entries, kafka.OnboardingResponse{ entries = append(entries, kafka.OnboardingResponse{
Attribute: "kafka_consumer_group_lag", Attribute: kafkaConsumerLag,
Message: "Metric kafka_consumer_group_lag is not present in the given time range.", Message: "Metric kafka_consumer_group_lag is not present in the given time range.",
Status: "0", Status: "0",
}) })
} else { } else {
entries = append(entries, kafka.OnboardingResponse{ entries = append(entries, kafka.OnboardingResponse{
Attribute: "kafka_consumer_group_lag", Attribute: kafkaConsumerLag,
Status: "1", Status: "1",
}) })
} }
@ -4327,7 +4364,7 @@ func (aH *APIHandler) autocompleteAggregateAttributes(w http.ResponseWriter, r *
switch req.DataSource { switch req.DataSource {
case v3.DataSourceMetrics: case v3.DataSourceMetrics:
response, err = aH.reader.GetMetricAggregateAttributes(r.Context(), orgID, req, true, false) response, err = aH.reader.GetMetricAggregateAttributes(r.Context(), orgID, req, false)
case v3.DataSourceLogs: case v3.DataSourceLogs:
response, err = aH.reader.GetLogAggregateAttributes(r.Context(), req) response, err = aH.reader.GetLogAggregateAttributes(r.Context(), req)
case v3.DataSourceTraces: case v3.DataSourceTraces:

View File

@ -16,12 +16,12 @@ import (
) )
var ( var (
metricToUseForClusters = "k8s_node_cpu_utilization" metricToUseForClusters = GetDotMetrics("k8s_node_cpu_utilization")
clusterAttrsToEnrich = []string{"k8s_cluster_name"} clusterAttrsToEnrich = []string{GetDotMetrics("k8s_cluster_name")}
// TODO(srikanthccv): change this to k8s_cluster_uid after showing the missing data banner // TODO(srikanthccv): change this to k8s_cluster_uid after showing the missing data banner
k8sClusterUIDAttrKey = "k8s_cluster_name" k8sClusterUIDAttrKey = GetDotMetrics("k8s_cluster_name")
queryNamesForClusters = map[string][]string{ queryNamesForClusters = map[string][]string{
"cpu": {"A"}, "cpu": {"A"},

Some files were not shown because too many files have changed in this diff Show More