fastly/compute_runtime.rs
1//! Functions for interacting with the runtime of the Compute service.
2//!
3
4use fastly_shared::FastlyStatus;
5use fastly_sys::fastly_compute_runtime::{get_heap_mib, get_vcpu_ms};
6#[cfg(not(target_env = "p1"))]
7use fastly_sys::service0_1_0::fastly::compute as wit;
8use std::sync::OnceLock;
9
10/// Get the amount of vCPU time that has passed since this instance was started,
11/// in milliseconds.
12///
13/// This function returns only time spent running on a vCPU, and does not include
14/// time spent performing any I/O operations. However, it is based on clock time
15/// passing, and so will include time spent executing hostcalls, is heavily
16/// affected by what core of what CPU is running the code, and can even be
17/// influenced by the state of the CPU.
18///
19/// As a result, this function *should not be used in benchmarking across runs*.
20/// It can be used, with caution, to compare the runtime of different operations
21/// within the same session.
22pub fn elapsed_vcpu_ms() -> Result<u64, FastlyStatus> {
23 let mut vcpu_time = 0u64;
24 let vcpu_time_result = unsafe { get_vcpu_ms(&mut vcpu_time) };
25 if vcpu_time_result != FastlyStatus::OK {
26 return Err(vcpu_time_result);
27 }
28 Ok(vcpu_time)
29}
30
31/// Get the current dynamic memory usage of this sandbox, rounded up to the nearest mebibyte (2^20
32/// bytes).
33///
34/// The memory accounted includes the WASM linear memory (i.e. heap memory), as well as some memory
35/// used by the hosting environment; for instance, HTTP bodies that have been read from a TCP
36/// connection, but not read by the WASM program. As such, this function provides only a snapshot
37/// in time: the memory usage can change without any action from the WASM program. It can also
38/// change across runs, as the Compute platform's memory usage changes. Consider the returned value
39/// with these possibilities in mind.
40pub fn heap_memory_snapshot_mib() -> Result<u32, FastlyStatus> {
41 let mut memory_mib = 0u32;
42 let result = unsafe { get_heap_mib(&mut memory_mib) };
43 if result != FastlyStatus::OK {
44 return Err(result);
45 }
46 Ok(memory_mib)
47}
48
49/// The hostname of the Fastly cache server which is executing the current instance, for
50/// example, `cache-jfk1034`.
51///
52/// Equivalent to the "FASTLY_HOSTNAME" environment variable and to [`server.hostname`] in VCL.
53///
54/// [`server.hostname`]: https://www.fastly.com/documentation/reference/vcl/variables/server/server-hostname/
55pub fn hostname() -> &'static str {
56 static HOSTNAME: OnceLock<String> = OnceLock::new();
57
58 #[cfg(target_env = "p1")]
59 {
60 HOSTNAME.get_or_init(|| std::env::var("FASTLY_HOSTNAME").unwrap())
61 }
62
63 #[cfg(not(target_env = "p1"))]
64 {
65 HOSTNAME.get_or_init(wit::compute_runtime::get_hostname)
66 }
67}
68
69/// The three-character identifying code of the [Fastly POP] in which the current instance is
70/// running.
71///
72/// Equivalent to the "FASTLY_POP" environment variable and to [`server.datacenter`] in VCL.
73///
74/// [Fastly POP]: https://www.fastly.com/documentation/guides/concepts/pop/
75/// [`server.datacenter`]: https://www.fastly.com/documentation/reference/vcl/variables/server/server-datacenter/
76pub fn pop() -> &'static str {
77 static POP: OnceLock<String> = OnceLock::new();
78
79 #[cfg(target_env = "p1")]
80 {
81 POP.get_or_init(|| std::env::var("FASTLY_POP").unwrap())
82 }
83
84 #[cfg(not(target_env = "p1"))]
85 {
86 POP.get_or_init(wit::compute_runtime::get_pop)
87 }
88}
89
90/// A code representing the general region of the world in which the [Fastly POP] processing the
91/// current Compute instance resides.
92///
93/// Equivalent to the "FASTLY_REGION" environment variable and to [`server.region`] in VCL, and has
94/// the same possible values.
95///
96/// [`server.region`]: https://www.fastly.com/documentation/reference/vcl/variables/server/server-region/
97/// [Fastly POP]: https://www.fastly.com/documentation/guides/concepts/pop/
98pub fn region() -> &'static str {
99 static REGION: OnceLock<String> = OnceLock::new();
100
101 #[cfg(target_env = "p1")]
102 {
103 REGION.get_or_init(|| std::env::var("FASTLY_REGION").unwrap())
104 }
105
106 #[cfg(not(target_env = "p1"))]
107 {
108 REGION.get_or_init(wit::compute_runtime::get_region)
109 }
110}
111
112/// The current cache identifier for this Fastly service.
113///
114/// Equivalent to the "FASTLY_CACHE_GENERATION" environment variable and to [`req.vcl.generation`]
115/// in VCL.
116///
117/// [`req.vcl.generation`]: https://www.fastly.com/documentation/reference/vcl/variables/miscellaneous/req-vcl-generation/
118pub fn cache_generation() -> u64 {
119 static CACHE_GENERATION: OnceLock<u64> = OnceLock::new();
120
121 #[cfg(target_env = "p1")]
122 {
123 *CACHE_GENERATION.get_or_init(|| {
124 std::env::var("FASTLY_CACHE_GENERATION")
125 .unwrap()
126 .parse()
127 .unwrap()
128 })
129 }
130
131 #[cfg(not(target_env = "p1"))]
132 {
133 *CACHE_GENERATION.get_or_init(wit::compute_runtime::get_cache_generation)
134 }
135}
136
137/// The customer ID of the Fastly customer account to which the currently executing service
138/// belongs.
139///
140/// Equivalent to the "FASTLY_CUSTOMER_ID" environment variable and to [`req.customer_id`] in VCL.
141///
142/// [`req.customer_id`]: https://www.fastly.com/documentation/reference/vcl/variables/miscellaneous/req-customer-id/
143pub fn customer_id() -> &'static str {
144 static CUSTOMER_ID: OnceLock<String> = OnceLock::new();
145
146 #[cfg(target_env = "p1")]
147 {
148 CUSTOMER_ID.get_or_init(|| std::env::var("FASTLY_CUSTOMER_ID").unwrap())
149 }
150
151 #[cfg(not(target_env = "p1"))]
152 {
153 CUSTOMER_ID.get_or_init(wit::compute_runtime::get_customer_id)
154 }
155}
156
157/// Whether the request is running in the service's [staging environment].
158///
159/// `false` for production or `true` for staging.
160///
161/// Equivalent to the "FASTLY_IS_STAGING" environment variable and to [`fastly.is_staging`] in VCL.
162///
163/// [`fastly.is_staging`]: https://www.fastly.com/documentation/reference/vcl/variables/miscellaneous/fastly-is-staging/
164/// [staging environment]: https://docs.fastly.com/products/staging
165pub fn is_staging() -> bool {
166 static IS_STAGING: OnceLock<bool> = OnceLock::new();
167
168 #[cfg(target_env = "p1")]
169 {
170 *IS_STAGING.get_or_init(
171 || match std::env::var("FASTLY_IS_STAGING").unwrap().as_str() {
172 "0" => false,
173 "1" => true,
174 _ => unreachable!(),
175 },
176 )
177 }
178
179 #[cfg(not(target_env = "p1"))]
180 {
181 *IS_STAGING.get_or_init(wit::compute_runtime::get_is_staging)
182 }
183}
184
185/// The identifier for the Fastly service that is processing the current request.
186///
187/// Equivalent to the "FASTLY_SERVICE_ID" environment variable and to [`req.service_id`] in VCL.
188///
189/// [`req.service_id`]: https://www.fastly.com/documentation/reference/vcl/variables/miscellaneous/req-service-id/
190pub fn service_id() -> &'static str {
191 static SERVICE_ID: OnceLock<String> = OnceLock::new();
192
193 #[cfg(target_env = "p1")]
194 {
195 SERVICE_ID.get_or_init(|| std::env::var("FASTLY_SERVICE_ID").unwrap())
196 }
197
198 #[cfg(not(target_env = "p1"))]
199 {
200 SERVICE_ID.get_or_init(wit::compute_runtime::get_service_id)
201 }
202}
203
204/// The version number for the Fastly service that is processing the current request.
205///
206/// Equivalent to the "FASTLY_SERVICE_VERSION" environment variable and to [`req.vcl.version`]
207/// in VCL.
208///
209/// [`req.vcl.version`]: https://www.fastly.com/documentation/reference/vcl/variables/miscellaneous/req-vcl-version/
210pub fn service_version() -> u64 {
211 static SERVICE_VERSION: OnceLock<u64> = OnceLock::new();
212
213 #[cfg(target_env = "p1")]
214 {
215 *SERVICE_VERSION.get_or_init(|| {
216 std::env::var("FASTLY_SERVICE_VERSION")
217 .unwrap()
218 .parse()
219 .unwrap()
220 })
221 }
222
223 #[cfg(not(target_env = "p1"))]
224 {
225 *SERVICE_VERSION.get_or_init(wit::compute_runtime::get_service_version)
226 }
227}
228
229#[doc(hidden)]
230pub fn namespace_id() -> &'static str {
231 static NAMESPACE_ID: OnceLock<String> = OnceLock::new();
232
233 #[cfg(target_env = "p1")]
234 {
235 NAMESPACE_ID.get_or_init(|| std::env::var("FASTLY_NAMESPACE_ID").unwrap())
236 }
237
238 #[cfg(not(target_env = "p1"))]
239 {
240 NAMESPACE_ID.get_or_init(wit::compute_runtime::get_hostname)
241 }
242}
243
244/// A UUID generated by Fastly for each sandbox.
245///
246/// This is often a useful value to include in log messages, and also to send to upstream
247/// servers as an additional custom HTTP header, allowing for straightforward correlation of
248/// which WebAssembly session processed a request to requests later processed by an origin
249/// server. If a session is used to process multiple downstream requests, then you may wish to
250/// use the per-request UUID associated with each individual request handle instead of this
251/// function.
252///
253/// Equivalent to the "FASTLY_TRACE_ID" environment variable.
254pub fn sandbox_id() -> &'static str {
255 static SANDBOX_ID: OnceLock<String> = OnceLock::new();
256
257 // There is no `FASTLY_SANDBOX_ID`, however `FASTLY_TRACE_ID` is a
258 // per-sandbox identifier.
259 #[cfg(target_env = "p1")]
260 {
261 SANDBOX_ID.get_or_init(|| std::env::var("FASTLY_TRACE_ID").unwrap())
262 }
263
264 #[cfg(not(target_env = "p1"))]
265 {
266 SANDBOX_ID.get_or_init(wit::compute_runtime::get_sandbox_id)
267 }
268}