1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-11-24 23:01:05 +03:00

More OTEL attributes on HTTP requests

This commit is contained in:
Quentin Gliech
2022-04-08 14:16:34 +02:00
parent d43a8f1a00
commit f4ff7c296c
4 changed files with 56 additions and 9 deletions

1
Cargo.lock generated
View File

@@ -2102,6 +2102,7 @@ dependencies = [
"axum", "axum",
"bytes 1.1.0", "bytes 1.1.0",
"futures-util", "futures-util",
"headers",
"http", "http",
"http-body", "http-body",
"hyper", "hyper",

View File

@@ -9,6 +9,7 @@ license = "Apache-2.0"
axum = "0.5.1" axum = "0.5.1"
bytes = "1.1.0" bytes = "1.1.0"
futures-util = "0.3.21" futures-util = "0.3.21"
headers = "0.3.7"
http = "0.2.6" http = "0.2.6"
http-body = "0.4.4" http-body = "0.4.4"
hyper = "0.14.18" hyper = "0.14.18"

View File

@@ -15,11 +15,13 @@
use std::{borrow::Cow, net::SocketAddr}; use std::{borrow::Cow, net::SocketAddr};
use axum::extract::{ConnectInfo, MatchedPath}; use axum::extract::{ConnectInfo, MatchedPath};
use headers::{ContentLength, HeaderMapExt, Host, UserAgent};
use http::{Method, Request, Version}; use http::{Method, Request, Version};
use hyper::client::connect::dns::Name; use hyper::client::connect::dns::Name;
use opentelemetry::trace::{SpanBuilder, SpanKind}; use opentelemetry::trace::{SpanBuilder, SpanKind};
use opentelemetry_semantic_conventions::trace::{ use opentelemetry_semantic_conventions::trace::{
HTTP_FLAVOR, HTTP_METHOD, HTTP_URL, NET_HOST_NAME, NET_PEER_IP, NET_PEER_PORT, HTTP_FLAVOR, HTTP_HOST, HTTP_METHOD, HTTP_REQUEST_CONTENT_LENGTH, HTTP_ROUTE, HTTP_TARGET,
HTTP_USER_AGENT, NET_HOST_NAME, NET_PEER_IP, NET_PEER_PORT, NET_TRANSPORT,
}; };
pub trait MakeSpanBuilder<R> { pub trait MakeSpanBuilder<R> {
@@ -114,12 +116,28 @@ impl SpanFromHttpRequest {
impl<B> MakeSpanBuilder<Request<B>> for SpanFromHttpRequest { impl<B> MakeSpanBuilder<Request<B>> for SpanFromHttpRequest {
fn make_span_builder(&self, request: &Request<B>) -> SpanBuilder { fn make_span_builder(&self, request: &Request<B>) -> SpanBuilder {
let attributes = vec![ let mut attributes = vec![
HTTP_METHOD.string(http_method_str(request.method())), HTTP_METHOD.string(http_method_str(request.method())),
HTTP_FLAVOR.string(http_flavor(request.version())), HTTP_FLAVOR.string(http_flavor(request.version())),
HTTP_URL.string(request.uri().to_string()), HTTP_TARGET.string(request.uri().to_string()),
]; ];
let headers = request.headers();
if let Some(host) = headers.typed_get::<Host>() {
attributes.push(HTTP_HOST.string(host.to_string()));
}
if let Some(user_agent) = headers.typed_get::<UserAgent>() {
attributes.push(HTTP_USER_AGENT.string(user_agent.to_string()));
}
if let Some(ContentLength(content_length)) = headers.typed_get() {
if let Ok(content_length) = content_length.try_into() {
attributes.push(HTTP_REQUEST_CONTENT_LENGTH.i64(content_length));
}
}
SpanBuilder::from_name(self.operation) SpanBuilder::from_name(self.operation)
.with_kind(self.span_kind.clone()) .with_kind(self.span_kind.clone())
.with_attributes(attributes) .with_attributes(attributes)
@@ -134,21 +152,40 @@ impl<B> MakeSpanBuilder<Request<B>> for SpanFromAxumRequest {
let mut attributes = vec![ let mut attributes = vec![
HTTP_METHOD.string(http_method_str(request.method())), HTTP_METHOD.string(http_method_str(request.method())),
HTTP_FLAVOR.string(http_flavor(request.version())), HTTP_FLAVOR.string(http_flavor(request.version())),
HTTP_URL.string(request.uri().to_string()), HTTP_TARGET.string(request.uri().to_string()),
]; ];
let headers = request.headers();
if let Some(host) = headers.typed_get::<Host>() {
attributes.push(HTTP_HOST.string(host.to_string()));
}
if let Some(user_agent) = headers.typed_get::<UserAgent>() {
attributes.push(HTTP_USER_AGENT.string(user_agent.to_string()));
}
if let Some(ContentLength(content_length)) = headers.typed_get() {
if let Ok(content_length) = content_length.try_into() {
attributes.push(HTTP_REQUEST_CONTENT_LENGTH.i64(content_length));
}
}
if let Some(ConnectInfo(addr)) = request.extensions().get::<ConnectInfo<SocketAddr>>() { if let Some(ConnectInfo(addr)) = request.extensions().get::<ConnectInfo<SocketAddr>>() {
attributes.push(NET_TRANSPORT.string("ip_tcp"));
attributes.push(NET_PEER_IP.string(addr.ip().to_string())); attributes.push(NET_PEER_IP.string(addr.ip().to_string()));
attributes.push(NET_PEER_PORT.i64(addr.port().into())); attributes.push(NET_PEER_PORT.i64(addr.port().into()));
} }
let path = if let Some(path) = request.extensions().get::<MatchedPath>() { let name = if let Some(path) = request.extensions().get::<MatchedPath>() {
path.as_str() let path = path.as_str().to_string();
attributes.push(HTTP_ROUTE.string(path.clone()));
path
} else { } else {
request.uri().path() request.uri().path().to_string()
}; };
SpanBuilder::from_name(path.to_string()) SpanBuilder::from_name(name)
.with_kind(SpanKind::Server) .with_kind(SpanKind::Server)
.with_attributes(attributes) .with_attributes(attributes)
} }

View File

@@ -12,11 +12,13 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use headers::{ContentLength, HeaderMapExt};
use http::Response; use http::Response;
use hyper::client::connect::HttpInfo; use hyper::client::connect::HttpInfo;
use opentelemetry::trace::SpanRef; use opentelemetry::trace::SpanRef;
use opentelemetry_semantic_conventions::trace::{ use opentelemetry_semantic_conventions::trace::{
HTTP_STATUS_CODE, NET_HOST_IP, NET_HOST_PORT, NET_PEER_IP, NET_PEER_PORT, HTTP_RESPONSE_CONTENT_LENGTH, HTTP_STATUS_CODE, NET_HOST_IP, NET_HOST_PORT, NET_PEER_IP,
NET_PEER_PORT,
}; };
pub trait OnResponse<R> { pub trait OnResponse<R> {
@@ -37,6 +39,12 @@ impl<B> OnResponse<Response<B>> for OnHttpResponse {
fn on_response(&self, span: &SpanRef<'_>, response: &Response<B>) { fn on_response(&self, span: &SpanRef<'_>, response: &Response<B>) {
span.set_attribute(HTTP_STATUS_CODE.i64(i64::from(response.status().as_u16()))); span.set_attribute(HTTP_STATUS_CODE.i64(i64::from(response.status().as_u16())));
if let Some(ContentLength(content_length)) = response.headers().typed_get() {
if let Ok(content_length) = content_length.try_into() {
span.set_attribute(HTTP_RESPONSE_CONTENT_LENGTH.i64(content_length));
}
}
// Get local and remote address from hyper's HttpInfo injected by the // Get local and remote address from hyper's HttpInfo injected by the
// HttpConnector // HttpConnector
if let Some(info) = response.extensions().get::<HttpInfo>() { if let Some(info) = response.extensions().get::<HttpInfo>() {