Skip to content

Commit 5813589

Browse files
authored
feat: remove high cardinality metrics (#406)
* removing high cardinality metrics * removing content_length as well * adding smoke test
1 parent cbf3c2f commit 5813589

File tree

4 files changed

+115
-0
lines changed

4 files changed

+115
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright The Hypertrace Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.hypertrace.agent.otel.extensions;
18+
19+
import io.opentelemetry.sdk.metrics.View;
20+
import java.util.Arrays;
21+
import java.util.HashSet;
22+
import java.util.Set;
23+
24+
public class MetricViewConfiguration {
25+
26+
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.peer.port",
33+
"http.user_agent",
34+
"enduser.id",
35+
"http.client_ip",
36+
"http.request_content_length",
37+
"http.response_content_length",
38+
"user_agent.original"));
39+
40+
// Build the view
41+
return View.builder()
42+
.setAttributeFilter(
43+
attributes -> {
44+
for (String attribute : excludedAttributes) {
45+
if (attributes.contains(attribute)) {
46+
return false;
47+
}
48+
}
49+
return true;
50+
})
51+
.build();
52+
}
53+
}

otel-extensions/src/main/java/org/hypertrace/agent/otel/extensions/config/HypertraceAgentConfiguration.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import com.google.common.annotations.VisibleForTesting;
2121
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
2222
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
23+
import io.opentelemetry.sdk.metrics.InstrumentSelector;
24+
import io.opentelemetry.sdk.metrics.View;
2325
import java.util.HashMap;
2426
import java.util.List;
2527
import java.util.Map;
@@ -28,6 +30,7 @@
2830
import org.hypertrace.agent.config.v1.Config.MetricReporterType;
2931
import org.hypertrace.agent.config.v1.Config.PropagationFormat;
3032
import org.hypertrace.agent.config.v1.Config.TraceReporterType;
33+
import org.hypertrace.agent.otel.extensions.MetricViewConfiguration;
3134
import org.slf4j.Logger;
3235
import org.slf4j.LoggerFactory;
3336

@@ -113,5 +116,12 @@ public static String toOtelPropagators(List<PropagationFormat> propagationFormat
113116
@Override
114117
public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) {
115118
autoConfigurationCustomizer.addPropertiesSupplier(this::getProperties);
119+
autoConfigurationCustomizer.addMeterProviderCustomizer(
120+
(builder, config) -> {
121+
View httpServerDurationView = MetricViewConfiguration.createView();
122+
builder.registerView(
123+
InstrumentSelector.builder().setName("*").build(), httpServerDurationView);
124+
return builder;
125+
});
116126
}
117127
}

smoke-tests/src/test/java/org/hypertrace/agent/smoketest/AbstractSmokeTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@
2020
import com.google.protobuf.util.JsonFormat;
2121
import io.opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest;
2222
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;
23+
import io.opentelemetry.proto.common.v1.KeyValue;
24+
import io.opentelemetry.proto.metrics.v1.Metric;
2325
import io.opentelemetry.proto.trace.v1.ScopeSpans;
2426
import io.opentelemetry.proto.trace.v1.Span;
2527
import java.io.IOException;
2628
import java.time.Duration;
2729
import java.util.Collection;
30+
import java.util.List;
2831
import java.util.concurrent.TimeUnit;
2932
import java.util.concurrent.atomic.AtomicLong;
3033
import java.util.jar.Attributes;
@@ -244,6 +247,46 @@ protected boolean hasMetricNamed(
244247
.anyMatch(metric -> metric.getName().equals(metricName));
245248
}
246249

250+
// Checks if a metric with the given name contains the specified attribute
251+
protected boolean hasMetricWithAttribute(
252+
String metricName,
253+
String attributeName,
254+
Collection<ExportMetricsServiceRequest> metricRequests) {
255+
256+
return metricRequests.stream()
257+
.flatMap(metricRequest -> metricRequest.getResourceMetricsList().stream())
258+
.flatMap(resourceMetrics -> resourceMetrics.getScopeMetricsList().stream())
259+
.flatMap(scopeMetrics -> scopeMetrics.getMetricsList().stream())
260+
.filter(metric -> metric.getName().equals(metricName))
261+
.anyMatch(metric -> metricHasAttribute(metric, attributeName));
262+
}
263+
264+
private boolean metricHasAttribute(Metric metric, String attributeName) {
265+
switch (metric.getDataCase()) {
266+
case GAUGE:
267+
return metric.getGauge().getDataPointsList().stream()
268+
.anyMatch(dataPoint -> hasAttribute(dataPoint.getAttributesList(), attributeName));
269+
case SUM:
270+
return metric.getSum().getDataPointsList().stream()
271+
.anyMatch(dataPoint -> hasAttribute(dataPoint.getAttributesList(), attributeName));
272+
case HISTOGRAM:
273+
return metric.getHistogram().getDataPointsList().stream()
274+
.anyMatch(dataPoint -> hasAttribute(dataPoint.getAttributesList(), attributeName));
275+
case EXPONENTIAL_HISTOGRAM:
276+
return metric.getExponentialHistogram().getDataPointsList().stream()
277+
.anyMatch(dataPoint -> hasAttribute(dataPoint.getAttributesList(), attributeName));
278+
case SUMMARY:
279+
return metric.getSummary().getDataPointsList().stream()
280+
.anyMatch(dataPoint -> hasAttribute(dataPoint.getAttributesList(), attributeName));
281+
default:
282+
return false;
283+
}
284+
}
285+
286+
private boolean hasAttribute(List<KeyValue> attributes, String attributeName) {
287+
return attributes.stream().anyMatch(attribute -> attribute.getKey().equals(attributeName));
288+
}
289+
247290
public static String getPropertyOrEnv(String propName) {
248291
String property = System.getProperty(propName);
249292
if (property != null && !property.isEmpty()) {

smoke-tests/src/test/java/org/hypertrace/agent/smoketest/SpringBootSmokeTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,15 @@ public void postJson() throws IOException, InterruptedException {
174174
Assertions.assertTrue(hasMetricNamed("processedSpans", metrics));
175175
Assertions.assertTrue(hasMetricNamed("queueSize", metrics));
176176
Assertions.assertTrue(hasMetricNamed("http.server.duration", metrics));
177+
178+
Assertions.assertTrue(hasMetricWithAttribute("http.server.duration", "http.method", metrics));
179+
Assertions.assertTrue(hasMetricWithAttribute("http.server.duration", "http.route", metrics));
180+
Assertions.assertFalse(
181+
hasMetricWithAttribute("http.server.duration", "net.sock.peer.addr", metrics));
182+
Assertions.assertFalse(
183+
hasMetricWithAttribute("http.server.duration", "http.request_content_length", metrics));
184+
Assertions.assertFalse(
185+
hasMetricWithAttribute("http.server.duration", "http.response_content_length", metrics));
177186
}
178187

179188
@Test

0 commit comments

Comments
 (0)