You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-08-07 17:03:01 +03:00
Have the listeners names in the metrics and traces
Also refactors the OTEL layer to have a separate metrics logic
This commit is contained in:
@@ -1,12 +1,15 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use opentelemetry::metrics::{Counter, Histogram, UpDownCounter};
|
use opentelemetry::{
|
||||||
|
metrics::{Counter, Histogram, UpDownCounter},
|
||||||
|
KeyValue,
|
||||||
|
};
|
||||||
use tower::Layer;
|
use tower::Layer;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
extract_context::DefaultExtractContext, inject_context::DefaultInjectContext,
|
extract_context::DefaultExtractContext, inject_context::DefaultInjectContext,
|
||||||
make_span_builder::DefaultMakeSpanBuilder, on_error::DefaultOnError,
|
make_metrics_labels::DefaultMakeMetricsLabels, make_span_builder::DefaultMakeSpanBuilder,
|
||||||
on_response::DefaultOnResponse, service::Trace,
|
on_error::DefaultOnError, on_response::DefaultOnResponse, service::Trace,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -14,6 +17,7 @@ pub struct TraceLayer<
|
|||||||
ExtractContext = DefaultExtractContext,
|
ExtractContext = DefaultExtractContext,
|
||||||
InjectContext = DefaultInjectContext,
|
InjectContext = DefaultInjectContext,
|
||||||
MakeSpanBuilder = DefaultMakeSpanBuilder,
|
MakeSpanBuilder = DefaultMakeSpanBuilder,
|
||||||
|
MakeMetricsLabels = DefaultMakeMetricsLabels,
|
||||||
OnResponse = DefaultOnResponse,
|
OnResponse = DefaultOnResponse,
|
||||||
OnError = DefaultOnError,
|
OnError = DefaultOnError,
|
||||||
> {
|
> {
|
||||||
@@ -21,12 +25,14 @@ pub struct TraceLayer<
|
|||||||
extract_context: ExtractContext,
|
extract_context: ExtractContext,
|
||||||
inject_context: InjectContext,
|
inject_context: InjectContext,
|
||||||
make_span_builder: MakeSpanBuilder,
|
make_span_builder: MakeSpanBuilder,
|
||||||
|
make_metrics_labels: MakeMetricsLabels,
|
||||||
on_response: OnResponse,
|
on_response: OnResponse,
|
||||||
on_error: OnError,
|
on_error: OnError,
|
||||||
|
|
||||||
inflight_requests: UpDownCounter<i64>,
|
inflight_requests: UpDownCounter<i64>,
|
||||||
request_counter: Counter<u64>,
|
request_counter: Counter<u64>,
|
||||||
request_histogram: Histogram<f64>,
|
request_histogram: Histogram<f64>,
|
||||||
|
static_attributes: Vec<KeyValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TraceLayer {
|
impl Default for TraceLayer {
|
||||||
@@ -63,8 +69,15 @@ impl TraceLayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError>
|
impl<ExtractContext, InjectContext, MakeSpanBuilder, MakeMetricsLabels, OnResponse, OnError>
|
||||||
TraceLayer<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError>
|
TraceLayer<
|
||||||
|
ExtractContext,
|
||||||
|
InjectContext,
|
||||||
|
MakeSpanBuilder,
|
||||||
|
MakeMetricsLabels,
|
||||||
|
OnResponse,
|
||||||
|
OnError,
|
||||||
|
>
|
||||||
{
|
{
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
@@ -77,6 +90,7 @@ impl<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError>
|
|||||||
ExtractContext: Default,
|
ExtractContext: Default,
|
||||||
InjectContext: Default,
|
InjectContext: Default,
|
||||||
MakeSpanBuilder: Default,
|
MakeSpanBuilder: Default,
|
||||||
|
MakeMetricsLabels: Default,
|
||||||
OnResponse: Default,
|
OnResponse: Default,
|
||||||
OnError: Default,
|
OnError: Default,
|
||||||
{
|
{
|
||||||
@@ -85,29 +99,55 @@ impl<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError>
|
|||||||
extract_context: ExtractContext::default(),
|
extract_context: ExtractContext::default(),
|
||||||
inject_context: InjectContext::default(),
|
inject_context: InjectContext::default(),
|
||||||
make_span_builder: MakeSpanBuilder::default(),
|
make_span_builder: MakeSpanBuilder::default(),
|
||||||
|
make_metrics_labels: MakeMetricsLabels::default(),
|
||||||
on_response: OnResponse::default(),
|
on_response: OnResponse::default(),
|
||||||
on_error: OnError::default(),
|
on_error: OnError::default(),
|
||||||
inflight_requests,
|
inflight_requests,
|
||||||
request_counter,
|
request_counter,
|
||||||
request_histogram,
|
request_histogram,
|
||||||
|
static_attributes: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_static_attribute(mut self, attribute: KeyValue) -> Self {
|
||||||
|
self.static_attributes.push(attribute);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_static_attributes(
|
||||||
|
mut self,
|
||||||
|
attributes: impl IntoIterator<Item = KeyValue>,
|
||||||
|
) -> Self {
|
||||||
|
self.static_attributes.extend(attributes);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn extract_context<NewExtractContext>(
|
pub fn extract_context<NewExtractContext>(
|
||||||
self,
|
self,
|
||||||
extract_context: NewExtractContext,
|
extract_context: NewExtractContext,
|
||||||
) -> TraceLayer<NewExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError> {
|
) -> TraceLayer<
|
||||||
|
NewExtractContext,
|
||||||
|
InjectContext,
|
||||||
|
MakeSpanBuilder,
|
||||||
|
MakeMetricsLabels,
|
||||||
|
OnResponse,
|
||||||
|
OnError,
|
||||||
|
> {
|
||||||
TraceLayer {
|
TraceLayer {
|
||||||
tracer: self.tracer,
|
tracer: self.tracer,
|
||||||
extract_context,
|
extract_context,
|
||||||
inject_context: self.inject_context,
|
inject_context: self.inject_context,
|
||||||
make_span_builder: self.make_span_builder,
|
make_span_builder: self.make_span_builder,
|
||||||
|
make_metrics_labels: self.make_metrics_labels,
|
||||||
on_response: self.on_response,
|
on_response: self.on_response,
|
||||||
on_error: self.on_error,
|
on_error: self.on_error,
|
||||||
inflight_requests: self.inflight_requests,
|
inflight_requests: self.inflight_requests,
|
||||||
request_counter: self.request_counter,
|
request_counter: self.request_counter,
|
||||||
request_histogram: self.request_histogram,
|
request_histogram: self.request_histogram,
|
||||||
|
static_attributes: self.static_attributes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,17 +155,26 @@ impl<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError>
|
|||||||
pub fn inject_context<NewInjectContext>(
|
pub fn inject_context<NewInjectContext>(
|
||||||
self,
|
self,
|
||||||
inject_context: NewInjectContext,
|
inject_context: NewInjectContext,
|
||||||
) -> TraceLayer<ExtractContext, NewInjectContext, MakeSpanBuilder, OnResponse, OnError> {
|
) -> TraceLayer<
|
||||||
|
ExtractContext,
|
||||||
|
NewInjectContext,
|
||||||
|
MakeSpanBuilder,
|
||||||
|
MakeMetricsLabels,
|
||||||
|
OnResponse,
|
||||||
|
OnError,
|
||||||
|
> {
|
||||||
TraceLayer {
|
TraceLayer {
|
||||||
tracer: self.tracer,
|
tracer: self.tracer,
|
||||||
extract_context: self.extract_context,
|
extract_context: self.extract_context,
|
||||||
inject_context,
|
inject_context,
|
||||||
make_span_builder: self.make_span_builder,
|
make_span_builder: self.make_span_builder,
|
||||||
|
make_metrics_labels: self.make_metrics_labels,
|
||||||
on_response: self.on_response,
|
on_response: self.on_response,
|
||||||
on_error: self.on_error,
|
on_error: self.on_error,
|
||||||
inflight_requests: self.inflight_requests,
|
inflight_requests: self.inflight_requests,
|
||||||
request_counter: self.request_counter,
|
request_counter: self.request_counter,
|
||||||
request_histogram: self.request_histogram,
|
request_histogram: self.request_histogram,
|
||||||
|
static_attributes: self.static_attributes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,17 +182,53 @@ impl<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError>
|
|||||||
pub fn make_span_builder<NewMakeSpanBuilder>(
|
pub fn make_span_builder<NewMakeSpanBuilder>(
|
||||||
self,
|
self,
|
||||||
make_span_builder: NewMakeSpanBuilder,
|
make_span_builder: NewMakeSpanBuilder,
|
||||||
) -> TraceLayer<ExtractContext, InjectContext, NewMakeSpanBuilder, OnResponse, OnError> {
|
) -> TraceLayer<
|
||||||
|
ExtractContext,
|
||||||
|
InjectContext,
|
||||||
|
NewMakeSpanBuilder,
|
||||||
|
MakeMetricsLabels,
|
||||||
|
OnResponse,
|
||||||
|
OnError,
|
||||||
|
> {
|
||||||
TraceLayer {
|
TraceLayer {
|
||||||
tracer: self.tracer,
|
tracer: self.tracer,
|
||||||
extract_context: self.extract_context,
|
extract_context: self.extract_context,
|
||||||
inject_context: self.inject_context,
|
inject_context: self.inject_context,
|
||||||
make_span_builder,
|
make_span_builder,
|
||||||
|
make_metrics_labels: self.make_metrics_labels,
|
||||||
on_response: self.on_response,
|
on_response: self.on_response,
|
||||||
on_error: self.on_error,
|
on_error: self.on_error,
|
||||||
inflight_requests: self.inflight_requests,
|
inflight_requests: self.inflight_requests,
|
||||||
request_counter: self.request_counter,
|
request_counter: self.request_counter,
|
||||||
request_histogram: self.request_histogram,
|
request_histogram: self.request_histogram,
|
||||||
|
static_attributes: self.static_attributes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn make_metrics_labels<NewMakeMetricsLabels>(
|
||||||
|
self,
|
||||||
|
make_metrics_labels: NewMakeMetricsLabels,
|
||||||
|
) -> TraceLayer<
|
||||||
|
ExtractContext,
|
||||||
|
InjectContext,
|
||||||
|
MakeSpanBuilder,
|
||||||
|
NewMakeMetricsLabels,
|
||||||
|
OnResponse,
|
||||||
|
OnError,
|
||||||
|
> {
|
||||||
|
TraceLayer {
|
||||||
|
tracer: self.tracer,
|
||||||
|
extract_context: self.extract_context,
|
||||||
|
inject_context: self.inject_context,
|
||||||
|
make_span_builder: self.make_span_builder,
|
||||||
|
make_metrics_labels,
|
||||||
|
on_response: self.on_response,
|
||||||
|
on_error: self.on_error,
|
||||||
|
inflight_requests: self.inflight_requests,
|
||||||
|
request_counter: self.request_counter,
|
||||||
|
request_histogram: self.request_histogram,
|
||||||
|
static_attributes: self.static_attributes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,17 +236,26 @@ impl<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError>
|
|||||||
pub fn on_response<NewOnResponse>(
|
pub fn on_response<NewOnResponse>(
|
||||||
self,
|
self,
|
||||||
on_response: NewOnResponse,
|
on_response: NewOnResponse,
|
||||||
) -> TraceLayer<ExtractContext, InjectContext, MakeSpanBuilder, NewOnResponse, OnError> {
|
) -> TraceLayer<
|
||||||
|
ExtractContext,
|
||||||
|
InjectContext,
|
||||||
|
MakeSpanBuilder,
|
||||||
|
MakeMetricsLabels,
|
||||||
|
NewOnResponse,
|
||||||
|
OnError,
|
||||||
|
> {
|
||||||
TraceLayer {
|
TraceLayer {
|
||||||
tracer: self.tracer,
|
tracer: self.tracer,
|
||||||
extract_context: self.extract_context,
|
extract_context: self.extract_context,
|
||||||
inject_context: self.inject_context,
|
inject_context: self.inject_context,
|
||||||
make_span_builder: self.make_span_builder,
|
make_span_builder: self.make_span_builder,
|
||||||
|
make_metrics_labels: self.make_metrics_labels,
|
||||||
on_response,
|
on_response,
|
||||||
on_error: self.on_error,
|
on_error: self.on_error,
|
||||||
inflight_requests: self.inflight_requests,
|
inflight_requests: self.inflight_requests,
|
||||||
request_counter: self.request_counter,
|
request_counter: self.request_counter,
|
||||||
request_histogram: self.request_histogram,
|
request_histogram: self.request_histogram,
|
||||||
|
static_attributes: self.static_attributes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,31 +263,57 @@ impl<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError>
|
|||||||
pub fn on_error<NewOnError>(
|
pub fn on_error<NewOnError>(
|
||||||
self,
|
self,
|
||||||
on_error: NewOnError,
|
on_error: NewOnError,
|
||||||
) -> TraceLayer<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, NewOnError> {
|
) -> TraceLayer<
|
||||||
|
ExtractContext,
|
||||||
|
InjectContext,
|
||||||
|
MakeSpanBuilder,
|
||||||
|
MakeMetricsLabels,
|
||||||
|
OnResponse,
|
||||||
|
NewOnError,
|
||||||
|
> {
|
||||||
TraceLayer {
|
TraceLayer {
|
||||||
tracer: self.tracer,
|
tracer: self.tracer,
|
||||||
extract_context: self.extract_context,
|
extract_context: self.extract_context,
|
||||||
inject_context: self.inject_context,
|
inject_context: self.inject_context,
|
||||||
make_span_builder: self.make_span_builder,
|
make_span_builder: self.make_span_builder,
|
||||||
|
make_metrics_labels: self.make_metrics_labels,
|
||||||
on_response: self.on_response,
|
on_response: self.on_response,
|
||||||
on_error,
|
on_error,
|
||||||
inflight_requests: self.inflight_requests,
|
inflight_requests: self.inflight_requests,
|
||||||
request_counter: self.request_counter,
|
request_counter: self.request_counter,
|
||||||
request_histogram: self.request_histogram,
|
request_histogram: self.request_histogram,
|
||||||
|
static_attributes: self.static_attributes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError, S> Layer<S>
|
impl<ExtractContext, InjectContext, MakeSpanBuilder, MakeMetricsLabels, OnResponse, OnError, S>
|
||||||
for TraceLayer<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError>
|
Layer<S>
|
||||||
|
for TraceLayer<
|
||||||
|
ExtractContext,
|
||||||
|
InjectContext,
|
||||||
|
MakeSpanBuilder,
|
||||||
|
MakeMetricsLabels,
|
||||||
|
OnResponse,
|
||||||
|
OnError,
|
||||||
|
>
|
||||||
where
|
where
|
||||||
ExtractContext: Clone,
|
ExtractContext: Clone,
|
||||||
InjectContext: Clone,
|
InjectContext: Clone,
|
||||||
MakeSpanBuilder: Clone,
|
MakeSpanBuilder: Clone,
|
||||||
|
MakeMetricsLabels: Clone,
|
||||||
OnResponse: Clone,
|
OnResponse: Clone,
|
||||||
OnError: Clone,
|
OnError: Clone,
|
||||||
{
|
{
|
||||||
type Service = Trace<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError, S>;
|
type Service = Trace<
|
||||||
|
ExtractContext,
|
||||||
|
InjectContext,
|
||||||
|
MakeSpanBuilder,
|
||||||
|
MakeMetricsLabels,
|
||||||
|
OnResponse,
|
||||||
|
OnError,
|
||||||
|
S,
|
||||||
|
>;
|
||||||
|
|
||||||
fn layer(&self, inner: S) -> Self::Service {
|
fn layer(&self, inner: S) -> Self::Service {
|
||||||
Trace::new(
|
Trace::new(
|
||||||
@@ -202,11 +322,13 @@ where
|
|||||||
self.extract_context.clone(),
|
self.extract_context.clone(),
|
||||||
self.inject_context.clone(),
|
self.inject_context.clone(),
|
||||||
self.make_span_builder.clone(),
|
self.make_span_builder.clone(),
|
||||||
|
self.make_metrics_labels.clone(),
|
||||||
self.on_response.clone(),
|
self.on_response.clone(),
|
||||||
self.on_error.clone(),
|
self.on_error.clone(),
|
||||||
self.inflight_requests.clone(),
|
self.inflight_requests.clone(),
|
||||||
self.request_counter.clone(),
|
self.request_counter.clone(),
|
||||||
self.request_histogram.clone(),
|
self.request_histogram.clone(),
|
||||||
|
self.static_attributes.clone(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
61
crates/http/src/layers/otel/make_metrics_labels.rs
Normal file
61
crates/http/src/layers/otel/make_metrics_labels.rs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use http::Request;
|
||||||
|
use opentelemetry::KeyValue;
|
||||||
|
|
||||||
|
use super::utils::http_method_str;
|
||||||
|
|
||||||
|
pub trait MakeMetricsLabels<R> {
|
||||||
|
fn make_metrics_labels(&self, request: &R) -> Vec<KeyValue>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub struct DefaultMakeMetricsLabels;
|
||||||
|
|
||||||
|
impl<R> MakeMetricsLabels<R> for DefaultMakeMetricsLabels {
|
||||||
|
fn make_metrics_labels(&self, _request: &R) -> Vec<KeyValue> {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub struct MetricsLabelsFromHttpRequest;
|
||||||
|
|
||||||
|
impl<B> MakeMetricsLabels<Request<B>> for MetricsLabelsFromHttpRequest {
|
||||||
|
fn make_metrics_labels(&self, request: &Request<B>) -> Vec<KeyValue> {
|
||||||
|
vec![KeyValue::new("method", http_method_str(request.method()))]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "axum")]
|
||||||
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
|
pub struct MetricsLabelsFromAxumRequest;
|
||||||
|
|
||||||
|
#[cfg(feature = "axum")]
|
||||||
|
impl<B> MakeMetricsLabels<Request<B>> for MetricsLabelsFromAxumRequest {
|
||||||
|
fn make_metrics_labels(&self, request: &Request<B>) -> Vec<KeyValue> {
|
||||||
|
let path: Cow<'static, str> = request
|
||||||
|
.extensions()
|
||||||
|
.get::<axum::extract::MatchedPath>()
|
||||||
|
.map_or("FALLBACK".into(), |path| path.as_str().to_owned().into());
|
||||||
|
|
||||||
|
vec![
|
||||||
|
KeyValue::new("method", http_method_str(request.method())),
|
||||||
|
KeyValue::new("route", path),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@@ -12,22 +12,21 @@
|
|||||||
// 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 std::{borrow::Cow, vec::Vec};
|
use std::borrow::Cow;
|
||||||
|
|
||||||
#[cfg(feature = "axum")]
|
#[cfg(feature = "axum")]
|
||||||
use axum::extract::{ConnectInfo, MatchedPath};
|
use axum::extract::{ConnectInfo, MatchedPath};
|
||||||
use headers::{ContentLength, HeaderMapExt, Host, UserAgent};
|
use headers::{ContentLength, HeaderMapExt, Host, UserAgent};
|
||||||
use http::{Method, Request, Version};
|
use http::Request;
|
||||||
#[cfg(feature = "client")]
|
#[cfg(feature = "client")]
|
||||||
use hyper::client::connect::dns::Name;
|
use hyper::client::connect::dns::Name;
|
||||||
use opentelemetry::{
|
use opentelemetry::trace::{SpanBuilder, SpanKind};
|
||||||
trace::{SpanBuilder, SpanKind},
|
|
||||||
KeyValue,
|
|
||||||
};
|
|
||||||
use opentelemetry_semantic_conventions::trace as SC;
|
use opentelemetry_semantic_conventions::trace as SC;
|
||||||
|
|
||||||
|
use super::utils::{http_flavor, http_method_str};
|
||||||
|
|
||||||
pub trait MakeSpanBuilder<R> {
|
pub trait MakeSpanBuilder<R> {
|
||||||
fn make_span_builder(&self, request: &R) -> (SpanBuilder, Vec<KeyValue>);
|
fn make_span_builder(&self, request: &R) -> SpanBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
@@ -51,36 +50,8 @@ impl Default for DefaultMakeSpanBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<R> MakeSpanBuilder<R> for DefaultMakeSpanBuilder {
|
impl<R> MakeSpanBuilder<R> for DefaultMakeSpanBuilder {
|
||||||
fn make_span_builder(&self, _request: &R) -> (SpanBuilder, Vec<KeyValue>) {
|
fn make_span_builder(&self, _request: &R) -> SpanBuilder {
|
||||||
(SpanBuilder::from_name(self.operation), Vec::new())
|
SpanBuilder::from_name(self.operation)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn http_method_str(method: &Method) -> Cow<'static, str> {
|
|
||||||
match method {
|
|
||||||
&Method::OPTIONS => "OPTIONS".into(),
|
|
||||||
&Method::GET => "GET".into(),
|
|
||||||
&Method::POST => "POST".into(),
|
|
||||||
&Method::PUT => "PUT".into(),
|
|
||||||
&Method::DELETE => "DELETE".into(),
|
|
||||||
&Method::HEAD => "HEAD".into(),
|
|
||||||
&Method::TRACE => "TRACE".into(),
|
|
||||||
&Method::CONNECT => "CONNECT".into(),
|
|
||||||
&Method::PATCH => "PATCH".into(),
|
|
||||||
other => other.to_string().into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn http_flavor(version: Version) -> Cow<'static, str> {
|
|
||||||
match version {
|
|
||||||
Version::HTTP_09 => "0.9".into(),
|
|
||||||
Version::HTTP_10 => "1.0".into(),
|
|
||||||
Version::HTTP_11 => "1.1".into(),
|
|
||||||
Version::HTTP_2 => "2.0".into(),
|
|
||||||
Version::HTTP_3 => "3.0".into(),
|
|
||||||
other => format!("{:?}", other).into(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,10 +88,9 @@ 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, Vec<KeyValue>) {
|
fn make_span_builder(&self, request: &Request<B>) -> SpanBuilder {
|
||||||
let method = SC::HTTP_METHOD.string(http_method_str(request.method()));
|
|
||||||
let mut attributes = vec![
|
let mut attributes = vec![
|
||||||
method.clone(),
|
SC::HTTP_METHOD.string(http_method_str(request.method())),
|
||||||
SC::HTTP_FLAVOR.string(http_flavor(request.version())),
|
SC::HTTP_FLAVOR.string(http_flavor(request.version())),
|
||||||
SC::HTTP_TARGET.string(request.uri().to_string()),
|
SC::HTTP_TARGET.string(request.uri().to_string()),
|
||||||
];
|
];
|
||||||
@@ -141,12 +111,9 @@ impl<B> MakeSpanBuilder<Request<B>> for SpanFromHttpRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let span_builder = 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)
|
||||||
|
|
||||||
let metrics_labels = vec![method];
|
|
||||||
(span_builder, metrics_labels)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,15 +123,21 @@ pub struct SpanFromAxumRequest;
|
|||||||
|
|
||||||
#[cfg(feature = "axum")]
|
#[cfg(feature = "axum")]
|
||||||
impl<B> MakeSpanBuilder<Request<B>> for SpanFromAxumRequest {
|
impl<B> MakeSpanBuilder<Request<B>> for SpanFromAxumRequest {
|
||||||
fn make_span_builder(&self, request: &Request<B>) -> (SpanBuilder, Vec<KeyValue>) {
|
fn make_span_builder(&self, request: &Request<B>) -> SpanBuilder {
|
||||||
let method = SC::HTTP_METHOD.string(http_method_str(request.method()));
|
let (name, route): (String, Cow<'static, str>) =
|
||||||
|
if let Some(path) = request.extensions().get::<MatchedPath>() {
|
||||||
let mut metrics_labels = vec![method.clone()];
|
let path = path.as_str().to_owned();
|
||||||
|
let name = path.clone();
|
||||||
|
(name, path.into())
|
||||||
|
} else {
|
||||||
|
(request.uri().path().to_owned(), Cow::Borrowed("FALLBACK"))
|
||||||
|
};
|
||||||
|
|
||||||
let mut attributes = vec![
|
let mut attributes = vec![
|
||||||
method,
|
SC::HTTP_METHOD.string(http_method_str(request.method())),
|
||||||
SC::HTTP_FLAVOR.string(http_flavor(request.version())),
|
SC::HTTP_FLAVOR.string(http_flavor(request.version())),
|
||||||
SC::HTTP_TARGET.string(request.uri().to_string()),
|
SC::HTTP_TARGET.string(request.uri().to_string()),
|
||||||
|
SC::HTTP_ROUTE.string(route),
|
||||||
];
|
];
|
||||||
|
|
||||||
let headers = request.headers();
|
let headers = request.headers();
|
||||||
@@ -192,23 +165,9 @@ impl<B> MakeSpanBuilder<Request<B>> for SpanFromAxumRequest {
|
|||||||
attributes.push(SC::NET_PEER_PORT.i64(addr.port().into()));
|
attributes.push(SC::NET_PEER_PORT.i64(addr.port().into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (name, route) = if let Some(path) = request.extensions().get::<MatchedPath>() {
|
SpanBuilder::from_name(name)
|
||||||
let path = path.as_str();
|
|
||||||
(path, path)
|
|
||||||
} else {
|
|
||||||
(request.uri().path(), "FALLBACK")
|
|
||||||
};
|
|
||||||
|
|
||||||
let route = SC::HTTP_ROUTE.string(route.to_owned());
|
|
||||||
attributes.push(route.clone());
|
|
||||||
metrics_labels.push(route);
|
|
||||||
|
|
||||||
(
|
|
||||||
SpanBuilder::from_name(name.to_owned())
|
|
||||||
.with_kind(SpanKind::Server)
|
.with_kind(SpanKind::Server)
|
||||||
.with_attributes(attributes),
|
.with_attributes(attributes)
|
||||||
metrics_labels,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,14 +177,11 @@ pub struct SpanFromDnsRequest;
|
|||||||
|
|
||||||
#[cfg(feature = "client")]
|
#[cfg(feature = "client")]
|
||||||
impl MakeSpanBuilder<Name> for SpanFromDnsRequest {
|
impl MakeSpanBuilder<Name> for SpanFromDnsRequest {
|
||||||
fn make_span_builder(&self, request: &Name) -> (SpanBuilder, Vec<KeyValue>) {
|
fn make_span_builder(&self, request: &Name) -> SpanBuilder {
|
||||||
let attributes = vec![SC::NET_HOST_NAME.string(request.as_str().to_owned())];
|
let attributes = vec![SC::NET_HOST_NAME.string(request.as_str().to_owned())];
|
||||||
|
|
||||||
(
|
|
||||||
SpanBuilder::from_name("resolve")
|
SpanBuilder::from_name("resolve")
|
||||||
.with_kind(SpanKind::Client)
|
.with_kind(SpanKind::Client)
|
||||||
.with_attributes(attributes.clone()),
|
.with_attributes(attributes)
|
||||||
attributes,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,15 +15,18 @@
|
|||||||
mod extract_context;
|
mod extract_context;
|
||||||
mod inject_context;
|
mod inject_context;
|
||||||
mod layer;
|
mod layer;
|
||||||
|
mod make_metrics_labels;
|
||||||
mod make_span_builder;
|
mod make_span_builder;
|
||||||
mod on_error;
|
mod on_error;
|
||||||
mod on_response;
|
mod on_response;
|
||||||
mod service;
|
mod service;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
pub type TraceHttpServerLayer = TraceLayer<
|
pub type TraceHttpServerLayer = TraceLayer<
|
||||||
ExtractFromHttpRequest,
|
ExtractFromHttpRequest,
|
||||||
DefaultInjectContext,
|
DefaultInjectContext,
|
||||||
SpanFromHttpRequest,
|
SpanFromHttpRequest,
|
||||||
|
MetricsLabelsFromHttpRequest,
|
||||||
OnHttpResponse,
|
OnHttpResponse,
|
||||||
DefaultOnError,
|
DefaultOnError,
|
||||||
>;
|
>;
|
||||||
@@ -32,6 +35,7 @@ pub type TraceHttpServer<S> = Trace<
|
|||||||
ExtractFromHttpRequest,
|
ExtractFromHttpRequest,
|
||||||
DefaultInjectContext,
|
DefaultInjectContext,
|
||||||
SpanFromHttpRequest,
|
SpanFromHttpRequest,
|
||||||
|
MetricsLabelsFromHttpRequest,
|
||||||
OnHttpResponse,
|
OnHttpResponse,
|
||||||
DefaultOnError,
|
DefaultOnError,
|
||||||
S,
|
S,
|
||||||
@@ -42,6 +46,7 @@ pub type TraceAxumServerLayer = TraceLayer<
|
|||||||
ExtractFromHttpRequest,
|
ExtractFromHttpRequest,
|
||||||
DefaultInjectContext,
|
DefaultInjectContext,
|
||||||
SpanFromAxumRequest,
|
SpanFromAxumRequest,
|
||||||
|
MetricsLabelsFromAxumRequest,
|
||||||
OnHttpResponse,
|
OnHttpResponse,
|
||||||
DefaultOnError,
|
DefaultOnError,
|
||||||
>;
|
>;
|
||||||
@@ -51,6 +56,7 @@ pub type TraceAxumServer<S> = Trace<
|
|||||||
ExtractFromHttpRequest,
|
ExtractFromHttpRequest,
|
||||||
DefaultInjectContext,
|
DefaultInjectContext,
|
||||||
SpanFromAxumRequest,
|
SpanFromAxumRequest,
|
||||||
|
MetricsLabelsFromAxumRequest,
|
||||||
OnHttpResponse,
|
OnHttpResponse,
|
||||||
DefaultOnError,
|
DefaultOnError,
|
||||||
S,
|
S,
|
||||||
@@ -60,6 +66,7 @@ pub type TraceHttpClientLayer = TraceLayer<
|
|||||||
DefaultExtractContext,
|
DefaultExtractContext,
|
||||||
InjectInHttpRequest,
|
InjectInHttpRequest,
|
||||||
SpanFromHttpRequest,
|
SpanFromHttpRequest,
|
||||||
|
MetricsLabelsFromHttpRequest,
|
||||||
OnHttpResponse,
|
OnHttpResponse,
|
||||||
DefaultOnError,
|
DefaultOnError,
|
||||||
>;
|
>;
|
||||||
@@ -68,6 +75,7 @@ pub type TraceHttpClient<S> = Trace<
|
|||||||
DefaultExtractContext,
|
DefaultExtractContext,
|
||||||
InjectInHttpRequest,
|
InjectInHttpRequest,
|
||||||
SpanFromHttpRequest,
|
SpanFromHttpRequest,
|
||||||
|
MetricsLabelsFromHttpRequest,
|
||||||
OnHttpResponse,
|
OnHttpResponse,
|
||||||
DefaultOnError,
|
DefaultOnError,
|
||||||
S,
|
S,
|
||||||
@@ -78,6 +86,7 @@ pub type TraceDnsLayer = TraceLayer<
|
|||||||
DefaultExtractContext,
|
DefaultExtractContext,
|
||||||
DefaultInjectContext,
|
DefaultInjectContext,
|
||||||
SpanFromDnsRequest,
|
SpanFromDnsRequest,
|
||||||
|
DefaultMakeMetricsLabels,
|
||||||
DefaultOnResponse,
|
DefaultOnResponse,
|
||||||
DefaultOnError,
|
DefaultOnError,
|
||||||
>;
|
>;
|
||||||
@@ -87,6 +96,7 @@ pub type TraceDns<S> = Trace<
|
|||||||
DefaultExtractContext,
|
DefaultExtractContext,
|
||||||
DefaultInjectContext,
|
DefaultInjectContext,
|
||||||
SpanFromDnsRequest,
|
SpanFromDnsRequest,
|
||||||
|
DefaultMakeMetricsLabels,
|
||||||
DefaultOnResponse,
|
DefaultOnResponse,
|
||||||
DefaultOnError,
|
DefaultOnError,
|
||||||
S,
|
S,
|
||||||
@@ -97,6 +107,7 @@ impl TraceHttpServerLayer {
|
|||||||
pub fn http_server() -> Self {
|
pub fn http_server() -> Self {
|
||||||
TraceLayer::with_namespace("http_server")
|
TraceLayer::with_namespace("http_server")
|
||||||
.make_span_builder(SpanFromHttpRequest::server())
|
.make_span_builder(SpanFromHttpRequest::server())
|
||||||
|
.make_metrics_labels(MetricsLabelsFromHttpRequest::default())
|
||||||
.on_response(OnHttpResponse)
|
.on_response(OnHttpResponse)
|
||||||
.extract_context(ExtractFromHttpRequest)
|
.extract_context(ExtractFromHttpRequest)
|
||||||
}
|
}
|
||||||
@@ -108,6 +119,7 @@ impl TraceAxumServerLayer {
|
|||||||
pub fn axum() -> Self {
|
pub fn axum() -> Self {
|
||||||
TraceLayer::with_namespace("http_server")
|
TraceLayer::with_namespace("http_server")
|
||||||
.make_span_builder(SpanFromAxumRequest)
|
.make_span_builder(SpanFromAxumRequest)
|
||||||
|
.make_metrics_labels(MetricsLabelsFromAxumRequest::default())
|
||||||
.on_response(OnHttpResponse)
|
.on_response(OnHttpResponse)
|
||||||
.extract_context(ExtractFromHttpRequest)
|
.extract_context(ExtractFromHttpRequest)
|
||||||
}
|
}
|
||||||
@@ -118,6 +130,7 @@ impl TraceHttpClientLayer {
|
|||||||
pub fn http_client(operation: &'static str) -> Self {
|
pub fn http_client(operation: &'static str) -> Self {
|
||||||
TraceLayer::with_namespace("http_client")
|
TraceLayer::with_namespace("http_client")
|
||||||
.make_span_builder(SpanFromHttpRequest::client(operation))
|
.make_span_builder(SpanFromHttpRequest::client(operation))
|
||||||
|
.make_metrics_labels(MetricsLabelsFromHttpRequest::default())
|
||||||
.on_response(OnHttpResponse)
|
.on_response(OnHttpResponse)
|
||||||
.inject_context(InjectInHttpRequest)
|
.inject_context(InjectInHttpRequest)
|
||||||
}
|
}
|
||||||
@@ -126,6 +139,7 @@ impl TraceHttpClientLayer {
|
|||||||
pub fn inner_http_client() -> Self {
|
pub fn inner_http_client() -> Self {
|
||||||
TraceLayer::with_namespace("inner_http_client")
|
TraceLayer::with_namespace("inner_http_client")
|
||||||
.make_span_builder(SpanFromHttpRequest::inner_client())
|
.make_span_builder(SpanFromHttpRequest::inner_client())
|
||||||
|
.make_metrics_labels(MetricsLabelsFromHttpRequest::default())
|
||||||
.on_response(OnHttpResponse)
|
.on_response(OnHttpResponse)
|
||||||
.inject_context(InjectInHttpRequest)
|
.inject_context(InjectInHttpRequest)
|
||||||
}
|
}
|
||||||
@@ -139,6 +153,9 @@ impl TraceDnsLayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use self::make_metrics_labels::{
|
||||||
|
DefaultMakeMetricsLabels, MetricsLabelsFromAxumRequest, MetricsLabelsFromHttpRequest,
|
||||||
|
};
|
||||||
pub use self::{
|
pub use self::{
|
||||||
extract_context::*, inject_context::*, layer::*, make_span_builder::*, on_error::*,
|
extract_context::*, inject_context::*, layer::*, make_span_builder::*, on_error::*,
|
||||||
on_response::*, service::*,
|
on_response::*, service::*,
|
||||||
|
@@ -16,7 +16,7 @@ use opentelemetry::{trace::SpanRef, KeyValue};
|
|||||||
use opentelemetry_semantic_conventions::trace::EXCEPTION_MESSAGE;
|
use opentelemetry_semantic_conventions::trace::EXCEPTION_MESSAGE;
|
||||||
|
|
||||||
pub trait OnError<E> {
|
pub trait OnError<E> {
|
||||||
fn on_error(&self, span: &SpanRef<'_>, err: &E) -> Vec<KeyValue>;
|
fn on_error(&self, span: &SpanRef<'_>, metrics_labels: &mut Vec<KeyValue>, err: &E);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
@@ -26,10 +26,8 @@ impl<E> OnError<E> for DefaultOnError
|
|||||||
where
|
where
|
||||||
E: std::fmt::Display,
|
E: std::fmt::Display,
|
||||||
{
|
{
|
||||||
fn on_error(&self, span: &SpanRef<'_>, err: &E) -> Vec<KeyValue> {
|
fn on_error(&self, span: &SpanRef<'_>, _metrics_labels: &mut Vec<KeyValue>, err: &E) {
|
||||||
let attributes = vec![EXCEPTION_MESSAGE.string(err.to_string())];
|
let attributes = vec![EXCEPTION_MESSAGE.string(err.to_string())];
|
||||||
span.add_event("exception".to_owned(), attributes);
|
span.add_event("exception".to_owned(), attributes);
|
||||||
|
|
||||||
Vec::new()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,15 +20,14 @@ use opentelemetry::{trace::SpanRef, KeyValue};
|
|||||||
use opentelemetry_semantic_conventions::trace as SC;
|
use opentelemetry_semantic_conventions::trace as SC;
|
||||||
|
|
||||||
pub trait OnResponse<R> {
|
pub trait OnResponse<R> {
|
||||||
fn on_response(&self, span: &SpanRef<'_>, response: &R) -> Vec<KeyValue>;
|
fn on_response(&self, span: &SpanRef<'_>, metrics_labels: &mut Vec<KeyValue>, response: &R);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
pub struct DefaultOnResponse;
|
pub struct DefaultOnResponse;
|
||||||
|
|
||||||
impl<R> OnResponse<R> for DefaultOnResponse {
|
impl<R> OnResponse<R> for DefaultOnResponse {
|
||||||
fn on_response(&self, _span: &SpanRef<'_>, _response: &R) -> Vec<KeyValue> {
|
fn on_response(&self, _span: &SpanRef<'_>, _metrics_labels: &mut Vec<KeyValue>, _response: &R) {
|
||||||
Vec::new()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,9 +35,15 @@ impl<R> OnResponse<R> for DefaultOnResponse {
|
|||||||
pub struct OnHttpResponse;
|
pub struct OnHttpResponse;
|
||||||
|
|
||||||
impl<B> OnResponse<Response<B>> for OnHttpResponse {
|
impl<B> OnResponse<Response<B>> for OnHttpResponse {
|
||||||
fn on_response(&self, span: &SpanRef<'_>, response: &Response<B>) -> Vec<KeyValue> {
|
fn on_response(
|
||||||
|
&self,
|
||||||
|
span: &SpanRef<'_>,
|
||||||
|
metrics_labels: &mut Vec<KeyValue>,
|
||||||
|
response: &Response<B>,
|
||||||
|
) {
|
||||||
let status_code = i64::from(response.status().as_u16());
|
let status_code = i64::from(response.status().as_u16());
|
||||||
span.set_attribute(SC::HTTP_STATUS_CODE.i64(status_code));
|
span.set_attribute(SC::HTTP_STATUS_CODE.i64(status_code));
|
||||||
|
metrics_labels.push(KeyValue::new("status_code", status_code));
|
||||||
|
|
||||||
if let Some(ContentLength(content_length)) = response.headers().typed_get() {
|
if let Some(ContentLength(content_length)) = response.headers().typed_get() {
|
||||||
if let Ok(content_length) = content_length.try_into() {
|
if let Ok(content_length) = content_length.try_into() {
|
||||||
@@ -55,7 +60,5 @@ impl<B> OnResponse<Response<B>> for OnHttpResponse {
|
|||||||
span.set_attribute(SC::NET_HOST_IP.string(info.local_addr().ip().to_string()));
|
span.set_attribute(SC::NET_HOST_IP.string(info.local_addr().ip().to_string()));
|
||||||
span.set_attribute(SC::NET_HOST_PORT.i64(info.local_addr().port().into()));
|
span.set_attribute(SC::NET_HOST_PORT.i64(info.local_addr().port().into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
vec![KeyValue::new("status_code", status_code)]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,26 +24,37 @@ use tower::Service;
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
extract_context::ExtractContext, inject_context::InjectContext,
|
extract_context::ExtractContext, inject_context::InjectContext,
|
||||||
make_span_builder::MakeSpanBuilder, on_error::OnError, on_response::OnResponse,
|
make_metrics_labels::MakeMetricsLabels, make_span_builder::MakeSpanBuilder, on_error::OnError,
|
||||||
|
on_response::OnResponse,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Trace<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError, S> {
|
pub struct Trace<
|
||||||
|
ExtractContext,
|
||||||
|
InjectContext,
|
||||||
|
MakeSpanBuilder,
|
||||||
|
MakeMetricsLabels,
|
||||||
|
OnResponse,
|
||||||
|
OnError,
|
||||||
|
S,
|
||||||
|
> {
|
||||||
inner: S,
|
inner: S,
|
||||||
tracer: Arc<opentelemetry::global::BoxedTracer>,
|
tracer: Arc<opentelemetry::global::BoxedTracer>,
|
||||||
extract_context: ExtractContext,
|
extract_context: ExtractContext,
|
||||||
inject_context: InjectContext,
|
inject_context: InjectContext,
|
||||||
make_span_builder: MakeSpanBuilder,
|
make_span_builder: MakeSpanBuilder,
|
||||||
|
make_metrics_labels: MakeMetricsLabels,
|
||||||
on_response: OnResponse,
|
on_response: OnResponse,
|
||||||
on_error: OnError,
|
on_error: OnError,
|
||||||
|
|
||||||
inflight_requests: UpDownCounter<i64>,
|
inflight_requests: UpDownCounter<i64>,
|
||||||
request_counter: Counter<u64>,
|
request_counter: Counter<u64>,
|
||||||
request_histogram: Histogram<f64>,
|
request_histogram: Histogram<f64>,
|
||||||
|
static_attributes: Vec<KeyValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError, S>
|
impl<ExtractContext, InjectContext, MakeSpanBuilder, MakeMetricsLabels, OnResponse, OnError, S>
|
||||||
Trace<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError, S>
|
Trace<ExtractContext, InjectContext, MakeSpanBuilder, MakeMetricsLabels, OnResponse, OnError, S>
|
||||||
{
|
{
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
@@ -52,11 +63,13 @@ impl<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError, S>
|
|||||||
extract_context: ExtractContext,
|
extract_context: ExtractContext,
|
||||||
inject_context: InjectContext,
|
inject_context: InjectContext,
|
||||||
make_span_builder: MakeSpanBuilder,
|
make_span_builder: MakeSpanBuilder,
|
||||||
|
make_metrics_labels: MakeMetricsLabels,
|
||||||
on_response: OnResponse,
|
on_response: OnResponse,
|
||||||
on_error: OnError,
|
on_error: OnError,
|
||||||
inflight_requests: UpDownCounter<i64>,
|
inflight_requests: UpDownCounter<i64>,
|
||||||
request_counter: Counter<u64>,
|
request_counter: Counter<u64>,
|
||||||
request_histogram: Histogram<f64>,
|
request_histogram: Histogram<f64>,
|
||||||
|
static_attributes: Vec<KeyValue>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: service,
|
inner: service,
|
||||||
@@ -65,12 +78,14 @@ impl<ExtractContext, InjectContext, MakeSpanBuilder, OnResponse, OnError, S>
|
|||||||
extract_context,
|
extract_context,
|
||||||
inject_context,
|
inject_context,
|
||||||
make_span_builder,
|
make_span_builder,
|
||||||
|
make_metrics_labels,
|
||||||
on_response,
|
on_response,
|
||||||
on_error,
|
on_error,
|
||||||
|
|
||||||
inflight_requests,
|
inflight_requests,
|
||||||
request_counter,
|
request_counter,
|
||||||
request_histogram,
|
request_histogram,
|
||||||
|
static_attributes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -98,8 +113,25 @@ impl Drop for InFlightGuard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Req, S, ExtractContextT, InjectContextT, MakeSpanBuilderT, OnResponseT, OnErrorT> Service<Req>
|
impl<
|
||||||
for Trace<ExtractContextT, InjectContextT, MakeSpanBuilderT, OnResponseT, OnErrorT, S>
|
Req,
|
||||||
|
S,
|
||||||
|
ExtractContextT,
|
||||||
|
InjectContextT,
|
||||||
|
MakeSpanBuilderT,
|
||||||
|
MakeMetricsLabelsT,
|
||||||
|
OnResponseT,
|
||||||
|
OnErrorT,
|
||||||
|
> Service<Req>
|
||||||
|
for Trace<
|
||||||
|
ExtractContextT,
|
||||||
|
InjectContextT,
|
||||||
|
MakeSpanBuilderT,
|
||||||
|
MakeMetricsLabelsT,
|
||||||
|
OnResponseT,
|
||||||
|
OnErrorT,
|
||||||
|
S,
|
||||||
|
>
|
||||||
where
|
where
|
||||||
ExtractContextT: ExtractContext<Req> + Send,
|
ExtractContextT: ExtractContext<Req> + Send,
|
||||||
InjectContextT: InjectContext<Req> + Send,
|
InjectContextT: InjectContext<Req> + Send,
|
||||||
@@ -107,6 +139,7 @@ where
|
|||||||
OnResponseT: OnResponse<S::Response> + Send + Clone + 'static,
|
OnResponseT: OnResponse<S::Response> + Send + Clone + 'static,
|
||||||
OnErrorT: OnError<S::Error> + Send + Clone + 'static,
|
OnErrorT: OnError<S::Error> + Send + Clone + 'static,
|
||||||
MakeSpanBuilderT: MakeSpanBuilder<Req> + Send,
|
MakeSpanBuilderT: MakeSpanBuilder<Req> + Send,
|
||||||
|
MakeMetricsLabelsT: MakeMetricsLabels<Req> + Send,
|
||||||
S::Future: Send + 'static,
|
S::Future: Send + 'static,
|
||||||
{
|
{
|
||||||
type Response = S::Response;
|
type Response = S::Response;
|
||||||
@@ -123,7 +156,15 @@ where
|
|||||||
let start_time = SystemTime::now();
|
let start_time = SystemTime::now();
|
||||||
|
|
||||||
let cx = self.extract_context.extract_context(&request);
|
let cx = self.extract_context.extract_context(&request);
|
||||||
let (span_builder, mut metrics_labels) = self.make_span_builder.make_span_builder(&request);
|
let mut span_builder = self.make_span_builder.make_span_builder(&request);
|
||||||
|
let mut metrics_labels = self.make_metrics_labels.make_metrics_labels(&request);
|
||||||
|
|
||||||
|
// Add the static attributes to the metrics and the span
|
||||||
|
metrics_labels.extend_from_slice(&self.static_attributes[..]);
|
||||||
|
let mut span_attributes = span_builder.attributes.unwrap_or_default();
|
||||||
|
span_attributes.extend(self.static_attributes.iter().cloned());
|
||||||
|
span_builder.attributes = Some(span_attributes);
|
||||||
|
|
||||||
let span = span_builder.start_with_context(self.tracer.as_ref(), &cx);
|
let span = span_builder.start_with_context(self.tracer.as_ref(), &cx);
|
||||||
|
|
||||||
let cx = cx.with_span(span);
|
let cx = cx.with_span(span);
|
||||||
@@ -144,11 +185,10 @@ where
|
|||||||
let _guard = guard;
|
let _guard = guard;
|
||||||
|
|
||||||
let span = cx.span();
|
let span = cx.span();
|
||||||
let extra_labels = match r {
|
match r {
|
||||||
Ok(response) => on_response.on_response(&span, response),
|
Ok(response) => on_response.on_response(&span, &mut metrics_labels, response),
|
||||||
Err(err) => on_error.on_error(&span, err),
|
Err(err) => on_error.on_error(&span, &mut metrics_labels, err),
|
||||||
};
|
};
|
||||||
metrics_labels.extend_from_slice(&extra_labels);
|
|
||||||
|
|
||||||
request_counter.add(&cx, 1, &metrics_labels);
|
request_counter.add(&cx, 1, &metrics_labels);
|
||||||
request_histogram.record(
|
request_histogram.record(
|
||||||
|
45
crates/http/src/layers/otel/utils.rs
Normal file
45
crates/http/src/layers/otel/utils.rs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use http::{Method, Version};
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super) fn http_method_str(method: &Method) -> Cow<'static, str> {
|
||||||
|
match method {
|
||||||
|
&Method::OPTIONS => "OPTIONS".into(),
|
||||||
|
&Method::GET => "GET".into(),
|
||||||
|
&Method::POST => "POST".into(),
|
||||||
|
&Method::PUT => "PUT".into(),
|
||||||
|
&Method::DELETE => "DELETE".into(),
|
||||||
|
&Method::HEAD => "HEAD".into(),
|
||||||
|
&Method::TRACE => "TRACE".into(),
|
||||||
|
&Method::CONNECT => "CONNECT".into(),
|
||||||
|
&Method::PATCH => "PATCH".into(),
|
||||||
|
other => other.to_string().into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(super) fn http_flavor(version: Version) -> Cow<'static, str> {
|
||||||
|
match version {
|
||||||
|
Version::HTTP_09 => "0.9".into(),
|
||||||
|
Version::HTTP_10 => "1.0".into(),
|
||||||
|
Version::HTTP_11 => "1.1".into(),
|
||||||
|
Version::HTTP_2 => "2.0".into(),
|
||||||
|
Version::HTTP_3 => "3.0".into(),
|
||||||
|
other => format!("{:?}", other).into(),
|
||||||
|
}
|
||||||
|
}
|
@@ -15,6 +15,7 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use http::{Request, Response};
|
use http::{Request, Response};
|
||||||
|
use opentelemetry::KeyValue;
|
||||||
use tower::{util::BoxCloneService, Layer, Service, ServiceBuilder, ServiceExt};
|
use tower::{util::BoxCloneService, Layer, Service, ServiceBuilder, ServiceExt};
|
||||||
use tower_http::{compression::CompressionBody, ServiceBuilderExt};
|
use tower_http::{compression::CompressionBody, ServiceBuilderExt};
|
||||||
|
|
||||||
@@ -51,10 +52,17 @@ where
|
|||||||
let builder = ServiceBuilder::new().compression();
|
let builder = ServiceBuilder::new().compression();
|
||||||
|
|
||||||
#[cfg(feature = "axum")]
|
#[cfg(feature = "axum")]
|
||||||
let builder = builder.layer(TraceLayer::axum());
|
let mut trace_layer = TraceLayer::axum();
|
||||||
|
|
||||||
#[cfg(not(feature = "axum"))]
|
#[cfg(not(feature = "axum"))]
|
||||||
let builder = builder.layer(TraceLayer::http_server());
|
let mut trace_layer = TraceLayer::http_server();
|
||||||
|
|
||||||
|
if let Some(name) = &self.listener_name {
|
||||||
|
trace_layer =
|
||||||
|
trace_layer.with_static_attribute(KeyValue::new("listener", name.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let builder = builder.layer(trace_layer);
|
||||||
|
|
||||||
builder.service(inner).boxed_clone()
|
builder.service(inner).boxed_clone()
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user