mirror of https://github.com/linkerd/linkerd2.git
proxy: Add destination labels to TapEvents (#814)
The Tap API supports key-value labels on endpoint metadata. The proxy was not setting these labels previously. In order to add these labels onto tap events, we store the original set of labels in an `Arc<HashMap>` on `DstLabels`. When tap events are emitted, the destination' labels are copied from the `DstLabels` into each event.
This commit is contained in:
parent
79bdc638b3
commit
689c42263a
|
@ -45,10 +45,16 @@ impl event::StreamResponseEnd {
|
||||||
eos,
|
eos,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let destination_meta = ctx.dst_labels()
|
||||||
|
.and_then(|b| b.borrow().clone())
|
||||||
|
.map(|d| tap_event::EndpointMeta {
|
||||||
|
labels: d.as_map().clone(),
|
||||||
|
});
|
||||||
|
|
||||||
common::TapEvent {
|
common::TapEvent {
|
||||||
source: Some((&ctx.server.remote).into()),
|
source: Some((&ctx.server.remote).into()),
|
||||||
destination: Some((&ctx.client.remote).into()),
|
destination: Some((&ctx.client.remote).into()),
|
||||||
destination_meta: None,
|
destination_meta,
|
||||||
event: Some(tap_event::Event::Http(tap_event::Http {
|
event: Some(tap_event::Event::Http(tap_event::Http {
|
||||||
event: Some(tap_event::http::Event::ResponseEnd(end)),
|
event: Some(tap_event::http::Event::ResponseEnd(end)),
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
|
use std::hash;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use http;
|
use http;
|
||||||
|
@ -48,8 +50,11 @@ enum Direction {
|
||||||
Outbound,
|
Outbound,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct DstLabels(Arc<str>);
|
pub struct DstLabels {
|
||||||
|
formatted: Arc<str>,
|
||||||
|
original: Arc<HashMap<String, String>>,
|
||||||
|
}
|
||||||
|
|
||||||
// ===== impl RequestLabels =====
|
// ===== impl RequestLabels =====
|
||||||
|
|
||||||
|
@ -204,27 +209,49 @@ impl DstLabels {
|
||||||
let mut labels = labels.into_iter();
|
let mut labels = labels.into_iter();
|
||||||
|
|
||||||
if let Some((k, v)) = labels.next() {
|
if let Some((k, v)) = labels.next() {
|
||||||
|
let mut original = HashMap::new();
|
||||||
|
|
||||||
// Format the first label pair without a leading comma, since we
|
// Format the first label pair without a leading comma, since we
|
||||||
// don't know where it is in the output labels at this point.
|
// don't know where it is in the output labels at this point.
|
||||||
let mut s = format!("dst_{}=\"{}\"", k, v);
|
let mut s = format!("dst_{}=\"{}\"", k, v);
|
||||||
|
original.insert(format!("{}", k), format!("{}", v));
|
||||||
|
|
||||||
// Format subsequent label pairs with leading commas, since
|
// Format subsequent label pairs with leading commas, since
|
||||||
// we know that we already formatted the first label pair.
|
// we know that we already formatted the first label pair.
|
||||||
for (k, v) in labels {
|
for (k, v) in labels {
|
||||||
write!(s, ",dst_{}=\"{}\"", k, v)
|
write!(s, ",dst_{}=\"{}\"", k, v)
|
||||||
.expect("writing to string should not fail");
|
.expect("writing to string should not fail");
|
||||||
|
original.insert(format!("{}", k), format!("{}", v));
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(DstLabels(Arc::from(s)))
|
Some(DstLabels {
|
||||||
|
formatted: Arc::from(s),
|
||||||
|
original: Arc::new(original),
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
// The iterator is empty; return None
|
// The iterator is empty; return None
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_map(&self) -> &HashMap<String, String> {
|
||||||
|
&self.original
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_str(&self) -> &str {
|
||||||
|
&self.formatted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simply hash the formatted string and no other fields on `DstLabels`.
|
||||||
|
impl hash::Hash for DstLabels {
|
||||||
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.formatted.hash(state)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for DstLabels {
|
impl fmt::Display for DstLabels {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "{}", self.0)
|
self.formatted.fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue