You've already forked authentication-service
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:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -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",
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>() {
|
||||||
|
|||||||
Reference in New Issue
Block a user