Skip to content

Commit 2675610

Browse files
committed
Allow setting a fault attribute for attributing whether guest or host to blame
Signed-off-by: Ryan Levick <[email protected]>
1 parent cfa16b2 commit 2675610

File tree

4 files changed

+47
-25
lines changed

4 files changed

+47
-25
lines changed

crates/factor-key-value/src/host.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::{Cas, SwapError};
22
use anyhow::{Context, Result};
33
use spin_core::{async_trait, wasmtime::component::Resource};
44
use spin_resource_table::Table;
5-
use spin_telemetry::OpenTelemetrySpanExt as _;
5+
use spin_telemetry::traces::{self, Fault};
66
use spin_world::v2::key_value;
77
use spin_world::wasi::keyvalue as wasi_keyvalue;
88
use std::{collections::HashSet, sync::Arc};
@@ -72,10 +72,7 @@ impl KeyValueDispatch {
7272
pub fn get_store<T: 'static>(&self, store: Resource<T>) -> anyhow::Result<&Arc<dyn Store>> {
7373
let res = self.stores.get(store.rep()).context("invalid store");
7474
if let Err(err) = &res {
75-
let current_span = tracing::Span::current();
76-
current_span.set_status(spin_telemetry::opentelemetry::trace::Status::error(
77-
err.to_string(),
78-
));
75+
traces::mark_as_error(err, Some(Fault::Host));
7976
}
8077
res
8178
}
@@ -190,12 +187,11 @@ impl key_value::HostStore for KeyValueDispatch {
190187

191188
/// Make sure that infrastructure related errors are tracked in the current span.
192189
fn track_error_on_span(err: Error) -> Error {
193-
if let Error::Other(_) | Error::StoreTableFull = &err {
194-
let current_span = tracing::Span::current();
195-
current_span.set_status(spin_telemetry::opentelemetry::trace::Status::error(
196-
err.to_string(),
197-
));
198-
}
190+
let fault = match err {
191+
Error::NoSuchStore | Error::AccessDenied => Fault::Guest,
192+
Error::StoreTableFull | Error::Other(_) => Fault::Host,
193+
};
194+
traces::mark_as_error(&err, Some(fault));
199195
err
200196
}
201197

crates/factor-variables/src/host.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use spin_factors::anyhow;
2-
use spin_telemetry::OpenTelemetrySpanExt as _;
2+
use spin_telemetry::traces::{self, Fault};
33
use spin_world::{v1, v2::variables, wasi::config as wasi_config};
44
use tracing::instrument;
55

@@ -73,19 +73,18 @@ impl wasi_config::store::Host for InstanceState {
7373
}
7474
}
7575

76+
/// Convert a `spin_expressions::Error` to a `variables::Error`, setting the current span's status and fault attribute.
7677
fn expressions_to_variables_err(err: spin_expressions::Error) -> variables::Error {
7778
use spin_expressions::Error;
79+
let fault = match err {
80+
Error::InvalidName(_) | Error::InvalidTemplate(_) | Error::Undefined(_) => Fault::Guest,
81+
Error::Provider(_) => Fault::Host,
82+
};
83+
traces::mark_as_error(&err, Some(fault));
7884
match err {
7985
Error::InvalidName(msg) => variables::Error::InvalidName(msg),
8086
Error::Undefined(msg) => variables::Error::Undefined(msg),
81-
other @ Error::InvalidTemplate(_) => variables::Error::Other(format!("{other}")),
82-
Error::Provider(err) => {
83-
// This error may not be caused by bad user input, so set the span status to error.
84-
let current_span = tracing::Span::current();
85-
current_span.set_status(spin_telemetry::opentelemetry::trace::Status::error(
86-
err.to_string(),
87-
));
88-
variables::Error::Provider(err.to_string())
89-
}
87+
Error::InvalidTemplate(_) => variables::Error::Other(format!("{err}")),
88+
Error::Provider(err) => variables::Error::Provider(err.to_string()),
9089
}
9190
}

crates/telemetry/src/lib.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ mod env;
1313
pub mod logs;
1414
pub mod metrics;
1515
mod propagation;
16-
mod traces;
17-
18-
pub use opentelemetry;
19-
pub use tracing_opentelemetry::OpenTelemetrySpanExt;
16+
pub mod traces;
2017

2118
#[cfg(feature = "testing")]
2219
pub mod testing;

crates/telemetry/src/traces.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use opentelemetry_sdk::{
55
Resource,
66
};
77
use tracing::Subscriber;
8+
use tracing_opentelemetry::OpenTelemetrySpanExt as _;
89
use tracing_subscriber::{registry::LookupSpan, EnvFilter, Layer};
910

1011
use crate::detector::SpinResourceDetector;
@@ -61,3 +62,32 @@ pub(crate) fn otel_tracing_layer<S: Subscriber + for<'span> LookupSpan<'span>>(
6162
.with_threads(false)
6263
.with_filter(env_filter))
6364
}
65+
66+
/// Indicate whether the error is more likely caused by the guest or the host.
67+
///
68+
/// This can be used to filter errors in telemetry or logging systems.
69+
#[derive(Debug)]
70+
pub enum Fault {
71+
/// The error is most likely caused by the guest.
72+
Guest,
73+
/// The error might have been caused by the host.
74+
Host,
75+
}
76+
77+
impl Fault {
78+
fn as_str(&self) -> &'static str {
79+
match self {
80+
Fault::Guest => "guest",
81+
Fault::Host => "host",
82+
}
83+
}
84+
}
85+
86+
/// Marks the current span as an error with the given error message and optional fault type.
87+
pub fn mark_as_error<E: std::fmt::Display>(err: &E, fault: Option<Fault>) {
88+
let current_span = tracing::Span::current();
89+
current_span.set_status(opentelemetry::trace::Status::error(err.to_string()));
90+
if let Some(fault) = fault {
91+
current_span.set_attribute("error.fault", fault.as_str());
92+
}
93+
}

0 commit comments

Comments
 (0)