Skip to content

Commit ebe955b

Browse files
Merge pull request #169 from spinframework/spin-3.6
Announcing Spin v3.6
2 parents a601ca2 + c88d5b0 commit ebe955b

2 files changed

Lines changed: 179 additions & 0 deletions

File tree

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
title = "Announcing Spin v3.6"
2+
date = "2026-02-11T17:45:05.449167Z"
3+
template = "blog_post"
4+
description = "Announcing the release of Spin v3.6: Onward to WASIp3 stabilization and experimental WASI-OTel!"
5+
tags = []
6+
7+
[extra]
8+
type = "post"
9+
author = "The Spin Project"
10+
11+
---
12+
13+
Earlier this week, the CNCF Spin project released [Spin v3.6.0](https://github.com/spinframework/spin/releases/tag/v3.6.0) which includes support for a new release candidate of the upcoming WASI Preview 3 (WASIp3) release, component instance reuse, and experimental support for the [WASI OTel (OpenTelemetry)](https://github.com/webAssembly/wasi-otel) proposal!
14+
15+
## WASI Preview 3 January Release Candidate
16+
17+
Spin 3.6 replaces the WASIp3 release candidate used in 3.5 with the newer January RC. As in Spin 3.5, this remains experimental, and we do not expect to support it in the next release of Spin. WASIp3 Rust SDK users **must** update from 5.1 to 5.2. (But if you're not using WASIp3 then you **don't** need to update.)
18+
19+
The main user-facing change in the January RC is that it now distinguishes two uses of HTTP: the case of components passing requests along a composition chain, and the case of components making requests to network services. This means components participating in middleware chains can interoperate according to the P3 specification, instead of ad hoc - that is, middleware components from different authors will mix and match with no additional configuration. This doesn't affect application developers, though - you still use your language or SDK HTTP API. But we're working on a middleware feature to let developers take advantage of it - stay tuned!
20+
21+
## WASIp3 Component Instance Reuse
22+
23+
A defining capability of WASIp3 is support for asynchronous component exports. Components can expose async functions that suspend and resume around I/O. And, critically for this, multiple calls may execute concurrently within the same component instance.
24+
25+
This leads to a fundamental shift in how WASI components execute. In WASIp2, component instances were effectively single-use. Runtimes assigned each request a fresh instance, which simplified correctness but imposed real costs: higher memory pressure, no amortisation of startup overhead, and tighter coupling between throughput and instance count. WASIp3 changes that contract. By making asynchronous exports and safe concurrency a first-class concern, the model allows a single component instance to serve many in-flight operations. Runtimes like Spin can therefore move from "one instance per request" toward managed concurrency within a bounded instance pool.
26+
27+
By default, Spin 3.6 reuses WASIp3 component instances both concurrently and serially, allowing multiple in-flight requests to share a single instance, and allowing an instance which is no longer in use to be reused for newly arriving requests.
28+
29+
For platform operators, this means:
30+
* Higher request density per node without linear growth in memory usage
31+
* More predictable performance under bursty or spiky workloads
32+
* Lower cold-start amplification, since fewer instances need to be created and torn down
33+
34+
It does, though, mean application developers need to alter some assumptions about instance lifecycles. Fortunately, these changes line up well with practices you're familiar with from other runtimes such as Axum or Express. If you're using 'global' (that is, instance-scoped) state as part of your request state, you'll need to address that. If you do truly need instace-level state, you must think about how to manage or protect that in the face of concurrent in-flight requests: long-lived state should be a deliberate design choice, not an accidental artifact.
35+
36+
Instance reuse is enabled by default for WASIp3 components, but remains experimental while WASIp3 continues toward formal stabilization. We expect these semantics to solidify alongside the WASI standard itself.
37+
38+
## WASI OTel (OpenTelemetry)
39+
40+
[WASI OTel](https://github.com/WebAssembly/wasi-otel) is a Phase 1 [WASI proposal](https://github.com/WebAssembly/WASI/blob/main/docs/Proposals.md) that defines WIT interfaces for emitting OpenTelemetry signals — traces, metrics, and logs — from within WebAssembly components. Spin 3.6 ships with experimental support for WASI OTel.
41+
42+
We're excited about this because observability is a big pain point in the WebAssembly ecosystem and WASI OTel is a step towards solving the problem. It unlocks first-class observability for Spin appications that tightly integrates with the host observability.
43+
44+
> Because this is still an in-progress proposal, the underlying WIT interfaces may change in future releases. That said, we think it's ready enough to start building with today. Try it out and let the WASI OTel team [know how it goes](https://github.com/WebAssembly/wasi-otel/issues)!
45+
46+
### Tracing a Rust Spin App
47+
48+
The [`opentelemetry-wasi`](https://github.com/calebschoepp/opentelemetry-wasi) crate provides a WASI backend for the standard OpenTelemetry [Rust SDK](https://docs.rs/opentelemetry/latest/opentelemetry/). It's what allows you to use OpenTelemetry within your WebAssembly component.
49+
50+
> The plan is to move this crate under the Bytecode Alliance, but for now you can pull it from its current home.
51+
52+
Let's build a minimal Rust Spin appplication to demo the tracing capabilities. The application will use the idiomatic [`tracing`](https://docs.rs/tracing/latest/tracing/) crate backed by OpenTelemetry. First scaffold a new application:
53+
54+
```bash
55+
spin new wasi-otel-demo -t http-rust --accept-defaults
56+
```
57+
58+
Add the following to the `[dependencies]` section in your `Cargo.toml`:
59+
60+
```toml
61+
[dependencies]
62+
...
63+
opentelemetry = "0.29"
64+
opentelemetry_sdk = "0.29"
65+
opentelemetry-wasi = { git = "https://github.com/calebschoepp/opentelemetry-wasi" }
66+
tracing = "0.1"
67+
tracing-opentelemetry = "0.30"
68+
tracing-subscriber = "0.3"
69+
```
70+
71+
Then in `src/lib.rs`:
72+
73+
**1. Make a bunch of OTel types available in the `use` section.**
74+
75+
```rust
76+
use opentelemetry::{trace::TracerProvider as _, Context};
77+
use opentelemetry_sdk::trace::SdkTracerProvider;
78+
use opentelemetry_wasi::{TraceContextPropagator, WasiPropagator, WasiSpanProcessor};
79+
use spin_sdk::{
80+
http::{IntoResponse, Request, Response},
81+
http_component,
82+
key_value::Store,
83+
};
84+
use tracing::instrument;
85+
use tracing_subscriber::{layer::SubscriberExt, registry, util::SubscriberInitExt};
86+
```
87+
88+
The key pieces here are:
89+
90+
- **`WasiSpanProcessor`** — a `SpanProcessor` that forwards span start/end events to the host via WASI OTel WIT calls instead of exporting them over the network from the guest.
91+
- **`TraceContextPropagator`** — extracts the host's span context so your component's spans are properly parented under the Spin-level request span.
92+
93+
**2. Set up the OTel context and environment.**
94+
95+
```rust
96+
#[http_component]
97+
fn handle_request(_req: Request) -> anyhow::Result<impl IntoResponse> {
98+
// Set up a tracer backed by the WASI span processor
99+
let wasi_processor = WasiSpanProcessor::new();
100+
let provider = SdkTracerProvider::builder()
101+
.with_span_processor(wasi_processor)
102+
.build();
103+
let tracer = provider.tracer("tracing-spin");
104+
105+
// Bridge the tracing crate to OpenTelemetry
106+
let tracing_layer = tracing_opentelemetry::layer().with_tracer(tracer);
107+
registry().with(tracing_layer).try_init().unwrap();
108+
109+
// Propagate the trace context from the Spin host so your
110+
// spans appear as children of the Spin-level request span
111+
let wasi_propagator = TraceContextPropagator::new();
112+
let _guard = wasi_propagator.extract(&Context::current()).attach();
113+
114+
main_operation(); // see below
115+
116+
Ok(Response::builder()
117+
.status(200)
118+
.header("content-type", "text/plain")
119+
.body("Hello, Spin!")
120+
.build())
121+
}
122+
```
123+
124+
**3. You can now use the standard `tracing` instrumentation in your functions.** Each function annotated with `#[instrument]` becomes an OTel span, and macros such as `tracing::info!` become span events. Notice that no WASI-specific APIs leak into your application code!
125+
126+
```rust
127+
#[instrument(fields(my_attribute = "my-value"))]
128+
fn main_operation() {
129+
tracing::info!(name: "Main span event", foo = "1");
130+
child_operation();
131+
}
132+
133+
#[instrument()]
134+
fn child_operation() {
135+
tracing::info!(name: "Sub span event", bar = 1);
136+
let store = Store::open_default().unwrap();
137+
store.set("foo", "bar".as_bytes()).unwrap();
138+
}
139+
```
140+
141+
**4. Your instrumented application is ready to build and run!**
142+
143+
Make sure to add the following to your `spin.toml` to allow key value access:
144+
145+
```toml
146+
key_value_stores = ["default"]
147+
```
148+
149+
Then, run the application with Spin's built-in OTel tooling:
150+
151+
```bash
152+
# Install the `otel` plugin
153+
spin plugin update
154+
spin plugin install otel
155+
156+
# Start the OpenTelemetry collector in the background
157+
spin otel setup
158+
159+
# Run Spin wired up to the OTel collector
160+
spin otel up -- --build --experimental-wasi-otel
161+
162+
# In another terminal
163+
curl localhost:3000
164+
```
165+
166+
Then open Jaeger (`spin otel open jaeger`) to view your traces.
167+
168+
![A screenshot of the traces](/static/image/wasi-otel-jaeger-trace.png)
169+
170+
> The `opentelemetry-wasi` crate also provides `WasiMetricExporter` and `WasiLogProcessor` for metrics and logs respectively. See the [`spin-basic` example](https://github.com/calebschoepp/opentelemetry-wasi/tree/main/rust/examples/spin-basic) for a complete demonstration of all three signals.
171+
172+
## Thank You
173+
174+
Thank you to all contributors for helping bring this release together. Thank you to our growing community and to the CNCF for their support and to the Bytecode Alliance for making such great strides on WASI.
175+
176+
## Stay In Touch
177+
Please join us for weekly [project meetings](https://github.com/spinframework/spin#getting-involved-and-contributing), chat in the [Spin CNCF Slack channel](https://cloud-native.slack.com/archives/C089NJ9G1V0) and follow on X (formerly Twitter) [@spinframework](https://twitter.com/spinframework)!
178+
179+
To get started with Spin and explore the latest features, follow the [Spin quickstart](https://spinframework.dev/v3/quickstart) which provides step-by-step instructions for installing Spin, creating your first application, and running it locally. Also head over to the [Spin Hub](https://spinframework.dev/hub) for inspiration on what you can build!
189 KB
Loading

0 commit comments

Comments
 (0)