Skip to content

Commit 810d05f

Browse files
committed
feat(wasi-observe): A WASI Observe host component
Signed-off-by: Caleb Schoepp <[email protected]>
1 parent caacf55 commit 810d05f

File tree

54 files changed

+2004
-103
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+2004
-103
lines changed

Cargo.lock

+53-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ terminal = { path = "crates/terminal" }
6666

6767
subprocess = "0.2.9"
6868
tempfile = "3.8.0"
69-
tokio = { version = "1.23", features = ["full"] }
69+
tokio = { version = "1.40", features = ["full"] }
7070
toml = "0.8"
7171
tracing = { workspace = true }
7272
url = "2.2.2"
@@ -84,6 +84,7 @@ openssl = { version = "0.10" }
8484
anyhow = { workspace = true, features = ["backtrace"] }
8585
conformance = { path = "tests/conformance-tests" }
8686
conformance-tests = { workspace = true }
87+
fake-opentelemetry-collector = { git = "https://github.com/davidB/tracing-opentelemetry-instrumentation-sdk", rev = "db4331666b8a2a940d45c8942e2b5b9fed8a87be" }
8788
hex = "0.4.3"
8889
http-body-util = { workspace = true }
8990
hyper = { workspace = true }

crates/factor-key-value/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ anyhow = "1.0"
99
lru = "0.9.0"
1010
serde = { version = "1.0", features = ["rc"] }
1111
spin-core = { path = "../core" }
12+
spin-factor-observe = { path = "../factor-observe" }
1213
spin-factors = { path = "../factors" }
1314
spin-locked-app = { path = "../locked-app" }
1415
spin-world = { path = "../world" }

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

+28-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::util::EmptyStoreManager;
22
use anyhow::{Context, Result};
33
use spin_core::{async_trait, wasmtime::component::Resource};
4+
use spin_factor_observe::ObserveContext;
45
use spin_world::v2::key_value;
56
use std::{collections::HashSet, sync::Arc};
67
use table::Table;
@@ -37,6 +38,7 @@ pub struct KeyValueDispatch {
3738
allowed_stores: HashSet<String>,
3839
manager: Arc<dyn StoreManager>,
3940
stores: Table<Arc<dyn Store>>,
41+
observe_context: Option<ObserveContext>,
4042
}
4143

4244
impl KeyValueDispatch {
@@ -49,12 +51,19 @@ impl KeyValueDispatch {
4951
allowed_stores: HashSet::new(),
5052
manager: Arc::new(EmptyStoreManager),
5153
stores: Table::new(capacity),
54+
observe_context: None,
5255
}
5356
}
5457

55-
pub fn init(&mut self, allowed_stores: HashSet<String>, manager: Arc<dyn StoreManager>) {
58+
pub fn init(
59+
&mut self,
60+
allowed_stores: HashSet<String>,
61+
manager: Arc<dyn StoreManager>,
62+
observe_context: Option<ObserveContext>,
63+
) {
5664
self.allowed_stores = allowed_stores;
5765
self.manager = manager;
66+
self.observe_context = observe_context;
5867
}
5968

6069
pub fn get_store(&self, store: Resource<key_value::Store>) -> anyhow::Result<&Arc<dyn Store>> {
@@ -79,6 +88,9 @@ impl key_value::Host for KeyValueDispatch {}
7988
impl key_value::HostStore for KeyValueDispatch {
8089
#[instrument(name = "spin_key_value.open", skip(self), err(level = Level::INFO), fields(otel.kind = "client", kv.backend=self.manager.summary(&name).unwrap_or("unknown".to_string())))]
8190
async fn open(&mut self, name: String) -> Result<Result<Resource<key_value::Store>, Error>> {
91+
if let Some(observe_context) = self.observe_context.as_ref() {
92+
observe_context.reparent_tracing_span()
93+
}
8294
Ok(async {
8395
if self.allowed_stores.contains(&name) {
8496
let store = self
@@ -99,6 +111,9 @@ impl key_value::HostStore for KeyValueDispatch {
99111
store: Resource<key_value::Store>,
100112
key: String,
101113
) -> Result<Result<Option<Vec<u8>>, Error>> {
114+
if let Some(observe_context) = self.observe_context.as_ref() {
115+
observe_context.reparent_tracing_span()
116+
}
102117
let store = self.get_store(store)?;
103118
Ok(store.get(&key).await)
104119
}
@@ -110,6 +125,9 @@ impl key_value::HostStore for KeyValueDispatch {
110125
key: String,
111126
value: Vec<u8>,
112127
) -> Result<Result<(), Error>> {
128+
if let Some(observe_context) = self.observe_context.as_ref() {
129+
observe_context.reparent_tracing_span()
130+
}
113131
let store = self.get_store(store)?;
114132
Ok(store.set(&key, &value).await)
115133
}
@@ -120,6 +138,9 @@ impl key_value::HostStore for KeyValueDispatch {
120138
store: Resource<key_value::Store>,
121139
key: String,
122140
) -> Result<Result<(), Error>> {
141+
if let Some(observe_context) = self.observe_context.as_ref() {
142+
observe_context.reparent_tracing_span()
143+
}
123144
let store = self.get_store(store)?;
124145
Ok(store.delete(&key).await)
125146
}
@@ -130,6 +151,9 @@ impl key_value::HostStore for KeyValueDispatch {
130151
store: Resource<key_value::Store>,
131152
key: String,
132153
) -> Result<Result<bool, Error>> {
154+
if let Some(observe_context) = self.observe_context.as_ref() {
155+
observe_context.reparent_tracing_span()
156+
}
133157
let store = self.get_store(store)?;
134158
Ok(store.exists(&key).await)
135159
}
@@ -139,6 +163,9 @@ impl key_value::HostStore for KeyValueDispatch {
139163
&mut self,
140164
store: Resource<key_value::Store>,
141165
) -> Result<Result<Vec<String>, Error>> {
166+
if let Some(observe_context) = self.observe_context.as_ref() {
167+
observe_context.reparent_tracing_span()
168+
}
142169
let store = self.get_store(store)?;
143170
Ok(store.get_keys().await)
144171
}

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

+7-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::{
88
};
99

1010
use anyhow::ensure;
11+
use spin_factor_observe::ObserveContext;
1112
use spin_factors::{
1213
ConfigureAppContext, Factor, FactorInstanceBuilder, InitContext, PrepareContext, RuntimeFactors,
1314
};
@@ -90,17 +91,19 @@ impl Factor for KeyValueFactor {
9091

9192
fn prepare<T: RuntimeFactors>(
9293
&self,
93-
ctx: PrepareContext<T, Self>,
94+
mut ctx: PrepareContext<T, Self>,
9495
) -> anyhow::Result<InstanceBuilder> {
9596
let app_state = ctx.app_state();
9697
let allowed_stores = app_state
9798
.component_allowed_stores
9899
.get(ctx.app_component().id())
99100
.expect("component should be in component_stores")
100101
.clone();
102+
let observe_context = ObserveContext::from_prepare_context(&mut ctx)?;
101103
Ok(InstanceBuilder {
102104
store_manager: app_state.store_manager.clone(),
103105
allowed_stores,
106+
observe_context,
104107
})
105108
}
106109
}
@@ -149,6 +152,7 @@ pub struct InstanceBuilder {
149152
store_manager: Arc<AppStoreManager>,
150153
/// The allowed stores for this component instance.
151154
allowed_stores: HashSet<String>,
155+
observe_context: ObserveContext,
152156
}
153157

154158
impl FactorInstanceBuilder for InstanceBuilder {
@@ -158,9 +162,10 @@ impl FactorInstanceBuilder for InstanceBuilder {
158162
let Self {
159163
store_manager,
160164
allowed_stores,
165+
observe_context,
161166
} = self;
162167
let mut dispatch = KeyValueDispatch::new_with_capacity(u32::MAX);
163-
dispatch.init(allowed_stores, store_manager);
168+
dispatch.init(allowed_stores, store_manager, Some(observe_context));
164169
Ok(dispatch)
165170
}
166171
}

crates/factor-llm/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ llm-cublas = ["llm", "spin-llm-local/cublas"]
1717
anyhow = "1.0"
1818
async-trait = "0.1"
1919
serde = "1.0"
20+
spin-factor-observe = { path = "../factor-observe" }
2021
spin-factors = { path = "../factors" }
2122
spin-llm-local = { path = "../llm-local", optional = true }
2223
spin-llm-remote-http = { path = "../llm-remote-http" }

crates/factor-llm/src/host.rs

+4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ impl v2::Host for InstanceState {
1515
prompt: String,
1616
params: Option<v2::InferencingParams>,
1717
) -> Result<v2::InferencingResult, v2::Error> {
18+
self.observe_context.reparent_tracing_span();
19+
1820
if !self.allowed_models.contains(&model) {
1921
return Err(access_denied_error(&model));
2022
}
@@ -42,6 +44,8 @@ impl v2::Host for InstanceState {
4244
model: v1::EmbeddingModel,
4345
data: Vec<String>,
4446
) -> Result<v2::EmbeddingsResult, v2::Error> {
47+
self.observe_context.reparent_tracing_span();
48+
4549
if !self.allowed_models.contains(&model) {
4650
return Err(access_denied_error(&model));
4751
}

0 commit comments

Comments
 (0)