Skip to content

Commit 8807012

Browse files
committed
add MetricEntityStateFiveEnums and MetricEntityStateFiveEnumsTest
1 parent 86057b9 commit 8807012

6 files changed

Lines changed: 901 additions & 3 deletions

File tree

internal/venice-client-common/src/main/java/com/linkedin/venice/stats/dimensions/VeniceMetricsDimensions.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ public enum VeniceMetricsDimensions {
3030
/** {@link com.linkedin.venice.stats.dimensions.MessageType} */
3131
VENICE_MESSAGE_TYPE("venice.message.type"),
3232

33-
/** Streaming delivery progress for batch responses (e.g., first, 50pct, 90pct, etc.) */
33+
/**
34+
* {@link StreamProgress} Streaming delivery progress for batch responses
35+
* (e.g., first, 50pct, 90pct, etc.)
36+
*/
3437
VENICE_STREAM_PROGRESS("venice.stream.progress"),
3538

3639
/** {@link RequestRetryAbortReason} */
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
package com.linkedin.venice.stats.metrics;
2+
3+
import com.linkedin.venice.stats.VeniceOpenTelemetryMetricsRepository;
4+
import com.linkedin.venice.stats.dimensions.VeniceDimensionInterface;
5+
import com.linkedin.venice.stats.dimensions.VeniceMetricsDimensions;
6+
import io.opentelemetry.api.common.Attributes;
7+
import io.tehuti.metrics.MeasurableStat;
8+
import java.util.Collections;
9+
import java.util.EnumMap;
10+
import java.util.List;
11+
import java.util.Map;
12+
import javax.annotation.Nonnull;
13+
14+
15+
/**
16+
* Similar to {@link MetricEntityStateOneEnum} but with five dynamic dimensions and 5 level EnumMap
17+
*/
18+
public class MetricEntityStateFiveEnums<E1 extends Enum<E1> & VeniceDimensionInterface, E2 extends Enum<E2> & VeniceDimensionInterface, E3 extends Enum<E3> & VeniceDimensionInterface, E4 extends Enum<E4> & VeniceDimensionInterface, E5 extends Enum<E5> & VeniceDimensionInterface>
19+
extends MetricEntityState {
20+
private final EnumMap<E1, EnumMap<E2, EnumMap<E3, EnumMap<E4, EnumMap<E5, Attributes>>>>> attributesEnumMap;
21+
22+
private final Class<E1> enumTypeClass1;
23+
private final Class<E2> enumTypeClass2;
24+
private final Class<E3> enumTypeClass3;
25+
private final Class<E4> enumTypeClass4;
26+
private final Class<E5> enumTypeClass5;
27+
28+
/** should not be called directly, call {@link #create} instead */
29+
private MetricEntityStateFiveEnums(
30+
MetricEntity metricEntity,
31+
VeniceOpenTelemetryMetricsRepository otelRepository,
32+
Map<VeniceMetricsDimensions, String> baseDimensionsMap,
33+
Class<E1> enumTypeClass1,
34+
Class<E2> enumTypeClass2,
35+
Class<E3> enumTypeClass3,
36+
Class<E4> enumTypeClass4,
37+
Class<E5> enumTypeClass5) {
38+
this(
39+
metricEntity,
40+
otelRepository,
41+
null,
42+
null,
43+
Collections.EMPTY_LIST,
44+
baseDimensionsMap,
45+
enumTypeClass1,
46+
enumTypeClass2,
47+
enumTypeClass3,
48+
enumTypeClass4,
49+
enumTypeClass5);
50+
}
51+
52+
/** should not be called directly, call {@link #create} instead */
53+
private MetricEntityStateFiveEnums(
54+
MetricEntity metricEntity,
55+
VeniceOpenTelemetryMetricsRepository otelRepository,
56+
TehutiSensorRegistrationFunction registerTehutiSensorFn,
57+
TehutiMetricNameEnum tehutiMetricNameEnum,
58+
List<MeasurableStat> tehutiMetricStats,
59+
Map<VeniceMetricsDimensions, String> baseDimensionsMap,
60+
Class<E1> enumTypeClass1,
61+
Class<E2> enumTypeClass2,
62+
Class<E3> enumTypeClass3,
63+
Class<E4> enumTypeClass4,
64+
Class<E5> enumTypeClass5) {
65+
super(
66+
metricEntity,
67+
otelRepository,
68+
baseDimensionsMap,
69+
registerTehutiSensorFn,
70+
tehutiMetricNameEnum,
71+
tehutiMetricStats);
72+
validateRequiredDimensions(
73+
metricEntity,
74+
null,
75+
baseDimensionsMap,
76+
enumTypeClass1,
77+
enumTypeClass2,
78+
enumTypeClass3,
79+
enumTypeClass4,
80+
enumTypeClass5);
81+
this.enumTypeClass1 = enumTypeClass1;
82+
this.enumTypeClass2 = enumTypeClass2;
83+
this.enumTypeClass3 = enumTypeClass3;
84+
this.enumTypeClass4 = enumTypeClass4;
85+
this.enumTypeClass5 = enumTypeClass5;
86+
this.attributesEnumMap = createAttributesEnumMap();
87+
}
88+
89+
/** Factory method with named parameters to ensure the passed in enumTypeClass are in the same order as E */
90+
public static <E1 extends Enum<E1> & VeniceDimensionInterface, E2 extends Enum<E2> & VeniceDimensionInterface, E3 extends Enum<E3> & VeniceDimensionInterface, E4 extends Enum<E4> & VeniceDimensionInterface, E5 extends Enum<E5> & VeniceDimensionInterface> MetricEntityStateFiveEnums<E1, E2, E3, E4, E5> create(
91+
MetricEntity metricEntity,
92+
VeniceOpenTelemetryMetricsRepository otelRepository,
93+
Map<VeniceMetricsDimensions, String> baseDimensionsMap,
94+
Class<E1> enumTypeClass1,
95+
Class<E2> enumTypeClass2,
96+
Class<E3> enumTypeClass3,
97+
Class<E4> enumTypeClass4,
98+
Class<E5> enumTypeClass5) {
99+
return new MetricEntityStateFiveEnums<>(
100+
metricEntity,
101+
otelRepository,
102+
baseDimensionsMap,
103+
enumTypeClass1,
104+
enumTypeClass2,
105+
enumTypeClass3,
106+
enumTypeClass4,
107+
enumTypeClass5);
108+
}
109+
110+
/** Overloaded Factory method for constructor with Tehuti parameters */
111+
public static <E1 extends Enum<E1> & VeniceDimensionInterface, E2 extends Enum<E2> & VeniceDimensionInterface, E3 extends Enum<E3> & VeniceDimensionInterface, E4 extends Enum<E4> & VeniceDimensionInterface, E5 extends Enum<E5> & VeniceDimensionInterface> MetricEntityStateFiveEnums<E1, E2, E3, E4, E5> create(
112+
MetricEntity metricEntity,
113+
VeniceOpenTelemetryMetricsRepository otelRepository,
114+
TehutiSensorRegistrationFunction registerTehutiSensorFn,
115+
TehutiMetricNameEnum tehutiMetricNameEnum,
116+
List<MeasurableStat> tehutiMetricStats,
117+
Map<VeniceMetricsDimensions, String> baseDimensionsMap,
118+
Class<E1> enumTypeClass1,
119+
Class<E2> enumTypeClass2,
120+
Class<E3> enumTypeClass3,
121+
Class<E4> enumTypeClass4,
122+
Class<E5> enumTypeClass5) {
123+
return new MetricEntityStateFiveEnums<>(
124+
metricEntity,
125+
otelRepository,
126+
registerTehutiSensorFn,
127+
tehutiMetricNameEnum,
128+
tehutiMetricStats,
129+
baseDimensionsMap,
130+
enumTypeClass1,
131+
enumTypeClass2,
132+
enumTypeClass3,
133+
enumTypeClass4,
134+
enumTypeClass5);
135+
}
136+
137+
/**
138+
* Creates an EnumMap of {@link Attributes} which will be used to lazy initialize the Attributes
139+
*/
140+
private EnumMap<E1, EnumMap<E2, EnumMap<E3, EnumMap<E4, EnumMap<E5, Attributes>>>>> createAttributesEnumMap() {
141+
if (!emitOpenTelemetryMetrics()) {
142+
return null;
143+
}
144+
145+
return new EnumMap<>(enumTypeClass1);
146+
}
147+
148+
/**
149+
* Manages the nested EnumMap structure for lazy initialization of Attributes.
150+
* The structure is a five-level nested EnumMap:
151+
* EnumMap<E1, EnumMap<E2, EnumMap<E3, EnumMap<E4, EnumMap<E5, Attributes>>>>>.
152+
* This allows efficient retrieval of Attributes based on five enum dimensions (E1, E2, E3, E4, E5).
153+
*
154+
* For thread safety considerations, refer {@link MetricEntityStateOneEnum#getAttributes}.
155+
*/
156+
public Attributes getAttributes(E1 dimension1, E2 dimension2, E3 dimension3, E4 dimension4, E5 dimension5) {
157+
if (!emitOpenTelemetryMetrics()) {
158+
return null;
159+
}
160+
161+
Attributes attributes = attributesEnumMap.computeIfAbsent(dimension1, k -> {
162+
validateInputDimension(k);
163+
return new EnumMap<>(enumTypeClass2);
164+
}).computeIfAbsent(dimension2, k -> {
165+
validateInputDimension(k);
166+
return new EnumMap<>(enumTypeClass3);
167+
}).computeIfAbsent(dimension3, k -> {
168+
validateInputDimension(k);
169+
return new EnumMap<>(enumTypeClass4);
170+
}).computeIfAbsent(dimension4, k -> {
171+
validateInputDimension(k);
172+
return new EnumMap<>(enumTypeClass5);
173+
}).computeIfAbsent(dimension5, k -> {
174+
validateInputDimension(k);
175+
return createAttributes(dimension1, dimension2, dimension3, dimension4, dimension5);
176+
});
177+
178+
if (attributes == null) {
179+
throw new IllegalArgumentException(
180+
"No Attributes found for dimensions: " + dimension1 + "," + dimension2 + "," + dimension3 + "," + dimension4
181+
+ "," + dimension5 + " for metric Entity: " + getMetricEntity().getMetricName());
182+
}
183+
return attributes;
184+
}
185+
186+
public void record(
187+
long value,
188+
@Nonnull E1 dimension1,
189+
@Nonnull E2 dimension2,
190+
@Nonnull E3 dimension3,
191+
@Nonnull E4 dimension4,
192+
@Nonnull E5 dimension5) {
193+
super.record(value, getAttributes(dimension1, dimension2, dimension3, dimension4, dimension5));
194+
}
195+
196+
public void record(
197+
double value,
198+
@Nonnull E1 dimension1,
199+
@Nonnull E2 dimension2,
200+
@Nonnull E3 dimension3,
201+
@Nonnull E4 dimension4,
202+
@Nonnull E5 dimension5) {
203+
super.record(value, getAttributes(dimension1, dimension2, dimension3, dimension4, dimension5));
204+
}
205+
206+
/** visible for testing */
207+
public EnumMap<E1, EnumMap<E2, EnumMap<E3, EnumMap<E4, EnumMap<E5, Attributes>>>>> getAttributesEnumMap() {
208+
return attributesEnumMap;
209+
}
210+
}

0 commit comments

Comments
 (0)