diff --git a/linkerd/http/metrics/src/requests.rs b/linkerd/http/metrics/src/requests.rs index 7a0df94b87..e755ef7fd8 100644 --- a/linkerd/http/metrics/src/requests.rs +++ b/linkerd/http/metrics/src/requests.rs @@ -24,6 +24,7 @@ where { last_update: Instant, total: Counter, + response_frames_total: Counter, by_status: HashMap, StatusMetrics>, } @@ -82,6 +83,7 @@ impl Default for Metrics { Self { last_update: Instant::now(), total: Counter::default(), + response_frames_total: Counter::default(), by_status: HashMap::default(), } } diff --git a/linkerd/http/metrics/src/requests/report.rs b/linkerd/http/metrics/src/requests/report.rs index 9b4b7e5766..ca3dba9125 100644 --- a/linkerd/http/metrics/src/requests/report.rs +++ b/linkerd/http/metrics/src/requests/report.rs @@ -30,6 +30,13 @@ where ) } + fn response_frames_total(&self) -> Metric<'_, Prefixed<'_, &'static str>, Counter> { + Metric::new( + self.prefix_key("response_frames_total"), + "Total number of chunks sent through HTTP as the response.", + ) + } + fn response_latency_ms( &self, ) -> Metric<'_, Prefixed<'_, &'static str>, Histogram> { @@ -128,6 +135,10 @@ where metric.fmt_help(f)?; Self::fmt_by_target(®istry, f, metric, |s| &s.total)?; + let metric = self.response_frames_total(); + metric.fmt_help(f)?; + Self::fmt_by_target(®istry, f, metric, |s| &s.response_frames_total)?; + if self.include_latencies { let metric = self.response_latency_ms(); metric.fmt_help(f)?; diff --git a/linkerd/http/metrics/src/requests/service.rs b/linkerd/http/metrics/src/requests/service.rs index ad1af7ecbc..9e0fe6c4e9 100644 --- a/linkerd/http/metrics/src/requests/service.rs +++ b/linkerd/http/metrics/src/requests/service.rs @@ -333,9 +333,8 @@ where C: ClassifyEos, C::Class: Hash + Eq, { - fn record_latency(self: Pin<&mut Self>) { + fn record_latency(self: Pin<&mut Self>, now: Instant) { let this = self.project(); - let now = Instant::now(); let lock = match this.metrics.as_mut() { Some(lock) => lock, @@ -377,6 +376,11 @@ where } } +fn count_frame(lock: &Mutex>) { + let metrics = lock.lock(); + metrics.response_frames_total.incr(); +} + fn measure_class( lock: &Arc>>, class: C, @@ -415,8 +419,11 @@ where let poll = ready!(self.as_mut().project().inner.poll_data(cx)); let frame = poll.map(|opt| opt.map_err(|e| self.as_mut().measure_err(e.into()))); + if let Some(lock) = self.metrics.as_ref().map(Arc::as_ref) { + count_frame(lock); + } if !(*self.as_mut().project().latency_recorded) { - self.record_latency(); + self.record_latency(Instant::now()); } Poll::Ready(frame) @@ -457,7 +464,7 @@ where { fn drop(mut self: Pin<&mut Self>) { if !self.as_ref().latency_recorded { - self.as_mut().record_latency(); + self.as_mut().record_latency(Instant::now()); } if let Some(c) = self.as_mut().project().classify.take().map(|c| c.eos(None)) {