-
Notifications
You must be signed in to change notification settings - Fork 168
Expand file tree
/
Copy pathOpenTelemetrySDKCustomizer.java
More file actions
134 lines (119 loc) · 6.64 KB
/
Copy pathOpenTelemetrySDKCustomizer.java
File metadata and controls
134 lines (119 loc) · 6.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
*
* * Copyright 2024 New Relic Corporation. All rights reserved.
* * SPDX-License-Identifier: Apache-2.0
*
*/
package io.opentelemetry.sdk.autoconfigure;
import com.newrelic.agent.bridge.AgentBridge;
import com.newrelic.api.agent.Agent;
import com.newrelic.api.agent.Logger;
import com.newrelic.api.agent.NewRelic;
import com.nr.agent.instrumentation.utils.config.OpenTelemetryConfig;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.metrics.Aggregation;
import io.opentelemetry.sdk.metrics.InstrumentSelector;
import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder;
import io.opentelemetry.sdk.metrics.View;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.resources.ResourceBuilder;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
import static com.nr.agent.instrumentation.utils.config.OpenTelemetryConfig.getOpenTelemetryMetricsExcludes;
/**
* Helper class for customizing OpenTelemetrySDK properties
* and resources for compatability with New Relic.
*/
final class OpenTelemetrySDKCustomizer {
static final AttributeKey<String> SERVICE_INSTANCE_ID_ATTRIBUTE_KEY = AttributeKey.stringKey("service.instance.id");
private static final String DEFAULT_COLLECTOR_HOST = "collector.newrelic.com";
static Map<String, String> applyProperties(ConfigProperties configProperties) {
return applyProperties(configProperties, NewRelic.getAgent());
}
/**
* Configure OpenTelemetry exporters to send data to the New Relic backend.
*/
static Map<String, String> applyProperties(ConfigProperties configProperties, Agent agent) {
final String existingEndpoint = configProperties.getString("otel.exporter.otlp.endpoint");
if (existingEndpoint == null) {
agent.getLogger().log(Level.INFO, "Auto-initializing OpenTelemetry SDK");
String host = agent.getConfig().getValue("host");
if (host == null) {
host = DEFAULT_COLLECTOR_HOST;
agent.getLogger().log(Level.WARNING,
"No host was configured for the OpenTelemetry metrics exporter endpoint. The exporter will use the default host for the New Relic US Production region: {0}",
DEFAULT_COLLECTOR_HOST);
}
final String endpoint = "https://" + host + ":443";
final String licenseKey = agent.getConfig().getValue("license_key");
final Map<String, String> properties = new HashMap<>();
properties.put("otel.exporter.otlp.headers", "api-key=" + licenseKey);
properties.put("otel.exporter.otlp.endpoint", endpoint);
properties.put("otel.metrics.exporter", "otlp"); // enable otlp metrics exporter
properties.put("otel.traces.exporter", "none"); // disable default traces exporter
properties.put("otel.logs.exporter", "none"); // disable default logs exporter
// otel.metric.export.interval should be set before otel.exporter.otlp.metrics.timeout for validation purposes
properties.put("otel.metric.export.interval",
String.valueOf(OpenTelemetryConfig.getOpenTelemetryMetricsExportInterval())); // metric reporting interval in milliseconds
properties.put("otel.exporter.otlp.metrics.timeout",
String.valueOf(OpenTelemetryConfig.getOpenTelemetryMetricsExportTimeout())); // metric reporting timeout in milliseconds
properties.put("otel.java.metrics.cardinality.limit", String.valueOf(OpenTelemetryConfig.getOpenTelemetryMetricsCardinality()));
properties.put("otel.exporter.otlp.protocol", "http/protobuf");
properties.put("otel.span.attribute.value.length.limit", "4095");
properties.put("otel.exporter.otlp.compression", "gzip");
properties.put("otel.exporter.otlp.metrics.temporality.preference", "DELTA");
properties.put("otel.exporter.otlp.metrics.default.histogram.aggregation", "BASE2_EXPONENTIAL_BUCKET_HISTOGRAM");
properties.put("otel.experimental.exporter.otlp.retry.enabled", "true");
properties.put("otel.experimental.resource.disabled.keys", "process.command_line");
final Object appName = agent.getConfig().getValue("app_name");
properties.put("otel.service.name", appName.toString());
return properties;
} else {
agent.getLogger().log(Level.WARNING,
"The OpenTelemetry exporter endpoint is set to {0}, the agent will not autoconfigure the SDK",
existingEndpoint);
}
return Collections.emptyMap();
}
static Resource applyResources(Resource resource, ConfigProperties configProperties) {
return applyResources(resource, AgentBridge.getAgent(), NewRelic.getAgent().getLogger());
}
/**
* Add the monitored service's entity.guid to resources.
*/
static Resource applyResources(Resource resource, com.newrelic.agent.bridge.Agent agent, Logger logger) {
logger.log(Level.FINE, "Appending OpenTelemetry resources");
final ResourceBuilder builder = new ResourceBuilder().putAll(resource);
final String instanceId = resource.getAttribute(SERVICE_INSTANCE_ID_ATTRIBUTE_KEY);
if (instanceId == null) {
builder.put(SERVICE_INSTANCE_ID_ATTRIBUTE_KEY, UUID.randomUUID().toString());
}
final String entityGuid = agent.getEntityGuid(true);
if (entityGuid != null) {
builder.put("entity.guid", entityGuid);
}
return builder.build();
}
/**
* Read list of excluded meters, and customize the meter provider to drop any with matching names.
*/
static SdkMeterProviderBuilder applyMeterExcludes(SdkMeterProviderBuilder sdkMeterProviderBuilder, ConfigProperties configProperties) {
return applyMeterExcludes(sdkMeterProviderBuilder, NewRelic.getAgent());
}
static SdkMeterProviderBuilder applyMeterExcludes(SdkMeterProviderBuilder sdkMeterProviderBuilder, Agent agent) {
final List<String> excludedMeters = getOpenTelemetryMetricsExcludes();
agent.getLogger().log(Level.FINE, "Suppressing excluded OpenTelemetry meters: {0}", excludedMeters);
for (String meterName : excludedMeters) {
sdkMeterProviderBuilder.registerView(
InstrumentSelector.builder().setMeterName(meterName).build(),
View.builder().setAggregation(Aggregation.drop()).build()
);
}
return sdkMeterProviderBuilder;
}
}