Compare commits

...

4 Commits

Author SHA1 Message Date
srikanthccv
a896731c5d refactor: inline canonical infrastructure metric names 2026-08-07 22:24:16 +05:30
srikanthccv
5b8067eeac chore: remove normalized metrics compatibility 2026-08-07 22:12:28 +05:30
Srikanth Chekuri
e0b278e8e2 test(querier): pin keyless-row semantics for filter operators (#12456)
## Summary

Adds an integration-test matrix that pins the deliberate keyless-row
contract for filter operators, independent of any feature work:

- **Negative operators are a set complement over all rows.** A row that
does not carry the key at all must match `!=`, `NOT IN`, `NOT LIKE`, and
`NOT CONTAINS`. Users opt into presence explicitly with `AND key
EXISTS`.
- **Positive operators carry an implicit existence guard**
(`FilterOperator.AddDefaultExistsFilter`), so keyless rows never
false-positive against sentinel defaults.
- **`EXISTS` / `NOT EXISTS` partition rows exactly** by key presence,
and `!= x AND EXISTS` is the documented composition for "present and not
x".
- **Numeric attributes inherit the map-default sentinel**: a missing key
reads as `0`, so `num != 5` includes keyless rows while `num != 0`
excludes them. This conflation is deliberate and pinned by name
(`numeric_neq_zero_sentinel_conflation`) as the reference point for any
value-expression change.

Coverage: 46 cases — one shared matrix over traces and logs (resource
and attribute contexts), metric labels (series without the label), the
numeric sentinel, and the EXISTS composition. The contract, matrix, seed
data, and assertions live together in one file so the contract reads top
to bottom.

## Why

These semantics were enforced only implicitly by the operator list in
`AddDefaultExistsFilter`, with no test naming the intent. That gap
allows an implementation change to alter negative-filter results
silently and lets new tests calibrate expectations against the
implementation instead of the contract. The attribute names used here
are deliberately outside every semantic-convention family, so this file
pins the base contract regardless of the semconv overlay state and
serves as the oracle that family-field behavior
(`queriertraces/13_semconv_evolution.py` in the semconv stack) must
mirror.

## Testing

- `uv run pytest --basetemp=./tmp/ --reuse
integration/tests/queriercommon/06_keyless_semantics.py` — 46/46 passed
against a stack built from main-based sources, and 2×46 against a
long-lived shared stack, confirming the set-based assertions stay stable
under environment reuse.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 15:30:07 +00:00
Srikanth Chekuri
a711cda7ba feat: generate semantic convention families (#12441)
## Summary

Adds the semantic-convention evolution foundation:

- vendors the OpenTelemetry schema and SigNoz overlay
- generates Go and TypeScript family tables deterministically
- exposes the Go resolver API for family members, current names, and
historical names
- adds generation checks and unit tests

Related to #6143.

## Stack

1. #12441 — Foundations (base: main)
2. #12442 — Phase 1 query (base: #12441)
3. #12443 — Phase 1 services (base: #12442)
4. #12444 — Phase 1 closure gate (base: #12443)
5. #12445 — Phase 2 signals (base: #12444)
6. #12446 — Phase 3 migration UX (base: #12445)
7. #12447 — Phase 4 rollout (base: #12446)

**Current layer:** #12441

## Testing

- `go test ./scripts/semconv`
- `go test ./pkg/types/telemetrytypes/semconv`
- `make semconv-check`

## Risk and rollback

This layer is additive apart from CI generation checks. Roll back by
reverting this PR; no stored telemetry is changed.
2026-08-07 15:27:50 +00:00
87 changed files with 2959 additions and 1634 deletions

View File

@@ -53,6 +53,21 @@ jobs:
with:
PRIMUS_REF: main
GO_VERSION: 1.24
semconv-generated:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
runs-on: ubuntu-latest
steps:
- name: self-checkout
uses: actions/checkout@v4
- name: go-install
uses: actions/setup-go@v5
with:
go-version: "1.24"
- name: check-semconv-generated-files
run: go run ./scripts/semconv -check
build:
if: |
github.event_name == 'merge_group' ||

View File

@@ -233,6 +233,10 @@ py-clean: ## Clear all pycache and pytest cache from tests directory recursively
##############################################################
# generate commands
##############################################################
.PHONY: semconv-generate
semconv-generate: ## Regenerate semantic-convention families for Go and TypeScript
@go run ./scripts/semconv
.PHONY: gen-mocks
gen-mocks:
@echo ">> Generating mocks"

View File

@@ -98,14 +98,6 @@ func (ah *APIHandler) getFeatureFlags(w http.ResponseWriter, r *http.Request) {
Route: "",
})
if constants.IsDotMetricsEnabled {
for idx, feature := range featureSet {
if feature.Name == licensetypes.DotMetricsEnabled {
featureSet[idx].Active = true
}
}
}
ah.Respond(w, featureSet)
}

View File

@@ -17,15 +17,3 @@ func GetOrDefaultEnv(key string, fallback string) string {
}
return v
}
// constant functions that override env vars
const DotMetricsEnabled = "DOT_METRICS_ENABLED"
var IsDotMetricsEnabled = false
func init() {
if GetOrDefaultEnv(DotMetricsEnabled, "true") == "true" {
IsDotMetricsEnabled = true
}
}

View File

@@ -24,19 +24,3 @@ export const Logout = async (): Promise<void> => {
window.dispatchEvent(new CustomEvent('LOGOUT'));
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

@@ -7,7 +7,6 @@ export enum FeatureKeys {
GATEWAY = 'gateway',
PREMIUM_SUPPORT = 'premium_support',
ANOMALY_DETECTION = 'anomaly_detection',
DOT_METRICS_ENABLED = 'dot_metrics_enabled',
USE_JSON_BODY = 'use_json_body',
ENABLE_AI_OBSERVABILITY = 'enable_ai_observability',
ENABLE_METRICS_REDUCTION = 'enable_metrics_reduction',

View File

@@ -0,0 +1,32 @@
// Code generated by scripts/semconv. DO NOT EDIT.
export type SemconvFamily = {
readonly current: string;
readonly old: readonly string[];
readonly kind: 'attribute' | 'metric';
readonly contexts: readonly string[];
readonly signals: readonly string[];
readonly applyToMetrics: readonly string[];
readonly valueMap: Readonly<Record<string, string>>;
};
export const SEMCONV_FAMILIES: readonly SemconvFamily[] = [
{
current: 'db.system.name',
old: ['db.system'],
kind: 'attribute',
contexts: [],
signals: [],
applyToMetrics: [],
valueMap: {},
},
{
current: 'deployment.environment.name',
old: ['deployment.environment'],
kind: 'attribute',
contexts: [],
signals: [],
applyToMetrics: [],
valueMap: {},
},
] as const;

View File

@@ -37,8 +37,6 @@ import { ErrorResponse, SuccessResponse } from 'types/api';
import { Exception, PayloadProps } from 'types/api/errors/getAll';
import { GlobalReducer } from 'types/reducer/globalTime';
import { FeatureKeys } from '../../constants/features';
import { useAppContext } from '../../providers/App/App';
import { FilterDropdownExtendsProps } from './types';
import {
extractFilterValues,
@@ -418,11 +416,6 @@ 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(
(
paginations: TablePaginationConfig,
@@ -458,7 +451,7 @@ function AllErrors(): JSX.Element {
useEffect(() => {
if (!isUndefined(errorCountResponse.data?.payload)) {
const selectedEnvironments = queries.find(
(val) => val.tagKey === getResourceDeploymentKeys(dotMetricsEnabled),
(val) => val.tagKey === getResourceDeploymentKeys(),
)?.tagValue;
logEvent('Exception: List page visited', {

View File

@@ -35,7 +35,6 @@ import { openInNewTab } from 'utils/navigation';
import triangleRulerUrl from '@/assets/Icons/triangle-ruler.svg';
import { FeatureKeys } from '../../../constants/features';
import { DOCS_LINKS } from '../constants';
import { columns, TIME_PICKER_OPTIONS } from './constants';
@@ -212,19 +211,13 @@ function ServiceMetrics({
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(
() =>
getQueryRangeRequestData({
topLevelOperations,
globalSelectedInterval,
dotMetricsEnabled,
}),
[globalSelectedInterval, topLevelOperations, dotMetricsEnabled],
[globalSelectedInterval, topLevelOperations],
);
const dataQueries = useGetQueriesRange(

View File

@@ -82,7 +82,7 @@ export function getHostMetricsQueryPayload(
start: number,
end: number,
): ReturnType<typeof getHostQueryPayload> {
return getHostQueryPayload(host.hostName, start, end, true);
return getHostQueryPayload(host.hostName, start, end);
}
export { hostWidgetInfo };

View File

@@ -121,12 +121,6 @@ jest.spyOn(appContextHooks, 'useAppContext').mockReturnValue({
plan_version: 'test-plan-version',
},
},
featureFlags: [
{
name: 'DOT_METRICS_ENABLED',
active: false,
},
],
} as any);
const mockEntity = {

View File

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

View File

@@ -12,13 +12,11 @@ import { useResizeObserver } from 'hooks/useDimensions';
import { GetMetricQueryRange } from 'lib/dashboard/getQueryResults';
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
import { useAppContext } from 'providers/App/App';
import { useTimezone } from 'providers/Timezone';
import { SuccessResponse } from 'types/api';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import uPlot from 'uplot';
import { FeatureKeys } from '../../../constants/features';
import { getPodQueryPayload, podWidgetInfo } from './constants';
function PodMetrics({
@@ -54,14 +52,9 @@ function PodMetrics({
scrollLeft: 0,
});
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const queryPayloads = useMemo(
() => getPodQueryPayload(clusterName, podName, start, end, dotMetricsEnabled),
[clusterName, end, podName, start, dotMetricsEnabled],
() => getPodQueryPayload(clusterName, podName, start, end),
[clusterName, end, podName, start],
);
const queries = useQueries(
queryPayloads.map((payload) => ({

View File

@@ -9,48 +9,21 @@ export const getPodQueryPayload = (
podName: string,
start: number,
end: number,
dotMetricsEnabled: boolean,
): GetQueryResultsProps[] => {
const k8sClusterNameKey = dotMetricsEnabled
? 'k8s.cluster.name'
: 'k8s_cluster_name';
const k8sPodNameKey = dotMetricsEnabled ? 'k8s.pod.name' : 'k8s_pod_name';
const containerCpuUtilKey = dotMetricsEnabled
? 'container.cpu.usage'
: 'container_cpu_usage';
const containerMemUsageKey = dotMetricsEnabled
? 'container.memory.usage'
: 'container_memory_usage';
const k8sContainerCpuReqKey = dotMetricsEnabled
? 'k8s.container.cpu_request'
: 'k8s_container_cpu_request';
const k8sContainerCpuLimitKey = dotMetricsEnabled
? 'k8s.container.cpu_limit'
: 'k8s_container_cpu_limit';
const k8sContainerMemReqKey = dotMetricsEnabled
? 'k8s.container.memory_request'
: 'k8s_container_memory_request';
const k8sContainerMemLimitKey = dotMetricsEnabled
? 'k8s.container.memory_limit'
: 'k8s_container_memory_limit';
const k8sPodFsAvailKey = dotMetricsEnabled
? 'k8s.pod.filesystem.available'
: 'k8s_pod_filesystem_available';
const k8sPodFsCapKey = dotMetricsEnabled
? 'k8s.pod.filesystem.capacity'
: 'k8s_pod_filesystem_capacity';
const k8sPodNetIoKey = dotMetricsEnabled
? 'k8s.pod.network.io'
: 'k8s_pod_network_io';
const podLegendTemplate = dotMetricsEnabled
? '{{k8s.pod.name}}'
: '{{k8s_pod_name}}';
const podLegendUsage = dotMetricsEnabled
? 'usage - {{k8s.pod.name}}'
: 'usage - {{k8s_pod_name}}';
const podLegendLimit = dotMetricsEnabled
? 'limit - {{k8s.pod.name}}'
: 'limit - {{k8s_pod_name}}';
const k8sClusterNameKey = 'k8s.cluster.name';
const k8sPodNameKey = 'k8s.pod.name';
const containerCpuUtilKey = 'container.cpu.usage';
const containerMemUsageKey = 'container.memory.usage';
const k8sContainerCpuReqKey = 'k8s.container.cpu_request';
const k8sContainerCpuLimitKey = 'k8s.container.cpu_limit';
const k8sContainerMemReqKey = 'k8s.container.memory_request';
const k8sContainerMemLimitKey = 'k8s.container.memory_limit';
const k8sPodFsAvailKey = 'k8s.pod.filesystem.available';
const k8sPodFsCapKey = 'k8s.pod.filesystem.capacity';
const k8sPodNetIoKey = 'k8s.pod.network.io';
const podLegendTemplate = '{{k8s.pod.name}}';
const podLegendUsage = 'usage - {{k8s.pod.name}}';
const podLegendLimit = 'limit - {{k8s.pod.name}}';
return [
{
@@ -1027,36 +1000,17 @@ export const getNodeQueryPayload = (
nodeName: string,
start: number,
end: number,
dotMetricsEnabled: boolean,
): GetQueryResultsProps[] => {
const k8sClusterNameKey = dotMetricsEnabled
? 'k8s.cluster.name'
: 'k8s_cluster_name';
const k8sNodeNameKey = dotMetricsEnabled ? 'k8s.node.name' : 'k8s_node_name';
const k8sNodeCpuTimeKey = dotMetricsEnabled
? 'k8s.node.cpu.time'
: 'k8s_node_cpu_time';
const k8sNodeAllocCpuKey = dotMetricsEnabled
? 'k8s.node.allocatable_cpu'
: 'k8s_node_allocatable_cpu';
const k8sNodeMemWsKey = dotMetricsEnabled
? 'k8s.node.memory.working_set'
: 'k8s_node_memory_working_set';
const k8sNodeAllocMemKey = dotMetricsEnabled
? 'k8s.node.allocatable_memory'
: 'k8s_node_allocatable_memory';
const k8sNodeNetIoKey = dotMetricsEnabled
? 'k8s.node.network.io'
: 'k8s_node_network_io';
const k8sNodeFsAvailKey = dotMetricsEnabled
? 'k8s.node.filesystem.available'
: 'k8s_node_filesystem_available';
const k8sNodeFsCapKey = dotMetricsEnabled
? 'k8s.node.filesystem.capacity'
: 'k8s_node_filesystem_capacity';
const podLegend = dotMetricsEnabled
? '{{k8s.node.name}}'
: '{{k8s_node_name}}';
const k8sClusterNameKey = 'k8s.cluster.name';
const k8sNodeNameKey = 'k8s.node.name';
const k8sNodeCpuTimeKey = 'k8s.node.cpu.time';
const k8sNodeAllocCpuKey = 'k8s.node.allocatable_cpu';
const k8sNodeMemWsKey = 'k8s.node.memory.working_set';
const k8sNodeAllocMemKey = 'k8s.node.allocatable_memory';
const k8sNodeNetIoKey = 'k8s.node.network.io';
const k8sNodeFsAvailKey = 'k8s.node.filesystem.available';
const k8sNodeFsCapKey = 'k8s.node.filesystem.capacity';
const podLegend = '{{k8s.node.name}}';
return [
{
@@ -1586,48 +1540,23 @@ export const getHostQueryPayload = (
hostName: string,
start: number,
end: number,
dotMetricsEnabled: boolean,
): GetQueryResultsProps[] => {
const hostNameKey = dotMetricsEnabled ? 'host.name' : 'host_name';
const cpuTimeKey = dotMetricsEnabled ? 'system.cpu.time' : 'system_cpu_time';
const memUsageKey = dotMetricsEnabled
? 'system.memory.usage'
: 'system_memory_usage';
const load1mKey = dotMetricsEnabled
? 'system.cpu.load_average.1m'
: 'system_cpu_load_average_1m';
const load5mKey = dotMetricsEnabled
? 'system.cpu.load_average.5m'
: 'system_cpu_load_average_5m';
const load15mKey = dotMetricsEnabled
? 'system.cpu.load_average.15m'
: 'system_cpu_load_average_15m';
const netIoKey = dotMetricsEnabled ? 'system.network.io' : 'system_network_io';
const netPktsKey = dotMetricsEnabled
? 'system.network.packets'
: 'system_network_packets';
const netErrKey = dotMetricsEnabled
? 'system.network.errors'
: 'system_network_errors';
const netDropKey = dotMetricsEnabled
? 'system.network.dropped'
: 'system_network_dropped';
const netConnKey = dotMetricsEnabled
? 'system.network.connections'
: 'system_network_connections';
const diskIoKey = dotMetricsEnabled ? 'system.disk.io' : 'system_disk_io';
const diskOpTimeKey = dotMetricsEnabled
? 'system.disk.operation_time'
: 'system_disk_operation_time';
const diskOpsKey = dotMetricsEnabled
? 'system.disk.operations'
: 'system_disk_operations';
const diskPendingKey = dotMetricsEnabled
? 'system.disk.pending_operations'
: 'system_disk_pending_operations';
const fsUsageKey = dotMetricsEnabled
? 'system.filesystem.usage'
: 'system_filesystem_usage';
const hostNameKey = 'host.name';
const cpuTimeKey = 'system.cpu.time';
const memUsageKey = 'system.memory.usage';
const load1mKey = 'system.cpu.load_average.1m';
const load5mKey = 'system.cpu.load_average.5m';
const load15mKey = 'system.cpu.load_average.15m';
const netIoKey = 'system.network.io';
const netPktsKey = 'system.network.packets';
const netErrKey = 'system.network.errors';
const netDropKey = 'system.network.dropped';
const netConnKey = 'system.network.connections';
const diskIoKey = 'system.disk.io';
const diskOpTimeKey = 'system.disk.operation_time';
const diskOpsKey = 'system.disk.operations';
const diskPendingKey = 'system.disk.pending_operations';
const fsUsageKey = 'system.filesystem.usage';
return [
{

View File

@@ -21,7 +21,6 @@ export const databaseCallsRPS = ({
servicename,
legend,
tagFilterItems,
dotMetricsEnabled,
}: DatabaseCallsRPSProps): QueryBuilderData => {
const autocompleteData: BaseAutocompleteData[] = [
{
@@ -33,7 +32,7 @@ export const databaseCallsRPS = ({
const groupBy: BaseAutocompleteData[] = [
{
dataType: DataTypes.String,
key: dotMetricsEnabled ? WidgetKeys.Db_system : WidgetKeys.Db_system_norm,
key: WidgetKeys.DbSystem,
type: 'tag',
},
];
@@ -42,9 +41,7 @@ export const databaseCallsRPS = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
dataType: DataTypes.String,
type: MetricsType.Resource,
},
@@ -75,7 +72,6 @@ export const databaseCallsRPS = ({
export const databaseCallsAvgDuration = ({
servicename,
tagFilterItems,
dotMetricsEnabled,
}: DatabaseCallProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = {
key: WidgetKeys.SignozDbLatencySum,
@@ -92,9 +88,7 @@ export const databaseCallsAvgDuration = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
dataType: DataTypes.String,
type: MetricsType.Resource,
},

View File

@@ -32,7 +32,6 @@ export const externalCallErrorPercent = ({
servicename,
legend,
tagFilterItems,
dotMetricsEnabled,
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = {
key: WidgetKeys.SignozExternalCallLatencyCount,
@@ -49,9 +48,7 @@ export const externalCallErrorPercent = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
dataType: DataTypes.String,
type: MetricsType.Resource,
},
@@ -61,7 +58,7 @@ export const externalCallErrorPercent = ({
{
id: '',
key: {
key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
key: WidgetKeys.StatusCode,
dataType: DataTypes.Int64,
type: MetricsType.Tag,
},
@@ -74,9 +71,7 @@ export const externalCallErrorPercent = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
dataType: DataTypes.String,
type: MetricsType.Resource,
},
@@ -120,7 +115,6 @@ export const externalCallErrorPercent = ({
export const externalCallDuration = ({
servicename,
tagFilterItems,
dotMetricsEnabled,
}: ExternalCallProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = {
dataType: DataTypes.Float64,
@@ -141,9 +135,7 @@ export const externalCallDuration = ({
id: '',
key: {
dataType: DataTypes.String,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
type: MetricsType.Resource,
},
op: OPERATORS.IN,
@@ -183,7 +175,6 @@ export const externalCallRpsByAddress = ({
servicename,
legend,
tagFilterItems,
dotMetricsEnabled,
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
const autocompleteData: BaseAutocompleteData[] = [
{
@@ -198,9 +189,7 @@ export const externalCallRpsByAddress = ({
id: '',
key: {
dataType: DataTypes.String,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
type: MetricsType.Resource,
},
op: OPERATORS.IN,
@@ -231,7 +220,6 @@ export const externalCallDurationByAddress = ({
servicename,
legend,
tagFilterItems,
dotMetricsEnabled,
}: ExternalCallDurationByAddressProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = {
dataType: DataTypes.Float64,
@@ -251,9 +239,7 @@ export const externalCallDurationByAddress = ({
id: '',
key: {
dataType: DataTypes.String,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
type: MetricsType.Resource,
},
op: OPERATORS.IN,

View File

@@ -37,15 +37,10 @@ export const latency = ({
tagFilterItems,
isSpanMetricEnable = false,
topLevelOperationsRoute,
dotMetricsEnabled,
}: LatencyProps): QueryBuilderData => {
const signozLatencyBucketMetrics = dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm;
const signozLatencyBucketMetrics = WidgetKeys.SignozLatencyBucket;
const signozMetricsServiceName = dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm;
const signozMetricsServiceName = WidgetKeys.OTelServiceName;
const newAutoCompleteData: BaseAutocompleteData = {
key: isSpanMetricEnable
? signozLatencyBucketMetrics
@@ -287,28 +282,21 @@ export const apDexMetricsQueryBuilderQueries = ({
threashold,
delta,
metricsBuckets,
dotMetricsEnabled,
}: ApDexMetricsQueryBuilderQueriesProps): QueryBuilderData => {
const autoCompleteDataA: BaseAutocompleteData = {
key: dotMetricsEnabled
? WidgetKeys.SignozLatencyCount
: WidgetKeys.SignozLatencyCountNorm,
key: WidgetKeys.SignozLatencyCount,
dataType: DataTypes.Float64,
type: '',
};
const autoCompleteDataB: BaseAutocompleteData = {
key: dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm,
key: WidgetKeys.SignozLatencyBucket,
dataType: DataTypes.Float64,
type: '',
};
const autoCompleteDataC: BaseAutocompleteData = {
key: dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm,
key: WidgetKeys.SignozLatencyBucket,
dataType: DataTypes.Float64,
type: '',
};
@@ -317,9 +305,7 @@ export const apDexMetricsQueryBuilderQueries = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
dataType: DataTypes.String,
type: MetricsType.Tag,
},
@@ -343,7 +329,7 @@ export const apDexMetricsQueryBuilderQueries = ({
{
id: '',
key: {
key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
key: WidgetKeys.StatusCode,
dataType: DataTypes.String,
type: MetricsType.Tag,
},
@@ -363,9 +349,7 @@ export const apDexMetricsQueryBuilderQueries = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
dataType: DataTypes.String,
type: MetricsType.Tag,
},
@@ -399,7 +383,7 @@ export const apDexMetricsQueryBuilderQueries = ({
{
id: '',
key: {
key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
key: WidgetKeys.StatusCode,
dataType: DataTypes.String,
type: MetricsType.Tag,
},
@@ -409,9 +393,7 @@ export const apDexMetricsQueryBuilderQueries = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
dataType: DataTypes.String,
type: MetricsType.Tag,
},
@@ -474,13 +456,10 @@ export const operationPerSec = ({
servicename,
tagFilterItems,
topLevelOperations,
dotMetricsEnabled,
}: OperationPerSecProps): QueryBuilderData => {
const autocompleteData: BaseAutocompleteData[] = [
{
key: dotMetricsEnabled
? WidgetKeys.SignozLatencyCount
: WidgetKeys.SignozLatencyCountNorm,
key: WidgetKeys.SignozLatencyCount,
dataType: DataTypes.Float64,
type: '',
},
@@ -491,9 +470,7 @@ export const operationPerSec = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
dataType: DataTypes.String,
type: MetricsType.Resource,
},
@@ -534,7 +511,6 @@ export const errorPercentage = ({
servicename,
tagFilterItems,
topLevelOperations,
dotMetricsEnabled,
}: OperationPerSecProps): QueryBuilderData => {
const autocompleteDataA: BaseAutocompleteData = {
key: WidgetKeys.SignozCallsTotal,
@@ -553,9 +529,7 @@ export const errorPercentage = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
dataType: DataTypes.String,
type: MetricsType.Resource,
},
@@ -575,7 +549,7 @@ export const errorPercentage = ({
{
id: '',
key: {
key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
key: WidgetKeys.StatusCode,
dataType: DataTypes.Int64,
type: MetricsType.Tag,
},
@@ -589,9 +563,7 @@ export const errorPercentage = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
dataType: DataTypes.String,
type: MetricsType.Resource,
},

View File

@@ -21,12 +21,9 @@ import { getQueryBuilderQuerieswithFormula } from './MetricsPageQueriesFactory';
export const topOperationQueries = ({
servicename,
dotMetricsEnabled,
}: TopOperationQueryFactoryProps): QueryBuilderData => {
const latencyAutoCompleteData: BaseAutocompleteData = {
key: dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm,
key: WidgetKeys.SignozLatencyBucket,
dataType: DataTypes.Float64,
type: '',
};
@@ -38,9 +35,7 @@ export const topOperationQueries = ({
};
const numOfCallAutoCompleteData: BaseAutocompleteData = {
key: dotMetricsEnabled
? WidgetKeys.SignozLatencyCount
: WidgetKeys.SignozLatencyCountNorm,
key: WidgetKeys.SignozLatencyCount,
dataType: DataTypes.Float64,
type: '',
};
@@ -49,9 +44,7 @@ export const topOperationQueries = ({
{
id: '',
key: {
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
dataType: DataTypes.String,
type: MetricsType.Resource,
},
@@ -65,9 +58,7 @@ export const topOperationQueries = ({
id: '',
key: {
dataType: DataTypes.String,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
type: MetricsType.Resource,
},
op: OPERATORS.IN,
@@ -77,7 +68,7 @@ export const topOperationQueries = ({
id: '',
key: {
dataType: DataTypes.Int64,
key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
key: WidgetKeys.StatusCode,
type: MetricsType.Tag,
},
op: OPERATORS.IN,

View File

@@ -28,8 +28,6 @@ import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import {
GraphTitle,
MENU_ITEMS,
@@ -89,12 +87,7 @@ function DBCall(): JSX.Element {
[queries],
);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const legend = dotMetricsEnabled ? '{{db.system}}' : '{{db_system}}';
const legend = '{{db.system}}';
const databaseCallsRPSWidget = useMemo(
() =>
@@ -106,7 +99,6 @@ function DBCall(): JSX.Element {
servicename,
legend,
tagFilterItems,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -117,7 +109,7 @@ function DBCall(): JSX.Element {
id: SERVICE_CHART_ID.dbCallsRPS,
fillSpans: false,
}),
[servicename, tagFilterItems, dotMetricsEnabled, legend],
[servicename, tagFilterItems, legend],
);
const databaseCallsAverageDurationWidget = useMemo(
() =>
@@ -128,7 +120,6 @@ function DBCall(): JSX.Element {
builder: databaseCallsAvgDuration({
servicename,
tagFilterItems,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -139,7 +130,7 @@ function DBCall(): JSX.Element {
id: GraphTitle.DATABASE_CALLS_AVG_DURATION,
fillSpans: true,
}),
[servicename, tagFilterItems, dotMetricsEnabled],
[servicename, tagFilterItems],
);
const stepInterval = useMemo(
@@ -157,7 +148,7 @@ function DBCall(): JSX.Element {
useEffect(() => {
if (!logEventCalledRef.current) {
const selectedEnvironments = queries.find(
(val) => val.tagKey === getResourceDeploymentKeys(dotMetricsEnabled),
(val) => val.tagKey === getResourceDeploymentKeys(),
)?.tagValue;
logEvent('APM: Service detail page visited', {

View File

@@ -30,8 +30,6 @@ import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import {
GraphTitle,
legend,
@@ -84,10 +82,6 @@ function External(): JSX.Element {
handleNonInQueryRange(resourceAttributesToTagFilterItems(queries)) || [],
[queries],
);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const externalCallErrorWidget = useMemo(
() =>
@@ -99,7 +93,6 @@ function External(): JSX.Element {
servicename,
legend: legend.address,
tagFilterItems,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -109,7 +102,7 @@ function External(): JSX.Element {
yAxisUnit: '%',
id: GraphTitle.EXTERNAL_CALL_ERROR_PERCENTAGE,
}),
[servicename, tagFilterItems, dotMetricsEnabled],
[servicename, tagFilterItems],
);
const selectedTraceTags = useMemo(
@@ -126,7 +119,6 @@ function External(): JSX.Element {
builder: externalCallDuration({
servicename,
tagFilterItems,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -137,7 +129,7 @@ function External(): JSX.Element {
id: GraphTitle.EXTERNAL_CALL_DURATION,
fillSpans: true,
}),
[servicename, tagFilterItems, dotMetricsEnabled],
[servicename, tagFilterItems],
);
const errorApmToTraceQuery = useGetAPMToTracesQueries({
@@ -171,7 +163,7 @@ function External(): JSX.Element {
useEffect(() => {
if (!logEventCalledRef.current) {
const selectedEnvironments = queries.find(
(val) => val.tagKey === getResourceDeploymentKeys(dotMetricsEnabled),
(val) => val.tagKey === getResourceDeploymentKeys(),
)?.tagValue;
logEvent('APM: Service detail page visited', {
@@ -194,7 +186,6 @@ function External(): JSX.Element {
servicename,
legend: legend.address,
tagFilterItems,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -205,7 +196,7 @@ function External(): JSX.Element {
id: GraphTitle.EXTERNAL_CALL_RPS_BY_ADDRESS,
fillSpans: true,
}),
[servicename, tagFilterItems, dotMetricsEnabled],
[servicename, tagFilterItems],
);
const externalCallDurationAddressWidget = useMemo(
@@ -218,7 +209,6 @@ function External(): JSX.Element {
servicename,
legend: legend.address,
tagFilterItems,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -229,7 +219,7 @@ function External(): JSX.Element {
id: GraphTitle.EXTERNAL_CALL_DURATION_BY_ADDRESS,
fillSpans: true,
}),
[servicename, tagFilterItems, dotMetricsEnabled],
[servicename, tagFilterItems],
);
const apmToTraceQuery = useGetAPMToTracesQueries({

View File

@@ -93,15 +93,12 @@ function Application(): JSX.Element {
// eslint-disable-next-line react-hooks/exhaustive-deps
[handleSetTimeStamp],
);
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const logEventCalledRef = useRef(false);
useEffect(() => {
if (!logEventCalledRef.current) {
const selectedEnvironments = queries.find(
(val) => val.tagKey === getResourceDeploymentKeys(dotMetricsEnabled),
(val) => val.tagKey === getResourceDeploymentKeys(),
)?.tagValue;
logEvent('APM: Service detail page visited', {
@@ -159,7 +156,6 @@ function Application(): JSX.Element {
servicename,
tagFilterItems,
topLevelOperations: topLevelOperationsRoute,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -169,7 +165,7 @@ function Application(): JSX.Element {
yAxisUnit: 'ops',
id: SERVICE_CHART_ID.rps,
}),
[servicename, tagFilterItems, topLevelOperationsRoute, dotMetricsEnabled],
[servicename, tagFilterItems, topLevelOperationsRoute],
);
const errorPercentageWidget = useMemo(
@@ -182,7 +178,6 @@ function Application(): JSX.Element {
servicename,
tagFilterItems,
topLevelOperations: topLevelOperationsRoute,
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -193,7 +188,7 @@ function Application(): JSX.Element {
id: SERVICE_CHART_ID.errorPercentage,
fillSpans: true,
}),
[servicename, tagFilterItems, topLevelOperationsRoute, dotMetricsEnabled],
[servicename, tagFilterItems, topLevelOperationsRoute],
);
const stepInterval = useMemo(

View File

@@ -22,8 +22,6 @@ import { apDexMetricsQueryBuilderQueries } from 'container/MetricsApplication/Me
import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid';
import { FeatureKeys } from '../../../../../constants/features';
import { useAppContext } from '../../../../../providers/App/App';
import { IServiceName } from '../../types';
import { ApDexMetricsProps } from './types';
@@ -38,10 +36,6 @@ function ApDexMetrics({
}: ApDexMetricsProps): JSX.Element {
const { servicename: encodedServiceName } = useParams<IServiceName>();
const servicename = decodeURIComponent(encodedServiceName);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const apDexMetricsWidget = useMemo(
() =>
getWidgetQueryBuilder({
@@ -55,7 +49,6 @@ function ApDexMetrics({
threashold: thresholdValue || 0,
delta: delta || false,
metricsBuckets: metricsBuckets || [],
dotMetricsEnabled,
}),
clickhouse_sql: [],
id: uuid(),
@@ -81,7 +74,6 @@ function ApDexMetrics({
tagFilterItems,
thresholdValue,
topLevelOperationsRoute,
dotMetricsEnabled,
],
);

View File

@@ -3,8 +3,6 @@ import Spinner from 'components/Spinner';
import { useGetMetricMeta } from 'hooks/apDex/useGetMetricMeta';
import useErrorNotification from 'hooks/useErrorNotification';
import { FeatureKeys } from '../../../../../constants/features';
import { useAppContext } from '../../../../../providers/App/App';
import { WidgetKeys } from '../../../constant';
import { IServiceName } from '../../types';
import ApDexMetrics from './ApDexMetrics';
@@ -20,17 +18,8 @@ function ApDexMetricsApplication({
const { servicename: encodedServiceName } = useParams<IServiceName>();
const servicename = decodeURIComponent(encodedServiceName);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const signozLatencyBucketMetrics = dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm;
const { data, isLoading, error } = useGetMetricMeta(
signozLatencyBucketMetrics,
WidgetKeys.SignozLatencyBucket,
servicename,
);
useErrorNotification(error);

View File

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

View File

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

View File

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

View File

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

View File

@@ -32,5 +32,4 @@ export interface DatabaseCallsRPSProps extends DatabaseCallProps {
export interface DatabaseCallProps {
servicename: IServiceName['servicename'];
tagFilterItems: TagFilterItem[];
dotMetricsEnabled: boolean;
}

View File

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

View File

@@ -14,8 +14,6 @@ import { SelectOption } from 'types/common/select';
import { popupContainer } from 'utils/selectPopupContainer';
import { v4 as uuid } from 'uuid';
import { FeatureKeys } from '../../constants/features';
import { useAppContext } from '../../providers/App/App';
import QueryChip from './components/QueryChip';
import { QueryChipItem, SearchContainer } from './styles';
@@ -42,12 +40,7 @@ function ResourceAttributesFilter({
SelectOption<string, string>[]
>([]);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const resourceDeploymentKey = getResourceDeploymentKeys(dotMetricsEnabled);
const resourceDeploymentKey = getResourceDeploymentKeys();
const [selectedEnvironments, setSelectedEnvironments] = useState<string[]>([]);
@@ -73,14 +66,14 @@ function ResourceAttributesFilter({
}, [queries, resourceDeploymentKey]);
useEffect(() => {
getEnvironmentTagKeys(dotMetricsEnabled).then((tagKeys) => {
getEnvironmentTagKeys().then((tagKeys) => {
if (tagKeys && Array.isArray(tagKeys) && tagKeys.length > 0) {
getEnvironmentTagValues(dotMetricsEnabled).then((tagValues) => {
getEnvironmentTagValues().then((tagValues) => {
setEnvironments(tagValues);
});
}
});
}, [dotMetricsEnabled]);
}, []);
return (
<div className="resourceAttributesFilter-container">

View File

@@ -3,8 +3,6 @@ import {
getResourceDeploymentKeys,
} from 'hooks/useResourceAttribute/utils';
import { FeatureKeys } from '../../../../constants/features';
import { useAppContext } from '../../../../providers/App/App';
import { QueryChipContainer, QueryChipItem } from '../../styles';
import { IQueryChipProps } from './types';
@@ -13,13 +11,7 @@ function QueryChip({ queryData, onClose }: IQueryChipProps): JSX.Element {
onClose(queryData.id);
};
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const isClosable =
queryData.tagKey !== getResourceDeploymentKeys(dotMetricsEnabled);
const isClosable = queryData.tagKey !== getResourceDeploymentKeys();
return (
<QueryChipContainer>

View File

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

View File

@@ -19,13 +19,10 @@ import {
export const serviceMetricsQuery = (
topLevelOperation: [keyof ServiceDataProps, string[]],
dotMetricsEnabled: boolean,
): QueryBuilderData => {
const p99AutoCompleteData: BaseAutocompleteData = {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? WidgetKeys.Signoz_latency_bucket
: WidgetKeys.Signoz_latency_bucket_norm,
key: WidgetKeys.SignozLatencyBucket,
type: '',
};
@@ -53,9 +50,7 @@ export const serviceMetricsQuery = (
id: '',
key: {
dataType: DataTypes.String,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
type: MetricsType.Resource,
},
op: OPERATORS.IN,
@@ -78,9 +73,7 @@ export const serviceMetricsQuery = (
id: '',
key: {
dataType: DataTypes.String,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
type: MetricsType.Resource,
},
op: OPERATORS.IN,
@@ -90,7 +83,7 @@ export const serviceMetricsQuery = (
id: '',
key: {
dataType: DataTypes.Int64,
key: dotMetricsEnabled ? WidgetKeys.StatusCode : WidgetKeys.StatusCodeNorm,
key: WidgetKeys.StatusCode,
type: MetricsType.Tag,
},
op: OPERATORS.IN,
@@ -113,9 +106,7 @@ export const serviceMetricsQuery = (
id: '',
key: {
dataType: DataTypes.String,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
type: MetricsType.Resource,
},
op: OPERATORS.IN,
@@ -138,9 +129,7 @@ export const serviceMetricsQuery = (
id: '',
key: {
dataType: DataTypes.String,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
type: MetricsType.Resource,
},
op: OPERATORS.IN,
@@ -193,9 +182,7 @@ export const serviceMetricsQuery = (
const groupBy: BaseAutocompleteData[] = [
{
dataType: DataTypes.String,
key: dotMetricsEnabled
? WidgetKeys.Service_name
: WidgetKeys.Service_name_norm,
key: WidgetKeys.OTelServiceName,
type: MetricsType.Tag,
},
];

View File

@@ -17,8 +17,6 @@ import { AppState } from 'store/reducers';
import { GlobalReducer } from 'types/reducer/globalTime';
import { Tags } from 'types/reducer/trace';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import SkipOnBoardingModal from '../SkipOnBoardModal';
import ServiceTraceTable from './ServiceTracesTable';
@@ -40,11 +38,6 @@ function ServiceTraces(): JSX.Element {
selectedTags,
});
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
useErrorNotification(error);
const services = data || [];
@@ -62,7 +55,7 @@ function ServiceTraces(): JSX.Element {
useEffect(() => {
if (!logEventCalledRef.current && !isUndefined(data)) {
const selectedEnvironments = queries.find(
(val) => val.tagKey === getResourceDeploymentKeys(dotMetricsEnabled),
(val) => val.tagKey === getResourceDeploymentKeys(),
)?.tagValue;
const rps = data.reduce((total, service) => total + service.callRate, 0);

View File

@@ -26,7 +26,6 @@ export interface ServiceMetricsTableProps {
export interface GetQueryRangeRequestDataProps {
topLevelOperations: [keyof ServiceDataProps, string[]][];
globalSelectedInterval: Time | CustomTimeType;
dotMetricsEnabled: boolean;
}
export interface GetServiceListFromQueryProps {

View File

@@ -26,7 +26,6 @@ export function getSeriesValue(
export const getQueryRangeRequestData = ({
topLevelOperations,
globalSelectedInterval,
dotMetricsEnabled,
}: GetQueryRangeRequestDataProps): GetQueryResultsProps[] => {
const requestData: GetQueryResultsProps[] = [];
topLevelOperations.forEach((operation) => {
@@ -34,7 +33,7 @@ export const getQueryRangeRequestData = ({
query: {
queryType: EQueryType.QUERY_BUILDER,
promql: [],
builder: serviceMetricsQuery(operation, dotMetricsEnabled),
builder: serviceMetricsQuery(operation),
clickhouse_sql: [],
id: uuid(),
},

View File

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

View File

@@ -48,7 +48,6 @@ type IuseFetchKeysAndValues = {
export const useFetchKeysAndValues = (
searchValue: string,
query: IBuilderQuery,
dotMetricsEnabled: boolean,
searchKey: string,
shouldUseSuggestions?: boolean,
isInfraMonitoring?: boolean,

View File

@@ -6,8 +6,6 @@ import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery';
import { encode } from 'js-base64';
import { FeatureKeys } from '../../constants/features';
import { useAppContext } from '../../providers/App/App';
import { whilelistedKeys } from './config';
import { ResourceContext } from './context';
import {
@@ -58,11 +56,6 @@ 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(
(queries: IResourceAttribute[]): void => {
urlQuery.set(
@@ -78,7 +71,7 @@ function ResourceProvider({ children }: Props): JSX.Element {
const loadTagKeys = (): void => {
handleLoading(true);
GetTagKeys(dotMetricsEnabled)
GetTagKeys()
.then((tagKeys) => {
const options = mappingWithRoutesAndKeys(pathname, tagKeys);
setOptionsData({ options, mode: undefined });
@@ -161,15 +154,15 @@ function ResourceProvider({ children }: Props): JSX.Element {
setSelectedQueries([...value]);
},
[optionsData.mode, step, staging, dotMetricsEnabled, pathname],
[optionsData.mode, step, staging, pathname],
);
const handleEnvironmentChange = useCallback(
(environments: string[]): void => {
const staging = [getResourceDeploymentKeys(dotMetricsEnabled), 'IN'];
const staging = [getResourceDeploymentKeys(), 'IN'];
const queriesCopy = queries.filter(
(query) => query.tagKey !== getResourceDeploymentKeys(dotMetricsEnabled),
(query) => query.tagKey !== getResourceDeploymentKeys(),
);
if (environments && Array.isArray(environments) && environments.length > 0) {
@@ -184,7 +177,7 @@ function ResourceProvider({ children }: Props): JSX.Element {
setStep('Idle');
},
[dispatchQueries, dotMetricsEnabled, queries],
[dispatchQueries, queries],
);
const handleClose = useCallback(

View File

@@ -2,13 +2,9 @@ import { ReactNode } from 'react';
import { QueryClient, QueryClientProvider } from 'react-query';
import { Router } from 'react-router-dom';
import { act, renderHook, waitFor } from '@testing-library/react';
import { FeatureKeys } from 'constants/features';
import ROUTES from 'constants/routes';
import { createMemoryHistory, MemoryHistory } from 'history';
import { encode } from 'js-base64';
import { AppContext } from 'providers/App/App';
import { IAppContext } from 'providers/App/types';
import { getAppContextMock } from 'tests/test-utils';
import ResourceProvider from '../ResourceProvider';
import useResourceAttribute from '../useResourceAttribute';
@@ -55,10 +51,8 @@ const mockTagValues = getResourceAttributesTagValues as jest.MockedFunction<
function createWrapper({
routerHistory,
appContextOverrides,
}: {
routerHistory: MemoryHistory;
appContextOverrides?: Partial<IAppContext>;
}): ({ children }: { children: ReactNode }) => JSX.Element {
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
@@ -66,13 +60,9 @@ function createWrapper({
return function Wrapper({ children }: { children: ReactNode }): JSX.Element {
return (
<QueryClientProvider client={queryClient}>
<AppContext.Provider
value={getAppContextMock('ADMIN', appContextOverrides)}
>
<Router history={routerHistory}>
<ResourceProvider>{children}</ResourceProvider>
</Router>
</AppContext.Provider>
<Router history={routerHistory}>
<ResourceProvider>{children}</ResourceProvider>
</Router>
</QueryClientProvider>
);
};
@@ -411,7 +401,7 @@ describe('ResourceProvider', () => {
});
describe('handleEnvironmentChange', () => {
it('adds an environment query when envs are provided', async () => {
it('adds a dotted environment query when envs are provided', async () => {
const routerHistory = createMemoryHistory({ initialEntries: ['/'] });
const { result } = renderHook(() => useResourceAttribute(), {
wrapper: createWrapper({ routerHistory }),
@@ -424,7 +414,7 @@ describe('ResourceProvider', () => {
await waitFor(() => {
expect(result.current.queries).toHaveLength(1);
expect(result.current.queries[0]).toMatchObject({
tagKey: 'resource_deployment_environment',
tagKey: 'resource_deployment.environment',
operator: 'IN',
tagValue: ['production'],
});
@@ -435,7 +425,7 @@ describe('ResourceProvider', () => {
const seeded = [
{
id: 'env',
tagKey: 'resource_deployment_environment',
tagKey: 'resource_deployment.environment',
operator: 'IN',
tagValue: ['production'],
},
@@ -459,7 +449,7 @@ describe('ResourceProvider', () => {
await waitFor(() => {
const tagKeys = result.current.queries.map((q) => q.tagKey);
expect(tagKeys).not.toContain('resource_deployment_environment');
expect(tagKeys).not.toContain('resource_deployment.environment');
expect(tagKeys).toContain('resource_service_name');
});
});
@@ -468,7 +458,7 @@ describe('ResourceProvider', () => {
const seeded = [
{
id: 'env',
tagKey: 'resource_deployment_environment',
tagKey: 'resource_deployment.environment',
operator: 'IN',
tagValue: ['production'],
},
@@ -486,43 +476,13 @@ describe('ResourceProvider', () => {
await waitFor(() => {
const envQueries = result.current.queries.filter(
(q) => q.tagKey === 'resource_deployment_environment',
(q) => q.tagKey === 'resource_deployment.environment',
);
expect(envQueries).toHaveLength(1);
expect(envQueries[0].tagValue).toStrictEqual(['staging']);
});
});
it('uses the dotted deployment env key when DOT_METRICS_ENABLED is active', async () => {
const routerHistory = createMemoryHistory({ initialEntries: ['/'] });
const { result } = renderHook(() => useResourceAttribute(), {
wrapper: createWrapper({
routerHistory,
appContextOverrides: {
featureFlags: [
{
name: FeatureKeys.DOT_METRICS_ENABLED,
active: true,
usage: 0,
usage_limit: -1,
route: '',
},
],
},
}),
});
act(() => {
result.current.handleEnvironmentChange(['production']);
});
await waitFor(() => {
expect(result.current.queries[0].tagKey).toBe(
'resource_deployment.environment',
);
});
});
it('preserves unrelated query params when dispatching', async () => {
const routerHistory = createMemoryHistory({
initialEntries: ['/?tab=overview'],

View File

@@ -5,13 +5,13 @@ import { mappingWithRoutesAndKeys } from '../utils';
describe('useResourceAttribute config', () => {
describe('whilelistedKeys', () => {
it('should include underscore-notation keys (DOT_METRICS_ENABLED=false)', () => {
it('should include underscore-notation keys', () => {
expect(whilelistedKeys).toContain('resource_deployment_environment');
expect(whilelistedKeys).toContain('resource_k8s_cluster_name');
expect(whilelistedKeys).toContain('resource_k8s_cluster_namespace');
});
it('should include dot-notation keys (DOT_METRICS_ENABLED=true)', () => {
it('should include dot-notation keys', () => {
expect(whilelistedKeys).toContain('resource_deployment.environment');
expect(whilelistedKeys).toContain('resource_k8s.cluster.name');
expect(whilelistedKeys).toContain('resource_k8s.cluster.namespace');

View File

@@ -144,19 +144,11 @@ export const OperatorSchema: IOption[] = OperatorConversions.map(
}),
);
export const getResourceDeploymentKeys = (
dotMetricsEnabled: boolean,
): string => {
if (dotMetricsEnabled) {
return 'resource_deployment.environment';
}
return 'resource_deployment_environment';
};
export const getResourceDeploymentKeys = (): string =>
'resource_deployment.environment';
export const GetTagKeys = async (
dotMetricsEnabled: boolean,
): Promise<IOption[]> => {
const resourceDeploymentKey = getResourceDeploymentKeys(dotMetricsEnabled);
export const GetTagKeys = async (): Promise<IOption[]> => {
const resourceDeploymentKey = getResourceDeploymentKeys();
const { payload } = await getResourceAttributesTagKeys({
metricName: 'signoz_calls_total',
match: 'resource_',
@@ -176,12 +168,10 @@ export const GetTagKeys = async (
}));
};
export const getEnvironmentTagKeys = async (
dotMetricsEnabled: boolean,
): Promise<IOption[]> => {
export const getEnvironmentTagKeys = async (): Promise<IOption[]> => {
const { payload } = await getResourceAttributesTagKeys({
metricName: 'signoz_calls_total',
match: getResourceDeploymentKeys(dotMetricsEnabled),
match: getResourceDeploymentKeys(),
});
if (!payload || !payload?.data) {
return [];
@@ -194,11 +184,9 @@ export const getEnvironmentTagKeys = async (
}));
};
export const getEnvironmentTagValues = async (
dotMetricsEnabled: boolean,
): Promise<IOption[]> => {
export const getEnvironmentTagValues = async (): Promise<IOption[]> => {
const { payload } = await getResourceAttributesTagValues({
tagKey: getResourceDeploymentKeys(dotMetricsEnabled),
tagKey: getResourceDeploymentKeys(),
metricName: 'signoz_calls_total',
});

View File

@@ -4,8 +4,6 @@ import { CardContainer } from 'container/GridCardLayout/styles';
import { useIsDarkMode } from 'hooks/useDarkMode';
import { Widgets } from 'types/api/dashboard/getAll';
import { FeatureKeys } from '../../../../constants/features';
import { useAppContext } from '../../../../providers/App/App';
import MetricPageGridGraph from './MetricPageGraph';
import {
getAverageRequestLatencyWidgetData,
@@ -73,20 +71,15 @@ function MetricColumnGraphs({
}): JSX.Element {
const { t } = useTranslation('messagingQueues');
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const metricsData = [
{
title: t('metricGraphCategory.brokerMetrics.title'),
description: t('metricGraphCategory.brokerMetrics.description'),
graphCount: [
getBrokerCountWidgetData(dotMetricsEnabled),
getRequestTimesWidgetData(dotMetricsEnabled),
getProducerFetchRequestPurgatoryWidgetData(dotMetricsEnabled),
getBrokerNetworkThroughputWidgetData(dotMetricsEnabled),
getBrokerCountWidgetData(),
getRequestTimesWidgetData(),
getProducerFetchRequestPurgatoryWidgetData(),
getBrokerNetworkThroughputWidgetData(),
],
id: 'broker-metrics',
},
@@ -94,11 +87,11 @@ function MetricColumnGraphs({
title: t('metricGraphCategory.producerMetrics.title'),
description: t('metricGraphCategory.producerMetrics.description'),
graphCount: [
getIoWaitTimeWidgetData(dotMetricsEnabled),
getRequestResponseWidgetData(dotMetricsEnabled),
getAverageRequestLatencyWidgetData(dotMetricsEnabled),
getKafkaProducerByteRateWidgetData(dotMetricsEnabled),
getBytesConsumedWidgetData(dotMetricsEnabled),
getIoWaitTimeWidgetData(),
getRequestResponseWidgetData(),
getAverageRequestLatencyWidgetData(),
getKafkaProducerByteRateWidgetData(),
getBytesConsumedWidgetData(),
],
id: 'producer-metrics',
},
@@ -106,11 +99,11 @@ function MetricColumnGraphs({
title: t('metricGraphCategory.consumerMetrics.title'),
description: t('metricGraphCategory.consumerMetrics.description'),
graphCount: [
getConsumerOffsetWidgetData(dotMetricsEnabled),
getConsumerGroupMemberWidgetData(dotMetricsEnabled),
getConsumerLagByGroupWidgetData(dotMetricsEnabled),
getConsumerFetchRateWidgetData(dotMetricsEnabled),
getMessagesConsumedWidgetData(dotMetricsEnabled),
getConsumerOffsetWidgetData(),
getConsumerGroupMemberWidgetData(),
getConsumerLagByGroupWidgetData(),
getConsumerFetchRateWidgetData(),
getMessagesConsumedWidgetData(),
],
id: 'consumer-metrics',
},

View File

@@ -8,8 +8,6 @@ import { useIsDarkMode } from 'hooks/useDarkMode';
import { ChevronDown, ChevronUp } from '@signozhq/icons';
import { Widgets } from 'types/api/dashboard/getAll';
import { FeatureKeys } from '../../../../constants/features';
import { useAppContext } from '../../../../providers/App/App';
import MetricColumnGraphs from './MetricColumnGraphs';
import MetricPageGridGraph from './MetricPageGraph';
import {
@@ -97,11 +95,6 @@ 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 metricSections = [
@@ -110,10 +103,10 @@ function MetricPage(): JSX.Element {
title: t('metricGraphCategory.brokerJVMMetrics.title'),
description: t('metricGraphCategory.brokerJVMMetrics.description'),
graphCount: [
getJvmGCCountWidgetData(dotMetricsEnabled),
getJvmGcCollectionsElapsedWidgetData(dotMetricsEnabled),
getCpuRecentUtilizationWidgetData(dotMetricsEnabled),
getJvmMemoryHeapWidgetData(dotMetricsEnabled),
getJvmGCCountWidgetData(),
getJvmGcCollectionsElapsedWidgetData(),
getCpuRecentUtilizationWidgetData(),
getJvmMemoryHeapWidgetData(),
],
},
{
@@ -121,10 +114,10 @@ function MetricPage(): JSX.Element {
title: t('metricGraphCategory.partitionMetrics.title'),
description: t('metricGraphCategory.partitionMetrics.description'),
graphCount: [
getPartitionCountPerTopicWidgetData(dotMetricsEnabled),
getCurrentOffsetPartitionWidgetData(dotMetricsEnabled),
getOldestOffsetWidgetData(dotMetricsEnabled),
getInsyncReplicasWidgetData(dotMetricsEnabled),
getPartitionCountPerTopicWidgetData(),
getCurrentOffsetPartitionWidgetData(),
getOldestOffsetWidgetData(),
getInsyncReplicasWidgetData(),
],
},
];
@@ -138,7 +131,7 @@ function MetricPage(): JSX.Element {
// Only log when first graph has rendered and we haven't logged yet
if (renderedGraphCountRef.current === 1 && !hasLoggedRef.current) {
logEvent('MQ Kafka: Metric view', {
void logEvent('MQ Kafka: Metric view', {
graphRendered: true,
});
hasLoggedRef.current = true;

View File

@@ -78,21 +78,15 @@ export function getWidgetQuery(
};
}
export const getRequestTimesWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getRequestTimesWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
// choose key based on flag
key: dotMetricsEnabled
? 'kafka.request.time.avg'
: 'kafka_request_time_avg',
// mirror into the id as well
id: 'kafka_request_time_avg--float64--Gauge--true',
key: 'kafka.request.time.avg',
id: 'kafka.request.time.avg--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -122,15 +116,15 @@ export const getRequestTimesWidgetData = (
}),
);
export const getBrokerCountWidgetData = (dotMetricsEnabled: boolean): Widgets =>
export const getBrokerCountWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled ? 'kafka.brokers' : 'kafka_brokers',
id: 'kafka_brokers--float64--Gauge--true',
key: 'kafka.brokers',
id: 'kafka.brokers--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'sum',
@@ -156,20 +150,15 @@ export const getBrokerCountWidgetData = (dotMetricsEnabled: boolean): Widgets =>
}),
);
export const getProducerFetchRequestPurgatoryWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getProducerFetchRequestPurgatoryWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
// inline ternary based on dotMetricsEnabled
key: dotMetricsEnabled ? 'kafka.purgatory.size' : 'kafka_purgatory_size',
id: `${
dotMetricsEnabled ? 'kafka.purgatory.size' : 'kafka_purgatory_size'
}--float64--Gauge--true`,
key: 'kafka.purgatory.size',
id: 'kafka.purgatory.size--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -196,24 +185,15 @@ export const getProducerFetchRequestPurgatoryWidgetData = (
}),
);
export const getBrokerNetworkThroughputWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getBrokerNetworkThroughputWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
// inline ternary based on dotMetricsEnabled
key: dotMetricsEnabled
? 'kafka_server_brokertopicmetrics_total_replicationbytesinpersec_oneminuterate'
: 'kafka_server_brokertopicmetrics_bytesoutpersec_oneminuterate',
id: `${
dotMetricsEnabled
? 'kafka_server_brokertopicmetrics_total_replicationbytesinpersec_oneminuterate'
: 'kafka_server_brokertopicmetrics_bytesoutpersec_oneminuterate'
}--float64--Gauge--true`,
key: 'kafka_server_brokertopicmetrics_total_replicationbytesinpersec_oneminuterate',
id: 'kafka_server_brokertopicmetrics_total_replicationbytesinpersec_oneminuterate--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -240,22 +220,15 @@ export const getBrokerNetworkThroughputWidgetData = (
}),
);
export const getIoWaitTimeWidgetData = (dotMetricsEnabled: boolean): Widgets =>
export const getIoWaitTimeWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
// inline ternary based on dotMetricsEnabled
key: dotMetricsEnabled
? 'kafka.producer.io_waittime_total'
: 'kafka_producer_io_waittime_total',
id: `${
dotMetricsEnabled
? 'kafka.producer.io_waittime_total'
: 'kafka_producer_io_waittime_total'
}--float64--Sum--true`,
key: 'kafka.producer.io_waittime_total',
id: 'kafka.producer.io_waittime_total--float64--Sum--true',
type: 'Sum',
},
aggregateOperator: 'rate',
@@ -282,23 +255,15 @@ export const getIoWaitTimeWidgetData = (dotMetricsEnabled: boolean): Widgets =>
}),
);
export const getRequestResponseWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getRequestResponseWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'kafka.producer.request_rate'
: 'kafka_producer_request_rate',
id: `${
dotMetricsEnabled
? 'kafka.producer.request_rate'
: 'kafka_producer_request_rate'
}--float64--Gauge--true`,
key: 'kafka.producer.request_rate',
id: 'kafka.producer.request_rate--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -321,14 +286,8 @@ export const getRequestResponseWidgetData = (
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'kafka.producer.response_rate'
: 'kafka_producer_response_rate',
id: `${
dotMetricsEnabled
? 'kafka.producer.response_rate'
: 'kafka_producer_response_rate'
}--float64--Gauge--true`,
key: 'kafka.producer.response_rate',
id: 'kafka.producer.response_rate--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -355,23 +314,15 @@ export const getRequestResponseWidgetData = (
}),
);
export const getAverageRequestLatencyWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getAverageRequestLatencyWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'kafka.producer.request_latency_avg'
: 'kafka_producer_request_latency_avg',
id: `${
dotMetricsEnabled
? 'kafka.producer.request_latency_avg'
: 'kafka_producer_request_latency_avg'
}--float64--Gauge--true`,
key: 'kafka.producer.request_latency_avg',
id: 'kafka.producer.request_latency_avg--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -398,23 +349,15 @@ export const getAverageRequestLatencyWidgetData = (
}),
);
export const getKafkaProducerByteRateWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getKafkaProducerByteRateWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'kafka.producer.byte_rate'
: 'kafka_producer_byte_rate',
id: `${
dotMetricsEnabled
? 'kafka.producer.byte_rate'
: 'kafka_producer_byte_rate'
}--float64--Gauge--true`,
key: 'kafka.producer.byte_rate',
id: 'kafka.producer.byte_rate--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -442,31 +385,21 @@ export const getKafkaProducerByteRateWidgetData = (
timeAggregation: 'avg',
},
],
title: dotMetricsEnabled
? 'kafka.producer.byte_rate'
: 'kafka_producer_byte_rate',
title: 'kafka.producer.byte_rate',
description:
'Helps measure the data output rate from the producer, indicating the load a producer is placing on Kafka brokers.',
}),
);
export const getBytesConsumedWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getBytesConsumedWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'kafka.consumer.bytes_consumed_rate'
: 'kafka_consumer_bytes_consumed_rate',
id: `${
dotMetricsEnabled
? 'kafka.consumer.bytes_consumed_rate'
: 'kafka_consumer_bytes_consumed_rate'
}--float64--Gauge--true`,
key: 'kafka.consumer.bytes_consumed_rate',
id: 'kafka.consumer.bytes_consumed_rate--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -494,23 +427,15 @@ export const getBytesConsumedWidgetData = (
}),
);
export const getConsumerOffsetWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getConsumerOffsetWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'kafka.consumer_group.offset'
: 'kafka_consumer_group_offset',
id: `${
dotMetricsEnabled
? 'kafka.consumer_group.offset'
: 'kafka_consumer_group_offset'
}--float64--Gauge--true`,
key: 'kafka.consumer_group.offset',
id: 'kafka.consumer_group.offset--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -556,23 +481,15 @@ export const getConsumerOffsetWidgetData = (
}),
);
export const getConsumerGroupMemberWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getConsumerGroupMemberWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'kafka.consumer_group.members'
: 'kafka_consumer_group_members',
id: `${
dotMetricsEnabled
? 'kafka.consumer_group.members'
: 'kafka_consumer_group_members'
}--float64--Gauge--true`,
key: 'kafka.consumer_group.members',
id: 'kafka.consumer_group.members--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'sum',
@@ -605,23 +522,15 @@ export const getConsumerGroupMemberWidgetData = (
}),
);
export const getConsumerLagByGroupWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getConsumerLagByGroupWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'kafka.consumer_group.lag'
: 'kafka_consumer_group_lag',
id: `${
dotMetricsEnabled
? 'kafka.consumer_group.lag'
: 'kafka_consumer_group_lag'
}--float64--Gauge--true`,
key: 'kafka.consumer_group.lag',
id: 'kafka.consumer_group.lag--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -667,23 +576,15 @@ export const getConsumerLagByGroupWidgetData = (
}),
);
export const getConsumerFetchRateWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getConsumerFetchRateWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'kafka.consumer.fetch_rate'
: 'kafka_consumer_fetch_rate',
id: `${
dotMetricsEnabled
? 'kafka.consumer.fetch_rate'
: 'kafka_consumer_fetch_rate'
}--float64--Gauge--true`,
key: 'kafka.consumer.fetch_rate',
id: 'kafka.consumer.fetch_rate--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -696,7 +597,7 @@ export const getConsumerFetchRateWidgetData = (
{
dataType: DataTypes.String,
id: 'service_name--string--tag--false',
key: dotMetricsEnabled ? 'service.name' : 'service_name',
key: 'service.name',
type: 'tag',
},
],
@@ -717,23 +618,15 @@ export const getConsumerFetchRateWidgetData = (
}),
);
export const getMessagesConsumedWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getMessagesConsumedWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'kafka.consumer.records_consumed_rate'
: 'kafka_consumer_records_consumed_rate',
id: `${
dotMetricsEnabled
? 'kafka.consumer.records_consumed_rate'
: 'kafka_consumer_records_consumed_rate'
}--float64--Gauge--true`,
key: 'kafka.consumer.records_consumed_rate',
id: 'kafka.consumer.records_consumed_rate--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -760,21 +653,15 @@ export const getMessagesConsumedWidgetData = (
}),
);
export const getJvmGCCountWidgetData = (dotMetricsEnabled: boolean): Widgets =>
export const getJvmGCCountWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'jvm.gc.collections.count'
: 'jvm_gc_collections_count',
id: `${
dotMetricsEnabled
? 'jvm.gc.collections.count'
: 'jvm_gc_collections_count'
}--float64--Sum--true`,
key: 'jvm.gc.collections.count',
id: 'jvm.gc.collections.count--float64--Sum--true',
type: 'Sum',
},
aggregateOperator: 'rate',
@@ -801,23 +688,15 @@ export const getJvmGCCountWidgetData = (dotMetricsEnabled: boolean): Widgets =>
}),
);
export const getJvmGcCollectionsElapsedWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getJvmGcCollectionsElapsedWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'jvm.gc.collections.elapsed'
: 'jvm_gc_collections_elapsed',
id: `${
dotMetricsEnabled
? 'jvm.gc.collections.elapsed'
: 'jvm_gc_collections_elapsed'
}--float64--Sum--true`,
key: 'jvm.gc.collections.elapsed',
id: 'jvm.gc.collections.elapsed--float64--Sum--true',
type: 'Sum',
},
aggregateOperator: 'rate',
@@ -838,31 +717,21 @@ export const getJvmGcCollectionsElapsedWidgetData = (
timeAggregation: 'rate',
},
],
title: dotMetricsEnabled
? 'jvm.gc.collections.elapsed'
: 'jvm_gc_collections_elapsed',
title: 'jvm.gc.collections.elapsed',
description:
'Measures the total time (usually in milliseconds) spent on garbage collection (GC) events in the Java Virtual Machine (JVM).',
}),
);
export const getCpuRecentUtilizationWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getCpuRecentUtilizationWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'jvm.cpu.recent_utilization'
: 'jvm_cpu_recent_utilization',
id: `${
dotMetricsEnabled
? 'jvm.cpu.recent_utilization'
: 'jvm_cpu_recent_utilization'
}--float64--Gauge--true`,
key: 'jvm.cpu.recent_utilization',
id: 'jvm.cpu.recent_utilization--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -889,19 +758,15 @@ export const getCpuRecentUtilizationWidgetData = (
}),
);
export const getJvmMemoryHeapWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getJvmMemoryHeapWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled ? 'jvm.memory.heap.max' : 'jvm_memory_heap_max',
id: `${
dotMetricsEnabled ? 'jvm.memory.heap.max' : 'jvm_memory_heap_max'
}--float64--Gauge--true`,
key: 'jvm.memory.heap.max',
id: 'jvm.memory.heap.max--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -928,21 +793,15 @@ export const getJvmMemoryHeapWidgetData = (
}),
);
export const getPartitionCountPerTopicWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getPartitionCountPerTopicWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'kafka.topic.partitions'
: 'kafka_topic_partitions',
id: `${
dotMetricsEnabled ? 'kafka.topic.partitions' : 'kafka_topic_partitions'
}--float64--Gauge--true`,
key: 'kafka.topic.partitions',
id: 'kafka.topic.partitions--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'sum',
@@ -975,23 +834,15 @@ export const getPartitionCountPerTopicWidgetData = (
}),
);
export const getCurrentOffsetPartitionWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getCurrentOffsetPartitionWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'kafka.partition.current_offset'
: 'kafka_partition_current_offset',
id: `${
dotMetricsEnabled
? 'kafka.partition.current_offset'
: 'kafka_partition_current_offset'
}--float64--Gauge--true`,
key: 'kafka.partition.current_offset',
id: 'kafka.partition.current_offset--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -1031,23 +882,15 @@ export const getCurrentOffsetPartitionWidgetData = (
}),
);
export const getOldestOffsetWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getOldestOffsetWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'kafka.partition.oldest_offset'
: 'kafka_partition_oldest_offset',
id: `${
dotMetricsEnabled
? 'kafka.partition.oldest_offset'
: 'kafka_partition_oldest_offset'
}--float64--Gauge--true`,
key: 'kafka.partition.oldest_offset',
id: 'kafka.partition.oldest_offset--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',
@@ -1087,23 +930,15 @@ export const getOldestOffsetWidgetData = (
}),
);
export const getInsyncReplicasWidgetData = (
dotMetricsEnabled: boolean,
): Widgets =>
export const getInsyncReplicasWidgetData = (): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
key: dotMetricsEnabled
? 'kafka.partition.replicas_in_sync'
: 'kafka_partition_replicas_in_sync',
id: `${
dotMetricsEnabled
? 'kafka.partition.replicas_in_sync'
: 'kafka_partition_replicas_in_sync'
}--float64--Gauge--true`,
key: 'kafka.partition.replicas_in_sync',
id: 'kafka.partition.replicas_in_sync--float64--Gauge--true',
type: 'Gauge',
},
aggregateOperator: 'avg',

View File

@@ -11,8 +11,6 @@ import useDebouncedFn from 'hooks/useDebouncedFunction';
import useUrlQuery from 'hooks/useUrlQuery';
import { Check, Share2 } from '@signozhq/icons';
import { FeatureKeys } from '../../../constants/features';
import { useAppContext } from '../../../providers/App/App';
import { useGetAllConfigOptions } from './useGetAllConfigOptions';
import './MQConfigOptions.styles.scss';
@@ -40,19 +38,11 @@ const useConfigOptions = (
isFetching: boolean;
options: DefaultOptionType[];
} => {
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const [searchText, setSearchText] = useState<string>('');
const { isFetching, options } = useGetAllConfigOptions(
{
attributeKey: type,
searchText,
},
dotMetricsEnabled,
);
const { isFetching, options } = useGetAllConfigOptions({
attributeKey: type,
searchText,
});
const handleDebouncedSearch = useDebouncedFn((searchText): void => {
setSearchText(searchText as string);
}, 500);

View File

@@ -3,7 +3,6 @@ import { useCallback, useMemo, useRef } from 'react';
import { useDispatch } from 'react-redux';
import { useHistory, useLocation } from 'react-router-dom';
import logEvent from 'api/common/logEvent';
import { FeatureKeys } from 'constants/features';
import { QueryParams } from 'constants/query';
import { PANEL_TYPES } from 'constants/queryBuilder';
import { ViewMenuAction } from 'container/GridCardLayout/config';
@@ -12,7 +11,6 @@ import { Card } from 'container/GridCardLayout/styles';
import { getWidgetQueryBuilder } from 'container/MetricsApplication/MetricsApplication.factory';
import { useIsDarkMode } from 'hooks/useDarkMode';
import useUrlQuery from 'hooks/useUrlQuery';
import { useAppContext } from 'providers/App/App';
import { UpdateTimeInterval } from 'store/actions';
import {
@@ -34,15 +32,9 @@ function MessagingQueuesGraph(): JSX.Element {
[consumerGrp, topic, partition],
);
const { featureFlags } = useAppContext();
const dotMetricsEnabled =
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
?.active || false;
const widgetData = useMemo(
() =>
getWidgetQueryBuilder(getWidgetQuery({ filterItems, dotMetricsEnabled })),
[filterItems, dotMetricsEnabled],
() => getWidgetQueryBuilder(getWidgetQuery({ filterItems })),
[filterItems],
);
const history = useHistory();
@@ -81,7 +73,7 @@ function MessagingQueuesGraph(): JSX.Element {
const checkIfDataExists = (isDataAvailable: boolean): void => {
if (!isLogEventCalled.current) {
isLogEventCalled.current = true;
logEvent('Messaging Queues: Graph data fetched', {
void logEvent('Messaging Queues: Graph data fetched', {
isDataAvailable,
});
}

View File

@@ -16,7 +16,6 @@ export interface GetAllConfigOptionsResponse {
export function useGetAllConfigOptions(
props: ConfigOptions,
dotMetricsEnabled: boolean,
): GetAllConfigOptionsResponse {
const { attributeKey, searchText } = props;
@@ -26,9 +25,7 @@ export function useGetAllConfigOptions(
const { payload } = await getAttributesValues({
aggregateOperator: 'avg',
dataSource: DataSource.METRICS,
aggregateAttribute: dotMetricsEnabled
? 'kafka.consumer_group.lag'
: 'kafka_consumer_group_lag',
aggregateAttribute: 'kafka.consumer_group.lag',
attributeKey,
searchText: searchText ?? '',
filterAttributeKeyDataType: DataTypes.String,

View File

@@ -94,10 +94,8 @@ export function getFiltersFromConfigOptions(
export function getWidgetQuery({
filterItems,
dotMetricsEnabled,
}: {
filterItems: TagFilterItem[];
dotMetricsEnabled: boolean;
}): GetWidgetQueryBuilderProps {
return {
title: 'Consumer Lag',
@@ -112,14 +110,8 @@ export function getWidgetQuery({
{
aggregateAttribute: {
dataType: DataTypes.Float64,
id: `${
dotMetricsEnabled
? 'kafka.consumer_group.lag'
: 'kafka_consumer_group_lag'
}--float64--Gauge--true`,
key: dotMetricsEnabled
? 'kafka.consumer_group.lag'
: 'kafka_consumer_group_lag',
id: 'kafka.consumer_group.lag--float64--Gauge--true',
key: 'kafka.consumer_group.lag',
type: 'Gauge',
},
aggregateOperator: 'max',

View File

@@ -3190,11 +3190,6 @@ func (r *ClickHouseReader) GetMetricAttributeValues(ctx context.Context, orgID v
var rows driver.Rows
var attributeValues v3.FilterAttributeValueResponse
normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
reductionEnabled := r.fl.BooleanOrEmpty(ctx, flagger.FeatureEnableMetricsReduction, featuretypes.NewFlaggerEvaluationContext(orgID))
if reductionEnabled {
@@ -3206,7 +3201,7 @@ func (r *ClickHouseReader) GetMetricAttributeValues(ctx context.Context, orgID v
query = query + fmt.Sprintf(" LIMIT %d;", req.Limit)
}
names := []string{req.AggregateAttribute}
names = append(names, metrics.GetTransitionedMetric(req.AggregateAttribute, normalized))
names = append(names, metrics.GetTransitionedMetric(req.AggregateAttribute))
rows, err = r.db.Query(ctx, query, req.FilterAttributeKey, names, req.FilterAttributeKey, fmt.Sprintf("%%%s%%", req.SearchText), common.PastDayRoundOff())
@@ -5448,112 +5443,3 @@ func (r *ClickHouseReader) SearchTraces(ctx context.Context, params *model.Searc
return &searchSpansResult, nil
}
func (r *ClickHouseReader) GetNormalizedStatus(
ctx context.Context,
orgID valuer.UUID,
metricNames []string,
) (map[string]bool, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetNormalizedStatus",
})
if len(metricNames) == 0 {
return map[string]bool{}, nil
}
result := make(map[string]bool, len(metricNames))
buildKey := func(name string) string {
return constants.NormalizedMetricsMapCacheKey + ":" + name
}
uncached := make([]string, 0, len(metricNames))
for _, m := range metricNames {
var status model.MetricsNormalizedMap
if err := r.cache.Get(ctx, orgID, buildKey(m), &status); err == nil {
result[m] = status.IsUnNormalized
} else {
uncached = append(uncached, m)
}
}
if len(uncached) == 0 {
return result, nil
}
placeholders := "'" + strings.Join(uncached, "', '") + "'"
reductionEnabled := r.fl.BooleanOrEmpty(ctx, flagger.FeatureEnableMetricsReduction, featuretypes.NewFlaggerEvaluationContext(orgID))
var q string
if reductionEnabled {
q = fmt.Sprintf(
`SELECT metric_name, toUInt8(__normalized)
FROM (
SELECT metric_name, __normalized FROM %s.%s WHERE metric_name IN (%s)
UNION ALL
SELECT metric_name, __normalized FROM %s.%s WHERE metric_name IN (%s)
)
GROUP BY metric_name, __normalized`,
signozMetricDBName, signozTSTableNameV41Day, placeholders,
signozMetricDBName, signozTSTableNameV4Reduced, placeholders,
)
} else {
q = fmt.Sprintf(
`SELECT metric_name, toUInt8(__normalized)
FROM %s.%s
WHERE metric_name IN (%s)
GROUP BY metric_name, __normalized`,
signozMetricDBName, signozTSTableNameV41Day, placeholders,
)
}
rows, err := r.db.Query(ctx, q)
if err != nil {
return nil, err
}
defer rows.Close()
// tmp[m] collects the set {0,1} for a metric name, truth table
tmp := make(map[string]map[uint8]struct{}, len(uncached))
for rows.Next() {
var (
name string
normalized uint8
)
if err := rows.Scan(&name, &normalized); err != nil {
return nil, err
}
if _, ok := tmp[name]; !ok {
tmp[name] = make(map[uint8]struct{}, 2)
}
tmp[name][normalized] = struct{}{}
}
if err := rows.Err(); err != nil {
return nil, err
}
for _, m := range uncached {
set := tmp[m]
switch {
case len(set) == 0:
return nil, fmt.Errorf("metric %q not found in ClickHouse", m)
case len(set) == 2:
result[m] = true
default:
_, hasUnnorm := set[0]
result[m] = hasUnnorm
}
status := model.MetricsNormalizedMap{
MetricName: m,
IsUnNormalized: result[m],
}
_ = r.cache.Set(ctx, orgID, buildKey(m), &status, 0)
}
return result, nil
}

View File

@@ -56,7 +56,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/app/queryBuilder"
tracesV3 "github.com/SigNoz/signoz/pkg/query-service/app/traces/v3"
tracesV4 "github.com/SigNoz/signoz/pkg/query-service/app/traces/v4"
"github.com/SigNoz/signoz/pkg/query-service/constants"
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/types"
@@ -1052,10 +1051,6 @@ func prepareQuery(r *http.Request) (string, error) {
return "", tmplErr
}
if !constants.IsDotMetricsEnabled {
return queryBuf.String(), nil
}
query = queryBuf.String()
// Now handle $var replacements (simple string replace)
@@ -1608,13 +1603,6 @@ func (aH *APIHandler) getFeatureFlags(w http.ResponseWriter, r *http.Request) {
Route: "",
})
if constants.IsDotMetricsEnabled {
for idx, feature := range featureSet {
if feature.Name == licensetypes.DotMetricsEnabled {
featureSet[idx].Active = true
}
}
}
aH.Respond(w, featureSet)
}
@@ -2055,12 +2043,8 @@ 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"
}
var kafkaConsumerFetchLatencyAvg string = "kafka.consumer.fetch_latency_avg"
var kafkaConsumerLag string = "kafka.consumer_group.lag"
if !fetchLatencyState && !consumerLagState {
entries = append(entries, kafka.OnboardingResponse{

View File

@@ -18,12 +18,12 @@ import (
)
var (
metricToUseForClusters = GetDotMetrics("k8s_node_cpu_usage")
metricToUseForClusters = "k8s.node.cpu.usage"
clusterAttrsToEnrich = []string{GetDotMetrics("k8s_cluster_name")}
clusterAttrsToEnrich = []string{"k8s.cluster.name"}
// TODO(srikanthccv): change this to k8s_cluster_uid after showing the missing data banner
k8sClusterUIDAttrKey = GetDotMetrics("k8s_cluster_name")
k8sClusterUIDAttrKey = "k8s.cluster.name"
queryNamesForClusters = map[string][]string{
"cpu": {"A"},

View File

@@ -9,250 +9,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
)
var dotMetricMap = map[string]string{
"system_uptime": "system.uptime",
"system_cpu_physical_count": "system.cpu.physical.count",
"system_cpu_logical_count": "system.cpu.logical.count",
"system_cpu_time": "system.cpu.time",
"system_cpu_frequency": "system.cpu.frequency",
"system_cpu_utilization": "system.cpu.utilization",
"system_cpu_load_average_15m": "system.cpu.load_average.15m",
"system_memory_usage": "system.memory.usage",
"system_memory_limit": "system.memory.limit",
"system_memory_utilization": "system.memory.utilization",
"system_memory_linux_available": "system.memory.linux.available",
"system_memory_linux_shared": "system.memory.linux.shared",
"system_memory_linux_slab_usage": "system.memory.linux.slab.usage",
"system_paging_usage": "system.paging.usage",
"system_paging_utilization": "system.paging.utilization",
"system_paging_faults": "system.paging.faults",
"system_paging_operations": "system.paging.operations",
"system_disk_io": "system.disk.io",
"system_disk_operations": "system.disk.operations",
"system_disk_io_time": "system.disk.io_time",
"system_disk_operation_time": "system.disk.operation_time",
"system_disk_merged": "system.disk.merged",
"system_disk_limit": "system.disk.limit",
"system_filesystem_usage": "system.filesystem.usage",
"system_filesystem_utilization": "system.filesystem.utilization",
"system_filesystem_limit": "system.filesystem.limit",
"system_network_errors": "system.network.errors",
"system_network_io": "system.network.io",
"system_network_connections": "system.network.connections",
"system_network_dropped": "system.network.dropped",
"system_network_packets": "system.network.packets",
"system_processes_count": "system.processes.count",
"system_processes_created": "system.processes.created",
"system_disk_pending_operations": "system.disk.pending_operations",
"system_disk_weighted_io_time": "system.disk.weighted_io_time",
"system_filesystem_inodes_usage": "system.filesystem.inodes.usage",
"system_network_conntrack_count": "system.network.conntrack.count",
"system_network_conntrack_max": "system.network.conntrack.max",
"system_cpu_load_average_1m": "system.cpu.load_average.1m",
"system_cpu_load_average_5m": "system.cpu.load_average.5m",
"host_name": "host.name",
"k8s_cluster_name": "k8s.cluster.name",
"k8s_node_name": "k8s.node.name",
"k8s_pod_memory_usage": "k8s.pod.memory.usage",
"k8s_pod_cpu_request_utilization": "k8s.pod.cpu_request_utilization",
"k8s_pod_memory_request_utilization": "k8s.pod.memory_request_utilization",
"k8s_pod_cpu_limit_utilization": "k8s.pod.cpu_limit_utilization",
"k8s_pod_memory_limit_utilization": "k8s.pod.memory_limit_utilization",
"k8s_container_restarts": "k8s.container.restarts",
"k8s_pod_phase": "k8s.pod.phase",
"k8s_node_allocatable_cpu": "k8s.node.allocatable_cpu",
"k8s_node_allocatable_memory": "k8s.node.allocatable_memory",
"k8s_node_memory_usage": "k8s.node.memory.usage",
"k8s_node_condition_ready": "k8s.node.condition_ready",
"k8s_daemonset_desired_scheduled_nodes": "k8s.daemonset.desired_scheduled_nodes",
"k8s_daemonset_current_scheduled_nodes": "k8s.daemonset.current_scheduled_nodes",
"k8s_deployment_desired": "k8s.deployment.desired",
"k8s_deployment_available": "k8s.deployment.available",
"k8s_job_desired_successful_pods": "k8s.job.desired_successful_pods",
"k8s_job_active_pods": "k8s.job.active_pods",
"k8s_job_failed_pods": "k8s.job.failed_pods",
"k8s_job_successful_pods": "k8s.job.successful_pods",
"k8s_statefulset_desired_pods": "k8s.statefulset.desired_pods",
"k8s_statefulset_current_pods": "k8s.statefulset.current_pods",
"k8s_namespace_name": "k8s.namespace.name",
"k8s_deployment_name": "k8s.deployment.name",
"k8s_cronjob_name": "k8s.cronjob.name",
"k8s_job_name": "k8s.job.name",
"k8s_daemonset_name": "k8s.daemonset.name",
"os_type": "os.type",
"process_cgroup": "process.cgroup",
"process_pid": "process.pid",
"process_parent_pid": "process.parent_pid",
"process_owner": "process.owner",
"process_executable_path": "process.executable.path",
"process_executable_name": "process.executable.name",
"process_command_line": "process.command_line",
"process_command": "process.command",
"process_memory_usage": "process.memory.usage",
"process_memory_virtual": "process.memory.virtual",
"process_cpu_time": "process.cpu.time",
"process_disk_io": "process.disk.io",
"nfs_client_net_count": "nfs.client.net.count",
"nfs_client_net_tcp_connection_accepted": "nfs.client.net.tcp.connection.accepted",
"nfs_client_operation_count": "nfs.client.operation.count",
"nfs_client_procedure_count": "nfs.client.procedure.count",
"nfs_client_rpc_authrefresh_count": "nfs.client.rpc.authrefresh.count",
"nfs_client_rpc_count": "nfs.client.rpc.count",
"nfs_client_rpc_retransmit_count": "nfs.client.rpc.retransmit.count",
"nfs_server_fh_stale_count": "nfs.server.fh.stale.count",
"nfs_server_io": "nfs.server.io",
"nfs_server_net_count": "nfs.server.net.count",
"nfs_server_net_tcp_connection_accepted": "nfs.server.net.tcp.connection.accepted",
"nfs_server_operation_count": "nfs.server.operation.count",
"nfs_server_procedure_count": "nfs.server.procedure.count",
"nfs_server_repcache_requests": "nfs.server.repcache.requests",
"nfs_server_rpc_count": "nfs.server.rpc.count",
"nfs_server_thread_count": "nfs.server.thread.count",
"k8s_persistentvolumeclaim_name": "k8s.persistentvolumeclaim.name",
"k8s_volume_available": "k8s.volume.available",
"k8s_volume_capacity": "k8s.volume.capacity",
"k8s_volume_inodes": "k8s.volume.inodes",
"k8s_volume_inodes_free": "k8s.volume.inodes.free",
"k8s_pod_uid": "k8s.pod.uid",
"k8s_pod_name": "k8s.pod.name",
"k8s_container_name": "k8s.container.name",
"container_id": "container.id",
"k8s_volume_name": "k8s.volume.name",
"k8s_volume_type": "k8s.volume.type",
"aws_volume_id": "aws.volume.id",
"fs_type": "fs.type",
"partition": "partition",
"gce_pd_name": "gce.pd.name",
"glusterfs_endpoints_name": "glusterfs.endpoints.name",
"glusterfs_path": "glusterfs.path",
"interface": "interface",
"direction": "direction",
"k8s_node_cpu_usage": "k8s.node.cpu.usage",
"k8s_node_cpu_time": "k8s.node.cpu.time",
"k8s_node_memory_available": "k8s.node.memory.available",
"k8s_node_memory_rss": "k8s.node.memory.rss",
"k8s_node_memory_working_set": "k8s.node.memory.working_set",
"k8s_node_memory_page_faults": "k8s.node.memory.page_faults",
"k8s_node_memory_major_page_faults": "k8s.node.memory.major_page_faults",
"k8s_node_filesystem_available": "k8s.node.filesystem.available",
"k8s_node_filesystem_capacity": "k8s.node.filesystem.capacity",
"k8s_node_filesystem_usage": "k8s.node.filesystem.usage",
"k8s_node_network_io": "k8s.node.network.io",
"k8s_node_network_errors": "k8s.node.network.errors",
"k8s_node_uptime": "k8s.node.uptime",
"k8s_pod_cpu_usage": "k8s.pod.cpu.usage",
"k8s_pod_cpu_time": "k8s.pod.cpu.time",
"k8s_pod_memory_available": "k8s.pod.memory.available",
"k8s_pod_cpu_node_utilization": "k8s.pod.cpu.node.utilization",
"k8s_pod_memory_node_utilization": "k8s.pod.memory.node.utilization",
"k8s_pod_memory_rss": "k8s.pod.memory.rss",
"k8s_pod_memory_working_set": "k8s.pod.memory.working_set",
"k8s_pod_memory_page_faults": "k8s.pod.memory.page_faults",
"k8s_pod_memory_major_page_faults": "k8s.pod.memory.major_page_faults",
"k8s_pod_filesystem_available": "k8s.pod.filesystem.available",
"k8s_pod_filesystem_capacity": "k8s.pod.filesystem.capacity",
"k8s_pod_filesystem_usage": "k8s.pod.filesystem.usage",
"k8s_pod_network_io": "k8s.pod.network.io",
"k8s_pod_network_errors": "k8s.pod.network.errors",
"k8s_pod_uptime": "k8s.pod.uptime",
"container_cpu_usage": "container.cpu.usage",
"container_cpu_time": "container.cpu.time",
"container_memory_available": "container.memory.available",
"container_memory_usage": "container.memory.usage",
"k8s_container_cpu_node_utilization": "k8s.container.cpu.node.utilization",
"k8s_container_cpu_limit_utilization": "k8s.container.cpu_limit_utilization",
"k8s_container_cpu_request_utilization": "k8s.container.cpu_request_utilization",
"k8s_container_memory_node_utilization": "k8s.container.memory.node.utilization",
"k8s_container_memory_limit_utilization": "k8s.container.memory_limit_utilization",
"k8s_container_memory_request_utilization": "k8s.container.memory_request_utilization",
"container_memory_rss": "container.memory.rss",
"container_memory_working_set": "container.memory.working_set",
"container_memory_page_faults": "container.memory.page_faults",
"container_memory_major_page_faults": "container.memory.major_page_faults",
"container_filesystem_available": "container.filesystem.available",
"container_filesystem_capacity": "container.filesystem.capacity",
"container_filesystem_usage": "container.filesystem.usage",
"container_uptime": "container.uptime",
"k8s_volume_inodes_used": "k8s.volume.inodes.used",
"k8s_namespace_uid": "k8s.namespace.uid",
"container_image_name": "container.image.name",
"container_image_tag": "container.image.tag",
"k8s_pod_qos_class": "k8s.pod.qos_class",
"k8s_replicaset_name": "k8s.replicaset.name",
"k8s_replicaset_uid": "k8s.replicaset.uid",
"k8s_replicationcontroller_name": "k8s.replicationcontroller.name",
"k8s_replicationcontroller_uid": "k8s.replicationcontroller.uid",
"k8s_resourcequota_uid": "k8s.resourcequota.uid",
"k8s_resourcequota_name": "k8s.resourcequota.name",
"k8s_statefulset_uid": "k8s.statefulset.uid",
"k8s_statefulset_name": "k8s.statefulset.name",
"k8s_deployment_uid": "k8s.deployment.uid",
"k8s_cronjob_uid": "k8s.cronjob.uid",
"k8s_daemonset_uid": "k8s.daemonset.uid",
"k8s_hpa_uid": "k8s.hpa.uid",
"k8s_hpa_name": "k8s.hpa.name",
"k8s_hpa_scaletargetref_kind": "k8s.hpa.scaletargetref.kind",
"k8s_hpa_scaletargetref_name": "k8s.hpa.scaletargetref.name",
"k8s_hpa_scaletargetref_apiversion": "k8s.hpa.scaletargetref.apiversion",
"k8s_job_uid": "k8s.job.uid",
"k8s_kubelet_version": "k8s.kubelet.version",
"container_runtime": "container.runtime",
"container_runtime_version": "container.runtime.version",
"os_description": "os.description",
"openshift_clusterquota_uid": "openshift.clusterquota.uid",
"openshift_clusterquota_name": "openshift.clusterquota.name",
"k8s_container_status_last_terminated_reason": "k8s.container.status.last_terminated_reason",
"resource": "resource",
"condition": "condition",
"k8s_container_cpu_request": "k8s.container.cpu_request",
"k8s_container_cpu_limit": "k8s.container.cpu_limit",
"k8s_container_memory_request": "k8s.container.memory_request",
"k8s_container_memory_limit": "k8s.container.memory_limit",
"k8s_container_storage_request": "k8s.container.storage_request",
"k8s_container_storage_limit": "k8s.container.storage_limit",
"k8s_container_ephemeralstorage_request": "k8s.container.ephemeralstorage_request",
"k8s_container_ephemeralstorage_limit": "k8s.container.ephemeralstorage_limit",
"k8s_container_ready": "k8s.container.ready",
"k8s_pod_status_reason": "k8s.pod.status_reason",
"k8s_cronjob_active_jobs": "k8s.cronjob.active_jobs",
"k8s_daemonset_misscheduled_nodes": "k8s.daemonset.misscheduled_nodes",
"k8s_daemonset_ready_nodes": "k8s.daemonset.ready_nodes",
"k8s_hpa_max_replicas": "k8s.hpa.max_replicas",
"k8s_hpa_min_replicas": "k8s.hpa.min_replicas",
"k8s_hpa_current_replicas": "k8s.hpa.current_replicas",
"k8s_hpa_desired_replicas": "k8s.hpa.desired_replicas",
"k8s_job_max_parallel_pods": "k8s.job.max_parallel_pods",
"k8s_namespace_phase": "k8s.namespace.phase",
"k8s_replicaset_desired": "k8s.replicaset.desired",
"k8s_replicaset_available": "k8s.replicaset.available",
"k8s_replication_controller_desired": "k8s.replication_controller.desired",
"k8s_replication_controller_available": "k8s.replication_controller.available",
"k8s_resource_quota_hard_limit": "k8s.resource_quota.hard_limit",
"k8s_resource_quota_used": "k8s.resource_quota.used",
"k8s_statefulset_updated_pods": "k8s.statefulset.updated_pods",
"k8s_node_condition": "k8s.node.condition",
}
const fromWhereQuery = `
FROM %s.%s
WHERE metric_name IN (%s)
@@ -262,39 +18,39 @@ WHERE metric_name IN (%s)
var (
// TODO(srikanthccv): import metadata yaml from receivers and use generated files to check the metrics
podMetricNamesToCheck = []string{
GetDotMetrics("k8s_pod_cpu_usage"),
GetDotMetrics("k8s_pod_memory_working_set"),
GetDotMetrics("k8s_pod_cpu_request_utilization"),
GetDotMetrics("k8s_pod_memory_request_utilization"),
GetDotMetrics("k8s_pod_cpu_limit_utilization"),
GetDotMetrics("k8s_pod_memory_limit_utilization"),
GetDotMetrics("k8s_container_restarts"),
GetDotMetrics("k8s_pod_phase"),
"k8s.pod.cpu.usage",
"k8s.pod.memory.working_set",
"k8s.pod.cpu_request_utilization",
"k8s.pod.memory_request_utilization",
"k8s.pod.cpu_limit_utilization",
"k8s.pod.memory_limit_utilization",
"k8s.container.restarts",
"k8s.pod.phase",
}
nodeMetricNamesToCheck = []string{
GetDotMetrics("k8s_node_cpu_usage"),
GetDotMetrics("k8s_node_allocatable_cpu"),
GetDotMetrics("k8s_node_memory_working_set"),
GetDotMetrics("k8s_node_allocatable_memory"),
GetDotMetrics("k8s_node_condition_ready"),
"k8s.node.cpu.usage",
"k8s.node.allocatable_cpu",
"k8s.node.memory.working_set",
"k8s.node.allocatable_memory",
"k8s.node.condition_ready",
}
clusterMetricNamesToCheck = []string{
GetDotMetrics("k8s_daemonset_desired_scheduled_nodes"),
GetDotMetrics("k8s_daemonset_current_scheduled_nodes"),
GetDotMetrics("k8s_deployment_desired"),
GetDotMetrics("k8s_deployment_available"),
GetDotMetrics("k8s_job_desired_successful_pods"),
GetDotMetrics("k8s_job_active_pods"),
GetDotMetrics("k8s_job_failed_pods"),
GetDotMetrics("k8s_job_successful_pods"),
GetDotMetrics("k8s_statefulset_desired_pods"),
GetDotMetrics("k8s_statefulset_current_pods"),
"k8s.daemonset.desired_scheduled_nodes",
"k8s.daemonset.current_scheduled_nodes",
"k8s.deployment.desired",
"k8s.deployment.available",
"k8s.job.desired_successful_pods",
"k8s.job.active_pods",
"k8s.job.failed_pods",
"k8s.job.successful_pods",
"k8s.statefulset.desired_pods",
"k8s.statefulset.current_pods",
}
optionalPodMetricNamesToCheck = []string{
GetDotMetrics("k8s_pod_cpu_request_utilization"),
GetDotMetrics("k8s_pod_memory_request_utilization"),
GetDotMetrics("k8s_pod_cpu_limit_utilization"),
GetDotMetrics("k8s_pod_memory_limit_utilization"),
"k8s.pod.cpu_request_utilization",
"k8s.pod.memory_request_utilization",
"k8s.pod.cpu_limit_utilization",
"k8s.pod.memory_limit_utilization",
}
// did they ever send _any_ pod metrics?
@@ -332,15 +88,15 @@ SELECT
any(JSONExtractString(labels, '%s')) as k8s_job_name,
JSONExtractString(labels, '%s') as k8s_pod_name
`,
GetDotMetrics("k8s_cluster_name"),
GetDotMetrics("k8s_node_name"),
GetDotMetrics("k8s_namespace_name"),
GetDotMetrics("k8s_deployment_name"),
GetDotMetrics("k8s_statefulset_name"),
GetDotMetrics("k8s_daemonset_name"),
GetDotMetrics("k8s_cronjob_name"),
GetDotMetrics("k8s_job_name"),
GetDotMetrics("k8s_pod_name"),
"k8s.cluster.name",
"k8s.node.name",
"k8s.namespace.name",
"k8s.deployment.name",
"k8s.statefulset.name",
"k8s.daemonset.name",
"k8s.cronjob.name",
"k8s.job.name",
"k8s.pod.name",
)
filterGroupQuery = fmt.Sprintf(`
@@ -349,7 +105,7 @@ AND JSONExtractString(labels, '%s')
GROUP BY k8s_pod_name
LIMIT 1 BY k8s_cluster_name, k8s_node_name, k8s_namespace_name
`,
GetDotMetrics("k8s_namespace_name"),
"k8s.namespace.name",
)
isSendingRequiredMetadataQuery = selectQuery + fromWhereQuery + filterGroupQuery
@@ -450,12 +206,3 @@ func getParamsForTopVolumes(req model.VolumeListRequest) (int64, string, string)
func localQueryToDistributedQuery(query string) string {
return strings.Replace(query, ".time_series_v4", ".distributed_time_series_v4", 1)
}
func GetDotMetrics(key string) string {
if constants.IsDotMetricsEnabled {
if _, ok := dotMetricMap[key]; ok {
return dotMetricMap[key]
}
}
return key
}

View File

@@ -18,18 +18,18 @@ import (
)
var (
metricToUseForDaemonSets = GetDotMetrics("k8s_pod_cpu_usage")
k8sDaemonSetNameAttrKey = GetDotMetrics("k8s_daemonset_name")
metricToUseForDaemonSets = "k8s.pod.cpu.usage"
k8sDaemonSetNameAttrKey = "k8s.daemonset.name"
metricNamesForDaemonSets = map[string]string{
"desired_nodes": GetDotMetrics("k8s_daemonset_desired_scheduled_nodes"),
"available_nodes": GetDotMetrics("k8s_daemonset_current_scheduled_nodes"),
"desired_nodes": "k8s.daemonset.desired_scheduled_nodes",
"available_nodes": "k8s.daemonset.current_scheduled_nodes",
}
daemonSetAttrsToEnrich = []string{
GetDotMetrics("k8s_daemonset_name"),
GetDotMetrics("k8s_namespace_name"),
GetDotMetrics("k8s_cluster_name"),
"k8s.daemonset.name",
"k8s.namespace.name",
"k8s.cluster.name",
}
queryNamesForDaemonSets = map[string][]string{

View File

@@ -18,18 +18,18 @@ import (
)
var (
metricToUseForDeployments = GetDotMetrics("k8s_pod_cpu_usage")
k8sDeploymentNameAttrKey = GetDotMetrics("k8s_deployment_name")
metricToUseForDeployments = "k8s.pod.cpu.usage"
k8sDeploymentNameAttrKey = "k8s.deployment.name"
metricNamesForDeployments = map[string]string{
"desired_pods": GetDotMetrics("k8s_deployment_desired"),
"available_pods": GetDotMetrics("k8s_deployment_available"),
"desired_pods": "k8s.deployment.desired",
"available_pods": "k8s.deployment.available",
}
deploymentAttrsToEnrich = []string{
GetDotMetrics("k8s_deployment_name"),
GetDotMetrics("k8s_namespace_name"),
GetDotMetrics("k8s_cluster_name"),
"k8s.deployment.name",
"k8s.namespace.name",
"k8s.cluster.name",
}
queryNamesForDeployments = map[string][]string{

View File

@@ -45,15 +45,15 @@ var (
"mode",
"mountpoint",
"type",
GetDotMetrics("os_type"),
GetDotMetrics("process_cgroup"),
GetDotMetrics("process_command"),
GetDotMetrics("process_command_line"),
GetDotMetrics("process_executable_name"),
GetDotMetrics("process_executable_path"),
GetDotMetrics("process_owner"),
GetDotMetrics("process_parent_pid"),
GetDotMetrics("process_pid"),
"os.type",
"process.cgroup",
"process.command",
"process.command_line",
"process.executable.name",
"process.executable.path",
"process.owner",
"process.parent_pid",
"process.pid",
}
queryNamesForTopHosts = map[string][]string{
@@ -64,65 +64,65 @@ var (
}
// TODO(srikanthccv): remove hardcoded metric name and support keys from any system metric
metricToUseForHostAttributes = GetDotMetrics("system_cpu_load_average_15m")
hostNameAttrKey = GetDotMetrics("host_name")
metricToUseForHostAttributes = "system.cpu.load_average.15m"
hostNameAttrKey = "host.name"
agentNameToIgnore = "k8s-infra-otel-agent"
hostAttrsToEnrich = []string{
GetDotMetrics("os_type"),
"os.type",
}
metricNamesForHosts = map[string]string{
"filesystem": GetDotMetrics("system_filesystem_usage"),
"cpu": GetDotMetrics("system_cpu_time"),
"memory": GetDotMetrics("system_memory_usage"),
"load15": GetDotMetrics("system_cpu_load_average_15m"),
"wait": GetDotMetrics("system_cpu_time"),
"filesystem": "system.filesystem.usage",
"cpu": "system.cpu.time",
"memory": "system.memory.usage",
"load15": "system.cpu.load_average.15m",
"wait": "system.cpu.time",
}
uniqueMetricNamesForHosts = []string{
GetDotMetrics("system_uptime"),
GetDotMetrics("system_cpu_time"),
GetDotMetrics("system_cpu_load_average_1m"),
GetDotMetrics("system_cpu_load_average_5m"),
GetDotMetrics("system_cpu_load_average_15m"),
GetDotMetrics("system_memory_usage"),
GetDotMetrics("system_paging_usage"),
GetDotMetrics("system_paging_faults"),
GetDotMetrics("system_paging_operations"),
GetDotMetrics("system_disk_io"),
GetDotMetrics("system_disk_operations"),
GetDotMetrics("system_disk_io_time"),
GetDotMetrics("system_disk_operation_time"),
GetDotMetrics("system_disk_merged"),
GetDotMetrics("system_disk_pending_operations"),
GetDotMetrics("system_disk_weighted_io_time"),
GetDotMetrics("system_filesystem_usage"),
GetDotMetrics("system_filesystem_inodes_usage"),
GetDotMetrics("system_network_io"),
GetDotMetrics("system_network_errors"),
GetDotMetrics("system_network_connections"),
GetDotMetrics("system_network_dropped"),
GetDotMetrics("system_network_packets"),
GetDotMetrics("system_processes_count"),
GetDotMetrics("system_processes_created"),
GetDotMetrics("process_cpu_time"),
GetDotMetrics("process_disk_io"),
GetDotMetrics("process_memory_usage"),
GetDotMetrics("process_memory_virtual"),
GetDotMetrics("nfs_client_net_count"),
GetDotMetrics("nfs_client_net_tcp_connection_accepted"),
GetDotMetrics("nfs_client_operation_count"),
GetDotMetrics("nfs_client_procedure_count"),
GetDotMetrics("nfs_client_rpc_authrefresh_count"),
GetDotMetrics("nfs_client_rpc_count"),
GetDotMetrics("nfs_client_rpc_retransmit_count"),
GetDotMetrics("nfs_server_fh_stale_count"),
GetDotMetrics("nfs_server_io"),
GetDotMetrics("nfs_server_net_count"),
GetDotMetrics("nfs_server_net_tcp_connection_accepted"),
GetDotMetrics("nfs_server_operation_count"),
GetDotMetrics("nfs_server_procedure_count"),
GetDotMetrics("nfs_server_repcache_requests"),
GetDotMetrics("nfs_server_rpc_count"),
GetDotMetrics("nfs_server_thread_count"),
"system.uptime",
"system.cpu.time",
"system.cpu.load_average.1m",
"system.cpu.load_average.5m",
"system.cpu.load_average.15m",
"system.memory.usage",
"system.paging.usage",
"system.paging.faults",
"system.paging.operations",
"system.disk.io",
"system.disk.operations",
"system.disk.io_time",
"system.disk.operation_time",
"system.disk.merged",
"system.disk.pending_operations",
"system.disk.weighted_io_time",
"system.filesystem.usage",
"system.filesystem.inodes.usage",
"system.network.io",
"system.network.errors",
"system.network.connections",
"system.network.dropped",
"system.network.packets",
"system.processes.count",
"system.processes.created",
"process.cpu.time",
"process.disk.io",
"process.memory.usage",
"process.memory.virtual",
"nfs.client.net.count",
"nfs.client.net.tcp.connection.accepted",
"nfs.client.operation.count",
"nfs.client.procedure.count",
"nfs.client.rpc.authrefresh.count",
"nfs.client.rpc.count",
"nfs.client.rpc.retransmit.count",
"nfs.server.fh.stale.count",
"nfs.server.io",
"nfs.server.net.count",
"nfs.server.net.tcp.connection.accepted",
"nfs.server.operation.count",
"nfs.server.procedure.count",
"nfs.server.repcache.requests",
"nfs.server.rpc.count",
"nfs.server.thread.count",
}
)
@@ -351,8 +351,8 @@ func (h *HostsRepo) IsSendingK8SAgentMetrics(ctx context.Context, req model.Host
AND unix_milli >= toUnixTimestamp(now() - INTERVAL 60 MINUTE) * 1000
AND JSONExtractString(labels, '%s') LIKE '%%-otel-agent%%'
AND fingerprint GLOBAL IN (%s)`,
GetDotMetrics("k8s_cluster_name"), GetDotMetrics("k8s_node_name"),
constants.SIGNOZ_METRIC_DBNAME, constants.SIGNOZ_TIMESERIES_V4_TABLENAME, namesStr, GetDotMetrics("host_name"), queryForRecentFingerprints)
"k8s.cluster.name", "k8s.node.name",
constants.SIGNOZ_METRIC_DBNAME, constants.SIGNOZ_TIMESERIES_V4_TABLENAME, namesStr, "host.name", queryForRecentFingerprints)
result, err := h.reader.GetListResultV3(ctx, query)
if err != nil {
@@ -363,13 +363,13 @@ func (h *HostsRepo) IsSendingK8SAgentMetrics(ctx context.Context, req model.Host
nodeNames := make(map[string]struct{})
for _, row := range result {
switch v := row.Data[GetDotMetrics("k8s_cluster_name")].(type) {
switch v := row.Data["k8s.cluster.name"].(type) {
case string:
clusterNames[v] = struct{}{}
case *string:
clusterNames[*v] = struct{}{}
}
switch v := row.Data[GetDotMetrics("k8s_node_name")].(type) {
switch v := row.Data["k8s.node.name"].(type) {
case string:
nodeNames[v] = struct{}{}
case *string:
@@ -535,7 +535,7 @@ func (h *HostsRepo) GetHostList(ctx context.Context, orgID valuer.UUID, req mode
if _, ok := hostAttrs[record.HostName]; ok {
record.Meta = hostAttrs[record.HostName]
}
if osType, ok := record.Meta[GetDotMetrics("os_type")]; ok {
if osType, ok := record.Meta["os.type"]; ok {
record.OS = osType
}
record.Active = activeHosts[record.HostName]

View File

@@ -18,20 +18,20 @@ import (
)
var (
metricToUseForJobs = GetDotMetrics("k8s_job_desired_successful_pods")
k8sJobNameAttrKey = GetDotMetrics("k8s_job_name")
metricToUseForJobs = "k8s.job.desired_successful_pods"
k8sJobNameAttrKey = "k8s.job.name"
metricNamesForJobs = map[string]string{
"desired_successful_pods": GetDotMetrics("k8s_job_desired_successful_pods"),
"active_pods": GetDotMetrics("k8s_job_active_pods"),
"failed_pods": GetDotMetrics("k8s_job_failed_pods"),
"successful_pods": GetDotMetrics("k8s_job_successful_pods"),
"desired_successful_pods": "k8s.job.desired_successful_pods",
"active_pods": "k8s.job.active_pods",
"failed_pods": "k8s.job.failed_pods",
"successful_pods": "k8s.job.successful_pods",
}
jobAttrsToEnrich = []string{
GetDotMetrics("k8s_job_name"),
GetDotMetrics("k8s_namespace_name"),
GetDotMetrics("k8s_cluster_name"),
"k8s.job.name",
"k8s.namespace.name",
"k8s.cluster.name",
}
queryNamesForJobs = map[string][]string{
@@ -54,7 +54,7 @@ var (
QueryName: "H",
DataSource: v3.DataSourceMetrics,
AggregateAttribute: v3.AttributeKey{
Key: GetDotMetrics(metricNamesForJobs["desired_successful_pods"]),
Key: metricNamesForJobs["desired_successful_pods"],
DataType: v3.AttributeKeyDataTypeFloat64,
},
Temporality: v3.Unspecified,
@@ -74,7 +74,7 @@ var (
QueryName: "I",
DataSource: v3.DataSourceMetrics,
AggregateAttribute: v3.AttributeKey{
Key: GetDotMetrics(metricNamesForJobs["active_pods"]),
Key: metricNamesForJobs["active_pods"],
DataType: v3.AttributeKeyDataTypeFloat64,
},
Temporality: v3.Unspecified,
@@ -94,7 +94,7 @@ var (
QueryName: "J",
DataSource: v3.DataSourceMetrics,
AggregateAttribute: v3.AttributeKey{
Key: GetDotMetrics(metricNamesForJobs["failed_pods"]),
Key: metricNamesForJobs["failed_pods"],
DataType: v3.AttributeKeyDataTypeFloat64,
},
Temporality: v3.Unspecified,
@@ -114,7 +114,7 @@ var (
QueryName: "K",
DataSource: v3.DataSourceMetrics,
AggregateAttribute: v3.AttributeKey{
Key: GetDotMetrics(metricNamesForJobs["successful_pods"]),
Key: metricNamesForJobs["successful_pods"],
DataType: v3.AttributeKeyDataTypeFloat64,
},
Temporality: v3.Unspecified,
@@ -327,7 +327,7 @@ func (d *JobsRepo) GetJobList(ctx context.Context, orgID valuer.UUID, req model.
}
if req.OrderBy == nil {
req.OrderBy = &v3.OrderBy{ColumnName: GetDotMetrics("desired_pods"), Order: v3.DirectionDesc}
req.OrderBy = &v3.OrderBy{ColumnName: "desired_pods", Order: v3.DirectionDesc}
}
if req.GroupBy == nil {

View File

@@ -18,11 +18,11 @@ import (
)
var (
metricToUseForNamespaces = GetDotMetrics("k8s_pod_cpu_usage")
metricToUseForNamespaces = "k8s.pod.cpu.usage"
namespaceAttrsToEnrich = []string{
GetDotMetrics("k8s_namespace_name"),
GetDotMetrics("k8s_cluster_name"),
"k8s.namespace.name",
"k8s.cluster.name",
}
queryNamesForNamespaces = map[string][]string{
@@ -33,11 +33,11 @@ var (
namespaceQueryNames = []string{"A", "D", "H", "I", "J", "K"}
attributesKeysForNamespaces = []v3.AttributeKey{
{Key: GetDotMetrics("k8s_namespace_name")},
{Key: GetDotMetrics("k8s_cluster_name")},
{Key: "k8s.namespace.name"},
{Key: "k8s.cluster.name"},
}
k8sNamespaceNameAttrKey = GetDotMetrics("k8s_namespace_name")
k8sNamespaceNameAttrKey = "k8s.namespace.name"
)
type NamespacesRepo struct {

View File

@@ -21,11 +21,11 @@ import (
)
var (
metricToUseForNodes = GetDotMetrics("k8s_node_cpu_usage")
metricToUseForNodes = "k8s.node.cpu.usage"
nodeAttrsToEnrich = []string{GetDotMetrics("k8s_node_name"), GetDotMetrics("k8s_node_uid"), GetDotMetrics("k8s_cluster_name")}
nodeAttrsToEnrich = []string{"k8s.node.name", "k8s.node.uid", "k8s.cluster.name"}
k8sNodeGroupAttrKey = GetDotMetrics("k8s_node_name")
k8sNodeGroupAttrKey = "k8s.node.name"
queryNamesForNodes = map[string][]string{
"cpu": {"A"},
@@ -36,11 +36,11 @@ var (
nodeQueryNames = []string{"A", "B", "C", "D", "E", "F"}
metricNamesForNodes = map[string]string{
"cpu": GetDotMetrics("k8s_node_cpu_usage"),
"cpu_allocatable": GetDotMetrics("k8s_node_allocatable_cpu"),
"memory": GetDotMetrics("k8s_node_memory_working_set"),
"memory_allocatable": GetDotMetrics("k8s_node_allocatable_memory"),
"node_condition": GetDotMetrics("k8s_node_condition_ready"),
"cpu": "k8s.node.cpu.usage",
"cpu_allocatable": "k8s.node.allocatable_cpu",
"memory": "k8s.node.memory.working_set",
"memory_allocatable": "k8s.node.allocatable_memory",
"node_condition": "k8s.node.condition_ready",
}
)

View File

@@ -21,22 +21,22 @@ import (
)
var (
metricToUseForPods = GetDotMetrics("k8s_pod_cpu_usage")
metricToUseForPods = "k8s.pod.cpu.usage"
podAttrsToEnrich = []string{
GetDotMetrics("k8s_pod_uid"),
GetDotMetrics("k8s_pod_name"),
GetDotMetrics("k8s_namespace_name"),
GetDotMetrics("k8s_node_name"),
GetDotMetrics("k8s_deployment_name"),
GetDotMetrics("k8s_statefulset_name"),
GetDotMetrics("k8s_daemonset_name"),
GetDotMetrics("k8s_job_name"),
GetDotMetrics("k8s_cronjob_name"),
GetDotMetrics("k8s_cluster_name"),
"k8s.pod.uid",
"k8s.pod.name",
"k8s.namespace.name",
"k8s.node.name",
"k8s.deployment.name",
"k8s.statefulset.name",
"k8s.daemonset.name",
"k8s.job.name",
"k8s.cronjob.name",
"k8s.cluster.name",
}
k8sPodUIDAttrKey = GetDotMetrics("k8s_pod_uid")
k8sPodUIDAttrKey = "k8s.pod.uid"
queryNamesForPods = map[string][]string{
"cpu": {"A"},
@@ -51,14 +51,14 @@ var (
podQueryNames = []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"}
metricNamesForPods = map[string]string{
"cpu": GetDotMetrics("k8s_pod_cpu_usage"),
"cpu_request": GetDotMetrics("k8s_pod_cpu_request_utilization"),
"cpu_limit": GetDotMetrics("k8s_pod_cpu_limit_utilization"),
"memory": GetDotMetrics("k8s_pod_memory_working_set"),
"memory_request": GetDotMetrics("k8s_pod_memory_request_utilization"),
"memory_limit": GetDotMetrics("k8s_pod_memory_limit_utilization"),
"restarts": GetDotMetrics("k8s_container_restarts"),
"pod_phase": GetDotMetrics("k8s_pod_phase"),
"cpu": "k8s.pod.cpu.usage",
"cpu_request": "k8s.pod.cpu_request_utilization",
"cpu_limit": "k8s.pod.cpu_limit_utilization",
"memory": "k8s.pod.memory.working_set",
"memory_request": "k8s.pod.memory_request_utilization",
"memory_limit": "k8s.pod.memory_limit_utilization",
"restarts": "k8s.container.restarts",
"pod_phase": "k8s.pod.phase",
}
)
@@ -169,7 +169,7 @@ func (p *PodsRepo) SendingRequiredMetadata(ctx context.Context) ([]model.PodOnbo
// for each pod, check if we have all the required metadata
for _, row := range result {
status := model.PodOnboardingStatus{}
switch v := row.Data[GetDotMetrics("k8s_cluster_name")].(type) {
switch v := row.Data["k8s.cluster.name"].(type) {
case string:
status.HasClusterName = true
status.ClusterName = v
@@ -177,7 +177,7 @@ func (p *PodsRepo) SendingRequiredMetadata(ctx context.Context) ([]model.PodOnbo
status.HasClusterName = *v != ""
status.ClusterName = *v
}
switch v := row.Data[GetDotMetrics("k8s_node_name")].(type) {
switch v := row.Data["k8s.node.name"].(type) {
case string:
status.HasNodeName = true
status.NodeName = v
@@ -185,7 +185,7 @@ func (p *PodsRepo) SendingRequiredMetadata(ctx context.Context) ([]model.PodOnbo
status.HasNodeName = *v != ""
status.NodeName = *v
}
switch v := row.Data[GetDotMetrics("k8s_namespace_name")].(type) {
switch v := row.Data["k8s.namespace.name"].(type) {
case string:
status.HasNamespaceName = true
status.NamespaceName = v
@@ -193,38 +193,38 @@ func (p *PodsRepo) SendingRequiredMetadata(ctx context.Context) ([]model.PodOnbo
status.HasNamespaceName = *v != ""
status.NamespaceName = *v
}
switch v := row.Data[GetDotMetrics("k8s_deployment_name")].(type) {
switch v := row.Data["k8s.deployment.name"].(type) {
case string:
status.HasDeploymentName = true
case *string:
status.HasDeploymentName = *v != ""
}
switch v := row.Data[GetDotMetrics("k8s_statefulset_name")].(type) {
switch v := row.Data["k8s.statefulset.name"].(type) {
case string:
status.HasStatefulsetName = true
case *string:
status.HasStatefulsetName = *v != ""
}
switch v := row.Data[GetDotMetrics("k8s_daemonset_name")].(type) {
switch v := row.Data["k8s.daemonset.name"].(type) {
case string:
status.HasDaemonsetName = true
case *string:
status.HasDaemonsetName = *v != ""
}
switch v := row.Data[GetDotMetrics("k8s_cronjob_name")].(type) {
switch v := row.Data["k8s.cronjob.name"].(type) {
case string:
status.HasCronjobName = true
case *string:
status.HasCronjobName = *v != ""
}
switch v := row.Data[GetDotMetrics("k8s_job_name")].(type) {
switch v := row.Data["k8s.job.name"].(type) {
case string:
status.HasJobName = true
case *string:
status.HasJobName = *v != ""
}
switch v := row.Data[GetDotMetrics("k8s_pod_name")].(type) {
switch v := row.Data["k8s.pod.name"].(type) {
case string:
status.PodName = v
case *string:

View File

@@ -23,15 +23,15 @@ var (
"memory": {"C"},
}
processPIDAttrKey = GetDotMetrics("process_pid")
processPIDAttrKey = "process.pid"
metricNamesForProcesses = map[string]string{
"cpu": GetDotMetrics("process_cpu_time"),
"memory": GetDotMetrics("process_memory_usage"),
"cpu": "process.cpu.time",
"memory": "process.memory.usage",
}
metricToUseForProcessAttributes = GetDotMetrics("process_memory_usage")
processNameAttrKey = GetDotMetrics("process_executable_name")
processCMDAttrKey = GetDotMetrics("process_command")
processCMDLineAttrKey = GetDotMetrics("process_command_line")
metricToUseForProcessAttributes = "process.memory.usage"
processNameAttrKey = "process.executable.name"
processCMDAttrKey = "process.command"
processCMDLineAttrKey = "process.command_line"
)
type ProcessesRepo struct {
@@ -46,7 +46,7 @@ func NewProcessesRepo(reader interfaces.Reader, querierV2 interfaces.Querier) *P
func (p *ProcessesRepo) GetProcessAttributeKeys(ctx context.Context, orgID valuer.UUID, req v3.FilterAttributeKeyRequest) (*v3.FilterAttributeKeyResponse, error) {
// TODO(srikanthccv): remove hardcoded metric name and support keys from any system metric
req.DataSource = v3.DataSourceMetrics
req.AggregateAttribute = GetDotMetrics("process_memory_usage")
req.AggregateAttribute = "process.memory.usage"
if req.Limit == 0 {
req.Limit = 50
}
@@ -71,7 +71,7 @@ func (p *ProcessesRepo) GetProcessAttributeKeys(ctx context.Context, orgID value
func (p *ProcessesRepo) GetProcessAttributeValues(ctx context.Context, orgID valuer.UUID, req v3.FilterAttributeValueRequest) (*v3.FilterAttributeValueResponse, error) {
req.DataSource = v3.DataSourceMetrics
req.AggregateAttribute = GetDotMetrics("process_memory_usage")
req.AggregateAttribute = "process.memory.usage"
if req.Limit == 0 {
req.Limit = 50
}
@@ -87,7 +87,7 @@ func (p *ProcessesRepo) getMetadataAttributes(ctx context.Context,
req model.ProcessListRequest) (map[string]map[string]string, error) {
processAttrs := map[string]map[string]string{}
keysToAdd := []string{GetDotMetrics("process_pid"), GetDotMetrics("process_executable_name"), GetDotMetrics("process_command"), GetDotMetrics("process_command_line")}
keysToAdd := []string{"process.pid", "process.executable.name", "process.command", "process.command_line"}
for _, key := range keysToAdd {
hasKey := false
for _, groupByKey := range req.GroupBy {

View File

@@ -18,19 +18,19 @@ import (
)
var (
metricToUseForVolumes = GetDotMetrics("k8s_volume_available")
metricToUseForVolumes = "k8s.volume.available"
volumeAttrsToEnrich = []string{
GetDotMetrics("k8s_pod_uid"),
GetDotMetrics("k8s_pod_name"),
GetDotMetrics("k8s_namespace_name"),
GetDotMetrics("k8s_node_name"),
GetDotMetrics("k8s_statefulset_name"),
GetDotMetrics("k8s_cluster_name"),
GetDotMetrics("k8s_persistentvolumeclaim_name"),
"k8s.pod.uid",
"k8s.pod.name",
"k8s.namespace.name",
"k8s.node.name",
"k8s.statefulset.name",
"k8s.cluster.name",
"k8s.persistentvolumeclaim.name",
}
k8sPersistentVolumeClaimNameAttrKey = GetDotMetrics("k8s_persistentvolumeclaim_name")
k8sPersistentVolumeClaimNameAttrKey = "k8s.persistentvolumeclaim.name"
queryNamesForVolumes = map[string][]string{
"available": {"A"},
@@ -44,11 +44,11 @@ var (
volumeQueryNames = []string{"A", "B", "C", "D", "E", "F1"}
metricNamesForVolumes = map[string]string{
"available": GetDotMetrics("k8s_volume_available"),
"capacity": GetDotMetrics("k8s_volume_capacity"),
"inodes": GetDotMetrics("k8s_volume_inodes"),
"inodes_free": GetDotMetrics("k8s_volume_inodes_free"),
"inodes_used": GetDotMetrics("k8s_volume_inodes_used"),
"available": "k8s.volume.available",
"capacity": "k8s.volume.capacity",
"inodes": "k8s.volume.inodes",
"inodes_free": "k8s.volume.inodes.free",
"inodes_used": "k8s.volume.inodes.used",
}
)

View File

@@ -18,18 +18,18 @@ import (
)
var (
metricToUseForStatefulSets = GetDotMetrics("k8s_pod_cpu_usage")
k8sStatefulSetNameAttrKey = GetDotMetrics("k8s_statefulset_name")
metricToUseForStatefulSets = "k8s.pod.cpu.usage"
k8sStatefulSetNameAttrKey = "k8s.statefulset.name"
metricNamesForStatefulSets = map[string]string{
"desired_pods": GetDotMetrics("k8s_statefulset_desired_pods"),
"available_pods": GetDotMetrics("k8s_statefulset_current_pods"),
"desired_pods": "k8s.statefulset.desired_pods",
"available_pods": "k8s.statefulset.current_pods",
}
statefulSetAttrsToEnrich = []string{
GetDotMetrics("k8s_statefulset_name"),
GetDotMetrics("k8s_namespace_name"),
GetDotMetrics("k8s_cluster_name"),
"k8s.statefulset.name",
"k8s.namespace.name",
"k8s.cluster.name",
}
queryNamesForStatefulSets = map[string][]string{

View File

@@ -4,13 +4,13 @@ import v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
var (
metricNamesForWorkloads = map[string]string{
"cpu": GetDotMetrics("k8s_pod_cpu_usage"),
"cpu_request": GetDotMetrics("k8s_pod_cpu_request_utilization"),
"cpu_limit": GetDotMetrics("k8s_pod_cpu_limit_utilization"),
"memory": GetDotMetrics("k8s_pod_memory_working_set"),
"memory_request": GetDotMetrics("k8s_pod_memory_request_utilization"),
"memory_limit": GetDotMetrics("k8s_pod_memory_limit_utilization"),
"restarts": GetDotMetrics("k8s_container_restarts"),
"cpu": "k8s.pod.cpu.usage",
"cpu_request": "k8s.pod.cpu_request_utilization",
"cpu_limit": "k8s.pod.cpu_limit_utilization",
"memory": "k8s.pod.memory.working_set",
"memory_request": "k8s.pod.memory_request_utilization",
"memory_limit": "k8s.pod.memory_limit_utilization",
"restarts": "k8s.container.restarts",
}
)

View File

@@ -4,7 +4,6 @@ import (
"fmt"
"github.com/SigNoz/signoz/pkg/query-service/common"
"github.com/SigNoz/signoz/pkg/query-service/constants"
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
)
@@ -67,11 +66,6 @@ func buildBuilderQueriesProducerBytes(
attributeCache *Clients,
) (map[string]*v3.BuilderQuery, error) {
normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
bq := make(map[string]*v3.BuilderQuery)
queryName := "byte_rate"
@@ -80,7 +74,7 @@ func buildBuilderQueriesProducerBytes(
StepInterval: common.MinAllowedStepInterval(unixMilliStart, unixMilliEnd),
DataSource: v3.DataSourceMetrics,
AggregateAttribute: v3.AttributeKey{
Key: getDotMetrics("kafka_producer_byte_rate", normalized),
Key: "kafka.producer.byte-rate",
DataType: v3.AttributeKeyDataTypeFloat64,
Type: v3.AttributeKeyType("Gauge"),
IsColumn: true,
@@ -94,7 +88,7 @@ func buildBuilderQueriesProducerBytes(
Items: []v3.FilterItem{
{
Key: v3.AttributeKey{
Key: getDotMetrics("service_name", normalized),
Key: "service.name",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeString,
},
@@ -116,7 +110,7 @@ func buildBuilderQueriesProducerBytes(
ReduceTo: v3.ReduceToOperatorAvg,
GroupBy: []v3.AttributeKey{
{
Key: getDotMetrics("service_name", normalized),
Key: "service.name",
DataType: v3.AttributeKeyDataTypeString,
Type: v3.AttributeKeyTypeTag,
},
@@ -139,17 +133,12 @@ func buildBuilderQueriesNetwork(
bq := make(map[string]*v3.BuilderQuery)
queryName := "latency"
normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
chq := &v3.BuilderQuery{
QueryName: queryName,
StepInterval: common.MinAllowedStepInterval(unixMilliStart, unixMilliEnd),
DataSource: v3.DataSourceMetrics,
AggregateAttribute: v3.AttributeKey{
Key: getDotMetrics("kafka_consumer_fetch_latency_avg", normalized),
Key: "kafka.consumer.fetch_latency_avg",
},
AggregateOperator: v3.AggregateOperatorAvg,
Temporality: v3.Unspecified,
@@ -160,7 +149,7 @@ func buildBuilderQueriesNetwork(
Items: []v3.FilterItem{
{
Key: v3.AttributeKey{
Key: getDotMetrics("service_name", normalized),
Key: "service.name",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeString,
},
@@ -169,7 +158,7 @@ func buildBuilderQueriesNetwork(
},
{
Key: v3.AttributeKey{
Key: getDotMetrics("client_id", normalized),
Key: "client-id",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeString,
},
@@ -178,7 +167,7 @@ func buildBuilderQueriesNetwork(
},
{
Key: v3.AttributeKey{
Key: getDotMetrics("service_instance_id", normalized),
Key: "service.instance.id",
Type: v3.AttributeKeyTypeTag,
DataType: v3.AttributeKeyDataTypeString,
},
@@ -191,17 +180,17 @@ func buildBuilderQueriesNetwork(
ReduceTo: v3.ReduceToOperatorAvg,
GroupBy: []v3.AttributeKey{
{
Key: getDotMetrics("service_name", normalized),
Key: "service.name",
DataType: v3.AttributeKeyDataTypeString,
Type: v3.AttributeKeyTypeTag,
},
{
Key: getDotMetrics("client_id", normalized),
Key: "client-id",
DataType: v3.AttributeKeyDataTypeString,
Type: v3.AttributeKeyTypeTag,
},
{
Key: getDotMetrics("service_instance_id", normalized),
Key: "service.instance.id",
DataType: v3.AttributeKeyDataTypeString,
Type: v3.AttributeKeyTypeTag,
},
@@ -218,17 +207,12 @@ func BuildBuilderQueriesKafkaOnboarding(messagingQueue *MessagingQueue) (*v3.Que
unixMilliStart := messagingQueue.Start / 1000000
unixMilliEnd := messagingQueue.End / 1000000
normalized := true
if constants.IsDotMetricsEnabled {
normalized = false
}
buiderQuery := &v3.BuilderQuery{
QueryName: "fetch_latency",
StepInterval: common.MinAllowedStepInterval(unixMilliStart, unixMilliEnd),
DataSource: v3.DataSourceMetrics,
AggregateAttribute: v3.AttributeKey{
Key: getDotMetrics("kafka_consumer_fetch_latency_avg", normalized),
Key: "kafka.consumer.fetch_latency_avg",
},
AggregateOperator: v3.AggregateOperatorCount,
Temporality: v3.Unspecified,
@@ -243,7 +227,7 @@ func BuildBuilderQueriesKafkaOnboarding(messagingQueue *MessagingQueue) (*v3.Que
StepInterval: common.MinAllowedStepInterval(unixMilliStart, unixMilliEnd),
DataSource: v3.DataSourceMetrics,
AggregateAttribute: v3.AttributeKey{
Key: getDotMetrics("kafka_consumer_group_lag", normalized),
Key: "kafka.consumer_group.lag",
},
AggregateOperator: v3.AggregateOperatorCount,
Temporality: v3.Unspecified,
@@ -427,19 +411,3 @@ func buildCompositeQuery(chq *v3.ClickHouseQuery, queryContext string) (*v3.Comp
PanelType: v3.PanelTypeTable,
}, nil
}
func getDotMetrics(metricName string, normalized bool) string {
dotMetricsMap := map[string]string{
"kafka_producer_byte_rate": "kafka.producer.byte-rate",
"service_name": "service.name",
"kafka_consumer_fetch_latency_avg": "kafka.consumer.fetch_latency_avg",
"service_instance_id": "service.instance.id",
"client_id": "client-id",
"kafka_consumer_group_lag": "kafka.consumer_group.lag",
}
if _, ok := dotMetricsMap[metricName]; ok && !normalized {
return dotMetricsMap[metricName]
} else {
return metricName
}
}

View File

@@ -258,11 +258,7 @@ func PrepareTimeseriesFilterQuery(start, end int64, mq *v3.BuilderQuery) (string
conditions = append(conditions, fmt.Sprintf("metric_name IN %s", utils.ClickHouseFormattedMetricNames(mq.AggregateAttribute.Key)))
conditions = append(conditions, fmt.Sprintf("temporality = '%s'", mq.Temporality))
if constants.IsDotMetricsEnabled {
conditions = append(conditions, "__normalized = false")
} else {
conditions = append(conditions, "__normalized = true")
}
conditions = append(conditions, "__normalized = false")
start, end, tableName := whichTSTableToUse(start, end, mq)
@@ -354,11 +350,7 @@ func PrepareTimeseriesFilterQueryV3(start, end int64, mq *v3.BuilderQuery) (stri
conditions = append(conditions, fmt.Sprintf("metric_name IN %s", utils.ClickHouseFormattedMetricNames(mq.AggregateAttribute.Key)))
conditions = append(conditions, fmt.Sprintf("temporality = '%s'", mq.Temporality))
if constants.IsDotMetricsEnabled {
conditions = append(conditions, "__normalized = false")
} else {
conditions = append(conditions, "__normalized = true")
}
conditions = append(conditions, "__normalized = false")
start, end, tableName := whichTSTableToUse(start, end, mq)

View File

@@ -6,9 +6,6 @@ import (
"strings"
"sync"
"github.com/prometheus/prometheus/promql/parser"
"github.com/SigNoz/signoz/pkg/errors"
logsV4 "github.com/SigNoz/signoz/pkg/query-service/app/logs/v4"
metricsV3 "github.com/SigNoz/signoz/pkg/query-service/app/metrics/v3"
metricsV4 "github.com/SigNoz/signoz/pkg/query-service/app/metrics/v4"
@@ -278,59 +275,3 @@ func (q *querier) runBuilderQuery(
Series: resultSeries,
}
}
// ValidateMetricNames function is used to print all those queries who are still using old normalized metrics and not new metrics.
func (q *querier) ValidateMetricNames(ctx context.Context, query *v3.CompositeQuery, orgID valuer.UUID) {
var metricNames []string
switch query.QueryType {
case v3.QueryTypePromQL:
for _, query := range query.PromQueries {
expr, err := q.parser.ParseExpr(query.Query)
if err != nil {
q.logger.DebugContext(ctx, "error parsing promql expression", "query", query.Query, errors.Attr(err))
continue
}
parser.Inspect(expr, func(node parser.Node, path []parser.Node) error {
if vs, ok := node.(*parser.VectorSelector); ok {
for _, m := range vs.LabelMatchers {
if m.Name == "__name__" {
metricNames = append(metricNames, m.Value)
}
}
}
return nil
})
}
metrics, err := q.reader.GetNormalizedStatus(ctx, orgID, metricNames)
if err != nil {
q.logger.DebugContext(ctx, "error getting corresponding normalized metrics", errors.Attr(err))
return
}
for metricName, metricPresent := range metrics {
if metricPresent {
continue
} else {
q.logger.WarnContext(ctx, "using normalized metric name", "metrics", metricName)
continue
}
}
case v3.QueryTypeBuilder:
for _, query := range query.BuilderQueries {
metricName := query.AggregateAttribute.Key
metricNames = append(metricNames, metricName)
}
metrics, err := q.reader.GetNormalizedStatus(ctx, orgID, metricNames)
if err != nil {
q.logger.DebugContext(ctx, "error getting corresponding normalized metrics", errors.Attr(err))
return
}
for metricName, metricPresent := range metrics {
if metricPresent {
continue
} else {
q.logger.WarnContext(ctx, "using normalized metric name", "metrics", metricName)
continue
}
}
}
}

View File

@@ -515,9 +515,6 @@ func (q *querier) QueryRange(ctx context.Context, orgID valuer.UUID, params *v3.
var results []*v3.Result
var err error
var errQueriesByName map[string]error
if !q.testingMode && q.reader != nil {
q.ValidateMetricNames(ctx, params.CompositeQuery, orgID)
}
if params.CompositeQuery != nil {
switch params.CompositeQuery.QueryType {
case v3.QueryTypeBuilder:

View File

@@ -212,7 +212,7 @@ func TestBuildQueryWithThreeOrMoreQueriesRefAndFormula(t *testing.T) {
// So(queries["F5"], ShouldContainSubstring, "SELECT A.ts as ts, ((A.value - B.value) / B.value) * 100")
// So(strings.Count(queries["F5"], " ON "), ShouldEqual, 1)
})
t.Run("TestBuildQueryWithDotMetricNameAndAttribute", func(t *testing.T) {
t.Run("TestBuildQueryWithMetricNameAndAttribute", func(t *testing.T) {
q := &v3.QueryRangeParamsV3{
Start: 1735036101000,
End: 1735637901000,

View File

@@ -3,7 +3,6 @@ package constants
import (
"maps"
"os"
"regexp"
"strconv"
"github.com/SigNoz/signoz/pkg/query-service/model"
@@ -26,12 +25,6 @@ const OrderBySpanCount = "span_count"
var MetricsExplorerClickhouseThreads = GetOrDefaultEnvInt("METRICS_EXPLORER_CLICKHOUSE_THREADS", 8)
var UpdatedMetricsMetadataCachePrefix = GetOrDefaultEnv("METRICS_UPDATED_METADATA_CACHE_KEY", "UPDATED_METRICS_METADATA")
const NormalizedMetricsMapCacheKey = "NORMALIZED_METRICS_MAP_CACHE_KEY"
const NormalizedMetricsMapQueryThreads = 10
var NormalizedMetricsMapRegex = regexp.MustCompile(`[^a-zA-Z0-9]`)
var NormalizedMetricsMapQuantileRegex = regexp.MustCompile(`(?i)([._-]?quantile.*)$`)
func GetEvalDelay() valuer.TextDuration {
evalDelayStr := GetOrDefaultEnv("RULES_EVAL_DELAY", "2m")
evalDelayDuration, err := valuer.ParseTextDuration(evalDelayStr)
@@ -671,16 +664,11 @@ var OldToNewTraceFieldsMap = map[string]string{
var StaticFieldsTraces = map[string]v3.AttributeKey{}
var IsDotMetricsEnabled = false
var MaxJSONFlatteningDepth = 1
func init() {
StaticFieldsTraces = maps.Clone(NewStaticFieldsTraces)
maps.Copy(StaticFieldsTraces, DeprecatedStaticFieldsTraces)
if GetOrDefaultEnv(DotMetricsEnabled, "true") == "true" {
IsDotMetricsEnabled = true
}
// set max flattening depth
depth, err := strconv.Atoi(GetOrDefaultEnv(maxJSONFlatteningDepth, "1"))
if err == nil {
@@ -708,5 +696,4 @@ var MaterializedDataTypeMap = map[string]string{
const InspectMetricsMaxTimeDiff = 1800000
const DotMetricsEnabled = "DOT_METRICS_ENABLED"
const maxJSONFlatteningDepth = "MAX_JSON_FLATTENING_DEPTH"

View File

@@ -108,7 +108,6 @@ type Reader interface {
GetUpdatedMetricsMetadata(ctx context.Context, orgID valuer.UUID, metricNames ...string) (map[string]*model.UpdateMetricsMetadata, *model.ApiError)
CheckForLabelsInMetric(ctx context.Context, orgID valuer.UUID, metricName string, labels []string) (bool, *model.ApiError)
GetNormalizedStatus(ctx context.Context, orgID valuer.UUID, metricNames []string) (map[string]bool, error)
}
type Querier interface {

View File

@@ -1,27 +1,14 @@
package metrics
var MetricsUnderTransition = map[string]string{
"k8s_pod_cpu_utilization": "k8s_pod_cpu_usage",
"k8s_node_cpu_utilization": "k8s_node_cpu_usage",
"container_cpu_utilization": "container_cpu_usage",
}
var DotMetricsUnderTransition = map[string]string{
"k8s.pod.cpu.utilization": "k8s.pod.cpu.usage",
"k8s.node.cpu.utilization": "k8s.node.cpu.usage",
"container.cpu.utilization": "container.cpu.usage",
}
func GetTransitionedMetric(metric string, normalized bool) string {
if normalized {
if _, ok := MetricsUnderTransition[metric]; ok {
return MetricsUnderTransition[metric]
}
return metric
} else {
if _, ok := DotMetricsUnderTransition[metric]; ok {
return DotMetricsUnderTransition[metric]
}
return metric
func GetTransitionedMetric(metric string) string {
if transitionedMetric, ok := MetricsUnderTransition[metric]; ok {
return transitionedMetric
}
return metric
}

View File

@@ -1,15 +0,0 @@
package model
import "encoding/json"
type MetricsNormalizedMap struct {
MetricName string `json:"metricName"`
IsUnNormalized bool `json:"isUnNormalized"`
}
func (c *MetricsNormalizedMap) MarshalBinary() (data []byte, err error) {
return json.Marshal(c)
}
func (c *MetricsNormalizedMap) UnmarshalBinary(data []byte) error {
return json.Unmarshal(data, c)
}

View File

@@ -234,7 +234,7 @@ func ClickHouseFormattedValue(v interface{}) string {
func ClickHouseFormattedMetricNames(v interface{}) string {
if name, ok := v.(string); ok {
transitionedMetrics := metrics.GetTransitionedMetric(name, !constants.IsDotMetricsEnabled)
transitionedMetrics := metrics.GetTransitionedMetric(name)
if transitionedMetrics != name {
return ClickHouseFormattedValue([]interface{}{transitionedMetrics})
} else {

View File

@@ -0,0 +1,22 @@
// Code generated by scripts/semconv. DO NOT EDIT.
package semconv
var families = []Family{
{
Current: "db.system.name",
Old: []string{"db.system"},
Kind: KindAttribute,
Contexts: nil,
Signals: nil,
ApplyToMetrics: nil,
},
{
Current: "deployment.environment.name",
Old: []string{"deployment.environment"},
Kind: KindAttribute,
Contexts: nil,
Signals: nil,
ApplyToMetrics: nil,
},
}

127
pkg/semconv/semconv.go Normal file
View File

@@ -0,0 +1,127 @@
package semconv
import (
"slices"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"github.com/SigNoz/signoz/pkg/valuer"
)
//go:generate go run ../../scripts/semconv
// Kind identifies whether a family describes an attribute or a metric name.
type Kind struct {
valuer.String
}
// Family is one logical telemetry field. Old is ordered from the most recent
// predecessor to the oldest one and therefore also defines fallback order.
type Family struct {
Current string
Old []string
Kind Kind
Contexts []telemetrytypes.FieldContext
Signals []telemetrytypes.Signal
ApplyToMetrics []string
ValueMap map[string]string
}
var (
KindAttribute = Kind{String: valuer.NewString("attribute")}
KindMetric = Kind{String: valuer.NewString("metric")}
)
var memberToFamilies, familyMembers = buildIndexes()
// Enum returns the acceptable values for Kind.
func (Kind) Enum() []any {
return []any{KindAttribute, KindMetric}
}
// Lookup returns the enabled family containing selector.Name for kind. The
// returned family must not be modified.
func Lookup(kind Kind, selector telemetrytypes.FieldKeySelector) (Family, bool) {
idx, ok := lookupIndex(kind, selector)
if !ok {
return Family{}, false
}
return families[idx], true
}
// Members returns the current name first, followed by historical names in
// fallback order. A name outside an enabled family is returned unchanged. The
// returned slice must not be modified.
func Members(kind Kind, selector telemetrytypes.FieldKeySelector) []string {
idx, ok := lookupIndex(kind, selector)
if !ok {
return []string{selector.Name}
}
return familyMembers[idx]
}
// Current returns the current name for selector.Name, or the input name when
// it does not belong to an enabled family.
func Current(kind Kind, selector telemetrytypes.FieldKeySelector) string {
idx, ok := lookupIndex(kind, selector)
if !ok {
return selector.Name
}
return families[idx].Current
}
// All returns every enabled family. The returned slice and families must not be
// modified.
func All() []Family {
return families
}
func buildIndexes() (map[string][]int, [][]string) {
index := make(map[string][]int)
members := make([][]string, len(families))
for i, family := range families {
members[i] = make([]string, 0, len(family.Old)+1)
members[i] = append(members[i], family.Current)
members[i] = append(members[i], family.Old...)
index[family.Current] = append(index[family.Current], i)
for _, old := range family.Old {
index[old] = append(index[old], i)
}
}
return index, members
}
func lookupIndex(kind Kind, selector telemetrytypes.FieldKeySelector) (int, bool) {
for _, idx := range memberToFamilies[selector.Name] {
if matchesSelector(families[idx], kind, selector) {
return idx, true
}
}
return 0, false
}
func matchesSelector(family Family, kind Kind, selector telemetrytypes.FieldKeySelector) bool {
if family.Kind != kind {
return false
}
if selector.Signal != telemetrytypes.SignalUnspecified && len(family.Signals) > 0 {
if !slices.Contains(family.Signals, selector.Signal) {
return false
}
}
if selector.FieldContext != telemetrytypes.FieldContextUnspecified && len(family.Contexts) > 0 {
if !slices.Contains(family.Contexts, selector.FieldContext) {
return false
}
}
if selector.Signal == telemetrytypes.SignalMetrics && len(family.ApplyToMetrics) > 0 {
if selector.MetricContext == nil {
return false
}
return slices.Contains(family.ApplyToMetrics, selector.MetricContext.MetricName)
}
return true
}

View File

@@ -0,0 +1,80 @@
package semconv
import (
"testing"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"github.com/stretchr/testify/assert"
)
func TestMembersReturnsCurrentBeforeHistoricalName(t *testing.T) {
selector := telemetrytypes.FieldKeySelector{
Name: "deployment.environment",
Signal: telemetrytypes.SignalTraces,
FieldContext: telemetrytypes.FieldContextResource,
}
assert.Equal(t,
[]string{"deployment.environment.name", "deployment.environment"},
Members(KindAttribute, selector),
"members should use current-first fallback order",
)
}
func TestCurrentReturnsCanonicalName(t *testing.T) {
selector := telemetrytypes.FieldKeySelector{
Name: "deployment.environment",
Signal: telemetrytypes.SignalTraces,
FieldContext: telemetrytypes.FieldContextResource,
}
assert.Equal(t,
"deployment.environment.name",
Current(KindAttribute, selector),
"historical name should resolve to the current family name",
)
}
func TestAllScopedFamilyMatchesSupportedScopes(t *testing.T) {
tests := []struct {
name string
signal telemetrytypes.Signal
fieldContext telemetrytypes.FieldContext
}{
{name: "trace resource", signal: telemetrytypes.SignalTraces, fieldContext: telemetrytypes.FieldContextResource},
{name: "trace attribute", signal: telemetrytypes.SignalTraces, fieldContext: telemetrytypes.FieldContextAttribute},
{name: "log resource", signal: telemetrytypes.SignalLogs, fieldContext: telemetrytypes.FieldContextResource},
{name: "log attribute", signal: telemetrytypes.SignalLogs, fieldContext: telemetrytypes.FieldContextAttribute},
{name: "metric resource", signal: telemetrytypes.SignalMetrics, fieldContext: telemetrytypes.FieldContextResource},
{name: "metric attribute", signal: telemetrytypes.SignalMetrics, fieldContext: telemetrytypes.FieldContextAttribute},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
selector := telemetrytypes.FieldKeySelector{
Name: "deployment.environment",
Signal: test.signal,
FieldContext: test.fieldContext,
}
assert.Equal(t,
"deployment.environment.name",
Current(KindAttribute, selector),
"an all-scoped family should match every supported signal and attribute context",
)
})
}
}
func TestMembersReturnsInputWhenKindDoesNotMatch(t *testing.T) {
selector := telemetrytypes.FieldKeySelector{
Name: "deployment.environment",
Signal: telemetrytypes.SignalTraces,
}
assert.Equal(t,
[]string{"deployment.environment"},
Members(KindMetric, selector),
"an attribute family must not match a metric-name lookup",
)
}

View File

@@ -12,8 +12,7 @@ var (
Gateway = valuer.NewString("gateway")
PremiumSupport = valuer.NewString("premium_support")
AnomalyDetection = valuer.NewString("anomaly_detection")
DotMetricsEnabled = valuer.NewString("dot_metrics_enabled")
AnomalyDetection = valuer.NewString("anomaly_detection")
// License State.
LicenseStatusInvalid = valuer.NewString("invalid")
@@ -60,13 +59,6 @@ var BasicPlan = []*Feature{
UsageLimit: -1,
Route: "",
},
{
Name: DotMetricsEnabled,
Active: false,
Usage: 0,
UsageLimit: -1,
Route: "",
},
}
var EnterprisePlan = []*Feature{
@@ -112,21 +104,6 @@ var EnterprisePlan = []*Feature{
UsageLimit: -1,
Route: "",
},
{
Name: DotMetricsEnabled,
Active: false,
Usage: 0,
UsageLimit: -1,
Route: "",
},
}
var DefaultFeatureSet = []*Feature{
{
Name: DotMetricsEnabled,
Active: false,
Usage: 0,
UsageLimit: -1,
Route: "",
},
}
var DefaultFeatureSet = []*Feature{}

721
scripts/semconv/generate.go Normal file
View File

@@ -0,0 +1,721 @@
package main
import (
"bytes"
"errors"
"flag"
"fmt"
"go/format"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"gopkg.in/yaml.v3"
)
const (
kindAttribute = "attribute"
kindMetric = "metric"
)
type stringListFlag []string
func (f *stringListFlag) String() string { return strings.Join(*f, ",") }
func (f *stringListFlag) Set(value string) error {
*f = append(*f, value)
return nil
}
type schemaFile struct {
FileFormat string `yaml:"file_format"`
SchemaURL string `yaml:"schema_url"`
Versions map[string]schemaVersion `yaml:"versions"`
}
type schemaVersion struct {
All changeSection `yaml:"all"`
Resources changeSection `yaml:"resources"`
Spans changeSection `yaml:"spans"`
Logs changeSection `yaml:"logs"`
Metrics changeSection `yaml:"metrics"`
}
type changeSection struct {
Changes []schemaChange `yaml:"changes"`
}
type schemaChange struct {
RenameAttributes *attributeRename `yaml:"rename_attributes"`
RenameMetrics map[string]string `yaml:"rename_metrics"`
}
type attributeRename struct {
AttributeMap map[string]string `yaml:"attribute_map"`
ApplyToMetrics []string `yaml:"apply_to_metrics"`
}
type overlayFile struct {
DefaultEnabled bool `yaml:"default_enabled"`
// Families is keyed only by current name. One name cannot carry separate
// policies for attribute and metric families; set kind explicitly whenever
// a metric-name family is configured.
Families map[string]overlayFamily `yaml:"families"`
}
type overlayFamily struct {
Enabled *bool `yaml:"enabled"`
Kind string `yaml:"kind"`
Old []string `yaml:"old"`
AddOld []string `yaml:"add_old"`
ExcludeOld []string `yaml:"exclude_old"`
Contexts []string `yaml:"contexts"`
Signals []string `yaml:"signals"`
AddContexts []string `yaml:"add_contexts"`
AddSignals []string `yaml:"add_signals"`
ApplyToMetrics []string `yaml:"apply_to_metrics"`
AddApplyToMetrics []string `yaml:"add_apply_to_metrics"`
ValueMap map[string]string `yaml:"value_map"`
}
type edge struct {
old string
current string
kind string
contexts []string
signals []string
allContexts bool
allSignals bool
applyToMetrics []string
}
type graphKey struct{ kind, name string }
type generatedFamily struct {
Current string
Old []string
Kind string
Contexts []string
Signals []string
ApplyToMetrics []string
ValueMap map[string]string
}
func main() {
root, err := findRepoRoot()
if err != nil {
fatal(err)
}
var schemaPaths stringListFlag
flag.Var(&schemaPaths, "schema", "schema source (repeatable)")
overlayPath := flag.String("overlay", filepath.Join(root, "scripts/semconv/overlay.yaml"), "SigNoz overlay")
goOutput := flag.String("go-out", filepath.Join(root, "pkg/semconv/families_gen.go"), "generated Go output")
tsOutput := flag.String("ts-out", filepath.Join(root, "frontend/src/constants/generated/semconvFamilies.gen.ts"), "generated TypeScript output")
check := flag.Bool("check", false, "fail if generated files are stale")
flag.Parse()
if len(schemaPaths) == 0 {
schemaPaths = append(schemaPaths, filepath.Join(root, "scripts/semconv/schema-1.42.0.yaml"))
}
families, err := generate(schemaPaths, *overlayPath)
if err != nil {
fatal(err)
}
goBytes, err := renderGo(families)
if err != nil {
fatal(err)
}
tsBytes := renderTypeScript(families)
if *check {
if err := checkFile(*goOutput, goBytes); err != nil {
fatal(err)
}
if err := checkFile(*tsOutput, tsBytes); err != nil {
fatal(err)
}
return
}
if err := os.WriteFile(*goOutput, goBytes, 0o644); err != nil {
fatal(err)
}
if err := os.WriteFile(*tsOutput, tsBytes, 0o644); err != nil {
fatal(err)
}
}
func fatal(err error) {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
func findRepoRoot() (string, error) {
dir, err := os.Getwd()
if err != nil {
return "", err
}
for {
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
return dir, nil
}
parent := filepath.Dir(dir)
if parent == dir {
return "", errors.New("could not find repository root")
}
dir = parent
}
}
func generate(schemaPaths []string, overlayPath string) ([]generatedFamily, error) {
var schemas []schemaFile
for _, path := range schemaPaths {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("read schema %s: %w", path, err)
}
var schema schemaFile
if err := decodeKnownFields(data, &schema); err != nil {
return nil, fmt.Errorf("parse schema %s: %w", path, err)
}
schemas = append(schemas, schema)
}
overlayData, err := os.ReadFile(overlayPath)
if err != nil {
return nil, fmt.Errorf("read overlay: %w", err)
}
var overlay overlayFile
if err := decodeKnownFields(overlayData, &overlay); err != nil {
return nil, fmt.Errorf("parse overlay: %w", err)
}
return buildFamilies(schemas, overlay)
}
func decodeKnownFields(data []byte, target any) error {
decoder := yaml.NewDecoder(bytes.NewReader(data))
decoder.KnownFields(true)
return decoder.Decode(target)
}
func collectEdges(schemas []schemaFile) ([]edge, error) {
var edges []edge
for _, schema := range schemas {
versions := make([]string, 0, len(schema.Versions))
versionParts := make(map[string][3]int, len(schema.Versions))
for version := range schema.Versions {
parts, err := parseSchemaVersion(version)
if err != nil {
return nil, err
}
versions = append(versions, version)
versionParts[version] = parts
}
sort.Slice(versions, func(i, j int) bool {
return compareVersionParts(versionParts[versions[i]], versionParts[versions[j]]) < 0
})
for _, versionName := range versions {
version := schema.Versions[versionName]
var versionEdges []edge
sections := []struct {
name string
section changeSection
}{
{name: "all", section: version.All},
{name: "resources", section: version.Resources},
{name: "spans", section: version.Spans},
{name: "logs", section: version.Logs},
{name: "metrics", section: version.Metrics},
}
for _, scoped := range sections {
contexts, signals, allContexts, allSignals, err := scopeForSection(scoped.name)
if err != nil {
return nil, err
}
for _, change := range scoped.section.Changes {
if change.RenameAttributes != nil {
for _, old := range sortedMapKeys(change.RenameAttributes.AttributeMap) {
versionEdges = append(versionEdges, edge{
old: old, current: change.RenameAttributes.AttributeMap[old], kind: kindAttribute,
contexts: contexts, signals: signals,
allContexts: allContexts, allSignals: allSignals,
applyToMetrics: change.RenameAttributes.ApplyToMetrics,
})
}
}
for _, old := range sortedMapKeys(change.RenameMetrics) {
versionEdges = append(versionEdges, edge{
old: old, current: change.RenameMetrics[old], kind: kindMetric,
contexts: []string{"metric"}, signals: []string{"metrics"},
})
}
}
}
if err := rejectSameVersionChains(versionName, versionEdges); err != nil {
return nil, err
}
edges = append(edges, versionEdges...)
}
}
return edges, nil
}
func rejectSameVersionChains(version string, edges []edge) error {
oldNames := make(map[graphKey]struct{}, len(edges))
for _, item := range edges {
oldNames[graphKey{kind: item.kind, name: item.old}] = struct{}{}
}
for _, item := range edges {
if _, ok := oldNames[graphKey{kind: item.kind, name: item.current}]; ok {
return fmt.Errorf(
"schema version %q contains a same-version %s rename chain through %q",
version,
item.kind,
item.current,
)
}
}
return nil
}
func parseSchemaVersion(version string) ([3]int, error) {
parts := strings.Split(version, ".")
if len(parts) != 3 {
return [3]int{}, fmt.Errorf("schema version %q must contain major, minor, and patch numbers", version)
}
var parsed [3]int
for i, part := range parts {
value, err := strconv.Atoi(part)
if err != nil || value < 0 {
return [3]int{}, fmt.Errorf("schema version %q contains invalid numeric component %q", version, part)
}
parsed[i] = value
}
return parsed, nil
}
func compareVersionParts(left, right [3]int) int {
for i := range left {
if left[i] < right[i] {
return -1
}
if left[i] > right[i] {
return 1
}
}
return 0
}
func scopeForSection(section string) (contexts, signals []string, allContexts, allSignals bool, err error) {
switch section {
case "all":
return nil, nil, true, true, nil
case "resources":
return []string{"resource"}, nil, false, true, nil
case "spans":
return []string{"attribute"}, []string{"traces"}, false, false, nil
case "logs":
return []string{"attribute"}, []string{"logs"}, false, false, nil
case "metrics":
return []string{"attribute"}, []string{"metrics"}, false, false, nil
default:
return nil, nil, false, false, fmt.Errorf("unsupported schema section %q", section)
}
}
func buildFamilies(schemas []schemaFile, overlay overlayFile) ([]generatedFamily, error) {
edges, err := collectEdges(schemas)
if err != nil {
return nil, err
}
next := make(map[graphKey]string)
for _, item := range edges {
key := graphKey{kind: item.kind, name: item.old}
if existing, ok := next[key]; ok && existing == item.current {
// Repeated entries are common in chained schema histories. Treat an
// identical edge as a no-op so it cannot sever a later edge in the
// same chain (A -> B, B -> C, then a repeated A -> B).
continue
}
// Schema history occasionally repeats an old name with a newer direct
// destination or rolls a rename back. Edges are collected
// oldest-to-newest, so the latest published current name must be a root.
delete(next, graphKey{kind: item.kind, name: item.current})
next[key] = item.current
}
type familyState struct {
family generatedFamily
distance map[string]int
allContexts bool
allSignals bool
}
states := map[graphKey]*familyState{}
for _, item := range edges {
root, distance, err := rootFor(next, item.kind, item.old)
if err != nil {
return nil, err
}
key := graphKey{kind: item.kind, name: root}
state := states[key]
if state == nil {
state = &familyState{
family: generatedFamily{Current: root, Kind: item.kind},
distance: map[string]int{},
}
states[key] = state
}
if prior, ok := state.distance[item.old]; !ok || distance < prior {
state.distance[item.old] = distance
}
state.allContexts = state.allContexts || item.allContexts
state.allSignals = state.allSignals || item.allSignals
state.family.Contexts = appendUnique(state.family.Contexts, item.contexts...)
state.family.Signals = appendUnique(state.family.Signals, item.signals...)
state.family.ApplyToMetrics = appendUnique(state.family.ApplyToMetrics, item.applyToMetrics...)
}
for _, state := range states {
for old := range state.distance {
if old != state.family.Current {
state.family.Old = append(state.family.Old, old)
}
}
sort.Slice(state.family.Old, func(i, j int) bool {
left, right := state.family.Old[i], state.family.Old[j]
if state.distance[left] != state.distance[right] {
return state.distance[left] < state.distance[right]
}
return left < right
})
if state.allContexts {
state.family.Contexts = nil
} else {
sort.Strings(state.family.Contexts)
}
if state.allSignals {
state.family.Signals = nil
} else {
sort.Strings(state.family.Signals)
}
sort.Strings(state.family.ApplyToMetrics)
}
for _, current := range sortedMapKeys(overlay.Families) {
policy := overlay.Families[current]
kind, err := normalizedOverlayKind(current, policy)
if err != nil {
return nil, err
}
policy.Kind = kind
overlay.Families[current] = policy
key := graphKey{kind: kind, name: current}
state := states[key]
if state == nil {
if len(policy.Old) == 0 {
return nil, fmt.Errorf(
"overlay family %q with kind %q is absent from schemas and has no old members",
current,
kind,
)
}
state = &familyState{
family: generatedFamily{Current: current, Kind: kind, Old: append([]string(nil), policy.Old...)},
distance: map[string]int{},
}
states[key] = state
}
applyOverlay(&state.family, policy)
}
var result []generatedFamily
for key, state := range states {
policy, hasPolicy := overlay.Families[key.name]
enabled := overlay.DefaultEnabled
if hasPolicy && policy.Kind != key.kind {
hasPolicy = false
}
if hasPolicy && policy.Enabled != nil {
enabled = *policy.Enabled
}
if !enabled {
continue
}
if len(state.family.Old) == 0 {
return nil, fmt.Errorf(
"enabled family %q with kind %q has no old members",
state.family.Current,
state.family.Kind,
)
}
sort.Strings(state.family.Contexts)
sort.Strings(state.family.Signals)
sort.Strings(state.family.ApplyToMetrics)
result = append(result, state.family)
}
sort.Slice(result, func(i, j int) bool {
if result[i].Current != result[j].Current {
return result[i].Current < result[j].Current
}
return result[i].Kind < result[j].Kind
})
return result, nil
}
func rootFor(next map[graphKey]string, kind, name string) (string, int, error) {
seen := map[string]bool{}
distance := 0
for {
if seen[name] {
return "", 0, fmt.Errorf("rename cycle for %s %q", kind, name)
}
seen[name] = true
current, ok := next[graphKey{kind: kind, name: name}]
if !ok {
return name, distance, nil
}
name = current
distance++
}
}
func normalizedOverlayKind(current string, policy overlayFamily) (string, error) {
kind := policy.Kind
if kind == "" {
kind = kindAttribute
}
if kind != kindAttribute && kind != kindMetric {
return "", fmt.Errorf("overlay family %q has unsupported kind %q", current, kind)
}
return kind, nil
}
func applyOverlay(family *generatedFamily, policy overlayFamily) {
if policy.Kind != "" {
family.Kind = policy.Kind
}
if policy.Old != nil {
family.Old = append([]string(nil), policy.Old...)
}
family.Old = appendUnique(family.Old, policy.AddOld...)
if len(policy.ExcludeOld) > 0 {
excluded := make(map[string]bool, len(policy.ExcludeOld))
for _, old := range policy.ExcludeOld {
excluded[old] = true
}
family.Old = deleteMatching(family.Old, excluded)
}
if policy.Contexts != nil {
family.Contexts = append([]string(nil), policy.Contexts...)
}
if policy.Signals != nil {
family.Signals = append([]string(nil), policy.Signals...)
}
family.Contexts = appendUnique(family.Contexts, policy.AddContexts...)
family.Signals = appendUnique(family.Signals, policy.AddSignals...)
if policy.ApplyToMetrics != nil {
family.ApplyToMetrics = append([]string(nil), policy.ApplyToMetrics...)
}
family.ApplyToMetrics = appendUnique(family.ApplyToMetrics, policy.AddApplyToMetrics...)
if policy.ValueMap != nil {
family.ValueMap = make(map[string]string, len(policy.ValueMap))
for old, current := range policy.ValueMap {
family.ValueMap[old] = current
}
}
}
func appendUnique(values []string, additions ...string) []string {
seen := make(map[string]bool, len(values)+len(additions))
for _, value := range values {
seen[value] = true
}
for _, value := range additions {
if value == "" || seen[value] {
continue
}
seen[value] = true
values = append(values, value)
}
return values
}
func deleteMatching(values []string, excluded map[string]bool) []string {
result := values[:0]
for _, value := range values {
if !excluded[value] {
result = append(result, value)
}
}
return result
}
func renderGo(families []generatedFamily) ([]byte, error) {
var out bytes.Buffer
out.WriteString("// Code generated by scripts/semconv. DO NOT EDIT.\n\n")
out.WriteString("package semconv\n\n")
needsTelemetryTypes := false
for _, family := range families {
if len(family.Contexts) > 0 || len(family.Signals) > 0 {
needsTelemetryTypes = true
break
}
}
if needsTelemetryTypes {
out.WriteString("import \"github.com/SigNoz/signoz/pkg/types/telemetrytypes\"\n\n")
}
out.WriteString("var families = []Family{\n")
for _, family := range families {
contexts, err := goFieldContextSlice(family.Contexts)
if err != nil {
return nil, fmt.Errorf("render family %q: %w", family.Current, err)
}
signals, err := goSignalSlice(family.Signals)
if err != nil {
return nil, fmt.Errorf("render family %q: %w", family.Current, err)
}
out.WriteString("\t{\n")
fmt.Fprintf(&out, "\t\tCurrent: %s,\n", strconv.Quote(family.Current))
fmt.Fprintf(&out, "\t\tOld: %s,\n", goStringSlice(family.Old))
if family.Kind == kindMetric {
out.WriteString("\t\tKind: KindMetric,\n")
} else {
out.WriteString("\t\tKind: KindAttribute,\n")
}
fmt.Fprintf(&out, "\t\tContexts: %s,\n", contexts)
fmt.Fprintf(&out, "\t\tSignals: %s,\n", signals)
fmt.Fprintf(&out, "\t\tApplyToMetrics: %s,\n", goStringSlice(family.ApplyToMetrics))
if len(family.ValueMap) > 0 {
out.WriteString("\t\tValueMap: map[string]string{\n")
keys := sortedMapKeys(family.ValueMap)
for _, key := range keys {
fmt.Fprintf(&out, "\t\t\t%s: %s,\n", strconv.Quote(key), strconv.Quote(family.ValueMap[key]))
}
out.WriteString("\t\t},\n")
}
out.WriteString("\t},\n")
}
out.WriteString("}\n")
return format.Source(out.Bytes())
}
func goStringSlice(values []string) string {
if len(values) == 0 {
return "nil"
}
quoted := make([]string, len(values))
for i, value := range values {
quoted[i] = strconv.Quote(value)
}
return "[]string{" + strings.Join(quoted, ", ") + "}"
}
func goFieldContextSlice(values []string) (string, error) {
if len(values) == 0 {
return "nil", nil
}
constants := make([]string, len(values))
for i, value := range values {
switch value {
case "metric":
constants[i] = "telemetrytypes.FieldContextMetric"
case "resource":
constants[i] = "telemetrytypes.FieldContextResource"
case "attribute":
constants[i] = "telemetrytypes.FieldContextAttribute"
default:
return "", fmt.Errorf("unsupported field context %q", value)
}
}
return "[]telemetrytypes.FieldContext{" + strings.Join(constants, ", ") + "}", nil
}
func goSignalSlice(values []string) (string, error) {
if len(values) == 0 {
return "nil", nil
}
constants := make([]string, len(values))
for i, value := range values {
switch value {
case "traces":
constants[i] = "telemetrytypes.SignalTraces"
case "logs":
constants[i] = "telemetrytypes.SignalLogs"
case "metrics":
constants[i] = "telemetrytypes.SignalMetrics"
default:
return "", fmt.Errorf("unsupported signal %q", value)
}
}
return "[]telemetrytypes.Signal{" + strings.Join(constants, ", ") + "}", nil
}
func renderTypeScript(families []generatedFamily) []byte {
var out bytes.Buffer
out.WriteString("// Code generated by scripts/semconv. DO NOT EDIT.\n\n")
out.WriteString("export type SemconvFamily = {\n")
out.WriteString("\treadonly current: string;\n\treadonly old: readonly string[];\n")
out.WriteString("\treadonly kind: 'attribute' | 'metric';\n")
out.WriteString("\treadonly contexts: readonly string[];\n\treadonly signals: readonly string[];\n")
out.WriteString("\treadonly applyToMetrics: readonly string[];\n")
out.WriteString("\treadonly valueMap: Readonly<Record<string, string>>;\n};\n\n")
out.WriteString("export const SEMCONV_FAMILIES: readonly SemconvFamily[] = [\n")
for _, family := range families {
out.WriteString("\t{\n")
fmt.Fprintf(&out, "\t\tcurrent: %s,\n", tsString(family.Current))
fmt.Fprintf(&out, "\t\told: %s,\n", tsStringSlice(family.Old))
fmt.Fprintf(&out, "\t\tkind: %s,\n", tsString(family.Kind))
fmt.Fprintf(&out, "\t\tcontexts: %s,\n", tsStringSlice(family.Contexts))
fmt.Fprintf(&out, "\t\tsignals: %s,\n", tsStringSlice(family.Signals))
fmt.Fprintf(&out, "\t\tapplyToMetrics: %s,\n", tsStringSlice(family.ApplyToMetrics))
out.WriteString("\t\tvalueMap: {")
keys := sortedMapKeys(family.ValueMap)
for i, key := range keys {
if i > 0 {
out.WriteString(", ")
}
fmt.Fprintf(&out, "%s: %s", tsString(key), tsString(family.ValueMap[key]))
}
out.WriteString("},\n\t},\n")
}
out.WriteString("] as const;\n")
return out.Bytes()
}
func tsString(value string) string {
quoted := strconv.Quote(value)
return "'" + strings.ReplaceAll(quoted[1:len(quoted)-1], "'", `\'`) + "'"
}
func tsStringSlice(values []string) string {
quoted := make([]string, len(values))
for i, value := range values {
quoted[i] = tsString(value)
}
return "[" + strings.Join(quoted, ", ") + "]"
}
func sortedMapKeys[T any](values map[string]T) []string {
keys := make([]string, 0, len(values))
for key := range values {
keys = append(keys, key)
}
sort.Strings(keys)
return keys
}
func checkFile(path string, expected []byte) error {
actual, err := os.ReadFile(path)
if err != nil {
return fmt.Errorf("generated file %s is missing: run go run ./scripts/semconv", path)
}
if !bytes.Equal(actual, expected) {
return fmt.Errorf("generated file %s is stale: run go run ./scripts/semconv", path)
}
return nil
}

View File

@@ -0,0 +1,376 @@
package main
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestSchemaDecoderRejectsUnsupportedSection(t *testing.T) {
var schema schemaFile
err := decodeKnownFields([]byte(`
versions:
1.0.0:
span_events:
changes:
- rename_events:
event_map:
old: current
`), &schema)
assert.ErrorContains(t, err, "field span_events not found", "unsupported schema sections must fail generation")
}
func TestBuildFamiliesRejectsMalformedSchemaVersion(t *testing.T) {
var schema schemaFile
require.NoError(t, decodeKnownFields([]byte(`
versions:
latest:
spans:
changes: []
`), &schema), "test schema must decode")
_, err := buildFamilies([]schemaFile{schema}, overlayFile{})
assert.ErrorContains(t, err, `schema version "latest"`, "malformed versions must not be silently reordered")
}
func TestBuildFamiliesResolvesRenameChain(t *testing.T) {
var schema schemaFile
require.NoError(t, decodeKnownFields([]byte(`
versions:
4.0.0:
spans:
changes:
- rename_attributes:
attribute_map:
a: b
3.0.0:
spans:
changes:
- rename_attributes:
attribute_map:
b: c
x: c
2.0.0:
spans:
changes:
- rename_attributes:
attribute_map:
a: b
- rename_attributes:
attribute_map:
a: b
`), &schema), "test schema must decode")
enabled := true
families, err := buildFamilies([]schemaFile{schema}, overlayFile{Families: map[string]overlayFamily{
"c": {Enabled: &enabled},
}})
require.NoError(t, err)
assert.Equal(t, []generatedFamily{{
Current: "c",
Old: []string{"b", "x", "a"},
Kind: kindAttribute,
Contexts: []string{"attribute"},
Signals: []string{"traces"},
}}, families, "predecessors should be ordered by distance and then name")
}
func TestBuildFamiliesMapsSchemaSectionsToScopes(t *testing.T) {
var schema schemaFile
require.NoError(t, decodeKnownFields([]byte(`
versions:
1.0.0:
all:
changes:
- rename_attributes:
attribute_map:
all.old: all.current
resources:
changes:
- rename_attributes:
attribute_map:
resource.old: resource.current
logs:
changes:
- rename_attributes:
attribute_map:
log.old: log.current
metrics:
changes:
- rename_attributes:
attribute_map:
state: cpu.mode
apply_to_metrics: [system.cpu.time]
- rename_metrics:
old.metric: current.metric
`), &schema), "test schema must decode")
enabled := true
families, err := buildFamilies([]schemaFile{schema}, overlayFile{Families: map[string]overlayFamily{
"all.current": {Enabled: &enabled},
"resource.current": {Enabled: &enabled},
"log.current": {Enabled: &enabled},
"cpu.mode": {Enabled: &enabled},
"current.metric": {Enabled: &enabled, Kind: kindMetric},
}})
require.NoError(t, err)
assert.Equal(t, []generatedFamily{
{
Current: "all.current", Old: []string{"all.old"}, Kind: kindAttribute,
Contexts: nil, Signals: nil,
},
{
Current: "cpu.mode", Old: []string{"state"}, Kind: kindAttribute,
Contexts: []string{"attribute"}, Signals: []string{"metrics"},
ApplyToMetrics: []string{"system.cpu.time"},
},
{
Current: "current.metric", Old: []string{"old.metric"}, Kind: kindMetric,
Contexts: []string{"metric"}, Signals: []string{"metrics"},
},
{
Current: "log.current", Old: []string{"log.old"}, Kind: kindAttribute,
Contexts: []string{"attribute"}, Signals: []string{"logs"},
},
{
Current: "resource.current", Old: []string{"resource.old"}, Kind: kindAttribute,
Contexts: []string{"resource"},
},
}, families, "schema sections should produce their documented signal and context scopes")
}
func TestOverlayAddsFamilyWithoutSchemaHistory(t *testing.T) {
enabled := true
families, err := buildFamilies(nil, overlayFile{Families: map[string]overlayFamily{
"added.current": {
Enabled: &enabled,
Old: []string{"added.old"},
Contexts: []string{"resource"},
Signals: []string{"traces"},
},
}})
require.NoError(t, err)
assert.Equal(t, []generatedFamily{{
Current: "added.current",
Old: []string{"added.old"},
Kind: kindAttribute,
Contexts: []string{"resource"},
Signals: []string{"traces"},
}}, families, "an explicit overlay family should not require schema history")
}
func TestOverlayOverridesGeneratedFamily(t *testing.T) {
var schema schemaFile
require.NoError(t, decodeKnownFields([]byte(`
versions:
1.0.0:
spans:
changes:
- rename_attributes:
attribute_map:
old: current
`), &schema), "test schema must decode")
enabled := true
families, err := buildFamilies([]schemaFile{schema}, overlayFile{Families: map[string]overlayFamily{
"current": {
Enabled: &enabled,
AddOld: []string{"older"},
ExcludeOld: []string{"old"},
AddContexts: []string{"resource"},
AddSignals: []string{"logs"},
ValueMap: map[string]string{"legacy": "current"},
},
}})
require.NoError(t, err)
assert.Equal(t, []generatedFamily{{
Current: "current",
Old: []string{"older"},
Kind: kindAttribute,
Contexts: []string{"attribute", "resource"},
Signals: []string{"logs", "traces"},
ValueMap: map[string]string{"legacy": "current"},
}}, families, "overlay additions and exclusions should be applied to the generated family")
}
func TestOverlayDisablesFamilyWhenDefaultIsEnabled(t *testing.T) {
var schema schemaFile
require.NoError(t, decodeKnownFields([]byte(`
versions:
1.0.0:
spans:
changes:
- rename_attributes:
attribute_map:
old: current
`), &schema), "test schema must decode")
disabled := false
families, err := buildFamilies([]schemaFile{schema}, overlayFile{
DefaultEnabled: true,
Families: map[string]overlayFamily{
"current": {Enabled: &disabled},
},
})
require.NoError(t, err)
assert.Empty(t, families, "an explicitly disabled family must override default_enabled")
}
func TestRenderGoIsDeterministic(t *testing.T) {
families := []generatedFamily{{
Current: "current", Old: []string{"old"}, Kind: kindAttribute,
ValueMap: map[string]string{"b": "2", "a": "1"},
}}
first, err := renderGo(families)
require.NoError(t, err)
second, err := renderGo(families)
require.NoError(t, err)
assert.Equal(t, first, second, "Go generation must not depend on map iteration order")
}
func TestRenderGoUsesCanonicalTelemetryTypes(t *testing.T) {
families := []generatedFamily{{
Current: "current", Old: []string{"old"}, Kind: kindAttribute,
Contexts: []string{"resource"}, Signals: []string{"traces"},
}}
output, err := renderGo(families)
require.NoError(t, err)
assert.Contains(t, string(output), "telemetrytypes.FieldContextResource", "generated contexts should use telemetrytypes")
assert.Contains(t, string(output), "telemetrytypes.SignalTraces", "generated signals should use telemetrytypes")
}
func TestRenderTypeScriptIsDeterministic(t *testing.T) {
families := []generatedFamily{{
Current: "current", Old: []string{"old"}, Kind: kindAttribute,
ValueMap: map[string]string{"b": "2", "a": "1"},
}}
assert.Equal(t, renderTypeScript(families), renderTypeScript(families), "TypeScript generation must not depend on map iteration order")
}
func TestBuildFamiliesHandlesRenameRollback(t *testing.T) {
var schema schemaFile
require.NoError(t, decodeKnownFields([]byte(`
versions:
2.0.0:
metrics:
changes:
- rename_metrics:
temporary: original
1.0.0:
metrics:
changes:
- rename_metrics:
original: temporary
`), &schema), "test schema must decode")
enabled := true
families, err := buildFamilies([]schemaFile{schema}, overlayFile{Families: map[string]overlayFamily{
"original": {Enabled: &enabled, Kind: kindMetric},
}})
require.NoError(t, err)
assert.Equal(t, []generatedFamily{{
Current: "original",
Old: []string{"temporary"},
Kind: kindMetric,
Contexts: []string{"metric"},
Signals: []string{"metrics"},
}}, families, "the latest rollback destination should remain the family root")
}
func TestBuildFamiliesRejectsSameVersionRenameChain(t *testing.T) {
var schema schemaFile
require.NoError(t, decodeKnownFields([]byte(`
versions:
1.0.0:
spans:
changes:
- rename_attributes:
attribute_map:
x: y
y: z
`), &schema), "test schema must decode")
_, err := buildFamilies([]schemaFile{schema}, overlayFile{})
assert.ErrorContains(t, err, `same-version attribute rename chain through "y"`, "order-sensitive same-version chains must be rejected")
}
func TestBuildFamiliesRejectsOverlayFamilyWithoutHistory(t *testing.T) {
enabled := true
_, err := buildFamilies(nil, overlayFile{Families: map[string]overlayFamily{
"missing": {Enabled: &enabled},
}})
assert.ErrorContains(t, err, `overlay family "missing" with kind "attribute" is absent`, "an overlay cannot invent a family without old members")
}
func TestBuildFamiliesRejectsEnabledFamilyWithoutOldMembers(t *testing.T) {
var schema schemaFile
require.NoError(t, decodeKnownFields([]byte(`
versions:
1.0.0:
spans:
changes:
- rename_attributes:
attribute_map:
old: current
`), &schema), "test schema must decode")
enabled := true
_, err := buildFamilies([]schemaFile{schema}, overlayFile{Families: map[string]overlayFamily{
"current": {Enabled: &enabled, ExcludeOld: []string{"old"}},
}})
assert.ErrorContains(t, err, `enabled family "current" with kind "attribute" has no old members`, "exclude_old cannot empty an enabled family")
}
func TestOverlayKindDefaultsToAttribute(t *testing.T) {
var schema schemaFile
require.NoError(t, decodeKnownFields([]byte(`
versions:
1.0.0:
spans:
changes:
- rename_attributes:
attribute_map:
attribute.old: shared.current
metrics:
changes:
- rename_metrics:
metric.old: shared.current
`), &schema), "test schema must decode")
enabled := true
families, err := buildFamilies([]schemaFile{schema}, overlayFile{Families: map[string]overlayFamily{
"shared.current": {Enabled: &enabled},
}})
require.NoError(t, err)
assert.Equal(t, []generatedFamily{{
Current: "shared.current",
Old: []string{"attribute.old"},
Kind: kindAttribute,
Contexts: []string{"attribute"},
Signals: []string{"traces"},
}}, families, "a kind-less overlay policy should affect only the attribute family")
}
func TestCheckFileReportsStaleOutput(t *testing.T) {
path := filepath.Join(t.TempDir(), "generated.go")
require.NoError(t, os.WriteFile(path, []byte("old"), 0o600), "test output must be writable")
assert.ErrorContains(t, checkFile(path, []byte("new")), "is stale", "check mode must reject stale generated output")
}
func TestTypeScriptStringEscapesControlCharacters(t *testing.T) {
assert.Equal(t, `'line\n\t\x01\'\\end'`, tsString("line\n\t\x01'\\end"), "generated TypeScript strings must remain valid literals")
}

View File

@@ -0,0 +1,11 @@
# SigNoz semantic-convention rollout policy.
#
# Families are keyed by their current OpenTelemetry name. Schema-derived
# families are disabled by default so rollout remains explicit and reversible.
default_enabled: false
families:
deployment.environment.name:
enabled: true
db.system.name:
enabled: true

View File

@@ -0,0 +1,760 @@
file_format: 1.1.0
schema_url: https://opentelemetry.io/schemas/1.42.0
versions:
1.42.0:
metrics:
changes:
- rename_metrics:
v8js.memory.heap.limit: v8js.memory.heap.space.size
1.41.1:
1.41.0:
metrics:
changes:
- rename_metrics:
k8s.container.cpu.limit: k8s.container.cpu.limit.desired
k8s.container.cpu.limit_utilization: k8s.container.cpu.limit.utilization
k8s.container.cpu.request: k8s.container.cpu.request.desired
k8s.container.cpu.request_utilization: k8s.container.cpu.request.utilization
k8s.container.memory.limit: k8s.container.memory.limit.desired
k8s.container.memory.request: k8s.container.memory.request.desired
1.40.0:
all:
changes:
- rename_attributes:
attribute_map:
feature_flag.evaluation.error.message: feature_flag.error.message
metrics:
changes:
- rename_metrics:
system.memory.shared: system.memory.linux.shared
1.39.0:
all:
changes:
- rename_attributes:
attribute_map:
linux.memory.slab.state: system.memory.linux.slab.state
peer.service: service.peer.name
rpc.connect_rpc.error_code: rpc.response.status_code
rpc.connect_rpc.request.metadata: rpc.request.metadata
rpc.connect_rpc.response.metadata: rpc.response.metadata
rpc.grpc.request.metadata: rpc.request.metadata
rpc.grpc.response.metadata: rpc.response.metadata
rpc.jsonrpc.request_id: jsonrpc.request.id
rpc.jsonrpc.version: jsonrpc.protocol.version
rpc.system: rpc.system.name
metrics:
changes:
- rename_metrics:
process.open_file_descriptor.count: process.unix.file_descriptor.count
system.linux.memory.available: system.memory.linux.available
system.linux.memory.slab.usage: system.memory.linux.slab.usage
1.38.0:
all:
changes:
- rename_attributes:
attribute_map:
process.context_switch_type: process.context_switch.type
process.paging.fault_type: system.paging.fault.type
system.cpu.logical_number: cpu.logical_number
system.paging.type: system.paging.fault.type
system.process.status: process.state
system.processes.status: process.state
metrics:
changes:
- rename_metrics:
k8s.cronjob.active_jobs: k8s.cronjob.job.active
k8s.daemonset.current_scheduled_nodes: k8s.daemonset.node.current_scheduled
k8s.daemonset.desired_scheduled_nodes: k8s.daemonset.node.desired_scheduled
k8s.daemonset.misscheduled_nodes: k8s.daemonset.node.misscheduled
k8s.daemonset.ready_nodes: k8s.daemonset.node.ready
k8s.deployment.available_pods: k8s.deployment.pod.available
k8s.deployment.desired_pods: k8s.deployment.pod.desired
k8s.hpa.current_pods: k8s.hpa.pod.current
k8s.hpa.desired_pods: k8s.hpa.pod.desired
k8s.hpa.max_pods: k8s.hpa.pod.max
k8s.hpa.min_pods: k8s.hpa.pod.min
k8s.job.active_pods: k8s.job.pod.active
k8s.job.desired_successful_pods: k8s.job.pod.desired_successful
k8s.job.failed_pods: k8s.job.pod.failed
k8s.job.max_parallel_pods: k8s.job.pod.max_parallel
k8s.job.successful_pods: k8s.job.pod.successful
k8s.node.allocatable.cpu: k8s.node.cpu.allocatable
k8s.node.allocatable.ephemeral_storage: k8s.node.ephemeral_storage.allocatable
k8s.node.allocatable.memory: k8s.node.memory.allocatable
k8s.node.allocatable.pods: k8s.node.pod.allocatable
k8s.replicaset.available_pods: k8s.replicaset.pod.available
k8s.replicaset.desired_pods: k8s.replicaset.pod.desired
k8s.replication_controller.available_pods: k8s.replicationcontroller.pod.available
k8s.replication_controller.desired_pods: k8s.replicationcontroller.pod.desired
k8s.replicationcontroller.available_pods: k8s.replicationcontroller.pod.available
k8s.replicationcontroller.desired_pods: k8s.replicationcontroller.pod.desired
k8s.statefulset.current_pods: k8s.statefulset.pod.current
k8s.statefulset.desired_pods: k8s.statefulset.pod.desired
k8s.statefulset.ready_pods: k8s.statefulset.pod.ready
k8s.statefulset.updated_pods: k8s.statefulset.pod.updated
v8js.heap.space.available_size: v8js.memory.heap.space.available_size
v8js.heap.space.physical_size: v8js.memory.heap.space.physical_size
1.37.0:
all:
changes:
- rename_attributes:
attribute_map:
android.state: android.app.state
container.runtime: container.runtime.name
enduser.role: user.roles
gen_ai.openai.request.service_tier: openai.request.service_tier
gen_ai.openai.response.service_tier: openai.response.service_tier
gen_ai.openai.response.system_fingerprint: openai.response.system_fingerprint
gen_ai.system: gen_ai.provider.name
ios.state: ios.app.state
1.36.0:
1.35.0:
all:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/1698
- rename_attributes:
attribute_map:
az.namespace: azure.resource_provider.namespace
az.service_request_id: azure.service.request.id
metrics:
changes:
# https://github.com/open-telemetry/semantic-conventions/issues/1800
- rename_metrics:
system.network.connections: system.network.connection.count
1.34.0:
metrics:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/2295
- rename_metrics:
cpu.time: system.cpu.time
cpu.utilization: system.cpu.utilization
cpu.frequency: system.cpu.frequency
1.33.0:
all:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/1982
- rename_attributes:
attribute_map:
feature_flag.provider_name: feature_flag.provider.name
# https://github.com/open-telemetry/semantic-conventions/pull/1994
- rename_attributes:
attribute_map:
feature_flag.evaluation.error.message: error.message
1.32.0:
all:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/1989
- rename_attributes:
attribute_map:
feature_flag.evaluation.reason: feature_flag.result.reason
feature_flag.variant: feature_flag.result.variant
metrics:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/2042
- rename_metrics:
otel.sdk.span.live.count: otel.sdk.span.live
otel.sdk.span.ended.count: otel.sdk.span.ended
otel.sdk.processor.span.processed.count: otel.sdk.processor.span.processed
otel.sdk.exporter.span.inflight.count: otel.sdk.exporter.span.inflight
otel.sdk.exporter.span.exported.count: otel.sdk.exporter.span.exported
1.31.0:
all:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/1880
- rename_attributes:
attribute_map:
android.state: android.app.state
io.state: ios.app.state
metrics:
changes:
- rename_metrics:
k8s.replication_controller.desired_pods: k8s.replicationcontroller.desired_pods
k8s.replication_controller.available_pods: k8s.replicationcontroller.available_pods
# https://github.com/open-telemetry/semantic-conventions/pull/1896
- rename_metrics:
system.cpu.time: cpu.time
system.cpu.utilization: cpu.utilization
system.cpu.frequency: cpu.frequency
# https://github.com/open-telemetry/semantic-conventions/pull/1896
- rename_attributes:
attribute_map:
system.cpu.logical_number: cpu.logical_number
1.30.0:
all:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/1632
- rename_attributes:
attribute_map:
gen_ai.openai.request.seed: gen_ai.request.seed
system.network.state: network.connection.state
# https://github.com/open-telemetry/semantic-conventions/pull/1624
- rename_attributes:
attribute_map:
code.function: code.function.name
code.filepath: code.file.path
code.lineno: code.line.number
code.column: code.column.number
# https://github.com/open-telemetry/semantic-conventions/pull/1734
- rename_attributes:
attribute_map:
db.system: db.system.name
db.cassandra.coordinator.dc: cassandra.coordinator.dc
db.cassandra.coordinator.id: cassandra.coordinator.id
db.cassandra.consistency_level: cassandra.consistency.level
db.cassandra.idempotence: cassandra.query.idempotent
db.cassandra.page_size: cassandra.page.size
db.cassandra.speculative_execution_count: cassandra.speculative_execution.count
db.cosmosdb.client_id: azure.client.id
db.cosmosdb.connection_mode: azure.cosmosdb.connection.mode
db.cosmosdb.consistency_level: azure.cosmosdb.consistency.level
db.cosmosdb.request_charge: azure.cosmosdb.operation.request_charge
db.cosmosdb.request_content_length: azure.cosmosdb.request.body.size
db.cosmosdb.regions_contacted: azure.cosmosdb.operation.contacted_regions
db.cosmosdb.sub_status_code: azure.cosmosdb.response.sub_status_code
db.elasticsearch.node.name: elasticsearch.node.name
# db.elasticsearch.path_parts is a template attribute, schema transformation
# does not support it, adding as a comment for consistency
# db.elasticsearch.path_parts.<key> -> db.operation.parameter.<key>
metrics:
changes:
- rename_metrics:
db.client.cosmosdb.operation.request_charge: azure.cosmosdb.client.operation.request_charge
db.client.cosmosdb.active_instance.count: azure.cosmosdb.client.active_instance.count
1.29.0:
all:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/1520
- rename_attributes:
attribute_map:
process.executable.build_id.profiling: process.executable.build_id.htlhash
# https://github.com/open-telemetry/semantic-conventions/pull/1383
- rename_attributes:
attribute_map:
vcs.repository.change.id: vcs.change.id
vcs.repository.change.title: vcs.change.title
vcs.repository.ref.name: vcs.ref.head.name
vcs.repository.ref.revision: vcs.ref.head.revision
vcs.repository.ref.type: vcs.ref.head.type
metrics:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/1492
- rename_attributes:
attribute_map:
system.device: network.interface.name
apply_to_metrics:
- container.network.io
- system.network.dropped
- system.network.errors
- system.network.io
- system.network.connections
1.28.0:
metrics:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/1422
- rename_metrics:
messaging.client.published.messages: messaging.client.sent.messages
1.27.0:
all:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/1216
- rename_attributes:
attribute_map:
tls.client.server_name: server.address
# https://github.com/open-telemetry/semantic-conventions/pull/1075
- rename_attributes:
attribute_map:
deployment.environment: deployment.environment.name
# https://github.com/open-telemetry/semantic-conventions/pull/1245
- rename_attributes:
attribute_map:
messaging.kafka.message.offset: messaging.kafka.offset
# https://github.com/open-telemetry/semantic-conventions/pull/815
- rename_attributes:
attribute_map:
messaging.kafka.consumer.group: messaging.consumer.group.name
messaging.rocketmq.client_group: messaging.consumer.group.name
messaging.eventhubs.consumer.group: messaging.consumer.group.name
messaging.servicebus.destination.subscription_name: messaging.destination.subscription.name
# https://github.com/open-telemetry/semantic-conventions/pull/1200
- rename_attributes:
attribute_map:
gen_ai.usage.completion_tokens: gen_ai.usage.output_tokens
gen_ai.usage.prompt_tokens: gen_ai.usage.input_tokens
spans:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/1002
- rename_attributes:
attribute_map:
db.elasticsearch.cluster.name: db.namespace
metrics:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/1125
- rename_attributes:
attribute_map:
db.client.connections.state: db.client.connection.state
apply_to_metrics:
- db.client.connection.count
- rename_attributes:
attribute_map:
db.client.connections.pool.name: db.client.connection.pool.name
apply_to_metrics:
- db.client.connection.count
- db.client.connection.idle.max
- db.client.connection.idle.min
- db.client.connection.max
- db.client.connection.pending_requests
- db.client.connection.timeouts
- db.client.connection.create_time
- db.client.connection.wait_time
- db.client.connection.use_time
# https://github.com/open-telemetry/semantic-conventions/pull/1006
- rename_metrics:
messaging.publish.messages: messaging.client.published.messages
# https://github.com/open-telemetry/semantic-conventions/pull/1026
- rename_attributes:
attribute_map:
system.cpu.state: cpu.mode
process.cpu.state: cpu.mode
container.cpu.state: cpu.mode
apply_to_metrics:
- system.cpu.time
- system.cpu.utilization
- process.cpu.time
- process.cpu.utilization
- container.cpu.time
# https://github.com/open-telemetry/semantic-conventions/pull/1265
- rename_metrics:
jvm.buffer.memory.usage: jvm.buffer.memory.used
1.26.0:
metrics:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/966
- rename_metrics:
db.client.connections.usage: db.client.connection.count
db.client.connections.idle.max: db.client.connection.idle.max
db.client.connections.idle.min: db.client.connection.idle.min
db.client.connections.max: db.client.connection.max
db.client.connections.pending_requests: db.client.connection.pending_requests
db.client.connections.timeouts: db.client.connection.timeouts
# https://github.com/open-telemetry/semantic-conventions/pull/948
- rename_attributes:
attribute_map:
messaging.client_id: messaging.client.id
# https://github.com/open-telemetry/semantic-conventions/pull/909
- rename_attributes:
attribute_map:
state: db.client.connections.state
apply_to_metrics:
- db.client.connections.usage
- rename_attributes:
attribute_map:
pool.name: db.client.connections.pool.name
apply_to_metrics:
- db.client.connections.usage
- db.client.connections.idle.max
- db.client.connections.idle.min
- db.client.connections.max
- db.client.connections.pending_requests
- db.client.connections.timeouts
- db.client.connections.create_time
- db.client.connections.wait_time
- db.client.connections.use_time
all:
changes:
# https://github:com/open-telemetry/semantic-conventions/pull/731/
- rename_attributes:
attribute_map:
enduser.id: user.id
1.25.0:
spans:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/911
- rename_attributes:
attribute_map:
db.name: db.namespace
# https://github.com/open-telemetry/semantic-conventions/pull/870
- rename_attributes:
attribute_map:
db.sql.table: db.collection.name
db.mongodb.collection: db.collection.name
db.cosmosdb.container: db.collection.name
db.cassandra.table: db.collection.name
# https://github.com/open-telemetry/semantic-conventions/pull/798
- rename_attributes:
attribute_map:
messaging.kafka.destination.partition: messaging.destination.partition.id
# https://github.com/open-telemetry/semantic-conventions/pull/875
- rename_attributes:
attribute_map:
db.operation: db.operation.name
# https://github.com/open-telemetry/semantic-conventions/pull/913
- rename_attributes:
attribute_map:
messaging.operation: messaging.operation.type
# https://github.com/open-telemetry/semantic-conventions/pull/866
- rename_attributes:
attribute_map:
db.statement: db.query.text
metrics:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/484
- rename_attributes:
attribute_map:
system.processes.status: system.process.status
apply_to_metrics:
- system.processes.count
- rename_metrics:
system.processes.count: system.process.count
system.processes.created: system.process.created
# https://github.com/open-telemetry/semantic-conventions/pull/625
- rename_attributes:
attribute_map:
container.labels: container.label
k8s.pod.labels: k8s.pod.label
# https://github.com/open-telemetry/semantic-conventions/pull/330
- rename_metrics:
process.threads: process.thread.count
process.open_file_descriptors: process.open_file_descriptor.count
- rename_attributes:
attribute_map:
state: process.cpu.state
apply_to_metrics:
- process.cpu.time
- process.cpu.utilization
- rename_attributes:
attribute_map:
direction: disk.io.direction
apply_to_metrics:
- process.disk.io
- rename_attributes:
attribute_map:
type: process.context_switch_type
apply_to_metrics:
- process.context_switches
- rename_attributes:
attribute_map:
direction: network.io.direction
apply_to_metrics:
- process.network.io
- rename_attributes:
attribute_map:
type: process.paging.fault_type
apply_to_metrics:
- process.paging.faults
all:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/854
- rename_attributes:
attribute_map:
message.type: rpc.message.type
message.id: rpc.message.id
message.compressed_size: rpc.message.compressed_size
message.uncompressed_size: rpc.message.uncompressed_size
1.24.0:
metrics:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/536
- rename_metrics:
jvm.memory.usage: jvm.memory.used
jvm.memory.usage_after_last_gc: jvm.memory.used_after_last_gc
# https://github.com/open-telemetry/semantic-conventions/pull/530
- rename_attributes:
attribute_map:
system.network.io.direction: network.io.direction
system.disk.io.direction: disk.io.direction
1.23.1:
1.23.0:
metrics:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/20
- rename_attributes:
attribute_map:
thread.daemon: jvm.thread.daemon
apply_to_metrics:
- jvm.thread.count
1.22.0:
spans:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/229
- rename_attributes:
attribute_map:
messaging.message.payload_size_bytes: messaging.message.body.size
# https://github.com/open-telemetry/opentelemetry-specification/pull/374
- rename_attributes:
attribute_map:
http.resend_count: http.request.resend_count
metrics:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/224
- rename_metrics:
http.client.duration: http.client.request.duration
http.server.duration: http.server.request.duration
# https://github.com/open-telemetry/semantic-conventions/pull/241
- rename_metrics:
process.runtime.jvm.memory.usage: jvm.memory.usage
process.runtime.jvm.memory.committed: jvm.memory.committed
process.runtime.jvm.memory.limit: jvm.memory.limit
process.runtime.jvm.memory.usage_after_last_gc: jvm.memory.usage_after_last_gc
process.runtime.jvm.gc.duration: jvm.gc.duration
# also https://github.com/open-telemetry/semantic-conventions/pull/252
process.runtime.jvm.threads.count: jvm.thread.count
# also https://github.com/open-telemetry/semantic-conventions/pull/252
process.runtime.jvm.classes.loaded: jvm.class.loaded
# also https://github.com/open-telemetry/semantic-conventions/pull/252
process.runtime.jvm.classes.unloaded: jvm.class.unloaded
# also https://github.com/open-telemetry/semantic-conventions/pull/252
# and https://github.com/open-telemetry/semantic-conventions/pull/60
process.runtime.jvm.classes.current_loaded: jvm.class.count
process.runtime.jvm.cpu.time: jvm.cpu.time
process.runtime.jvm.cpu.recent_utilization: jvm.cpu.recent_utilization
process.runtime.jvm.memory.init: jvm.memory.init
process.runtime.jvm.system.cpu.utilization: jvm.system.cpu.utilization
process.runtime.jvm.system.cpu.load_1m: jvm.system.cpu.load_1m
# https://github.com/open-telemetry/semantic-conventions/pull/253
process.runtime.jvm.buffer.usage: jvm.buffer.memory.usage
# https://github.com/open-telemetry/semantic-conventions/pull/253
process.runtime.jvm.buffer.limit: jvm.buffer.memory.limit
process.runtime.jvm.buffer.count: jvm.buffer.count
# https://github.com/open-telemetry/semantic-conventions/pull/20
- rename_attributes:
attribute_map:
type: jvm.memory.type
pool: jvm.memory.pool.name
apply_to_metrics:
- jvm.memory.usage
- jvm.memory.committed
- jvm.memory.limit
- jvm.memory.usage_after_last_gc
- jvm.memory.init
- rename_attributes:
attribute_map:
name: jvm.gc.name
action: jvm.gc.action
apply_to_metrics:
- jvm.gc.duration
- rename_attributes:
attribute_map:
daemon: thread.daemon
apply_to_metrics:
- jvm.threads.count
- rename_attributes:
attribute_map:
pool: jvm.buffer.pool.name
apply_to_metrics:
- jvm.buffer.memory.usage
- jvm.buffer.memory.limit
- jvm.buffer.count
# https://github.com/open-telemetry/semantic-conventions/pull/89
- rename_attributes:
attribute_map:
state: system.cpu.state
cpu: system.cpu.logical_number
apply_to_metrics:
- system.cpu.time
- system.cpu.utilization
- rename_attributes:
attribute_map:
state: system.memory.state
apply_to_metrics:
- system.memory.usage
- system.memory.utilization
- rename_attributes:
attribute_map:
state: system.paging.state
apply_to_metrics:
- system.paging.usage
- system.paging.utilization
- rename_attributes:
attribute_map:
type: system.paging.type
direction: system.paging.direction
apply_to_metrics:
- system.paging.faults
- system.paging.operations
- rename_attributes:
attribute_map:
device: system.device
direction: system.disk.direction
apply_to_metrics:
- system.disk.io
- system.disk.operations
- system.disk.io_time
- system.disk.operation_time
- system.disk.merged
- rename_attributes:
attribute_map:
device: system.device
state: system.filesystem.state
type: system.filesystem.type
mode: system.filesystem.mode
mountpoint: system.filesystem.mountpoint
apply_to_metrics:
- system.filesystem.usage
- system.filesystem.utilization
- rename_attributes:
attribute_map:
device: system.device
direction: system.network.direction
protocol: network.protocol
state: system.network.state
apply_to_metrics:
- system.network.dropped
- system.network.packets
- system.network.errors
- system.network.io
- system.network.connections
- rename_attributes:
attribute_map:
status: system.processes.status
apply_to_metrics:
- system.processes.count
# https://github.com/open-telemetry/semantic-conventions/pull/247
- rename_metrics:
http.server.request.size: http.server.request.body.size
http.server.response.size: http.server.response.body.size
resources:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/178
- rename_attributes:
attribute_map:
telemetry.auto.version: telemetry.distro.version
1.21.0:
spans:
changes:
# https://github.com/open-telemetry/opentelemetry-specification/pull/3336
- rename_attributes:
attribute_map:
messaging.kafka.client_id: messaging.client_id
messaging.rocketmq.client_id: messaging.client_id
# https://github.com/open-telemetry/opentelemetry-specification/pull/3402
- rename_attributes:
attribute_map:
# net.peer.(name|port) attributes were usually populated on client side
# so they should be usually translated to server.(address|port)
# net.host.* attributes were only populated on server side
net.host.name: server.address
net.host.port: server.port
# was only populated on client side
net.sock.peer.name: server.socket.domain
# net.sock.peer.(addr|port) mapping is not possible
# since they applied to both client and server side
# were only populated on server side
net.sock.host.addr: server.socket.address
net.sock.host.port: server.socket.port
http.client_ip: client.address
# https://github.com/open-telemetry/opentelemetry-specification/pull/3426
- rename_attributes:
attribute_map:
net.protocol.name: network.protocol.name
net.protocol.version: network.protocol.version
net.host.connection.type: network.connection.type
net.host.connection.subtype: network.connection.subtype
net.host.carrier.name: network.carrier.name
net.host.carrier.mcc: network.carrier.mcc
net.host.carrier.mnc: network.carrier.mnc
net.host.carrier.icc: network.carrier.icc
# https://github.com/open-telemetry/opentelemetry-specification/pull/3355
- rename_attributes:
attribute_map:
http.method: http.request.method
http.status_code: http.response.status_code
http.scheme: url.scheme
http.url: url.full
http.request_content_length: http.request.body.size
http.response_content_length: http.response.body.size
metrics:
changes:
# https://github.com/open-telemetry/semantic-conventions/pull/53
- rename_metrics:
process.runtime.jvm.cpu.utilization: process.runtime.jvm.cpu.recent_utilization
1.20.0:
spans:
changes:
# https://github.com/open-telemetry/opentelemetry-specification/pull/3272
- rename_attributes:
attribute_map:
net.app.protocol.name: net.protocol.name
net.app.protocol.version: net.protocol.version
1.19.0:
spans:
changes:
# https://github.com/open-telemetry/opentelemetry-specification/pull/3209
- rename_attributes:
attribute_map:
faas.execution: faas.invocation_id
# https://github.com/open-telemetry/opentelemetry-specification/pull/3188
- rename_attributes:
attribute_map:
faas.id: cloud.resource_id
# https://github.com/open-telemetry/opentelemetry-specification/pull/3190
- rename_attributes:
attribute_map:
http.user_agent: user_agent.original
resources:
changes:
# https://github.com/open-telemetry/opentelemetry-specification/pull/3190
- rename_attributes:
attribute_map:
browser.user_agent: user_agent.original
1.18.0:
1.17.0:
spans:
changes:
# https://github.com/open-telemetry/opentelemetry-specification/pull/2957
- rename_attributes:
attribute_map:
messaging.consumer_id: messaging.consumer.id
messaging.protocol: net.app.protocol.name
messaging.protocol_version: net.app.protocol.version
messaging.destination: messaging.destination.name
messaging.temp_destination: messaging.destination.temporary
messaging.destination_kind: messaging.destination.kind
messaging.message_id: messaging.message.id
messaging.conversation_id: messaging.message.conversation_id
messaging.message_payload_size_bytes: messaging.message.payload_size_bytes
messaging.message_payload_compressed_size_bytes: messaging.message.payload_compressed_size_bytes
messaging.rabbitmq.routing_key: messaging.rabbitmq.destination.routing_key
messaging.kafka.message_key: messaging.kafka.message.key
messaging.kafka.partition: messaging.kafka.destination.partition
messaging.kafka.tombstone: messaging.kafka.message.tombstone
messaging.rocketmq.message_type: messaging.rocketmq.message.type
messaging.rocketmq.message_tag: messaging.rocketmq.message.tag
messaging.rocketmq.message_keys: messaging.rocketmq.message.keys
messaging.kafka.consumer_group: messaging.kafka.consumer.group
1.16.0:
1.15.0:
spans:
changes:
# https://github.com/open-telemetry/opentelemetry-specification/pull/2743
- rename_attributes:
attribute_map:
http.retry_count: http.resend_count
1.14.0:
1.13.0:
spans:
changes:
# https://github.com/open-telemetry/opentelemetry-specification/pull/2614
- rename_attributes:
attribute_map:
net.peer.ip: net.sock.peer.addr
net.host.ip: net.sock.host.addr
1.12.0:
1.11.0:
1.10.0:
1.9.0:
1.8.0:
spans:
changes:
- rename_attributes:
attribute_map:
db.cassandra.keyspace: db.name
db.hbase.namespace: db.name
1.7.0:
1.6.1:
1.5.0:
1.4.0:

View File

@@ -18,6 +18,7 @@ pytest_plugins = [
"fixtures.logs",
"fixtures.traces",
"fixtures.metrics",
"fixtures.queriercommon",
"fixtures.metadata",
"fixtures.meter",
"fixtures.browser",

View File

@@ -704,6 +704,7 @@ def build_raw_query(
order: list[dict] | None = None,
limit: int | None = None,
filter_expression: str | None = None,
select_fields: list[dict] | None = None,
step_interval: int = DEFAULT_STEP_INTERVAL,
disabled: bool = False,
) -> dict:
@@ -723,6 +724,9 @@ def build_raw_query(
if filter_expression:
spec["filter"] = {"expression": filter_expression}
if select_fields:
spec["selectFields"] = select_fields
return {"type": "builder_query", "spec": spec}

124
tests/fixtures/queriercommon.py vendored Normal file
View File

@@ -0,0 +1,124 @@
"""Seed data for the queriercommon keyless-semantics tests.
Three identities exist in every signal. GOLD and SILVER carry the test keys.
NONE carries no key at all. The tests assert which identities a filter
returns, so the membership of NONE is the point of every case.
The attribute names are outside every semantic-convention family, so the
seeded data pins base behavior with any semconv overlay state.
"""
from collections.abc import Callable, Generator
from datetime import UTC, datetime, timedelta
import pytest
from fixtures.logs import Logs
from fixtures.metrics import Metrics
from fixtures.querier import aligned_epoch
from fixtures.traces import TraceIdGenerator, Traces, TracesKind, TracesStatusCode
PREFIX = "keyless-sem"
STRING_KEY = "tenant.tier"
NUMBER_KEY = "retry.count"
METRIC_NAME = "keyless_semantics_gauge"
METRIC_LABEL = "tenant_tier"
# Row identities, keyed by the value of the string key that each row carries.
GOLD = f"{PREFIX}-gold"
SILVER = f"{PREFIX}-silver"
NONE = f"{PREFIX}-none" # carries no string key and no number key
# (identity, string-key value, number-key value, insert offset)
_ROWS = [
(GOLD, "gold", 0, timedelta(seconds=3)),
(SILVER, "silver", 5, timedelta(seconds=2)),
(NONE, None, None, timedelta(seconds=1)),
]
def _resources(identity: str, tier: str | None) -> dict:
base = {"service.name": identity}
if tier is not None:
base[STRING_KEY] = tier
return base
def _attributes(tier: str | None, retries: int | None) -> dict:
attrs: dict = {}
if tier is not None:
attrs[STRING_KEY] = tier
if retries is not None:
attrs[NUMBER_KEY] = retries
return attrs
@pytest.fixture(name="keyless_rows", scope="function")
def keyless_rows(
insert_logs: Callable[[list[Logs]], None],
insert_traces: Callable[[list[Traces]], None],
) -> Generator[datetime]:
"""Inserts one span and one log per identity: GOLD (string "gold",
number 0), SILVER (string "silver", number 5), and NONE (no keys).
Yields the base timestamp. Span name and log body are the identity."""
now = datetime.now(tz=UTC).replace(microsecond=0) - timedelta(minutes=1)
insert_traces(
[
Traces(
timestamp=now - offset,
duration=timedelta(milliseconds=10),
trace_id=TraceIdGenerator.trace_id(),
span_id=TraceIdGenerator.span_id(),
name=identity,
kind=TracesKind.SPAN_KIND_SERVER,
status_code=TracesStatusCode.STATUS_CODE_OK,
resources=_resources(identity, tier),
attributes=_attributes(tier, retries),
)
for identity, tier, retries, offset in _ROWS
]
)
insert_logs(
[
Logs(
timestamp=now - offset,
body=identity,
resources=_resources(identity, tier),
attributes=_attributes(tier, retries),
)
for identity, tier, retries, offset in _ROWS
]
)
yield now
@pytest.fixture(name="keyless_series", scope="function")
def keyless_series(insert_metrics: Callable[[list[Metrics]], None]) -> Generator[tuple[int, int]]:
"""Inserts three gauge series: GOLD and SILVER carry the metric label,
NONE does not. The `service` label is the identity. Yields the
(start, end) epoch-second window that covers the points."""
start = aligned_epoch(timedelta(minutes=30))
points = 5
def labels(identity: str, tier: str | None) -> dict:
base = {"service": identity}
if tier is not None:
base[METRIC_LABEL] = tier
return base
insert_metrics(
[
Metrics(
metric_name=METRIC_NAME,
labels=labels(identity, tier),
timestamp=datetime.fromtimestamp(start + minute * 60, tz=UTC),
value=10.0,
type_="Gauge",
is_monotonic=False,
)
for identity, tier in ((GOLD, "gold"), (SILVER, "silver"), (NONE, None))
for minute in range(points)
]
)
yield start, start + points * 60

View File

@@ -0,0 +1,202 @@
"""Pins the keyless-row contract for filter operators, per signal.
The contract (deliberate product semantics, enforced by
`FilterOperator.AddDefaultExistsFilter` in
pkg/types/querybuildertypes/querybuildertypesv5/builder_elements.go):
- Negative operators (!=, NOT IN, NOT LIKE, NOT CONTAINS, ...) are a set
complement over ALL rows: a row that does not carry the key at all MUST
match. Users opt into presence explicitly with `AND key EXISTS`.
- Positive operators carry an implicit existence guard: a keyless row must
NOT match `key = ''`-style comparisons against sentinel defaults.
- EXISTS / NOT EXISTS partition rows exactly by key presence.
- Numeric attributes inherit the map-default sentinel: a missing key reads
as 0, so `num != 0` excludes keyless rows while `num != 5` includes them.
This conflation is deliberate and pinned here as the reference for any
value-expression change (for example coalesce tails in semconv families).
Any implementation change that makes these assertions fail is a behavior
break, not a cleanup. Family-field behavior must mirror this matrix; see
queriertraces/13_semconv_evolution.py.
Seed data lives in fixtures/queriercommon.py: GOLD and SILVER carry the
keys, NONE carries none. Every case asserts which identities a filter
returns, so the membership of NONE is the point of each case.
"""
from collections.abc import Callable
from datetime import datetime, timedelta
from http import HTTPStatus
import pytest
from fixtures import types
from fixtures.auth import USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD
from fixtures.querier import (
RequestType,
build_builder_query,
build_order_by,
build_raw_query,
get_all_series,
get_column_data_from_response,
make_query_request,
)
from fixtures.queriercommon import (
GOLD,
METRIC_LABEL,
METRIC_NAME,
NONE,
NUMBER_KEY,
PREFIX,
SILVER,
STRING_KEY,
)
STRING_MATRIX = [
pytest.param("{key} = 'gold'", {GOLD}, id="eq_excludes_keyless"),
pytest.param("{key} != 'gold'", {SILVER, NONE}, id="neq_includes_keyless"),
pytest.param("{key} NOT IN ['gold', 'silver']", {NONE}, id="not_in_includes_keyless"),
pytest.param("NOT {key} LIKE '%gold%'", {SILVER, NONE}, id="not_like_includes_keyless"),
pytest.param("{key} NOT CONTAINS 'gol'", {SILVER, NONE}, id="not_contains_includes_keyless"),
pytest.param("{key} EXISTS", {GOLD, SILVER}, id="exists_partitions"),
pytest.param("{key} NOT EXISTS", {NONE}, id="not_exists_partitions"),
# "Present and not X" is a composition. It is not a new operator
# semantic.
pytest.param("{key} != 'gold' AND {key} EXISTS", {SILVER}, id="neq_composed_with_exists"),
]
NUMBER_MATRIX = [
pytest.param("{key} = 0", {GOLD}, id="numeric_eq_zero_excludes_keyless"),
pytest.param("{key} != 5", {GOLD, NONE}, id="numeric_neq_includes_keyless"),
pytest.param("{key} != 0", {SILVER}, id="numeric_neq_zero_sentinel_conflation"),
]
SIGNALS = [
pytest.param("traces", "span.name", "name", id="traces"),
pytest.param("logs", "body", "body", id="logs"),
]
@pytest.mark.parametrize("expression_template,expected", STRING_MATRIX)
@pytest.mark.parametrize("context", ["resource", "attribute"])
@pytest.mark.parametrize("signal,identity_field,identity_column", SIGNALS)
def test_negative_operators_include_keyless_rows(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token: Callable[[str, str], str],
keyless_rows: datetime,
signal: str,
identity_field: str,
identity_column: str,
context: str,
expression_template: str,
expected: set[str],
) -> None:
"""A negative operator is a set complement over all rows. Presence is an
explicit EXISTS opt-in. The contract holds the same way for resource and
attribute contexts, on traces and on logs."""
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
expression = expression_template.format(key=f"{context}.{STRING_KEY}")
response = make_query_request(
signoz,
token,
start_ms=int((keyless_rows - timedelta(minutes=2)).timestamp() * 1000),
end_ms=int((keyless_rows + timedelta(minutes=1)).timestamp() * 1000),
request_type=RequestType.RAW,
queries=[
build_raw_query(
"A",
signal,
limit=100,
filter_expression=expression,
order=[build_order_by("timestamp", "asc")],
select_fields=[{"name": identity_field}],
)
],
)
assert response.status_code == HTTPStatus.OK, response.text
# Sets keep the assertion stable when the shared stack is reused and
# older rows with the same identities remain.
matched = {name for name in get_column_data_from_response(response.json(), identity_column) if name.startswith(PREFIX)}
assert matched == expected, expression
@pytest.mark.parametrize("expression_template,expected", NUMBER_MATRIX)
@pytest.mark.parametrize("signal,identity_field,identity_column", SIGNALS)
def test_numeric_sentinel_semantics(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token: Callable[[str, str], str],
keyless_rows: datetime,
signal: str,
identity_field: str,
identity_column: str,
expression_template: str,
expected: set[str],
) -> None:
"""A missing numeric key reads as the map default 0. `!= 0` therefore
excludes rows without the key, and every other negative comparison
includes them. This is inherited sentinel behavior, pinned on purpose."""
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
expression = expression_template.format(key=f"attribute.{NUMBER_KEY}")
response = make_query_request(
signoz,
token,
start_ms=int((keyless_rows - timedelta(minutes=2)).timestamp() * 1000),
end_ms=int((keyless_rows + timedelta(minutes=1)).timestamp() * 1000),
request_type=RequestType.RAW,
queries=[
build_raw_query(
"A",
signal,
limit=100,
filter_expression=expression,
order=[build_order_by("timestamp", "asc")],
select_fields=[{"name": identity_field}],
)
],
)
assert response.status_code == HTTPStatus.OK, response.text
matched = {name for name in get_column_data_from_response(response.json(), identity_column) if name.startswith(PREFIX)}
assert matched == expected, expression
@pytest.mark.parametrize("expression_template,expected", STRING_MATRIX)
def test_metrics_negative_operators_include_keyless_series(
signoz: types.SigNoz,
create_user_admin: None, # pylint: disable=unused-argument
get_token: Callable[[str, str], str],
keyless_series: tuple[int, int],
expression_template: str,
expected: set[str],
) -> None:
"""The same contract holds for metric labels: a series without the label
matches every negative filter on it, and EXISTS opts into presence."""
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
expression = expression_template.format(key=METRIC_LABEL)
start, end = keyless_series
response = make_query_request(
signoz,
token,
start_ms=start * 1000,
end_ms=end * 1000,
queries=[
build_builder_query(
"A",
METRIC_NAME,
"avg",
"sum",
group_by=["service"],
filter_expression=expression,
)
],
)
assert response.status_code == HTTPStatus.OK, response.text
matched = {label["value"] for series in get_all_series(response.json(), "A") for label in series["labels"] if label["key"]["name"] == "service" and label["value"].startswith(PREFIX)}
assert matched == expected, expression

View File

@@ -47,9 +47,7 @@ def _data(
}
def _create_body(
*, name: str = "my-view", generate_name: bool = False, display_name: str = "My View", source: str = "logs", **data_kwargs
) -> dict:
def _create_body(*, name: str = "my-view", generate_name: bool = False, display_name: str = "My View", source: str = "logs", **data_kwargs) -> dict:
"""name is the immutable slug. Pass generate_name=True (and leave name
empty) to have the server generate one from display_name instead."""
return {"name": name, "generateName": generate_name, "source": source, "data": _data(display_name=display_name, **data_kwargs)}