Skip to content

Commit f843bef

Browse files
committed
adding allow list metric view configration and adding cardinality support
1 parent 9a04d90 commit f843bef

File tree

1 file changed

+100
-32
lines changed

1 file changed

+100
-32
lines changed

otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/MetricViewConfiguration.java

Lines changed: 100 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,45 +17,113 @@
1717
package org.hypertrace.agent.otel.extensions;
1818

1919
import io.opentelemetry.sdk.metrics.View;
20+
import java.lang.reflect.Field;
2021
import java.util.Arrays;
2122
import java.util.HashSet;
2223
import java.util.Set;
24+
import java.util.logging.Level;
25+
import java.util.logging.Logger;
2326

2427
public class MetricViewConfiguration {
28+
private static final Logger logger = Logger.getLogger(MetricViewConfiguration.class.getName());
2529

30+
// OpenTelemetry's cardinality limit property
31+
private static final String OTEL_CARDINALITY_LIMIT =
32+
"otel.experimental.metrics.cardinality.limit";
33+
34+
// Default HTTP attributes to include
35+
private static final Set<String> KEYS_TO_RETAIN =
36+
new HashSet<>(
37+
Arrays.asList(
38+
"http.method",
39+
"http.status_code",
40+
"http.scheme",
41+
"http.route",
42+
"rpc.method",
43+
"rpc.grpc.status_code",
44+
"rpc.service"));
45+
46+
/**
47+
* Creates a View with HTTP attribute filtering and cardinality limit based on OpenTelemetry
48+
* configuration.
49+
*
50+
* <p>The cardinality limit is set from the OpenTelemetry system property or environment variable:
51+
*
52+
* <ul>
53+
* <li>System property: otel.experimental.metrics.cardinality.limit
54+
* <li>Environment variable: OTEL_EXPERIMENTAL_METRICS_CARDINALITY_LIMIT
55+
* </ul>
56+
*
57+
* @return a configured View with HTTP attribute filtering and cardinality limit
58+
*/
2659
public static View createView() {
27-
// Attributes to exclude
28-
Set<String> excludedAttributes =
29-
new HashSet<>(
30-
Arrays.asList(
31-
"net.sock.peer.addr",
32-
"net.sock.host.addr",
33-
"net.sock.peer.port",
34-
"net.sock.host.port",
35-
"net.host.name",
36-
"net.host.port",
37-
"net.protocol.name",
38-
"net.protocol.version",
39-
"http.user_agent",
40-
"enduser.id",
41-
"http.client_ip",
42-
"http.route",
43-
"http.target",
44-
"http.request_content_length",
45-
"http.response_content_length",
46-
"user_agent.original"));
47-
48-
// Build the view
49-
return View.builder()
50-
.setAttributeFilter(
51-
attributes -> {
52-
for (String attribute : excludedAttributes) {
53-
if (attributes.contains(attribute)) {
60+
// Build the view with our attribute filter
61+
View view =
62+
View.builder()
63+
.setAttributeFilter(
64+
attributes -> {
65+
for (String attribute : KEYS_TO_RETAIN) {
66+
if (attributes.contains(attribute)) {
67+
return true;
68+
}
69+
}
5470
return false;
55-
}
56-
}
57-
return true;
58-
})
59-
.build();
71+
})
72+
.build();
73+
74+
Integer cardinalityLimit = getCardinalityLimit();
75+
76+
/* Only apply cardinality limit if it's explicitly configured
77+
The global cardinality configuration field 'otel.experimental.metrics.cardinality.limit' does not apply for custom views
78+
Also the view builder, does not have a setter for cardinality limit in 1.33.0 SDK we use.
79+
So using reflection to set the cardinality limit
80+
*/
81+
if (cardinalityLimit != null) {
82+
try {
83+
// Get the View class
84+
Class<?> viewClass = view.getClass();
85+
86+
// Get the cardinalityLimit field
87+
Field cardinalityLimitField = viewClass.getDeclaredField("cardinalityLimit");
88+
cardinalityLimitField.setAccessible(true);
89+
90+
// Set the cardinality limit
91+
cardinalityLimitField.set(view, cardinalityLimit);
92+
93+
} catch (Exception e) {
94+
logger.log(Level.WARNING, "Failed to set cardinality limit using reflection", e);
95+
}
96+
}
97+
98+
return view;
99+
}
100+
101+
/**
102+
* Gets the cardinality limit from OpenTelemetry's system property or environment variable.
103+
*
104+
* @return the configured cardinality limit, or null if not configured
105+
*/
106+
private static Integer getCardinalityLimit() {
107+
String limitValue = getProperty(OTEL_CARDINALITY_LIMIT);
108+
109+
if (limitValue != null && !limitValue.isEmpty()) {
110+
try {
111+
return Integer.parseInt(limitValue);
112+
} catch (NumberFormatException e) {
113+
logger.log(Level.WARNING, "Invalid cardinality limit value: " + limitValue, e);
114+
}
115+
}
116+
117+
return null; // No explicit configuration
118+
}
119+
120+
/**
121+
* Gets a property from system properties or environment variables.
122+
*
123+
* @param name the property name
124+
* @return the property value, or null if not set
125+
*/
126+
private static String getProperty(String name) {
127+
return System.getProperty(name, System.getenv(name.replaceAll("\\.", "_").toUpperCase()));
60128
}
61129
}

0 commit comments

Comments
 (0)