Skip to content

Commit 4104271

Browse files
feat(redis-cloud): add tracing instrumentation to API client (#452)
- Add #[instrument] spans to all HTTP methods for structured tracing - Add debug! logs for method/URL on each request - Add trace! logs for request bodies and response status - Follows same pattern as redis-enterprise client This establishes a consistent tracing pattern across both API clients for better observability and debugging. Partial fix for #105
1 parent f7e79ee commit 4104271

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

crates/redis-cloud/src/client.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::{CloudError as RestError, Result};
1010
use reqwest::Client;
1111
use serde::Serialize;
1212
use std::sync::Arc;
13+
use tracing::{debug, instrument, trace};
1314

1415
/// Builder for constructing a CloudClient with custom configuration
1516
///
@@ -134,8 +135,10 @@ impl CloudClient {
134135
}
135136

136137
/// Make a GET request with API key authentication
138+
#[instrument(skip(self), fields(method = "GET"))]
137139
pub async fn get<T: serde::de::DeserializeOwned>(&self, path: &str) -> Result<T> {
138140
let url = self.normalize_url(path);
141+
debug!("GET {}", url);
139142

140143
// Redis Cloud API uses these headers for authentication
141144
let response = self
@@ -146,16 +149,20 @@ impl CloudClient {
146149
.send()
147150
.await?;
148151

152+
trace!("Response status: {}", response.status());
149153
self.handle_response(response).await
150154
}
151155

152156
/// Make a POST request
157+
#[instrument(skip(self, body), fields(method = "POST"))]
153158
pub async fn post<B: Serialize, T: serde::de::DeserializeOwned>(
154159
&self,
155160
path: &str,
156161
body: &B,
157162
) -> Result<T> {
158163
let url = self.normalize_url(path);
164+
debug!("POST {}", url);
165+
trace!("Request body: {:?}", serde_json::to_value(body).ok());
159166

160167
// Same backwards header naming as GET
161168
let response = self
@@ -167,16 +174,20 @@ impl CloudClient {
167174
.send()
168175
.await?;
169176

177+
trace!("Response status: {}", response.status());
170178
self.handle_response(response).await
171179
}
172180

173181
/// Make a PUT request
182+
#[instrument(skip(self, body), fields(method = "PUT"))]
174183
pub async fn put<B: Serialize, T: serde::de::DeserializeOwned>(
175184
&self,
176185
path: &str,
177186
body: &B,
178187
) -> Result<T> {
179188
let url = self.normalize_url(path);
189+
debug!("PUT {}", url);
190+
trace!("Request body: {:?}", serde_json::to_value(body).ok());
180191

181192
// Same backwards header naming as GET
182193
let response = self
@@ -188,12 +199,15 @@ impl CloudClient {
188199
.send()
189200
.await?;
190201

202+
trace!("Response status: {}", response.status());
191203
self.handle_response(response).await
192204
}
193205

194206
/// Make a DELETE request
207+
#[instrument(skip(self), fields(method = "DELETE"))]
195208
pub async fn delete(&self, path: &str) -> Result<()> {
196209
let url = self.normalize_url(path);
210+
debug!("DELETE {}", url);
197211

198212
// Same backwards header naming as GET
199213
let response = self
@@ -204,6 +218,7 @@ impl CloudClient {
204218
.send()
205219
.await?;
206220

221+
trace!("Response status: {}", response.status());
207222
if response.status().is_success() {
208223
Ok(())
209224
} else {
@@ -227,27 +242,33 @@ impl CloudClient {
227242
}
228243

229244
/// Execute raw GET request returning JSON Value
245+
#[instrument(skip(self), fields(method = "GET"))]
230246
pub async fn get_raw(&self, path: &str) -> Result<serde_json::Value> {
231247
self.get(path).await
232248
}
233249

234250
/// Execute raw POST request with JSON body
251+
#[instrument(skip(self, body), fields(method = "POST"))]
235252
pub async fn post_raw(&self, path: &str, body: serde_json::Value) -> Result<serde_json::Value> {
236253
self.post(path, &body).await
237254
}
238255

239256
/// Execute raw PUT request with JSON body
257+
#[instrument(skip(self, body), fields(method = "PUT"))]
240258
pub async fn put_raw(&self, path: &str, body: serde_json::Value) -> Result<serde_json::Value> {
241259
self.put(path, &body).await
242260
}
243261

244262
/// Execute raw PATCH request with JSON body
263+
#[instrument(skip(self, body), fields(method = "PATCH"))]
245264
pub async fn patch_raw(
246265
&self,
247266
path: &str,
248267
body: serde_json::Value,
249268
) -> Result<serde_json::Value> {
250269
let url = self.normalize_url(path);
270+
debug!("PATCH {}", url);
271+
trace!("Request body: {:?}", body);
251272

252273
// Use backwards header names for compatibility
253274
let response = self
@@ -259,12 +280,15 @@ impl CloudClient {
259280
.send()
260281
.await?;
261282

283+
trace!("Response status: {}", response.status());
262284
self.handle_response(response).await
263285
}
264286

265287
/// Execute raw DELETE request returning any response body
288+
#[instrument(skip(self), fields(method = "DELETE"))]
266289
pub async fn delete_raw(&self, path: &str) -> Result<serde_json::Value> {
267290
let url = self.normalize_url(path);
291+
debug!("DELETE {}", url);
268292

269293
// Use backwards header names for compatibility
270294
let response = self
@@ -275,6 +299,7 @@ impl CloudClient {
275299
.send()
276300
.await?;
277301

302+
trace!("Response status: {}", response.status());
278303
if response.status().is_success() {
279304
if response.content_length() == Some(0) {
280305
Ok(serde_json::json!({"status": "deleted"}))
@@ -302,12 +327,15 @@ impl CloudClient {
302327
}
303328

304329
/// Execute DELETE request with JSON body (used by some endpoints like PrivateLink principals)
330+
#[instrument(skip(self, body), fields(method = "DELETE"))]
305331
pub async fn delete_with_body<T: serde::de::DeserializeOwned>(
306332
&self,
307333
path: &str,
308334
body: serde_json::Value,
309335
) -> Result<T> {
310336
let url = self.normalize_url(path);
337+
debug!("DELETE {} (with body)", url);
338+
trace!("Request body: {:?}", body);
311339

312340
let response = self
313341
.client
@@ -318,6 +346,7 @@ impl CloudClient {
318346
.send()
319347
.await?;
320348

349+
trace!("Response status: {}", response.status());
321350
self.handle_response(response).await
322351
}
323352

0 commit comments

Comments
 (0)