Skip to content

Commit 2f51a6a

Browse files
committed
add multi dimensions for managed metrics
1 parent 8d00cb5 commit 2f51a6a

File tree

8 files changed

+45
-22
lines changed

8 files changed

+45
-22
lines changed

api/v1alpha1/managedmetric_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ type ManagedMetricSpec struct {
3131
// Defines which managed resources to observe
3232
// +optional
3333
Target *GroupVersionKind `json:"target,omitempty"`
34+
// Defines dimensions of the metric. All specified fields must be nested strings. Nested slices are not supported.
35+
// If not specified, only status.conditions of the CR will be used as dimension.
36+
// +optional
37+
Dimensions map[string]string `json:"dimensions,omitempty"`
3438
// Define labels of your object to adapt filters of the query
3539
// +optional
3640
LabelSelector string `json:"labelSelector,omitempty"`

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/metrics-operator/embedded/crds/metrics.openmcp.cloud_managedmetrics.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ spec:
6565
description: Sets the description that will be used to identify the
6666
metric in Dynatrace(or other providers)
6767
type: string
68+
dimensions:
69+
additionalProperties:
70+
type: string
71+
description: |-
72+
Defines dimensions of the metric. All specified fields must be nested strings. Nested slices are not supported.
73+
If not specified, only status.conditions of the CR will be used as dimension.
74+
type: object
6875
fieldSelector:
6976
description: Define fields of your object to adapt filters of the
7077
query

internal/controller/datasink_utils.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ func (d *DataSinkCredentialsRetriever) GetDataSinkCredentials(ctx context.Contex
8989
return common.DataSinkCredentials{}, err
9090
}
9191

92+
localEnp := os.Getenv("LOCAL_DATASINK")
93+
if localEnp != "" {
94+
l.Info("Using LOCAL_DATASINK environment variable for DataSink endpoint.", "endpoint", localEnp)
95+
dataSink.Spec.Connection.Endpoint = localEnp
96+
}
97+
9298
// Extract endpoint from DataSink
9399
endpoint := dataSink.Spec.Connection.Endpoint
94100

internal/controller/managedmetric_controller.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"context"
2121
"fmt"
2222
"net/url"
23-
"strings"
2423
"time"
2524

2625
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -309,11 +308,7 @@ func getClusterInfo(config *rest.Config) (string, error) {
309308
return "localhost", nil
310309
}
311310

312-
// Remove any prefix (like "kubernetes" or "kubernetes.default.svc")
313-
parts := strings.Split(hostname, ".")
314-
clusterName := parts[0]
315-
316-
return clusterName, nil
311+
return hostname, nil
317312
}
318313

319314
// OrchestratorFactory is a function type for creating orchestrators

internal/controller/metric_controller_helpers_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,22 @@ func TestGetClusterInfo(t *testing.T) {
4545
{
4646
name: "KubernetesService",
4747
host: "https://kubernetes.default.svc:6443",
48-
expectedName: "kubernetes",
48+
expectedName: "kubernetes.default.svc",
4949
},
5050
{
5151
name: "CustomClusterName",
5252
host: "https://my-cluster-api.example.com:6443",
53-
expectedName: "my-cluster-api",
53+
expectedName: "my-cluster-api.example.com",
5454
},
5555
{
5656
name: "IPAddress",
5757
host: "https://192.168.1.1:6443",
58-
expectedName: "192", // The function only extracts the first part of the IP address
58+
expectedName: "192.168.1.1", // The function only extracts the first part of the IP address
5959
},
6060
{
6161
name: "WithPath",
6262
host: "https://kubernetes.default.svc:6443/api",
63-
expectedName: "kubernetes",
63+
expectedName: "kubernetes.default.svc",
6464
},
6565
}
6666

internal/orchestrator/managedhandler.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66
"slices"
77
"strconv"
8-
"strings"
98

109
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
1110
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -59,25 +58,27 @@ func (h *ManagedHandler) sendStatusBasedMetricValue(ctx context.Context) (string
5958
// Create a new data point for each resource
6059
dataPoint := clientoptl.NewDataPoint()
6160

62-
// Add GVK dimensions from resource
63-
gv, err := schema.ParseGroupVersion(cr.MangedResource.APIVersion)
61+
objMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&cr.MangedResource)
6462
if err != nil {
6563
return "", err
6664
}
67-
dataPoint.AddDimension(KIND, cr.MangedResource.Kind)
68-
dataPoint.AddDimension(GROUP, gv.Group)
69-
dataPoint.AddDimension(VERSION, gv.Version)
65+
66+
u := &unstructured.Unstructured{Object: objMap}
67+
68+
for key, expr := range h.metric.Spec.Dimensions {
69+
s, _, err := nestedPrimitiveValue(*u, expr)
70+
if err != nil {
71+
fmt.Printf("WARN: Could not parse expression '%s' for dimension field '%s'. Error: %v\n", key, expr, err)
72+
continue
73+
}
74+
dataPoint.AddDimension(key, s)
75+
}
7076

7177
// Add cluster dimension if available
7278
if h.clusterName != nil {
7379
dataPoint.AddDimension(CLUSTER, *h.clusterName)
7480
}
7581

76-
// Add status conditions as dimensions
77-
for typ, state := range cr.Status {
78-
dataPoint.AddDimension(strings.ToLower(typ), strconv.FormatBool(state))
79-
}
80-
8182
// Set the value to 1 for each resource
8283
dataPoint.SetValue(1)
8384

internal/orchestrator/orchestrator.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ const (
2929

3030
// APIVERSION Constant for k8s resource fields
3131
APIVERSION string = "apiVersion"
32+
33+
// NAME Constant for k8s resource fields
34+
CR_NAME string = "crName"
3235
)
3336

3437
// GenericHandler is used to monitor the metric

0 commit comments

Comments
 (0)