Skip to content

Commit c4b7588

Browse files
committed
Pipe observe factor through all the other factors
Signed-off-by: Caleb Schoepp <[email protected]>
1 parent 9e99d1e commit c4b7588

File tree

25 files changed

+201
-11
lines changed

25 files changed

+201
-11
lines changed

Cargo.lock

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/factor-key-value/Cargo.toml

Lines changed: 1 addition & 0 deletions
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

Lines changed: 28 additions & 1 deletion
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_locked_app::MetadataKey;
56
use spin_world::v2::key_value;
67
use std::{collections::HashSet, sync::Arc};
@@ -40,6 +41,7 @@ pub struct KeyValueDispatch {
4041
allowed_stores: HashSet<String>,
4142
manager: Arc<dyn StoreManager>,
4243
stores: Table<Arc<dyn Store>>,
44+
observe_context: Option<ObserveContext>,
4345
}
4446

4547
impl KeyValueDispatch {
@@ -52,12 +54,19 @@ impl KeyValueDispatch {
5254
allowed_stores: HashSet::new(),
5355
manager: Arc::new(EmptyStoreManager),
5456
stores: Table::new(capacity),
57+
observe_context: None,
5558
}
5659
}
5760

58-
pub fn init(&mut self, allowed_stores: HashSet<String>, manager: Arc<dyn StoreManager>) {
61+
pub fn init(
62+
&mut self,
63+
allowed_stores: HashSet<String>,
64+
manager: Arc<dyn StoreManager>,
65+
observe_context: Option<ObserveContext>,
66+
) {
5967
self.allowed_stores = allowed_stores;
6068
self.manager = manager;
69+
self.observe_context = observe_context;
6170
}
6271

6372
pub fn get_store(&self, store: Resource<key_value::Store>) -> anyhow::Result<&Arc<dyn Store>> {
@@ -82,6 +91,9 @@ impl key_value::Host for KeyValueDispatch {}
8291
impl key_value::HostStore for KeyValueDispatch {
8392
#[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())))]
8493
async fn open(&mut self, name: String) -> Result<Result<Resource<key_value::Store>, Error>> {
94+
if let Some(observe_context) = self.observe_context.as_ref() {
95+
observe_context.reparent_tracing_span()
96+
}
8597
Ok(async {
8698
if self.allowed_stores.contains(&name) {
8799
let store = self
@@ -102,6 +114,9 @@ impl key_value::HostStore for KeyValueDispatch {
102114
store: Resource<key_value::Store>,
103115
key: String,
104116
) -> Result<Result<Option<Vec<u8>>, Error>> {
117+
if let Some(observe_context) = self.observe_context.as_ref() {
118+
observe_context.reparent_tracing_span()
119+
}
105120
let store = self.get_store(store)?;
106121
Ok(store.get(&key).await)
107122
}
@@ -113,6 +128,9 @@ impl key_value::HostStore for KeyValueDispatch {
113128
key: String,
114129
value: Vec<u8>,
115130
) -> Result<Result<(), Error>> {
131+
if let Some(observe_context) = self.observe_context.as_ref() {
132+
observe_context.reparent_tracing_span()
133+
}
116134
let store = self.get_store(store)?;
117135
Ok(store.set(&key, &value).await)
118136
}
@@ -123,6 +141,9 @@ impl key_value::HostStore for KeyValueDispatch {
123141
store: Resource<key_value::Store>,
124142
key: String,
125143
) -> Result<Result<(), Error>> {
144+
if let Some(observe_context) = self.observe_context.as_ref() {
145+
observe_context.reparent_tracing_span()
146+
}
126147
let store = self.get_store(store)?;
127148
Ok(store.delete(&key).await)
128149
}
@@ -133,6 +154,9 @@ impl key_value::HostStore for KeyValueDispatch {
133154
store: Resource<key_value::Store>,
134155
key: String,
135156
) -> Result<Result<bool, Error>> {
157+
if let Some(observe_context) = self.observe_context.as_ref() {
158+
observe_context.reparent_tracing_span()
159+
}
136160
let store = self.get_store(store)?;
137161
Ok(store.exists(&key).await)
138162
}
@@ -142,6 +166,9 @@ impl key_value::HostStore for KeyValueDispatch {
142166
&mut self,
143167
store: Resource<key_value::Store>,
144168
) -> Result<Result<Vec<String>, Error>> {
169+
if let Some(observe_context) = self.observe_context.as_ref() {
170+
observe_context.reparent_tracing_span()
171+
}
145172
let store = self.get_store(store)?;
146173
Ok(store.get_keys().await)
147174
}

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::{
99

1010
use anyhow::ensure;
1111
use host::KEY_VALUE_STORES_KEY;
12+
use spin_factor_observe::{ObserveContext, ObserveFactor};
1213
use spin_factors::{
1314
ConfigureAppContext, Factor, FactorInstanceBuilder, InitContext, PrepareContext, RuntimeFactors,
1415
};
@@ -88,17 +89,23 @@ impl Factor for KeyValueFactor {
8889

8990
fn prepare<T: RuntimeFactors>(
9091
&self,
91-
ctx: PrepareContext<T, Self>,
92+
mut ctx: PrepareContext<T, Self>,
9293
) -> anyhow::Result<InstanceBuilder> {
9394
let app_state = ctx.app_state();
9495
let allowed_stores = app_state
9596
.component_allowed_stores
9697
.get(ctx.app_component().id())
9798
.expect("component should be in component_stores")
9899
.clone();
100+
let observe_context = match ctx.instance_builder::<ObserveFactor>() {
101+
Ok(factor) => Some(factor.get_observe_context()),
102+
Err(spin_factors::Error::NoSuchFactor(_)) => None,
103+
Err(e) => return Err(e.into()),
104+
};
99105
Ok(InstanceBuilder {
100106
store_manager: app_state.store_manager.clone(),
101107
allowed_stores,
108+
observe_context,
102109
})
103110
}
104111
}
@@ -147,6 +154,7 @@ pub struct InstanceBuilder {
147154
store_manager: Arc<AppStoreManager>,
148155
/// The allowed stores for this component instance.
149156
allowed_stores: HashSet<String>,
157+
observe_context: Option<ObserveContext>,
150158
}
151159

152160
impl FactorInstanceBuilder for InstanceBuilder {
@@ -156,9 +164,10 @@ impl FactorInstanceBuilder for InstanceBuilder {
156164
let Self {
157165
store_manager,
158166
allowed_stores,
167+
observe_context,
159168
} = self;
160169
let mut dispatch = KeyValueDispatch::new_with_capacity(u32::MAX);
161-
dispatch.init(allowed_stores, store_manager);
170+
dispatch.init(allowed_stores, store_manager, observe_context);
162171
Ok(dispatch)
163172
}
164173
}

crates/factor-llm/Cargo.toml

Lines changed: 1 addition & 0 deletions
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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ impl v2::Host for InstanceState {
1515
prompt: String,
1616
params: Option<v2::InferencingParams>,
1717
) -> Result<v2::InferencingResult, v2::Error> {
18+
if let Some(observe_context) = self.observe_context.as_ref() {
19+
observe_context.reparent_tracing_span()
20+
}
21+
1822
if !self.allowed_models.contains(&model) {
1923
return Err(access_denied_error(&model));
2024
}
@@ -42,6 +46,10 @@ impl v2::Host for InstanceState {
4246
model: v1::EmbeddingModel,
4347
data: Vec<String>,
4448
) -> Result<v2::EmbeddingsResult, v2::Error> {
49+
if let Some(observe_context) = self.observe_context.as_ref() {
50+
observe_context.reparent_tracing_span()
51+
}
52+
4553
if !self.allowed_models.contains(&model) {
4654
return Err(access_denied_error(&model));
4755
}

crates/factor-llm/src/lib.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::collections::{HashMap, HashSet};
55
use std::sync::Arc;
66

77
use async_trait::async_trait;
8+
use spin_factor_observe::{ObserveContext, ObserveFactor};
89
use spin_factors::{
910
ConfigureAppContext, Factor, PrepareContext, RuntimeFactors, SelfInstanceBuilder,
1011
};
@@ -76,7 +77,7 @@ impl Factor for LlmFactor {
7677

7778
fn prepare<T: RuntimeFactors>(
7879
&self,
79-
ctx: PrepareContext<T, Self>,
80+
mut ctx: PrepareContext<T, Self>,
8081
) -> anyhow::Result<Self::InstanceBuilder> {
8182
let allowed_models = ctx
8283
.app_state()
@@ -85,10 +86,16 @@ impl Factor for LlmFactor {
8586
.cloned()
8687
.unwrap_or_default();
8788
let engine = ctx.app_state().engine.clone();
89+
let observe_context = match ctx.instance_builder::<ObserveFactor>() {
90+
Ok(factor) => Some(factor.get_observe_context()),
91+
Err(spin_factors::Error::NoSuchFactor(_)) => None,
92+
Err(e) => return Err(e.into()),
93+
};
8894

8995
Ok(InstanceState {
9096
engine,
9197
allowed_models,
98+
observe_context,
9299
})
93100
}
94101
}
@@ -103,6 +110,7 @@ pub struct AppState {
103110
pub struct InstanceState {
104111
engine: Arc<Mutex<dyn LlmEngine>>,
105112
pub allowed_models: Arc<HashSet<String>>,
113+
observe_context: Option<ObserveContext>,
106114
}
107115

108116
/// The runtime configuration for the LLM factor.

crates/factor-outbound-http/src/lib.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,11 @@ impl Factor for OutboundHttpFactor {
7676
let outbound_networking = ctx.instance_builder::<OutboundNetworkingFactor>()?;
7777
let allowed_hosts = outbound_networking.allowed_hosts();
7878
let component_tls_configs = outbound_networking.component_tls_configs().clone();
79-
let observe_context = ctx
80-
.instance_builder::<ObserveFactor>()?
81-
.get_observe_context();
79+
let observe_context = match ctx.instance_builder::<ObserveFactor>() {
80+
Ok(factor) => Some(factor.get_observe_context()),
81+
Err(spin_factors::Error::NoSuchFactor(_)) => None,
82+
Err(e) => return Err(e.into()),
83+
};
8284
Ok(InstanceState {
8385
wasi_http_ctx: WasiHttpCtx::new(),
8486
allowed_hosts,
@@ -101,7 +103,7 @@ pub struct InstanceState {
101103
request_interceptor: Option<Arc<dyn OutboundHttpInterceptor>>,
102104
// Connection-pooling client for 'fermyon:spin/http' interface
103105
spin_http_client: Option<reqwest::Client>,
104-
observe_context: ObserveContext,
106+
observe_context: Option<ObserveContext>,
105107
}
106108

107109
impl InstanceState {

crates/factor-outbound-http/src/spin.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ impl spin_http::Host for crate::InstanceState {
1616
fields(otel.kind = "client", url.full = Empty, http.request.method = Empty,
1717
http.response.status_code = Empty, otel.name = Empty, server.address = Empty, server.port = Empty))]
1818
async fn send_request(&mut self, req: Request) -> Result<Response, HttpError> {
19-
self.observe_context.reparent_tracing_span();
19+
if let Some(observe_context) = self.observe_context.as_ref() {
20+
observe_context.reparent_tracing_span()
21+
}
2022

2123
let span = Span::current();
2224
record_request_fields(&span, &req);

crates/factor-outbound-http/src/wasi.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ impl<'a> WasiHttpView for WasiHttpImplInner<'a> {
8787
request: Request<wasmtime_wasi_http::body::HyperOutgoingBody>,
8888
config: wasmtime_wasi_http::types::OutgoingRequestConfig,
8989
) -> wasmtime_wasi_http::HttpResult<wasmtime_wasi_http::types::HostFutureIncomingResponse> {
90-
self.state.observe_context.reparent_tracing_span();
90+
if let Some(observe_context) = self.state.observe_context.as_ref() {
91+
observe_context.reparent_tracing_span()
92+
}
9193
Ok(HostFutureIncomingResponse::Pending(
9294
wasmtime_wasi::runtime::spawn(
9395
send_request_impl(

0 commit comments

Comments
 (0)