Compare commits

...

4 Commits

Author SHA1 Message Date
Nikhil Mantri
3d6ec85607 Merge branch 'main' into infraM/move_attributes_to_api_spec 2026-07-22 11:28:20 +05:30
Nikhil Mantri
cee7427db9 Merge branch 'main' into infraM/move_attributes_to_api_spec 2026-07-22 02:47:37 +05:30
nikhilmantri0902
d5be8d9928 chore: scope infra attribute-key enum to keys with backend consts
Drop the 9 raw-literal members (uids, replicaset, cronjob, volume type,
object kind/name, deployment env); enum now covers only the 11 keys
backed by existing *AttrKey consts. FE reverts the dropped keys to
string literals.
2026-07-22 02:46:57 +05:30
nikhilmantri0902
b27b28f3af chore: added spec for attributes 2026-07-22 02:10:57 +05:30
7 changed files with 190 additions and 13 deletions

View File

@@ -7,6 +7,7 @@ import (
"strings"
"github.com/SigNoz/signoz/pkg/types/authtypes"
"github.com/SigNoz/signoz/pkg/types/inframonitoringtypes"
"github.com/SigNoz/signoz/pkg/web"
"github.com/spf13/cobra"
"github.com/swaggest/jsonschema-go"
@@ -16,6 +17,8 @@ const webSettingsSchemaPath = "frontend/src/schemas/generated/webSettings.schema
const transactionGroupsSchemaPath = "frontend/src/schemas/generated/transactionGroups.schema.json"
const infraAttributeKeysSchemaPath = "frontend/src/schemas/generated/infraAttributeKeys.schema.json"
func registerGenerateConfig(parentCmd *cobra.Command) {
configCmd := &cobra.Command{
Use: "config",
@@ -38,6 +41,14 @@ func registerGenerateConfig(parentCmd *cobra.Command) {
},
})
configCmd.AddCommand(&cobra.Command{
Use: "infra-attribute-keys",
Short: "Generate JSON Schema for infra monitoring attribute keys",
RunE: func(currCmd *cobra.Command, args []string) error {
return generateInfraAttributeKeys()
},
})
parentCmd.AddCommand(configCmd)
}
@@ -99,3 +110,25 @@ func generateTransactionGroups() error {
return os.WriteFile(transactionGroupsSchemaPath, append(data, '\n'), 0o600)
}
func generateInfraAttributeKeys() error {
enum := make([]any, 0, len(inframonitoringtypes.AttributeKeyMembers))
names := make([]any, 0, len(inframonitoringtypes.AttributeKeyMembers))
for _, member := range inframonitoringtypes.AttributeKeyMembers {
enum = append(enum, member.Key.StringValue())
names = append(names, member.Name)
}
schema := jsonschema.Schema{}
schema.WithTitle("InfraAttributeKeys")
schema.WithType(*(&jsonschema.Type{}).WithSimpleTypes(jsonschema.String))
schema.WithEnum(enum...)
schema.WithExtraPropertiesItem("tsEnumNames", names)
data, err := json.MarshalIndent(schema, "", " ")
if err != nil {
return err
}
return os.WriteFile(infraAttributeKeysSchemaPath, append(data, '\n'), 0o600)
}

View File

@@ -25,7 +25,8 @@
"test": "jest",
"test:changedsince": "jest --changedSince=main --coverage --silent",
"generate:api": "orval --config ./orval.config.ts && sh scripts/post-types-generation.sh",
"generate:config:web-settings": "json2ts ./src/schemas/generated/webSettings.schema.json -o src/types/generated/webSettings.ts --style.useTabs --style.tabWidth=1 --style.singleQuote --bannerComment '/* AUTO GENERATED FILE - DO NOT EDIT - GENERATED FROM frontend/src/schemas/generated/webSettings.schema.json */'"
"generate:config:web-settings": "json2ts ./src/schemas/generated/webSettings.schema.json -o src/types/generated/webSettings.ts --style.useTabs --style.tabWidth=1 --style.singleQuote --bannerComment '/* AUTO GENERATED FILE - DO NOT EDIT - GENERATED FROM frontend/src/schemas/generated/webSettings.schema.json */'",
"generate:config:infra-attribute-keys": "json2ts ./src/schemas/generated/infraAttributeKeys.schema.json -o src/types/generated/infraAttributeKeys.ts --no-enableConstEnums --style.useTabs --style.tabWidth=1 --style.singleQuote --bannerComment '/* AUTO GENERATED FILE - DO NOT EDIT - GENERATED FROM frontend/src/schemas/generated/infraAttributeKeys.schema.json */'"
},
"engines": {
"node": ">=22.0.0",

View File

@@ -7,22 +7,24 @@ import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { EQueryType } from 'types/common/dashboard';
import { DataSource, ReduceOperators } from 'types/common/queryBuilder';
import { InfraAttributeKeys } from 'types/generated/infraAttributeKeys';
import { v4 } from 'uuid';
// TODO(backend): Find a way to generate this via openapi
// Keys backed by a backend constant are sourced from the generated
// InfraAttributeKeys enum; the rest remain FE-only string literals.
export const INFRA_MONITORING_ATTR_KEYS = {
// Host
HOST_NAME: 'host.name',
HOST_NAME: InfraAttributeKeys.HOST_NAME,
// Cluster
K8S_CLUSTER_NAME: 'k8s.cluster.name',
K8S_CLUSTER_NAME: InfraAttributeKeys.K8S_CLUSTER_NAME,
K8S_CLUSTER_UID: 'k8s.cluster.uid',
// Namespace
K8S_NAMESPACE_NAME: 'k8s.namespace.name',
K8S_NAMESPACE_NAME: InfraAttributeKeys.K8S_NAMESPACE_NAME,
// Node
K8S_NODE_NAME: 'k8s.node.name',
K8S_NODE_NAME: InfraAttributeKeys.K8S_NODE_NAME,
K8S_NODE_UID: 'k8s.node.uid',
K8S_NODE_CPU_USAGE: 'k8s.node.cpu.usage',
K8S_NODE_ALLOCATABLE_CPU: 'k8s.node.allocatable_cpu',
@@ -38,7 +40,7 @@ export const INFRA_MONITORING_ATTR_KEYS = {
K8S_NODE_NETWORK_ERRORS: 'k8s.node.network.errors',
// Pod
K8S_POD_NAME: 'k8s.pod.name',
K8S_POD_NAME: InfraAttributeKeys.K8S_POD_NAME,
K8S_POD_UID: 'k8s.pod.uid',
K8S_POD_CPU_USAGE: 'k8s.pod.cpu.usage',
K8S_POD_CPU_LIMIT_UTILIZATION: 'k8s.pod.cpu_limit_utilization',
@@ -56,26 +58,26 @@ export const INFRA_MONITORING_ATTR_KEYS = {
K8S_POD_NETWORK_ERRORS: 'k8s.pod.network.errors',
// Container
K8S_CONTAINER_NAME: 'k8s.container.name',
K8S_CONTAINER_NAME: InfraAttributeKeys.K8S_CONTAINER_NAME,
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',
// Deployment
K8S_DEPLOYMENT_NAME: 'k8s.deployment.name',
K8S_DEPLOYMENT_NAME: InfraAttributeKeys.K8S_DEPLOYMENT_NAME,
K8S_DEPLOYMENT_AVAILABLE: 'k8s.deployment.available',
K8S_DEPLOYMENT_DESIRED: 'k8s.deployment.desired',
// StatefulSet
K8S_STATEFULSET_NAME: 'k8s.statefulset.name',
K8S_STATEFULSET_NAME: InfraAttributeKeys.K8S_STATEFULSET_NAME,
K8S_STATEFULSET_CURRENT_PODS: 'k8s.statefulset.current_pods',
K8S_STATEFULSET_DESIRED_PODS: 'k8s.statefulset.desired_pods',
K8S_STATEFULSET_READY_PODS: 'k8s.statefulset.ready_pods',
K8S_STATEFULSET_UPDATED_PODS: 'k8s.statefulset.updated_pods',
// DaemonSet
K8S_DAEMONSET_NAME: 'k8s.daemonset.name',
K8S_DAEMONSET_NAME: InfraAttributeKeys.K8S_DAEMONSET_NAME,
K8S_DAEMONSET_CURRENT_SCHEDULED_NODES: 'k8s.daemonset.current_scheduled_nodes',
K8S_DAEMONSET_DESIRED_SCHEDULED_NODES: 'k8s.daemonset.desired_scheduled_nodes',
K8S_DAEMONSET_MISSCHEDULED_NODES: 'k8s.daemonset.misscheduled_nodes',
@@ -87,7 +89,7 @@ export const INFRA_MONITORING_ATTR_KEYS = {
K8S_REPLICASET_DESIRED: 'k8s.replicaset.desired',
// Job
K8S_JOB_NAME: 'k8s.job.name',
K8S_JOB_NAME: InfraAttributeKeys.K8S_JOB_NAME,
K8S_CRONJOB_NAME: 'k8s.cronjob.name',
K8S_JOB_ACTIVE_PODS: 'k8s.job.active_pods',
K8S_JOB_DESIRED_SUCCESSFUL_PODS: 'k8s.job.desired_successful_pods',
@@ -95,7 +97,8 @@ export const INFRA_MONITORING_ATTR_KEYS = {
K8S_JOB_SUCCESSFUL_PODS: 'k8s.job.successful_pods',
// Volume
K8S_PERSISTENT_VOLUME_CLAIM_NAME: 'k8s.persistentvolumeclaim.name',
K8S_PERSISTENT_VOLUME_CLAIM_NAME:
InfraAttributeKeys.K8S_PERSISTENT_VOLUME_CLAIM_NAME,
K8S_VOLUME_AVAILABLE: 'k8s.volume.available',
K8S_VOLUME_CAPACITY: 'k8s.volume.capacity',
K8S_VOLUME_INODES: 'k8s.volume.inodes',

View File

@@ -0,0 +1,30 @@
{
"title": "InfraAttributeKeys",
"enum": [
"host.name",
"k8s.cluster.name",
"k8s.namespace.name",
"k8s.node.name",
"k8s.pod.name",
"k8s.container.name",
"k8s.deployment.name",
"k8s.statefulset.name",
"k8s.daemonset.name",
"k8s.job.name",
"k8s.persistentvolumeclaim.name"
],
"type": "string",
"tsEnumNames": [
"HOST_NAME",
"K8S_CLUSTER_NAME",
"K8S_NAMESPACE_NAME",
"K8S_NODE_NAME",
"K8S_POD_NAME",
"K8S_CONTAINER_NAME",
"K8S_DEPLOYMENT_NAME",
"K8S_STATEFULSET_NAME",
"K8S_DAEMONSET_NAME",
"K8S_JOB_NAME",
"K8S_PERSISTENT_VOLUME_CLAIM_NAME"
]
}

View File

@@ -0,0 +1,15 @@
/* AUTO GENERATED FILE - DO NOT EDIT - GENERATED FROM frontend/src/schemas/generated/infraAttributeKeys.schema.json */
export enum InfraAttributeKeys {
HOST_NAME = 'host.name',
K8S_CLUSTER_NAME = 'k8s.cluster.name',
K8S_NAMESPACE_NAME = 'k8s.namespace.name',
K8S_NODE_NAME = 'k8s.node.name',
K8S_POD_NAME = 'k8s.pod.name',
K8S_CONTAINER_NAME = 'k8s.container.name',
K8S_DEPLOYMENT_NAME = 'k8s.deployment.name',
K8S_STATEFULSET_NAME = 'k8s.statefulset.name',
K8S_DAEMONSET_NAME = 'k8s.daemonset.name',
K8S_JOB_NAME = 'k8s.job.name',
K8S_PERSISTENT_VOLUME_CLAIM_NAME = 'k8s.persistentvolumeclaim.name',
}

View File

@@ -0,0 +1,49 @@
package inframonitoringtypes
import "github.com/SigNoz/signoz/pkg/valuer"
type AttributeKey struct {
valuer.String
}
var (
AttributeKeyHostName = AttributeKey{valuer.NewString(HostNameAttrKey)}
AttributeKeyK8SClusterName = AttributeKey{valuer.NewString(ClusterNameAttrKey)}
AttributeKeyK8SNamespaceName = AttributeKey{valuer.NewString(NamespaceNameAttrKey)}
AttributeKeyK8SNodeName = AttributeKey{valuer.NewString(NodeNameAttrKey)}
AttributeKeyK8SPodName = AttributeKey{valuer.NewString(PodNameAttrKey)}
AttributeKeyK8SContainerName = AttributeKey{valuer.NewString(ContainerNameAttrKey)}
AttributeKeyK8SDeploymentName = AttributeKey{valuer.NewString(DeploymentNameAttrKey)}
AttributeKeyK8SStatefulSetName = AttributeKey{valuer.NewString(StatefulSetNameAttrKey)}
AttributeKeyK8SDaemonSetName = AttributeKey{valuer.NewString(DaemonSetNameAttrKey)}
AttributeKeyK8SJobName = AttributeKey{valuer.NewString(JobNameAttrKey)}
AttributeKeyK8SPersistentVolumeClaimName = AttributeKey{valuer.NewString(PersistentVolumeClaimNameAttrKey)}
)
type AttributeKeyMember struct {
Name string
Key AttributeKey
}
var AttributeKeyMembers = []AttributeKeyMember{
{"HOST_NAME", AttributeKeyHostName},
{"K8S_CLUSTER_NAME", AttributeKeyK8SClusterName},
{"K8S_NAMESPACE_NAME", AttributeKeyK8SNamespaceName},
{"K8S_NODE_NAME", AttributeKeyK8SNodeName},
{"K8S_POD_NAME", AttributeKeyK8SPodName},
{"K8S_CONTAINER_NAME", AttributeKeyK8SContainerName},
{"K8S_DEPLOYMENT_NAME", AttributeKeyK8SDeploymentName},
{"K8S_STATEFULSET_NAME", AttributeKeyK8SStatefulSetName},
{"K8S_DAEMONSET_NAME", AttributeKeyK8SDaemonSetName},
{"K8S_JOB_NAME", AttributeKeyK8SJobName},
{"K8S_PERSISTENT_VOLUME_CLAIM_NAME", AttributeKeyK8SPersistentVolumeClaimName},
}
func (AttributeKey) Enum() []any {
members := make([]any, len(AttributeKeyMembers))
for i := range AttributeKeyMembers {
members[i] = AttributeKeyMembers[i].Key
}
return members
}

View File

@@ -0,0 +1,46 @@
package inframonitoringtypes
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestAttributeKeyMembersCoverBareConsts(t *testing.T) {
values := make(map[string]bool, len(AttributeKeyMembers))
for _, member := range AttributeKeyMembers {
values[member.Key.StringValue()] = true
}
bareConsts := []string{
HostNameAttrKey,
ClusterNameAttrKey,
NamespaceNameAttrKey,
NodeNameAttrKey,
PodNameAttrKey,
ContainerNameAttrKey,
DeploymentNameAttrKey,
StatefulSetNameAttrKey,
DaemonSetNameAttrKey,
JobNameAttrKey,
PersistentVolumeClaimNameAttrKey,
}
for _, bareConst := range bareConsts {
require.Truef(t, values[bareConst], "bare AttrKey const %q has no matching AttributeKey enum member", bareConst)
}
}
func TestAttributeKeyMembersAndEnumInSync(t *testing.T) {
enum := AttributeKey{}.Enum()
require.Len(t, enum, len(AttributeKeyMembers))
names := make(map[string]bool, len(AttributeKeyMembers))
for i, member := range AttributeKeyMembers {
require.NotEmpty(t, member.Name)
require.NotEmpty(t, member.Key.StringValue())
require.Falsef(t, names[member.Name], "duplicate member name %q", member.Name)
names[member.Name] = true
require.Equal(t, member.Key, enum[i])
}
}