Skip to content

Commit 61fc9fa

Browse files
committed
Adding ConfigInversion Telemetry component
1 parent 94cd99a commit 61fc9fa

File tree

5 files changed

+134
-0
lines changed

5 files changed

+134
-0
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package datadog.trace.api.telemetry;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collection;
5+
import java.util.Collections;
6+
import java.util.List;
7+
import java.util.concurrent.ArrayBlockingQueue;
8+
import java.util.concurrent.BlockingQueue;
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
12+
public class ConfigInversionMetricCollector
13+
implements MetricCollector<ConfigInversionMetricCollector.ConfigInversionMetric> {
14+
private static final Logger log = LoggerFactory.getLogger(ConfigInversionMetricCollector.class);
15+
private static final String CONFIG_INVERSION_KEY_TAG = "config_name:";
16+
private static final String CONFIG_INVERSION_METRIC_NAME = "untracked.config.detected";
17+
private static final String NAMESPACE = "tracers";
18+
private static final ConfigInversionMetricCollector INSTANCE =
19+
new ConfigInversionMetricCollector();
20+
21+
private final BlockingQueue<ConfigInversionMetricCollector.ConfigInversionMetric> metricsQueue;
22+
23+
private ConfigInversionMetricCollector() {
24+
this.metricsQueue = new ArrayBlockingQueue<>(RAW_QUEUE_SIZE);
25+
}
26+
27+
public static ConfigInversionMetricCollector getInstance() {
28+
return INSTANCE;
29+
}
30+
31+
public void setUndocumentedEnvVarMetric(String configName) {
32+
setMetricConfigInversionMetric(CONFIG_INVERSION_KEY_TAG + configName);
33+
}
34+
35+
private void setMetricConfigInversionMetric(final String... tags) {
36+
if (!metricsQueue.offer(
37+
new ConfigInversionMetricCollector.ConfigInversionMetric(
38+
NAMESPACE, true, CONFIG_INVERSION_METRIC_NAME, "count", 1, tags))) {
39+
log.debug("Unable to add telemetry metric {} for {}", CONFIG_INVERSION_METRIC_NAME, tags[0]);
40+
}
41+
}
42+
43+
@Override
44+
public void prepareMetrics() {
45+
// Nothing to do here
46+
}
47+
48+
@Override
49+
public Collection<ConfigInversionMetricCollector.ConfigInversionMetric> drain() {
50+
if (this.metricsQueue.isEmpty()) {
51+
return Collections.emptyList();
52+
}
53+
List<ConfigInversionMetricCollector.ConfigInversionMetric> drained =
54+
new ArrayList<>(this.metricsQueue.size());
55+
this.metricsQueue.drainTo(drained);
56+
return drained;
57+
}
58+
59+
public static class ConfigInversionMetric extends MetricCollector.Metric {
60+
public ConfigInversionMetric(
61+
String namespace,
62+
boolean common,
63+
String metricName,
64+
String type,
65+
Number value,
66+
final String... tags) {
67+
super(namespace, common, metricName, type, value, tags);
68+
}
69+
}
70+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package datadog.trace.api.telemetry
2+
3+
import datadog.trace.test.util.DDSpecification
4+
5+
import static datadog.trace.api.telemetry.ConfigInversionMetricCollector.CONFIG_INVERSION_METRIC_NAME
6+
7+
class ConfigInversionMetricCollectorTest extends DDSpecification {
8+
9+
def "should emit metric when unsupported env var is used"() {
10+
setup:
11+
def collector = ConfigInversionMetricCollector.getInstance()
12+
13+
when:
14+
ConfigInversionMetricCollectorTestHelper.checkAndEmitUnsupported("DD_UNKNOWN_FEATURE")
15+
collector.prepareMetrics()
16+
def metrics = collector.drain()
17+
18+
then:
19+
metrics.size() == 1
20+
def metric = metrics[0]
21+
metric.type == 'count'
22+
metric.value == 1
23+
metric.namespace == 'tracers'
24+
metric.metricName == CONFIG_INVERSION_METRIC_NAME
25+
metric.tags.size() == 1
26+
metric.tags[0] == 'config_name:DD_UNKNOWN_FEATURE'
27+
}
28+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package datadog.trace.api.telemetry;
2+
3+
import java.util.Arrays;
4+
import java.util.HashSet;
5+
import java.util.Set;
6+
7+
// Lightweight helper class to simulate Config Inversion ConfigHelper scenario where telemetry
8+
// metrics are emitted for "unknown" environment variables.
9+
public class ConfigInversionMetricCollectorTestHelper {
10+
private static final Set<String> SUPPORTED_ENV_VARS =
11+
new HashSet<>(Arrays.asList("DD_ENV", "DD_SERVICE"));
12+
13+
private static final ConfigInversionMetricCollector configInversionMetricCollector =
14+
ConfigInversionMetricCollector.getInstance();
15+
16+
public static void checkAndEmitUnsupported(String envVarName) {
17+
if (!SUPPORTED_ENV_VARS.contains(envVarName)) {
18+
configInversionMetricCollector.setUndocumentedEnvVarMetric(envVarName);
19+
}
20+
}
21+
}

telemetry/src/main/java/datadog/telemetry/TelemetrySystem.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import datadog.telemetry.integration.IntegrationPeriodicAction;
1111
import datadog.telemetry.log.LogPeriodicAction;
1212
import datadog.telemetry.metric.CiVisibilityMetricPeriodicAction;
13+
import datadog.telemetry.metric.ConfigInversionMetricPeriodicAction;
1314
import datadog.telemetry.metric.CoreMetricsPeriodicAction;
1415
import datadog.telemetry.metric.IastMetricPeriodicAction;
1516
import datadog.telemetry.metric.OtelEnvMetricPeriodicAction;
@@ -51,6 +52,7 @@ static Thread createTelemetryRunnable(
5152
if (telemetryMetricsEnabled) {
5253
actions.add(new CoreMetricsPeriodicAction());
5354
actions.add(new OtelEnvMetricPeriodicAction());
55+
actions.add(new ConfigInversionMetricPeriodicAction());
5456
actions.add(new IntegrationPeriodicAction());
5557
actions.add(new WafMetricPeriodicAction());
5658
if (Verbosity.OFF != Config.get().getIastTelemetryVerbosity()) {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package datadog.telemetry.metric;
2+
3+
import datadog.trace.api.telemetry.ConfigInversionMetricCollector;
4+
import datadog.trace.api.telemetry.MetricCollector;
5+
import edu.umd.cs.findbugs.annotations.NonNull;
6+
7+
public class ConfigInversionMetricPeriodicAction extends MetricPeriodicAction {
8+
@Override
9+
@NonNull
10+
public MetricCollector collector() {
11+
return ConfigInversionMetricCollector.getInstance();
12+
}
13+
}

0 commit comments

Comments
 (0)