Skip to content

Commit

Permalink
Use capnp map for tracing metadata
Browse files Browse the repository at this point in the history
Signed-off-by: Martin Michaelis <code@mgjm.de>
  • Loading branch information
mgjm committed Jul 11, 2023
1 parent f132a00 commit 3605b28
Show file tree
Hide file tree
Showing 10 changed files with 729 additions and 316 deletions.
18 changes: 0 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 26 additions & 8 deletions conmon-rs/common/proto/conmon.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ interface Conmon {
# Version
struct VersionRequest {
verbose @0 :Bool;
metadata @1 :Data;
metadataOld @1 :Data; # deprecated
metadata @2 :Metadata; # Standard metadata to carry.
}

struct VersionResponse {
Expand All @@ -18,7 +19,7 @@ interface Conmon {
rustVersion @6 :Text;
cargoVersion @7 :Text;
cargoTree @8 :Text;
metadata @9 :Data;
metadata @9 :Data; # deprecated (never used, remove in next major release)
}

version @0 (request: VersionRequest) -> (response: VersionResponse);
Expand All @@ -36,7 +37,8 @@ interface Conmon {
cleanupCmd @7 :List(Text);
globalArgs @8 :List(Text);
commandArgs @9 :List(Text);
metadata @10 :Data;
metadataOld @10 :Data; # deprecated
metadata @11 :Metadata; # Standard metadata to carry.
}

struct LogDriver {
Expand Down Expand Up @@ -68,7 +70,8 @@ interface Conmon {
timeoutSec @1 :UInt64;
command @2 :List(Text);
terminal @3 :Bool;
metadata @4 :Data;
metadataOld @4 :Data; # deprecated
metadata @5 :Metadata; # Standard metadata to carry.
}

struct ExecSyncContainerResponse {
Expand All @@ -87,7 +90,8 @@ interface Conmon {
socketPath @1 :Text;
execSessionId @2 :Text;
stopAfterStdinEof @3 :Bool;
metadata @4 :Data;
metadataOld @4 :Data; # deprecated
metadata @5 :Metadata; # Standard metadata to carry.
}

struct AttachResponse {
Expand All @@ -99,7 +103,8 @@ interface Conmon {
# ReopenLog
struct ReopenLogRequest {
id @0 :Text;
metadata @1 :Data;
metadataOld @1 :Data; # deprecated
metadata @2 :Metadata; # Standard metadata to carry.
}

struct ReopenLogResponse {
Expand All @@ -113,7 +118,9 @@ interface Conmon {
id @0 :Text; # container identifier
width @1 :UInt16; # columns in characters
height @2 :UInt16; # rows in characters
metadata @3 :Data;
metadataOld @3 :Data; # deprecated
metadata @4 :Metadata; # Standard metadata to carry.

}

struct SetWindowSizeResponse {
Expand All @@ -124,12 +131,13 @@ interface Conmon {
###############################################
# CreateNamespaces
struct CreateNamespacesRequest {
metadata @0 :Data; # Standard metadata to carry.
metadataOld @0 :Data; # deprecated
namespaces @1 :List(Namespace); # The list of namespaces to unshare.
uidMappings @2 :List(Text); # User ID mappings when unsharing the user namespace.
gidMappings @3 :List(Text); # Group ID mappings when unsharing the user namespace.
basePath @4 :Text; # The root path for storing the namespaces.
podId @5 :Text; # The pod identifier.
metadata @6 :Metadata; # Standard metadata to carry.
}

enum Namespace {
Expand All @@ -151,4 +159,14 @@ interface Conmon {
}

createNamespaces @6 (request: CreateNamespacesRequest) -> (response: CreateNamespacesResponse);

###############################################
# Helper types

using Metadata = TextTextMap;
using TextTextMap = List(TextTextMapEntry);
struct TextTextMapEntry {
key @0 :Text;
value @1 :Text;
}
}
1 change: 0 additions & 1 deletion conmon-rs/server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ prctl = "1.0.0"
regex = "1.9.1"
sendfd = { version = "0.4.3", features = ["tokio"] }
serde = { version = "1.0.168", features = ["derive"] }
serde_json = "1.0.100"
shadow-rs = "=0.23.0"
signal-hook = "0.3.15"
strum = { version = "0.25.0", features = ["derive"] }
Expand Down
81 changes: 81 additions & 0 deletions conmon-rs/server/src/capnp_util.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
pub(crate) use map_entry::into_map;

#[allow(unused)]
pub(crate) use map_entry::set_map;

/// Helper functions to convert between capnp maps (List's of MapEntries) and rust maps
mod map_entry {
use capnp::{
struct_list::{Builder, Reader},
traits::OwnedStruct,
};
use conmon_common::conmon_capnp::conmon;

/// Convert from a MapEntry capnp struct to a (key, value) tuple.
pub(crate) trait IntoKeyValue<'a, K, V>: OwnedStruct {
fn into_key_value(entry: Self::Reader<'a>) -> capnp::Result<(K, V)>;
}

/// Set the key and value properties of a MapEntry capnp struct.
pub(crate) trait SetKeyValue<K, V>: OwnedStruct {
fn set_key_value(entry: Self::Builder<'_>, key: K, value: V);
}

impl<'a, K, V> IntoKeyValue<'a, K, V> for conmon::text_text_map_entry::Owned
where
K: From<&'a str>,
V: From<&'a str>,
{
fn into_key_value(entry: Self::Reader<'a>) -> capnp::Result<(K, V)> {
Ok((entry.get_key()?.into(), entry.get_value()?.into()))
}
}

impl<K, V> SetKeyValue<K, V> for conmon::text_text_map_entry::Owned
where
K: AsRef<str>,
V: AsRef<str>,
{
fn set_key_value(mut entry: Self::Builder<'_>, key: K, value: V) {
entry.set_key(key.as_ref());
entry.set_value(value.as_ref());
}
}

/// Convert a capnp map reader (`struct_list::Reader`) into a rust map (`impl FromIterator<(K, V)>`).
pub(crate) fn into_map<'a, K, V, E, T>(reader: Reader<'a, E>) -> capnp::Result<T>
where
E: IntoKeyValue<'a, K, V>,
T: FromIterator<(K, V)>,
{
reader.into_iter().map(E::into_key_value).collect()
}

/// Set a capnp map property from a rust map (`impl IntoIterator<Item=(K, V)>`).
///
/// The `init` function is used to allocate a `struct_list::Builder`.
///
/// ## Example
/// Set the `exampleMap` property in the response capnp builder to the rust map `data`
/// ```ignore
/// set_from_map(data, |size| response.init_example_map(size));
/// ```
pub(crate) fn set_map<'a, K, V, E, T>(data: T, init: impl FnOnce(u32) -> Builder<'a, E>)
where
T: IntoIterator<Item = (K, V)>,
T::IntoIter: ExactSizeIterator,
E: SetKeyValue<K, V>,
{
let data = data.into_iter();
let size = if let Ok(size) = data.len().try_into() {
size
} else {
panic!("map with more then u32::MAX entries")
};
let mut list = init(size);
for (i, (key, value)) in data.enumerate() {
let entry = list.reborrow().get(i as u32);
E::set_key_value(entry, key, value);
}
}
}
1 change: 1 addition & 0 deletions conmon-rs/server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub use server::Server;
pub use version::Version;

mod attach;
mod capnp_util;
mod child;
mod child_reaper;
mod config;
Expand Down
9 changes: 6 additions & 3 deletions conmon-rs/server/src/telemetry.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/// Open Telemetry related source code.
use crate::capnp_util;
use anyhow::{Context, Result};
use capnp::struct_list::Reader;
use clap::crate_name;
use conmon_common::conmon_capnp::conmon;
use nix::unistd::gethostname;
use opentelemetry::{
global,
Expand Down Expand Up @@ -63,13 +66,13 @@ impl Telemetry {
}

/// Set a new parent context from the provided slice data.
pub fn set_parent_context(slice: &'_ [u8]) -> Result<()> {
if slice.is_empty() {
pub fn set_parent_context(reader: Reader<conmon::text_text_map_entry::Owned>) -> Result<()> {
if reader.is_empty() {
// Make it a noop if no data is provided.
return Ok(());
}

let metadata = Metadata(serde_json::from_slice(slice).context("parse slice as JSON")?);
let metadata = Metadata(capnp_util::into_map(reader)?);
let ctx = global::get_text_map_propagator(|prop| prop.extract(&metadata));
Span::current().set_parent(ctx);

Expand Down
Loading

0 comments on commit 3605b28

Please sign in to comment.