Skip to content

Commit 19d774d

Browse files
cecile75mhliddmcculls
authored
Add Otel Metrics configuration keys (#9868)
* update opentelemetry-api to 1.47.0 * add otel metrics configuration * solve P2 spotbugsMain * remove enum from jacocoTest coverage * fix :jacocoTestCoverageVerification for :utils:config-utils * add otel metrics configuration keys to Centralized Configuration * initialized at build time OtelConfig and OtelConfig * easy improvements following feedback * use previous existing function for Map * Update dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java Co-authored-by: mhlidd <matthew.li@datadoghq.com> * Update dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java Co-authored-by: mhlidd <matthew.li@datadoghq.com> * Update dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java Co-authored-by: mhlidd <matthew.li@datadoghq.com> * remove duplicate env vars Co-authored-by: mhlidd <matthew.li@datadoghq.com> * Fix spotlessss after commits from github * Refactor generic otel config * Clean * Re adapt class name for graalVM * renaming leftover * Fix runtime metrics * Include OtelMetricsConfig$Temporality along with the other new OTel metrics enums * Cleanup OTel constants * Put defaults in consistent location * Update comment * Replace concat call with + * Revert change to ConfigStrings * Rename OtelMetricsConfig to OtlpConfig and drop Exporter enum as it doesn't add value * Make ConfigProvider.getEnum more robust: make value uppercase and replace known bad characters before converting * Cleanup ConfigDefaults * Ensure agentHost is never empty * Cleanup metrics internal config * Remove static import * Cleanup metrics internal OTLP config * Add new DD metrics keys * Update test expectations: default protocol is now HTTP/PROTOBUF * Move OTel mappings out of Config * Implement OTel metrics mappings in OtelEnvironmentConfigSource * Cleanup * Warn when any OTel timeouts/intervals are configured with negative values * Remove unused fields --------- Co-authored-by: mhlidd <matthew.li@datadoghq.com> Co-authored-by: Stuart McCulloch <stuart.mcculloch@datadoghq.com>
1 parent 59d7f4e commit 19d774d

File tree

9 files changed

+609
-33
lines changed

9 files changed

+609
-33
lines changed

dd-java-agent/instrumentation/graal/native-image/src/main/java/datadog/trace/instrumentation/graal/nativeimage/NativeImageGeneratorRunnerInstrumentation.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ public static void onEnter(@Advice.Argument(value = 0, readOnly = false) String[
8484
+ "datadog.trace.api.ConfigDefaults:build_time,"
8585
+ "datadog.trace.api.ConfigOrigin:build_time,"
8686
+ "datadog.trace.api.ConfigSetting:build_time,"
87+
+ "datadog.trace.api.config.OtlpConfig$Protocol:build_time,"
88+
+ "datadog.trace.api.config.OtlpConfig$Temporality:build_time,"
8789
+ "datadog.trace.api.EventTracker:build_time,"
8890
+ "datadog.trace.api.InstrumenterConfig:build_time,"
8991
+ "datadog.trace.api.Functions:build_time,"

dd-trace-api/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ val excludedClassesCoverage by extra(
6363
"datadog.trace.payloadtags.PayloadTagsData",
6464
"datadog.trace.payloadtags.PayloadTagsData.PathAndValue",
6565
"datadog.trace.api.llmobs.LLMObsTags",
66+
"datadog.trace.api.config.OtlpConfig.Protocol",
67+
"datadog.trace.api.config.OtlpConfig.Temporality",
6668
)
6769
)
6870

dd-trace-api/src/main/java/datadog/trace/api/ConfigDefaults.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,16 @@ public final class ConfigDefaults {
101101
static final boolean DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_ENABLED = false;
102102
static final int DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT = 10;
103103

104+
public static final boolean DEFAULT_METRICS_OTEL_ENABLED = false;
105+
// Default recommended by Datadog; it differs from Otel’s default of 60000 (60s)
106+
static final int DEFAULT_METRICS_OTEL_INTERVAL = 10000; // ms
107+
// Default recommended by Datadog; it differs from Otel’s default of 30000 (30s)
108+
static final int DEFAULT_METRICS_OTEL_TIMEOUT = 7500; // ms
109+
110+
static final String DEFAULT_OTLP_HTTP_METRIC_ENDPOINT = "v1/metrics";
111+
static final String DEFAULT_OTLP_HTTP_PORT = "4318";
112+
static final String DEFAULT_OTLP_GRPC_PORT = "4317";
113+
104114
static final int DEFAULT_DOGSTATSD_START_DELAY = 15; // seconds
105115

106116
static final boolean DEFAULT_HEALTH_METRICS_ENABLED = true;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package datadog.trace.api.config;
2+
3+
public final class OtlpConfig {
4+
5+
public static final String METRICS_OTEL_ENABLED = "metrics.otel.enabled";
6+
public static final String METRICS_OTEL_INTERVAL = "metrics.otel.interval";
7+
public static final String METRICS_OTEL_TIMEOUT = "metrics.otel.timeout";
8+
9+
public static final String OTLP_METRICS_ENDPOINT = "otlp.metrics.endpoint";
10+
public static final String OTLP_METRICS_HEADERS = "otlp.metrics.headers";
11+
public static final String OTLP_METRICS_PROTOCOL = "otlp.metrics.protocol";
12+
public static final String OTLP_METRICS_TIMEOUT = "otlp.metrics.timeout";
13+
public static final String OTLP_METRICS_TEMPORALITY_PREFERENCE =
14+
"otlp.metrics.temporality.preference";
15+
16+
public enum Protocol {
17+
GRPC,
18+
HTTP_PROTOBUF,
19+
HTTP_JSON
20+
}
21+
22+
public enum Temporality {
23+
CUMULATIVE,
24+
DELTA,
25+
LOWMEMORY
26+
}
27+
28+
private OtlpConfig() {}
29+
}

internal-api/src/main/java/datadog/trace/api/Config.java

Lines changed: 130 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@
114114
import static datadog.trace.api.ConfigDefaults.DEFAULT_JMX_FETCH_MULTIPLE_RUNTIME_SERVICES_LIMIT;
115115
import static datadog.trace.api.ConfigDefaults.DEFAULT_LLM_OBS_AGENTLESS_ENABLED;
116116
import static datadog.trace.api.ConfigDefaults.DEFAULT_LOGS_INJECTION_ENABLED;
117+
import static datadog.trace.api.ConfigDefaults.DEFAULT_METRICS_OTEL_ENABLED;
118+
import static datadog.trace.api.ConfigDefaults.DEFAULT_METRICS_OTEL_INTERVAL;
119+
import static datadog.trace.api.ConfigDefaults.DEFAULT_METRICS_OTEL_TIMEOUT;
120+
import static datadog.trace.api.ConfigDefaults.DEFAULT_OTLP_GRPC_PORT;
121+
import static datadog.trace.api.ConfigDefaults.DEFAULT_OTLP_HTTP_METRIC_ENDPOINT;
122+
import static datadog.trace.api.ConfigDefaults.DEFAULT_OTLP_HTTP_PORT;
117123
import static datadog.trace.api.ConfigDefaults.DEFAULT_PARTIAL_FLUSH_MIN_SPANS;
118124
import static datadog.trace.api.ConfigDefaults.DEFAULT_PERF_METRICS_ENABLED;
119125
import static datadog.trace.api.ConfigDefaults.DEFAULT_PRIORITY_SAMPLING_ENABLED;
@@ -438,6 +444,14 @@
438444
import static datadog.trace.api.config.JmxFetchConfig.JMX_TAGS;
439445
import static datadog.trace.api.config.LlmObsConfig.LLMOBS_AGENTLESS_ENABLED;
440446
import static datadog.trace.api.config.LlmObsConfig.LLMOBS_ML_APP;
447+
import static datadog.trace.api.config.OtlpConfig.METRICS_OTEL_ENABLED;
448+
import static datadog.trace.api.config.OtlpConfig.METRICS_OTEL_INTERVAL;
449+
import static datadog.trace.api.config.OtlpConfig.METRICS_OTEL_TIMEOUT;
450+
import static datadog.trace.api.config.OtlpConfig.OTLP_METRICS_ENDPOINT;
451+
import static datadog.trace.api.config.OtlpConfig.OTLP_METRICS_HEADERS;
452+
import static datadog.trace.api.config.OtlpConfig.OTLP_METRICS_PROTOCOL;
453+
import static datadog.trace.api.config.OtlpConfig.OTLP_METRICS_TEMPORALITY_PREFERENCE;
454+
import static datadog.trace.api.config.OtlpConfig.OTLP_METRICS_TIMEOUT;
441455
import static datadog.trace.api.config.ProfilingConfig.PROFILING_AGENTLESS;
442456
import static datadog.trace.api.config.ProfilingConfig.PROFILING_AGENTLESS_DEFAULT;
443457
import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_FILE_OLD;
@@ -655,7 +669,6 @@
655669
import static datadog.trace.api.config.TracerConfig.TRACE_X_DATADOG_TAGS_MAX_LENGTH;
656670
import static datadog.trace.api.config.TracerConfig.WRITER_BAGGAGE_INJECT;
657671
import static datadog.trace.api.config.TracerConfig.WRITER_TYPE;
658-
import static datadog.trace.api.iast.IastDetectionMode.DEFAULT;
659672
import static datadog.trace.api.telemetry.LogCollector.SEND_TELEMETRY;
660673
import static datadog.trace.util.CollectionUtils.tryMakeImmutableList;
661674
import static datadog.trace.util.CollectionUtils.tryMakeImmutableSet;
@@ -666,6 +679,7 @@
666679
import datadog.environment.SystemProperties;
667680
import datadog.trace.api.civisibility.CiVisibilityWellKnownTags;
668681
import datadog.trace.api.config.GeneralConfig;
682+
import datadog.trace.api.config.OtlpConfig;
669683
import datadog.trace.api.config.ProfilingConfig;
670684
import datadog.trace.api.config.TracerConfig;
671685
import datadog.trace.api.iast.IastContext;
@@ -890,6 +904,15 @@ public static String getHostName() {
890904
private final boolean jmxFetchMultipleRuntimeServicesEnabled;
891905
private final int jmxFetchMultipleRuntimeServicesLimit;
892906

907+
private final boolean metricsOtelEnabled;
908+
private final int metricsOtelInterval;
909+
private final int metricsOtelTimeout;
910+
private final String otlpMetricsEndpoint;
911+
private final Map<String, String> otlpMetricsHeaders;
912+
private final OtlpConfig.Protocol otlpMetricsProtocol;
913+
private final int otlpMetricsTimeout;
914+
private final OtlpConfig.Temporality otlpMetricsTemporalityPreference;
915+
893916
// These values are default-ed to those of jmx fetch values as needed
894917
private final boolean healthMetricsEnabled;
895918
private final String healthMetricsStatsdHost;
@@ -1454,7 +1477,7 @@ private Config(final ConfigProvider configProvider, final InstrumenterConfig ins
14541477
}
14551478
}
14561479

1457-
if (agentHostFromEnvironment == null) {
1480+
if (agentHostFromEnvironment == null || agentHostFromEnvironment.isEmpty()) {
14581481
agentHost = DEFAULT_AGENT_HOST;
14591482
} else if (agentHostFromEnvironment.charAt(0) == '[') {
14601483
agentHost = agentHostFromEnvironment.substring(1, agentHostFromEnvironment.length() - 1);
@@ -1833,6 +1856,61 @@ private Config(final ConfigProvider configProvider, final InstrumenterConfig ins
18331856
statsDClientSocketBuffer = configProvider.getInteger(STATSD_CLIENT_SOCKET_BUFFER);
18341857
statsDClientSocketTimeout = configProvider.getInteger(STATSD_CLIENT_SOCKET_TIMEOUT);
18351858

1859+
metricsOtelEnabled =
1860+
configProvider.getBoolean(METRICS_OTEL_ENABLED, DEFAULT_METRICS_OTEL_ENABLED);
1861+
1862+
int otelInterval =
1863+
configProvider.getInteger(METRICS_OTEL_INTERVAL, DEFAULT_METRICS_OTEL_INTERVAL);
1864+
if (otelInterval < 0) {
1865+
log.warn("Invalid OTel metrics interval: {}. The value must be positive", otelInterval);
1866+
otelInterval = DEFAULT_METRICS_OTEL_INTERVAL;
1867+
}
1868+
metricsOtelInterval = otelInterval;
1869+
1870+
int otelTimeout = configProvider.getInteger(METRICS_OTEL_TIMEOUT, DEFAULT_METRICS_OTEL_TIMEOUT);
1871+
if (otelTimeout < 0) {
1872+
log.warn("Invalid OTel metrics timeout: {}. The value must be positive", otelTimeout);
1873+
otelTimeout = DEFAULT_METRICS_OTEL_TIMEOUT;
1874+
}
1875+
metricsOtelTimeout = otelTimeout;
1876+
1877+
// keep OTLP default timeout below the overall export timeout
1878+
int defaultOtlpTimeout = Math.min(metricsOtelTimeout, DEFAULT_METRICS_OTEL_TIMEOUT);
1879+
int otlpTimeout = configProvider.getInteger(OTLP_METRICS_TIMEOUT, defaultOtlpTimeout);
1880+
if (otlpTimeout < 0) {
1881+
log.warn("Invalid OTLP metrics timeout: {}. The value must be positive", otlpTimeout);
1882+
otlpTimeout = defaultOtlpTimeout;
1883+
}
1884+
otlpMetricsTimeout = otlpTimeout;
1885+
1886+
otlpMetricsHeaders = configProvider.getMergedMap(OTLP_METRICS_HEADERS, '=');
1887+
otlpMetricsProtocol =
1888+
configProvider.getEnum(
1889+
OTLP_METRICS_PROTOCOL, OtlpConfig.Protocol.class, OtlpConfig.Protocol.HTTP_PROTOBUF);
1890+
1891+
String otlpMetricsEndpointFromEnvironment = configProvider.getString(OTLP_METRICS_ENDPOINT);
1892+
if (otlpMetricsEndpointFromEnvironment == null) {
1893+
if (otlpMetricsProtocol == OtlpConfig.Protocol.GRPC) {
1894+
otlpMetricsEndpointFromEnvironment = "http://" + agentHost + ':' + DEFAULT_OTLP_GRPC_PORT;
1895+
} else {
1896+
otlpMetricsEndpointFromEnvironment =
1897+
"http://"
1898+
+ agentHost
1899+
+ ':'
1900+
+ DEFAULT_OTLP_HTTP_PORT
1901+
+ '/'
1902+
+ DEFAULT_OTLP_HTTP_METRIC_ENDPOINT;
1903+
}
1904+
}
1905+
otlpMetricsEndpoint = otlpMetricsEndpointFromEnvironment;
1906+
1907+
otlpMetricsTemporalityPreference =
1908+
configProvider.getEnum(
1909+
OTLP_METRICS_TEMPORALITY_PREFERENCE,
1910+
OtlpConfig.Temporality.class,
1911+
OtlpConfig.Temporality.DELTA);
1912+
1913+
// Runtime metrics are disabled if Otel metrics are enabled and the metrics exporter is none
18361914
runtimeMetricsEnabled = configProvider.getBoolean(RUNTIME_METRICS_ENABLED, true);
18371915

18381916
jmxFetchEnabled =
@@ -2158,7 +2236,8 @@ PROFILING_DATADOG_PROFILER_ENABLED, isDatadogProfilerSafeInCurrentEnvironment())
21582236
iastContextMode =
21592237
configProvider.getEnum(IAST_CONTEXT_MODE, IastContext.Mode.class, IastContext.Mode.REQUEST);
21602238
iastDetectionMode =
2161-
configProvider.getEnum(IAST_DETECTION_MODE, IastDetectionMode.class, DEFAULT);
2239+
configProvider.getEnum(
2240+
IAST_DETECTION_MODE, IastDetectionMode.class, IastDetectionMode.DEFAULT);
21622241
iastMaxConcurrentRequests = iastDetectionMode.getIastMaxConcurrentRequests(configProvider);
21632242
iastVulnerabilitiesPerRequest =
21642243
iastDetectionMode.getIastVulnerabilitiesPerRequest(configProvider);
@@ -4972,6 +5051,38 @@ public boolean isJmxFetchIntegrationEnabled(
49725051
return configProvider.isEnabled(integrationNames, "jmxfetch.", ".enabled", defaultEnabled);
49735052
}
49745053

5054+
public boolean isMetricsOtelEnabled() {
5055+
return metricsOtelEnabled;
5056+
}
5057+
5058+
public int getMetricsOtelInterval() {
5059+
return metricsOtelInterval;
5060+
}
5061+
5062+
public int getMetricsOtelTimeout() {
5063+
return metricsOtelTimeout;
5064+
}
5065+
5066+
public String getOtlpMetricsEndpoint() {
5067+
return otlpMetricsEndpoint;
5068+
}
5069+
5070+
public Map<String, String> getOtlpMetricsHeaders() {
5071+
return otlpMetricsHeaders;
5072+
}
5073+
5074+
public OtlpConfig.Protocol getOtlpMetricsProtocol() {
5075+
return otlpMetricsProtocol;
5076+
}
5077+
5078+
public int getOtlpMetricsTimeout() {
5079+
return otlpMetricsTimeout;
5080+
}
5081+
5082+
public OtlpConfig.Temporality getOtlpMetricsTemporalityPreference() {
5083+
return otlpMetricsTemporalityPreference;
5084+
}
5085+
49755086
public boolean isRuleEnabled(final String name) {
49765087
return isRuleEnabled(name, true);
49775088
}
@@ -5960,6 +6071,22 @@ public String toString() {
59606071
+ aiGuardEnabled
59616072
+ ", aiGuardEndpoint="
59626073
+ aiGuardEndpoint
6074+
+ ", metricsOtelEnabled="
6075+
+ metricsOtelEnabled
6076+
+ ", metricsOtelInterval="
6077+
+ metricsOtelInterval
6078+
+ ", metricsOtelTimeout="
6079+
+ metricsOtelTimeout
6080+
+ ", otlpMetricsEndpoint="
6081+
+ otlpMetricsEndpoint
6082+
+ ", otlpMetricsHeaders="
6083+
+ otlpMetricsHeaders
6084+
+ ", otlpMetricsProtocol="
6085+
+ otlpMetricsProtocol
6086+
+ ", otlpMetricsTimeout="
6087+
+ otlpMetricsTimeout
6088+
+ ", otlpMetricsTemporalityPreference="
6089+
+ otlpMetricsTemporalityPreference
59636090
+ ", serviceDiscoveryEnabled="
59646091
+ serviceDiscoveryEnabled
59656092
+ '}';

0 commit comments

Comments
 (0)