Skip to content

Commit 86cba45

Browse files
authored
Calculate target using existing otel metric attributes (#2467)
1 parent 038342c commit 86cba45

File tree

9 files changed

+87
-281
lines changed

9 files changed

+87
-281
lines changed

agent/agent-bootstrap/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/BootstrapSemanticAttributes.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,13 @@
2222
package io.opentelemetry.instrumentation.api.instrumenter;
2323

2424
import static io.opentelemetry.api.common.AttributeKey.booleanKey;
25-
import static io.opentelemetry.api.common.AttributeKey.stringKey;
2625

2726
import io.opentelemetry.api.common.AttributeKey;
2827

2928
public final class BootstrapSemanticAttributes {
3029

3130
public static final AttributeKey<Boolean> IS_SYNTHETIC =
3231
booleanKey("applicationinsights.internal.is_synthetic");
33-
public static final AttributeKey<String> TARGET =
34-
stringKey("applicationinsights.internal.target");
3532
public static final AttributeKey<Boolean> IS_PRE_AGGREGATED =
3633
booleanKey("applicationinsights.internal.is_pre_aggregated");
3734

agent/agent-bootstrap/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/http/HttpClientMetrics.java

Lines changed: 0 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
import static io.opentelemetry.instrumentation.api.instrumenter.BootstrapSemanticAttributes.IS_PRE_AGGREGATED;
2525
import static io.opentelemetry.instrumentation.api.instrumenter.BootstrapSemanticAttributes.IS_SYNTHETIC;
26-
import static io.opentelemetry.instrumentation.api.instrumenter.BootstrapSemanticAttributes.TARGET;
2726
import static java.util.logging.Level.FINE;
2827

2928
import com.google.auto.value.AutoValue;
@@ -122,7 +121,6 @@ public void onEnd(Context context, Attributes endAttributes, long endNanos) {
122121
Attributes durationAttributes =
123122
durationAndSizeAttributes.toBuilder()
124123
.put(IS_SYNTHETIC, UserAgents.isBot(endAttributes, state.startAttributes()))
125-
.put(TARGET, getTargetForHttpClientSpan(durationAndSizeAttributes))
126124
.build();
127125

128126
// END APPLICATION INSIGHTS CODE
@@ -146,120 +144,6 @@ public void onEnd(Context context, Attributes endAttributes, long endNanos) {
146144
}
147145
}
148146

149-
// this is copied from SpanDataMapper
150-
private static String getTargetForHttpClientSpan(Attributes attributes) {
151-
// from the spec, at least one of the following sets of attributes is required:
152-
// * http.url
153-
// * http.scheme, http.host, http.target
154-
// * http.scheme, net.peer.name, net.peer.port, http.target
155-
// * http.scheme, net.peer.ip, net.peer.port, http.target
156-
String target = getTargetFromPeerService(attributes);
157-
if (target != null) {
158-
return target;
159-
}
160-
// note http.host includes the port (at least when non-default)
161-
target = attributes.get(SemanticAttributes.HTTP_HOST);
162-
if (target != null) {
163-
String scheme = attributes.get(SemanticAttributes.HTTP_SCHEME);
164-
if ("http".equals(scheme)) {
165-
if (target.endsWith(":80")) {
166-
target = target.substring(0, target.length() - 3);
167-
}
168-
} else if ("https".equals(scheme)) {
169-
if (target.endsWith(":443")) {
170-
target = target.substring(0, target.length() - 4);
171-
}
172-
}
173-
return target;
174-
}
175-
String url = attributes.get(SemanticAttributes.HTTP_URL);
176-
if (url != null) {
177-
target = getTargetFromUrl(url);
178-
if (target != null) {
179-
return target;
180-
}
181-
}
182-
String scheme = attributes.get(SemanticAttributes.HTTP_SCHEME);
183-
int defaultPort;
184-
if ("http".equals(scheme)) {
185-
defaultPort = 80;
186-
} else if ("https".equals(scheme)) {
187-
defaultPort = 443;
188-
} else {
189-
defaultPort = 0;
190-
}
191-
target = getTargetFromNetAttributes(attributes, defaultPort);
192-
if (target != null) {
193-
return target;
194-
}
195-
// this should not happen, just a failsafe
196-
return "Http";
197-
}
198-
199-
// this is copied from SpanDataMapper
200-
@Nullable
201-
private static String getTargetFromPeerService(Attributes attributes) {
202-
// do not append port to peer.service
203-
return attributes.get(SemanticAttributes.PEER_SERVICE);
204-
}
205-
206-
// this is copied from SpanDataMapper
207-
@Nullable
208-
private static String getTargetFromNetAttributes(Attributes attributes, int defaultPort) {
209-
String target = getHostFromNetAttributes(attributes);
210-
if (target == null) {
211-
return null;
212-
}
213-
// append net.peer.port to target
214-
Long port = attributes.get(SemanticAttributes.NET_PEER_PORT);
215-
if (port != null && port != defaultPort) {
216-
return target + ":" + port;
217-
}
218-
return target;
219-
}
220-
221-
// this is copied from SpanDataMapper
222-
@Nullable
223-
private static String getHostFromNetAttributes(Attributes attributes) {
224-
String host = attributes.get(SemanticAttributes.NET_PEER_NAME);
225-
if (host != null) {
226-
return host;
227-
}
228-
return attributes.get(SemanticAttributes.NET_PEER_IP);
229-
}
230-
231-
// this is copied from SpanDataMapper
232-
@Nullable
233-
private static String getTargetFromUrl(String url) {
234-
int schemeEndIndex = url.indexOf(':');
235-
if (schemeEndIndex == -1) {
236-
// not a valid url
237-
return null;
238-
}
239-
240-
int len = url.length();
241-
if (schemeEndIndex + 2 < len
242-
&& url.charAt(schemeEndIndex + 1) == '/'
243-
&& url.charAt(schemeEndIndex + 2) == '/') {
244-
// has authority component
245-
// look for
246-
// '/' - start of path
247-
// '?' or end of string - empty path
248-
int index;
249-
for (index = schemeEndIndex + 3; index < len; index++) {
250-
char c = url.charAt(index);
251-
if (c == '/' || c == '?' || c == '#') {
252-
break;
253-
}
254-
}
255-
String target = url.substring(schemeEndIndex + 3, index);
256-
return target.isEmpty() ? null : target;
257-
} else {
258-
// has no authority
259-
return null;
260-
}
261-
}
262-
263147
@Nullable
264148
private static <T> T getAttribute(AttributeKey<T> key, Attributes... attributesList) {
265149
for (Attributes attributes : attributesList) {

agent/agent-bootstrap/src/main/java/io/opentelemetry/instrumentation/api/instrumenter/rpc/RpcClientMetrics.java

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
import static io.opentelemetry.instrumentation.api.instrumenter.BootstrapSemanticAttributes.IS_PRE_AGGREGATED;
2525
import static io.opentelemetry.instrumentation.api.instrumenter.BootstrapSemanticAttributes.IS_SYNTHETIC;
26-
import static io.opentelemetry.instrumentation.api.instrumenter.BootstrapSemanticAttributes.TARGET;
2726
import static java.util.logging.Level.FINE;
2827

2928
import com.google.auto.value.AutoValue;
@@ -36,10 +35,8 @@
3635
import io.opentelemetry.instrumentation.api.instrumenter.OperationListener;
3736
import io.opentelemetry.instrumentation.api.instrumenter.OperationMetrics;
3837
import io.opentelemetry.instrumentation.api.instrumenter.UserAgents;
39-
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
4038
import java.util.concurrent.TimeUnit;
4139
import java.util.logging.Logger;
42-
import javax.annotation.Nullable;
4340

4441
/**
4542
* {@link OperationListener} which keeps track of <a
@@ -101,14 +98,9 @@ public void onEnd(Context context, Attributes endAttributes, long endNanos) {
10198
// auto instrumentations
10299
Span.fromContext(context).setAttribute(IS_PRE_AGGREGATED, true);
103100

104-
String target = getTargetFromPeerAttributes(endAttributes, 0);
105-
if (target == null) {
106-
target = endAttributes.get(SemanticAttributes.RPC_SYSTEM);
107-
}
108101
attributes =
109102
attributes.toBuilder()
110103
.put(IS_SYNTHETIC, UserAgents.isBot(endAttributes, state.startAttributes()))
111-
.put(TARGET, target)
112104
.build();
113105

114106
// END APPLICATION INSIGHTS CODE
@@ -117,48 +109,6 @@ public void onEnd(Context context, Attributes endAttributes, long endNanos) {
117109
(endNanos - state.startTimeNanos()) / NANOS_PER_MS, attributes, context);
118110
}
119111

120-
// this is copied from SpanDataMapper
121-
@Nullable
122-
private static String getTargetFromPeerAttributes(Attributes attributes, int defaultPort) {
123-
String target = getTargetFromPeerService(attributes);
124-
if (target != null) {
125-
return target;
126-
}
127-
return getTargetFromNetAttributes(attributes, defaultPort);
128-
}
129-
130-
// this is copied from SpanDataMapper
131-
@Nullable
132-
private static String getTargetFromPeerService(Attributes attributes) {
133-
// do not append port to peer.service
134-
return attributes.get(SemanticAttributes.PEER_SERVICE);
135-
}
136-
137-
// this is copied from SpanDataMapper
138-
@Nullable
139-
private static String getTargetFromNetAttributes(Attributes attributes, int defaultPort) {
140-
String target = getHostFromNetAttributes(attributes);
141-
if (target == null) {
142-
return null;
143-
}
144-
// append net.peer.port to target
145-
Long port = attributes.get(SemanticAttributes.NET_PEER_PORT);
146-
if (port != null && port != defaultPort) {
147-
return target + ":" + port;
148-
}
149-
return target;
150-
}
151-
152-
// this is copied from SpanDataMapper
153-
@Nullable
154-
private static String getHostFromNetAttributes(Attributes attributes) {
155-
String host = attributes.get(SemanticAttributes.NET_PEER_NAME);
156-
if (host != null) {
157-
return host;
158-
}
159-
return attributes.get(SemanticAttributes.NET_PEER_IP);
160-
}
161-
162112
@AutoValue
163113
abstract static class State {
164114

agent/azure-monitor-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/MetricDataMapper.java

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
package com.azure.monitor.opentelemetry.exporter.implementation;
2323

2424
import static com.azure.monitor.opentelemetry.exporter.implementation.AiSemanticAttributes.IS_SYNTHETIC;
25-
import static com.azure.monitor.opentelemetry.exporter.implementation.AiSemanticAttributes.TARGET;
2625
import static io.opentelemetry.api.internal.Utils.checkArgument;
2726
import static io.opentelemetry.sdk.metrics.data.MetricDataType.DOUBLE_GAUGE;
2827
import static io.opentelemetry.sdk.metrics.data.MetricDataType.DOUBLE_SUM;
@@ -37,6 +36,7 @@
3736
import com.azure.monitor.opentelemetry.exporter.implementation.preaggregatedmetrics.DependencyExtractor;
3837
import com.azure.monitor.opentelemetry.exporter.implementation.preaggregatedmetrics.RequestExtractor;
3938
import com.azure.monitor.opentelemetry.exporter.implementation.utils.FormattedTime;
39+
import io.opentelemetry.api.common.Attributes;
4040
import io.opentelemetry.sdk.metrics.data.DoublePointData;
4141
import io.opentelemetry.sdk.metrics.data.HistogramPointData;
4242
import io.opentelemetry.sdk.metrics.data.LongPointData;
@@ -50,6 +50,7 @@
5050
import java.util.Set;
5151
import java.util.function.BiConsumer;
5252
import java.util.function.Consumer;
53+
import javax.annotation.Nullable;
5354
import org.slf4j.Logger;
5455
import org.slf4j.LoggerFactory;
5556

@@ -163,27 +164,48 @@ public static void updateMetricPointBuilder(
163164
pointBuilder.setName(metricData.getName());
164165
metricTelemetryBuilder.setMetricPoint(pointBuilder);
165166

167+
Attributes attributes = pointData.getAttributes();
166168
if (isPreAggregatedStandardMetric) {
167-
Long statusCode = pointData.getAttributes().get(SemanticAttributes.HTTP_STATUS_CODE);
169+
Long statusCode = attributes.get(SemanticAttributes.HTTP_STATUS_CODE);
168170
boolean success = isSuccess(statusCode, captureHttpServer4xxAsError);
169-
Boolean isSynthetic = pointData.getAttributes().get(IS_SYNTHETIC);
171+
Boolean isSynthetic = attributes.get(IS_SYNTHETIC);
170172
if (metricData.getName().contains(".server.")) {
171173
RequestExtractor.extract(metricTelemetryBuilder, statusCode, success, isSynthetic);
172174
} else if (metricData.getName().contains(".client.")) {
173-
String dependencyType =
174-
metricData.getName().startsWith("http")
175-
? "Http"
176-
: pointData.getAttributes().get(SemanticAttributes.RPC_SYSTEM);
177-
String target = pointData.getAttributes().get(TARGET);
175+
String dependencyType;
176+
int defaultPort;
177+
if (metricData.getName().startsWith("http")) {
178+
dependencyType = "Http";
179+
defaultPort = getDefaultPortForHttpScheme(attributes.get(SemanticAttributes.HTTP_SCHEME));
180+
} else {
181+
dependencyType = attributes.get(SemanticAttributes.RPC_SYSTEM);
182+
if (dependencyType == null) {
183+
// rpc.system is required by the semantic conventions
184+
dependencyType = "Unknown";
185+
}
186+
defaultPort = Integer.MAX_VALUE; // no default port for rpc
187+
}
188+
String target = SpanDataMapper.getTargetOrDefault(attributes, defaultPort, dependencyType);
178189
DependencyExtractor.extract(
179190
metricTelemetryBuilder, statusCode, success, dependencyType, target, isSynthetic);
180191
}
181192
} else {
182-
pointData
183-
.getAttributes()
184-
.forEach(
185-
(key, value) -> metricTelemetryBuilder.addProperty(key.getKey(), value.toString()));
193+
attributes.forEach(
194+
(key, value) -> metricTelemetryBuilder.addProperty(key.getKey(), value.toString()));
195+
}
196+
}
197+
198+
private static int getDefaultPortForHttpScheme(@Nullable String httpScheme) {
199+
if (httpScheme == null) {
200+
return Integer.MAX_VALUE;
201+
}
202+
if (httpScheme.equals("https")) {
203+
return 443;
204+
}
205+
if (httpScheme.equals("http")) {
206+
return 80;
186207
}
208+
return Integer.MAX_VALUE;
187209
}
188210

189211
private static boolean isSuccess(Long statusCode, boolean captureHttpServer4xxAsError) {

0 commit comments

Comments
 (0)