diff --git a/frontend/src/api/metrics/ApDex/getMetricMeta.ts b/frontend/src/api/metrics/ApDex/getMetricMeta.ts index 36466e1e69..e3045730a7 100644 --- a/frontend/src/api/metrics/ApDex/getMetricMeta.ts +++ b/frontend/src/api/metrics/ApDex/getMetricMeta.ts @@ -4,5 +4,6 @@ import { MetricMetaProps } from 'types/api/metrics/getApDex'; export const getMetricMeta = ( metricName: string, + servicename: string, ): Promise> => - axios.get(`/metric_meta?metricName=${metricName}`); + axios.get(`/metric_meta?metricName=${metricName}&serviceName=${servicename}`); diff --git a/frontend/src/container/MetricsApplication/Tabs/Overview/ApDex/ApDexMetricsApplication.tsx b/frontend/src/container/MetricsApplication/Tabs/Overview/ApDex/ApDexMetricsApplication.tsx index 542a1e9e8d..3ee5fbf7d8 100644 --- a/frontend/src/container/MetricsApplication/Tabs/Overview/ApDex/ApDexMetricsApplication.tsx +++ b/frontend/src/container/MetricsApplication/Tabs/Overview/ApDex/ApDexMetricsApplication.tsx @@ -1,7 +1,9 @@ import Spinner from 'components/Spinner'; import { useGetMetricMeta } from 'hooks/apDex/useGetMetricMeta'; import useErrorNotification from 'hooks/useErrorNotification'; +import { useParams } from 'react-router-dom'; +import { IServiceName } from '../../types'; import ApDexMetrics from './ApDexMetrics'; import { metricMeta } from './constants'; import { ApDexDataSwitcherProps } from './types'; @@ -13,7 +15,8 @@ function ApDexMetricsApplication({ thresholdValue, topLevelOperationsRoute, }: ApDexDataSwitcherProps): JSX.Element { - const { data, isLoading, error } = useGetMetricMeta(metricMeta); + const { servicename } = useParams(); + const { data, isLoading, error } = useGetMetricMeta(metricMeta, servicename); useErrorNotification(error); if (isLoading) { diff --git a/frontend/src/hooks/apDex/useGetMetricMeta.ts b/frontend/src/hooks/apDex/useGetMetricMeta.ts index fd364e598d..6bf28c35a0 100644 --- a/frontend/src/hooks/apDex/useGetMetricMeta.ts +++ b/frontend/src/hooks/apDex/useGetMetricMeta.ts @@ -5,8 +5,9 @@ import { MetricMetaProps } from 'types/api/metrics/getApDex'; export const useGetMetricMeta = ( metricName: string, + servicename: string, ): UseQueryResult, AxiosError> => useQuery, AxiosError>({ - queryKey: [{ metricName }], - queryFn: async () => getMetricMeta(metricName), + queryKey: [{ metricName, servicename }], + queryFn: async () => getMetricMeta(metricName, servicename), }); diff --git a/pkg/query-service/app/apdex.go b/pkg/query-service/app/apdex.go index 6854a91367..e3498d9c80 100644 --- a/pkg/query-service/app/apdex.go +++ b/pkg/query-service/app/apdex.go @@ -36,7 +36,8 @@ func (aH *APIHandler) getApdexSettings(w http.ResponseWriter, r *http.Request) { func (aH *APIHandler) getLatencyMetricMetadata(w http.ResponseWriter, r *http.Request) { metricName := r.URL.Query().Get("metricName") - metricMetadata, err := aH.reader.GetLatencyMetricMetadata(r.Context(), metricName, aH.preferDelta) + serviceName := r.URL.Query().Get("serviceName") + metricMetadata, err := aH.reader.GetLatencyMetricMetadata(r.Context(), metricName, serviceName, aH.preferDelta) if err != nil { RespondError(w, &model.ApiError{Err: err, Typ: model.ErrorInternal}, nil) return diff --git a/pkg/query-service/app/clickhouseReader/reader.go b/pkg/query-service/app/clickhouseReader/reader.go index 0340474596..3f11a4823a 100644 --- a/pkg/query-service/app/clickhouseReader/reader.go +++ b/pkg/query-service/app/clickhouseReader/reader.go @@ -4057,8 +4057,8 @@ func (r *ClickHouseReader) GetMetricAttributeValues(ctx context.Context, req *v3 return &attributeValues, nil } -func (r *ClickHouseReader) GetLatencyMetricMetadata(ctx context.Context, metricName string, preferDelta bool) (*v3.LatencyMetricMetadataResponse, error) { - query := fmt.Sprintf("SELECT DISTINCT(temporality) from %s.%s WHERE metric_name='%s'", signozMetricDBName, signozTSTableName, metricName) +func (r *ClickHouseReader) GetLatencyMetricMetadata(ctx context.Context, metricName, serviceName string, preferDelta bool) (*v3.LatencyMetricMetadataResponse, error) { + query := fmt.Sprintf("SELECT DISTINCT(temporality) from %s.%s WHERE metric_name='%s' AND JSONExtractString(labels, 'service_name') = '%s'", signozMetricDBName, signozTSTableName, metricName, serviceName) rows, err := r.db.Query(ctx, query, metricName) if err != nil { zap.S().Error(err) @@ -4077,7 +4077,7 @@ func (r *ClickHouseReader) GetLatencyMetricMetadata(ctx context.Context, metricN } } - query = fmt.Sprintf("SELECT DISTINCT(toFloat64(JSONExtractString(labels, 'le'))) as le from %s.%s WHERE metric_name='%s' ORDER BY le", signozMetricDBName, signozTSTableName, metricName) + query = fmt.Sprintf("SELECT DISTINCT(JSONExtractString(labels, 'le')) as le from %s.%s WHERE metric_name='%s' AND JSONExtractString(labels, 'service_name') = '%s' ORDER BY le", signozMetricDBName, signozTSTableName, metricName, serviceName) rows, err = r.db.Query(ctx, query, metricName) if err != nil { zap.S().Error(err) @@ -4087,10 +4087,18 @@ func (r *ClickHouseReader) GetLatencyMetricMetadata(ctx context.Context, metricN var leFloat64 []float64 for rows.Next() { - var le float64 - if err := rows.Scan(&le); err != nil { + var leStr string + if err := rows.Scan(&leStr); err != nil { return nil, fmt.Errorf("error while scanning rows: %s", err.Error()) } + le, err := strconv.ParseFloat(leStr, 64) + // ignore the error and continue if the value is not a float + // ideally this should not happen but we have seen ClickHouse + // returning empty string for some values + if err != nil { + zap.S().Error("error while parsing le value: ", err) + continue + } if math.IsInf(le, 0) { continue } diff --git a/pkg/query-service/interfaces/interface.go b/pkg/query-service/interfaces/interface.go index e2b2b49481..a75a2f5f30 100644 --- a/pkg/query-service/interfaces/interface.go +++ b/pkg/query-service/interfaces/interface.go @@ -98,7 +98,7 @@ type Reader interface { QueryDashboardVars(ctx context.Context, query string) (*model.DashboardVar, error) CheckClickHouse(ctx context.Context) error - GetLatencyMetricMetadata(context.Context, string, bool) (*v3.LatencyMetricMetadataResponse, error) + GetLatencyMetricMetadata(context.Context, string, string, bool) (*v3.LatencyMetricMetadataResponse, error) } type Querier interface {