Skip to content

Commit a745088

Browse files
committed
add support for multi-dimensional metrics
1 parent 8d00cb5 commit a745088

File tree

1 file changed

+30
-26
lines changed

1 file changed

+30
-26
lines changed

internal/orchestrator/metrichandler.go

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"strconv"
77
"strings"
88

9-
"github.com/samber/lo"
109
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1110
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1211
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -94,16 +93,17 @@ func (h *MetricHandler) projectionsMonitor(ctx context.Context, list *unstructur
9493
// Add base dimensions only if they have a non-empty value
9594
h.setDataPointBaseDimensions(dataPoint)
9695

97-
// Add projected dimensions for this specific group
98-
for _, pField := range group {
99-
// Add projected dimension only if the value is non-empty and no error occurred
100-
if pField.error == nil && pField.value != "" {
101-
dataPoint.AddDimension(pField.name, pField.value)
102-
} else {
103-
// Optionally log or handle projection errors
104-
recordErrors = append(recordErrors, fmt.Errorf("projection error for %s: %w", pField.name, pField.error))
96+
for _, inGroup := range group {
97+
for _, pField := range inGroup {
98+
// Add projected dimension only if the value is non-empty and no error occurred
99+
if pField.error == nil && pField.value != "" {
100+
dataPoint.AddDimension(pField.name, pField.value)
101+
} else {
102+
// Optionally log or handle projection errors
103+
recordErrors = append(recordErrors, fmt.Errorf("projection error for %s: %w", pField.name, pField.error))
104+
}
105105
}
106-
}
106+
107107
dataPoints = append(dataPoints, dataPoint)
108108
}
109109

@@ -158,27 +158,31 @@ func (e *projectedField) GetID() string {
158158
return fmt.Sprintf("%s: %s", e.name, e.value)
159159
}
160160

161-
func (h *MetricHandler) extractProjectionGroupsFrom(list *unstructured.UnstructuredList) map[string][]projectedField {
162-
// note: for now we only allow one projection, so we can use the first one
163-
// the reason for this is that if we have multiple projections, we need to create a cartesian product of all projections
164-
// this is to be done at a later time
165-
var collection []projectedField
161+
func (h *MetricHandler) extractProjectionGroupsFrom(list *unstructured.UnstructuredList) map[string][][]projectedField {
162+
var collection [][]projectedField
166163

167164
for _, obj := range list.Items {
168-
169-
projection := lo.FirstOr(h.metric.Spec.Projections, v1alpha1.Projection{})
170-
171-
if projection.Name != "" && projection.FieldPath != "" {
172-
name := projection.Name
173-
value, found, err := nestedPrimitiveValue(obj, projection.FieldPath)
174-
collection = append(collection, projectedField{name: name, value: value, found: found, error: err})
165+
var fields []projectedField
166+
for _, projection := range h.metric.Spec.Projections {
167+
if projection.Name != "" && projection.FieldPath != "" {
168+
name := projection.Name
169+
value, found, err := nestedPrimitiveValue(obj, projection.FieldPath)
170+
fields = append(fields, projectedField{name: name, value: value, found: found, error: err})
171+
}
175172
}
173+
collection = append(collection, fields)
176174
}
177175

178-
// group by the extracted values for the dimension .e.g. device: iPhone, device: Android and count them later
179-
groups := lo.GroupBy(collection, func(field projectedField) string {
180-
return field.GetID()
181-
})
176+
// Group by the combination of all projected values
177+
groups := make(map[string][][]projectedField)
178+
for _, fields := range collection {
179+
var keyParts []string
180+
for _, f := range fields {
181+
keyParts = append(keyParts, fmt.Sprintf("%s: %s", f.name, f.value))
182+
}
183+
key := strings.Join(keyParts, ", ")
184+
groups[key] = append(groups[key], fields)
185+
}
182186

183187
return groups
184188
}

0 commit comments

Comments
 (0)