Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update HTTP metrics 'view' code to match the specification #4556

Merged
merged 9 commits into from
Nov 6, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

package io.opentelemetry.instrumentation.api.instrumenter.http;

import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyDurationView;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyClientDurationView;

import com.google.auto.value.AutoValue;
import io.opentelemetry.api.common.Attributes;
Expand Down Expand Up @@ -76,7 +76,7 @@ public void end(Context context, Attributes endAttributes, long endNanos) {
}
duration.record(
(endNanos - state.startTimeNanos()) / NANOS_PER_MS,
applyDurationView(state.startAttributes(), endAttributes));
applyClientDurationView(state.startAttributes(), endAttributes));
}

@AutoValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
package io.opentelemetry.instrumentation.api.instrumenter.http;

import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyActiveRequestsView;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyDurationView;
import static io.opentelemetry.instrumentation.api.instrumenter.http.TemporaryMetricsView.applyServerDurationView;

import com.google.auto.value.AutoValue;
import io.opentelemetry.api.common.Attributes;
Expand Down Expand Up @@ -89,7 +89,7 @@ public void end(Context context, Attributes endAttributes, long endNanos) {
activeRequests.add(-1, applyActiveRequestsView(state.startAttributes()));
duration.record(
(endNanos - state.startTimeNanos()) / NANOS_PER_MS,
applyDurationView(state.startAttributes(), endAttributes));
applyServerDurationView(state.startAttributes(), endAttributes));
}

@AutoValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,17 @@
@SuppressWarnings("rawtypes")
final class TemporaryMetricsView {

private static final Set<AttributeKey> durationView = buildDurationView();
private static final Set<AttributeKey> durationAlwaysInclude = buildDurationAlwaysInclude();

private static final Set<AttributeKey> activeRequestsView = buildActiveRequestsView();

private static Set<AttributeKey> buildDurationView() {
private static Set<AttributeKey> buildDurationAlwaysInclude() {
// the list of included metrics is from
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/http-metrics.md#attributes
Set<AttributeKey> view = new HashSet<>();
view.add(SemanticAttributes.HTTP_METHOD);
view.add(SemanticAttributes.HTTP_HOST);
view.add(SemanticAttributes.HTTP_SCHEME);
view.add(SemanticAttributes.HTTP_STATUS_CODE);
view.add(SemanticAttributes.HTTP_FLAVOR);
view.add(SemanticAttributes.NET_PEER_NAME);
view.add(SemanticAttributes.NET_PEER_PORT);
view.add(SemanticAttributes.NET_PEER_IP);
view.add(SemanticAttributes.HTTP_SERVER_NAME);
view.add(SemanticAttributes.NET_HOST_NAME);
view.add(SemanticAttributes.NET_HOST_PORT);
view.add(SemanticAttributes.HTTP_STATUS_CODE); // Optional
view.add(SemanticAttributes.HTTP_FLAVOR); // Optional
return view;
}

Expand All @@ -52,10 +44,72 @@ private static Set<AttributeKey> buildActiveRequestsView() {
return view;
}

static Attributes applyDurationView(Attributes startAttributes, Attributes endAttributes) {
static Attributes applyClientDurationView(Attributes startAttributes, Attributes endAttributes) {
Set<AttributeKey> fullSet = new HashSet<>(durationAlwaysInclude);
// We pull identifying attributes according to:
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/http-metrics.md#attribute-alternatives
if (containsAttribute(SemanticAttributes.HTTP_URL, startAttributes, endAttributes)) {
// Use http.url alone
fullSet.add(SemanticAttributes.HTTP_URL);
} else if (containsAttribute(SemanticAttributes.HTTP_HOST, startAttributes, endAttributes)) {
// Use http.scheme, http.host and http.target
fullSet.add(SemanticAttributes.HTTP_SCHEME);
fullSet.add(SemanticAttributes.HTTP_HOST);
fullSet.add(SemanticAttributes.HTTP_TARGET);
jsuereth marked this conversation as resolved.
Show resolved Hide resolved
} else if (containsAttribute(
SemanticAttributes.NET_PEER_NAME, startAttributes, endAttributes)) {
// Use http.scheme, net.peer.name, net.peer.port and http.target
fullSet.add(SemanticAttributes.HTTP_SCHEME);
fullSet.add(SemanticAttributes.NET_PEER_NAME);
fullSet.add(SemanticAttributes.NET_PEER_PORT);
fullSet.add(SemanticAttributes.HTTP_TARGET);
} else {
// Use http.scheme, net.peer.ip, net.peer.port and http.target
fullSet.add(SemanticAttributes.HTTP_SCHEME);
fullSet.add(SemanticAttributes.NET_PEER_IP);
fullSet.add(SemanticAttributes.NET_PEER_PORT);
fullSet.add(SemanticAttributes.HTTP_TARGET);
}
AttributesBuilder filtered = Attributes.builder();
applyView(filtered, startAttributes, fullSet);
applyView(filtered, endAttributes, fullSet);
return filtered.build();
}

private static <T> boolean containsAttribute(
AttributeKey<T> key, Attributes startAttributes, Attributes endAttributes) {
return startAttributes.get(key) != null || endAttributes.get(key) != null;
}

static Attributes applyServerDurationView(Attributes startAttributes, Attributes endAttributes) {
Set<AttributeKey> fullSet = new HashSet<>(durationAlwaysInclude);
// We pull identifying attributes according to:
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/http-metrics.md#attribute-alternatives
if (containsAttribute(SemanticAttributes.HTTP_HOST, startAttributes, endAttributes)) {
// Use http.scheme, http.host and http.target
fullSet.add(SemanticAttributes.HTTP_SCHEME);
fullSet.add(SemanticAttributes.HTTP_HOST);
fullSet.add(SemanticAttributes.HTTP_TARGET);
} else if (containsAttribute(
SemanticAttributes.HTTP_SERVER_NAME, startAttributes, endAttributes)) {
// Use http.scheme, http.server_name, net.host.port, http.target
fullSet.add(SemanticAttributes.HTTP_SCHEME);
fullSet.add(SemanticAttributes.HTTP_SERVER_NAME);
fullSet.add(SemanticAttributes.HTTP_TARGET);
} else if (containsAttribute(
SemanticAttributes.NET_HOST_NAME, startAttributes, endAttributes)) {
// Use http.scheme, net.host.name, net.host.port, http.target
fullSet.add(SemanticAttributes.HTTP_SCHEME);
fullSet.add(SemanticAttributes.NET_HOST_NAME);
fullSet.add(SemanticAttributes.NET_HOST_PORT);
fullSet.add(SemanticAttributes.HTTP_TARGET);
} else {
// Use http.url
fullSet.add(SemanticAttributes.HTTP_URL);
jsuereth marked this conversation as resolved.
Show resolved Hide resolved
}
AttributesBuilder filtered = Attributes.builder();
applyView(filtered, startAttributes, durationView);
applyView(filtered, endAttributes, durationView);
applyView(filtered, startAttributes, fullSet);
applyView(filtered, endAttributes, fullSet);
return filtered.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ void collectsMetrics() {
Attributes.builder()
.put("http.method", "GET")
.put("http.host", "host")
.put("http.target", "/")
.put("http.scheme", "https")
.put("net.host.name", "localhost")
.put("net.host.port", 1234)
Expand Down Expand Up @@ -85,14 +86,12 @@ void collectsMetrics() {
.hasSum(150 /* millis */)
.attributes()
.containsOnly(
attributeEntry("http.scheme", "https"),
attributeEntry("http.host", "host"),
attributeEntry("http.target", "/"),
attributeEntry("http.method", "GET"),
attributeEntry("http.scheme", "https"),
attributeEntry("http.flavor", "2.0"),
attributeEntry("http.server_name", "server"),
attributeEntry("http.status_code", 200),
attributeEntry("net.host.name", "localhost"),
attributeEntry("net.host.port", 1234L))));
attributeEntry("http.status_code", 200))));
});

listener.end(context2, responseAttributes, nanos(300));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ void collectsMetrics() {
Attributes.builder()
.put("http.method", "GET")
.put("http.host", "host")
.put("http.target", "/")
.put("http.scheme", "https")
.put("net.host.name", "localhost")
.put("net.host.port", 1234)
Expand Down Expand Up @@ -120,14 +121,12 @@ void collectsMetrics() {
.hasSum(150 /* millis */)
.attributes()
.containsOnly(
attributeEntry("http.scheme", "https"),
attributeEntry("http.host", "host"),
attributeEntry("http.target", "/"),
attributeEntry("http.method", "GET"),
attributeEntry("http.scheme", "https"),
attributeEntry("http.flavor", "2.0"),
attributeEntry("http.server_name", "server"),
attributeEntry("http.status_code", 200),
attributeEntry("net.host.name", "localhost"),
attributeEntry("net.host.port", 1234L))));
attributeEntry("http.flavor", "2.0"))));
});

listener.end(context2, responseAttributes, nanos(300));
Expand Down
Loading