8000 feat(minimald,minvmd,minimal): OTEL-compatible log format and trace propagation by norrietaylor · Pull Request #835 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
8000
Diff view
50 changes: 49 additions & 1 deletion Cargo.lock

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

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ members = [
"crates/minimald",
"crates/minimald-rpc",
"crates/minvmd",
"crates/mlog",
"crates/remote-client",
"crates/remote-proto",
"crates/sandbox2",
Expand Down Expand Up @@ -93,12 +94,14 @@ hex = "0.4"
indicatif = "0.18"
indoc = "^2.0"
jaq-all = "0.2.0"
json-subscriber = "0.3"
libc = "0.2"
lzma-rs = "0.3"

# Revert back to crates.io dep once new version is released.
nickel-lang-core = { git = "https://github.com/nickel-lang/nickel.git", rev = "e8a0ab95e52ab31ac9a8ae1a3bef854d8de73cea", default-features = false, features = ["format"] }

opentelemetry-semantic-conventions = "0.32"
nix = { version = "0.31", features = ["fs", "user"] }
nutype = { version = "0.7", features = ["serde"] }
object = { version = "0.39", default-features = false, features = ["archive", "elf", "read_core", "std"] }
Expand Down Expand Up @@ -170,6 +173,7 @@ decode = { path = "crates/decode" }
diagnostics = { path = "crates/diagnostics" }
mctx = { path = "crates/mctx" }
minimald-rpc = { path = "crates/minimald-rpc" }
mlog = { path = "crates/mlog" }
mfile = { path = "crates/mfile" }
op = { path = "crates/op" }
ot = { path = "crates/ot" }
Expand Down
13 changes: 13 additions & 0 deletions crates/minimal/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ impl Client {
.await
.with_context(|| format!("open channel for {}", R::NAME))?;

send_traceparent(&channel).await;
channel
.request_subsystem(false, R::NAME)
.await
Expand Down Expand Up @@ -168,6 +169,7 @@ impl Client {
.channel_open_session()
.await
.context("open exec channel")?;
send_traceparent(&channel).await;
channel
.exec(true, command)
.await
Expand Down Expand Up @@ -207,6 +209,7 @@ impl Client {
.await
.context("open channel for workspace file upload")?;

send_traceparent(&channel).await;
channel
.set_env(true, "MINIMAL_SESSION_ID", session_id.to_string())
.await
Expand Down Expand Up @@ -267,6 +270,16 @@ pub fn resolve_socket_path(
Ok(resolve_provider_dir(minimal_dir_override)?.join(paths::SSH_SOCK_FILE))
}

/// Sends the process trace context as a `TRACEPARENT` channel env request.
/// Best-effort and reply-less: trace propagation is a diagnostic aid, and a
/// daemon predating the variable ignores unknown env names anyway.
async fn send_traceparent(channel: &russh::Channel<russh::client::Msg>) {
use minimald_rpc::trace::TRACEPARENT_ENV;
let _ = channel
.set_env(false, TRACEPARENT_ENV, crate::trace_context().traceparent())
.await;
}

#[cfg(test)]
mod tests {
use super::{Client, resolve_socket_path};
Expand Down
21 changes: 21 additions & 0 deletions crates/minimal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,28 @@ pub struct CompletionsArgs {
pub shell: Shell,
}

/// The process-wide trace context, minted once at command dispatch. The
/// root span carries its ids into every log line, and the SSH client sends
/// the same context to the daemon as a `TRACEPARENT` channel env request —
/// one grep joins host and guest records.
pub(crate) fn trace_context() -> &'static minimald_rpc::trace::TraceContext {
static CONTEXT: std::sync::OnceLock<minimald_rpc::trace::TraceContext> =
std::sync::OnceLock::new();
CONTEXT.get_or_init(minimald_rpc::trace::TraceContext::mint)
}

pub async fn run(cli: Cli) -> Result<(), anyhow::Error> {
use tracing::Instrument as _;
let ctx = trace_context();
let root = tracing::info_span!(
"cmd",
trace_id = %ctx.trace_id_hex(),
span_id = %ctx.span_id_hex(),
);
run_command(cli).instrument(root).await
}

async fn run_command(cli: Cli) -> Result<(), anyhow::Error> {
match cli.command {
Command::Ls(args) => cmd_ls(&cli.global_args, args).await,
Command::Activate(args) => cmd_activate(&cli.global_args, args).await,
Expand Down
2 changes: 2 additions & 0 deletions crates/minimald-rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ license.workspace = true
[dependencies]
constcat.workspace = true
chrono.workspace = true
hex.workspace = true
paths.workspace = true
rand.workspace = true
serde.workspace = true

sessions.workspace = true
Expand Down
2 changes: 2 additions & 0 deletions crates/minimald-rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use chrono::Utc;
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use sessions::SessionId;

pub mod trace;

pub use sessions::{EgressPolicy, IngressPolicy, IpProto, NetworkMode, PortMapping, SessionPolicy};

pub const RPC_SUBSYSTEM_PREFIX: &str = "minimald-v1-";
Expand Down
Loading
0