Skip to content

feat: adding allow list instead for metric view and cardinality configuration support #421

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 3, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,45 +17,112 @@
package org.hypertrace.agent.otel.extensions;

import io.opentelemetry.sdk.metrics.View;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

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

// OpenTelemetry's cardinality limit property
private static final String OTEL_CARDINALITY_LIMIT =
"otel.experimental.metrics.cardinality.limit";

// Default HTTP attributes to include
private static final Set<String> KEYS_TO_RETAIN =
new HashSet<>(
Arrays.asList(
"http.method",
"http.status_code",
"http.scheme",
"rpc.method",
"rpc.grpc.status_code",
"rpc.service"));

/**
* Creates a View with HTTP attribute filtering and cardinality limit based on OpenTelemetry
* configuration.
*
* <p>The cardinality limit is set from the OpenTelemetry system property or environment variable:
*
* <ul>
* <li>System property: otel.experimental.metrics.cardinality.limit
* <li>Environment variable: OTEL_EXPERIMENTAL_METRICS_CARDINALITY_LIMIT
* </ul>
*
* @return a configured View with HTTP attribute filtering and cardinality limit
*/
public static View createView() {
// Attributes to exclude
Set<String> excludedAttributes =
new HashSet<>(
Arrays.asList(
"net.sock.peer.addr",
"net.sock.host.addr",
"net.sock.peer.port",
"net.sock.host.port",
"net.host.name",
"net.host.port",
"net.protocol.name",
"net.protocol.version",
"http.user_agent",
"enduser.id",
"http.client_ip",
"http.route",
"http.target",
"http.request_content_length",
"http.response_content_length",
"user_agent.original"));

// Build the view
return View.builder()
.setAttributeFilter(
attributes -> {
for (String attribute : excludedAttributes) {
if (attributes.contains(attribute)) {
// Build the view with our attribute filter
View view =
View.builder()
.setAttributeFilter(
attributes -> {
for (String attribute : KEYS_TO_RETAIN) {
if (attributes.contains(attribute)) {
return true;
}
}
return false;
}
}
return true;
})
.build();
})
.build();

Integer cardinalityLimit = getCardinalityLimit();

/* Only apply cardinality limit if it's explicitly configured
The global cardinality configuration field 'otel.experimental.metrics.cardinality.limit' does not apply for custom views
Also the view builder, does not have a setter for cardinality limit in 1.33.0 SDK we use.
So using reflection to set the cardinality limit
*/
if (cardinalityLimit != null) {
try {
// Get the View class
Class<?> viewClass = view.getClass();

// Get the cardinalityLimit field
Field cardinalityLimitField = viewClass.getDeclaredField("cardinalityLimit");
cardinalityLimitField.setAccessible(true);

// Set the cardinality limit
cardinalityLimitField.set(view, cardinalityLimit);

} catch (Exception e) {
logger.log(Level.WARNING, "Failed to set cardinality limit using reflection", e);
}
}

return view;
}

/**
* Gets the cardinality limit from OpenTelemetry's system property or environment variable.
*
* @return the configured cardinality limit, or null if not configured
*/
private static Integer getCardinalityLimit() {
String limitValue = getProperty(OTEL_CARDINALITY_LIMIT);

if (limitValue != null && !limitValue.isEmpty()) {
try {
return Integer.parseInt(limitValue);
} catch (NumberFormatException e) {
logger.log(Level.WARNING, "Invalid cardinality limit value: " + limitValue, e);
}
}

return null; // No explicit configuration
}

/**
* Gets a property from system properties or environment variables.
*
* @param name the property name
* @return the property value, or null if not set
*/
private static String getProperty(String name) {
return System.getProperty(name, System.getenv(name.replaceAll("\\.", "_").toUpperCase()));
}
}
Loading