Skip to content
Merged
Show file tree
Hide file tree
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
4 changes: 4 additions & 0 deletions buildSrc/.kotlin/errors/errors-1754401818862.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
kotlin version: 2.0.21
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output:
1. Kotlin compile daemon is ready

Comment on lines +1 to +4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, is this file should be in Git?
Probably we need to add some new rule to .gitignore?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh... good point. I'll open a PR to remove it and add to gitignore. Thanks for catching this!

Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package datadog.trace.api.telemetry;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ConfigInversionMetricCollector
implements MetricCollector<ConfigInversionMetricCollector.ConfigInversionMetric> {
private static final Logger log = LoggerFactory.getLogger(ConfigInversionMetricCollector.class);
private static final String CONFIG_INVERSION_KEY_TAG = "config_name:";
private static final String CONFIG_INVERSION_METRIC_NAME = "untracked.config.detected";
private static final String NAMESPACE = "tracers";
private static final ConfigInversionMetricCollector INSTANCE =
new ConfigInversionMetricCollector();

private final BlockingQueue<ConfigInversionMetricCollector.ConfigInversionMetric> metricsQueue;

private ConfigInversionMetricCollector() {
this.metricsQueue = new ArrayBlockingQueue<>(RAW_QUEUE_SIZE);
}

public static ConfigInversionMetricCollector getInstance() {
return INSTANCE;
}

public void setUndocumentedEnvVarMetric(String configName) {
setMetricConfigInversionMetric(CONFIG_INVERSION_KEY_TAG + configName);
}

private void setMetricConfigInversionMetric(final String... tags) {
if (!metricsQueue.offer(
new ConfigInversionMetricCollector.ConfigInversionMetric(
NAMESPACE, true, CONFIG_INVERSION_METRIC_NAME, "count", 1, tags))) {
log.debug("Unable to add telemetry metric {} for {}", CONFIG_INVERSION_METRIC_NAME, tags[0]);
}
}

@Override
public void prepareMetrics() {
// Nothing to do here
}

@Override
public Collection<ConfigInversionMetricCollector.ConfigInversionMetric> drain() {
if (this.metricsQueue.isEmpty()) {
return Collections.emptyList();
}
List<ConfigInversionMetricCollector.ConfigInversionMetric> drained =
new ArrayList<>(this.metricsQueue.size());
this.metricsQueue.drainTo(drained);
return drained;
}

public static class ConfigInversionMetric extends MetricCollector.Metric {
public ConfigInversionMetric(
String namespace,
boolean common,
String metricName,
String type,
Number value,
final String... tags) {
super(namespace, common, metricName, type, value, tags);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package datadog.trace.api.telemetry

import datadog.trace.test.util.DDSpecification

import static datadog.trace.api.telemetry.ConfigInversionMetricCollector.CONFIG_INVERSION_METRIC_NAME

class ConfigInversionMetricCollectorTest extends DDSpecification {

def "should emit metric when unsupported env var is used"() {
setup:
def collector = ConfigInversionMetricCollector.getInstance()

when:
ConfigInversionMetricCollectorTestHelper.checkAndEmitUnsupported("DD_UNKNOWN_FEATURE")
collector.prepareMetrics()
def metrics = collector.drain()

then:
metrics.size() == 1
def metric = metrics[0]
metric.type == 'count'
metric.value == 1
metric.namespace == 'tracers'
metric.metricName == CONFIG_INVERSION_METRIC_NAME
metric.tags.size() == 1
metric.tags[0] == 'config_name:DD_UNKNOWN_FEATURE'
}

def "should not emit metric when supported env var is used"() {
setup:
def collector = ConfigInversionMetricCollector.getInstance()

when:
ConfigInversionMetricCollectorTestHelper.checkAndEmitUnsupported("DD_ENV")
collector.prepareMetrics()
def metrics = collector.drain()

then:
metrics.isEmpty()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package datadog.trace.api.telemetry;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

// Lightweight helper class to simulate Config Inversion ConfigHelper scenario where telemetry
// metrics are emitted for "unknown" environment variables.
public class ConfigInversionMetricCollectorTestHelper {
private static final Set<String> SUPPORTED_ENV_VARS =
new HashSet<>(Arrays.asList("DD_ENV", "DD_SERVICE"));

private static final ConfigInversionMetricCollector configInversionMetricCollector =
ConfigInversionMetricCollector.getInstance();

public static void checkAndEmitUnsupported(String envVarName) {
if (!SUPPORTED_ENV_VARS.contains(envVarName)) {
configInversionMetricCollector.setUndocumentedEnvVarMetric(envVarName);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import datadog.telemetry.integration.IntegrationPeriodicAction;
import datadog.telemetry.log.LogPeriodicAction;
import datadog.telemetry.metric.CiVisibilityMetricPeriodicAction;
import datadog.telemetry.metric.ConfigInversionMetricPeriodicAction;
import datadog.telemetry.metric.CoreMetricsPeriodicAction;
import datadog.telemetry.metric.IastMetricPeriodicAction;
import datadog.telemetry.metric.OtelEnvMetricPeriodicAction;
Expand Down Expand Up @@ -51,6 +52,7 @@ static Thread createTelemetryRunnable(
if (telemetryMetricsEnabled) {
actions.add(new CoreMetricsPeriodicAction());
actions.add(new OtelEnvMetricPeriodicAction());
actions.add(new ConfigInversionMetricPeriodicAction());
actions.add(new IntegrationPeriodicAction());
actions.add(new WafMetricPeriodicAction());
if (Verbosity.OFF != Config.get().getIastTelemetryVerbosity()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package datadog.telemetry.metric;

import datadog.trace.api.telemetry.ConfigInversionMetricCollector;
import datadog.trace.api.telemetry.MetricCollector;
import edu.umd.cs.findbugs.annotations.NonNull;

public class ConfigInversionMetricPeriodicAction extends MetricPeriodicAction {
@Override
@NonNull
public MetricCollector collector() {
return ConfigInversionMetricCollector.getInstance();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package datadog.telemetry.metric

import datadog.telemetry.TelemetryService
import datadog.telemetry.api.Metric
import spock.lang.Specification

class ConfigInversionMetricPeriodicActionTest extends Specification{

void 'test undocumented env var metric'() {
setup:
final telemetryService = Mock(TelemetryService)
final action = new ConfigInversionMetricPeriodicAction()

when:
action.collector().setUndocumentedEnvVarMetric("DD_ENV_VAR")
action.collector().prepareMetrics()
action.doIteration(telemetryService)

then:
1 * telemetryService.addMetric({ Metric metric ->
metric.namespace == 'tracers' &&
metric.metric == 'untracked.config.detected' &&
metric.points[0][1] == 1 &&
metric.tags == ['config_name:DD_ENV_VAR'] &&
metric.type == Metric.TypeEnum.COUNT
})
0 * _._
}
}