Skip to content

Commit 775da21

Browse files
committed
update Nimbus SDK to provide more information on serde_json::Errors
1 parent 3088693 commit 775da21

File tree

11 files changed

+114
-31
lines changed

11 files changed

+114
-31
lines changed

components/nimbus/src/error.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ pub enum NimbusError {
2121
RkvError(#[from] rkv::StoreError),
2222
#[error("IO error: {0}")]
2323
IOError(#[from] std::io::Error),
24-
#[error("JSON Error: {0}")]
25-
JSONError(#[from] serde_json::Error),
24+
#[error("JSON Error: {0} — {1}")]
25+
JSONError(String, String),
2626
#[error("EvaluationError: {0}")]
2727
EvaluationError(String),
2828
#[error("Invalid Expression - didn't evaluate to a bool")]
@@ -103,6 +103,13 @@ pub enum CirrusClientError {
103103
RequestMissingParameter(String),
104104
}
105105

106+
#[cfg(test)]
107+
impl From<serde_json::Error> for NimbusError {
108+
fn from(error: serde_json::Error) -> Self {
109+
NimbusError::JSONError("test".into(), error.to_string())
110+
}
111+
}
112+
106113
impl<'a> From<jexl_eval::error::EvaluationError<'a>> for NimbusError {
107114
fn from(eval_error: jexl_eval::error::EvaluationError<'a>) -> Self {
108115
NimbusError::EvaluationError(eval_error.to_string())

components/nimbus/src/sampling.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,15 @@ pub(crate) fn ratio_sample<T: serde::Serialize>(input: T, ratios: &[u32]) -> Res
9999
/// that is larger than 6 bytes (Should never occur)
100100
pub(crate) fn truncated_hash<T: serde::Serialize>(data: T) -> Result<[u8; 6]> {
101101
let mut hasher = Sha256::new();
102-
let data_str = serde_json::to_string(&data)?;
102+
let data_str = match serde_json::to_string(&data) {
103+
Ok(v) => v,
104+
Err(e) => {
105+
return Err(NimbusError::JSONError(
106+
"data_str = nimbus::sampling::truncated_hash::serde_json::to_string".into(),
107+
e.to_string(),
108+
))
109+
}
110+
};
103111
hasher.update(data_str.as_bytes());
104112
Ok(hasher.finalize()[0..6].try_into()?)
105113
}

components/nimbus/src/schema.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,15 @@ pub fn parse_experiments(payload: &str) -> Result<Vec<Experiment>> {
106106
// We first encode the response into a `serde_json::Value`
107107
// to allow us to deserialize each experiment individually,
108108
// omitting any malformed experiments
109-
let value: Value = serde_json::from_str(payload)?;
109+
let value: Value = match serde_json::from_str(payload) {
110+
Ok(v) => v,
111+
Err(e) => {
112+
return Err(NimbusError::JSONError(
113+
"value = nimbus::schema::parse_experiments::serde_json::from_str".into(),
114+
e.to_string(),
115+
))
116+
}
117+
};
110118
let data = value
111119
.get("data")
112120
.ok_or(NimbusError::InvalidExperimentFormat)?;

components/nimbus/src/stateful/behavior.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,14 @@ impl EventQueryType {
357357
self
358358
)));
359359
}
360-
let event = serde_json::from_value::<String>(args.first().unwrap().clone())?;
361-
let interval = serde_json::from_value::<String>(args.get(1).unwrap().clone())?;
360+
let event = match serde_json::from_value::<String>(args.first().unwrap().clone()) {
361+
Ok(v) => v,
362+
Err(e) => return Err(NimbusError::JSONError("event = nimbus::stateful::behavior::EventQueryType::validate_counting_arguments::serde_json::from_value".into(), e.to_string()))
363+
};
364+
let interval = match serde_json::from_value::<String>(args.get(1).unwrap().clone()) {
365+
Ok(v) => v,
366+
Err(e) => return Err(NimbusError::JSONError("interval = nimbus::stateful::behavior::EventQueryType::validate_counting_arguments::serde_json::from_value".into(), e.to_string()))
367+
};
362368
let interval = Interval::from_str(&interval)?;
363369
let num_buckets = match args.get(2).unwrap().as_f64() {
364370
Some(v) => v,
@@ -393,8 +399,14 @@ impl EventQueryType {
393399
self
394400
)));
395401
}
396-
let event = serde_json::from_value::<String>(args.first().unwrap().clone())?;
397-
let interval = serde_json::from_value::<String>(args.get(1).unwrap().clone())?;
402+
let event = match serde_json::from_value::<String>(args.first().unwrap().clone()) {
403+
Ok(v) => v,
404+
Err(e) => return Err(NimbusError::JSONError("event = nimbus::stateful::behavior::EventQueryType::validate_last_seen_arguments::serde_json::from_value".into(), e.to_string()))
405+
};
406+
let interval = match serde_json::from_value::<String>(args.get(1).unwrap().clone()) {
407+
Ok(v) => v,
408+
Err(e) => return Err(NimbusError::JSONError("interval = nimbus::stateful::behavior::EventQueryType::validate_last_seen_arguments::serde_json::from_value".into(), e.to_string()))
409+
};
398410
let interval = Interval::from_str(&interval)?;
399411
let zero = &Value::from(0);
400412
let starting_bucket = match args.get(2).unwrap_or(zero).as_f64() {

components/nimbus/src/stateful/nimbus_client.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,12 @@ impl NimbusClient {
163163
.read_from_db(db)?;
164164

165165
if let Some(recorded_context) = &self.recorded_context {
166-
let targeting_helper = self.create_targeting_helper_with_context(serde_json::to_value(
166+
let targeting_helper = self.create_targeting_helper_with_context(match serde_json::to_value(
167167
&state.targeting_attributes,
168-
)?);
168+
) {
169+
Ok(v) => v,
170+
Err(e) => return Err(NimbusError::JSONError("targeting_helper = nimbus::stateful::nimbus_client::NimbusClient::begin_initialize::serde_json::to_value".into(), e.to_string()))
171+
});
169172
recorded_context.execute_queries(targeting_helper.as_ref())?;
170173
state
171174
.targeting_attributes
@@ -512,7 +515,10 @@ impl NimbusClient {
512515
let mut buf = String::new();
513516
file.read_to_string(&mut buf)?;
514517

515-
let res = serde_json::from_str::<DateTime<Utc>>(&buf)?;
518+
let res = match serde_json::from_str::<DateTime<Utc>>(&buf) {
519+
Ok(v) => v,
520+
Err(e) => return Err(NimbusError::JSONError("res = nimbus::stateful::nimbus_client::get_creation_date_from_path::serde_json::from_str".into(), e.to_string()))
521+
};
516522
Ok(res)
517523
}
518524

@@ -630,7 +636,10 @@ impl NimbusClient {
630636

631637
fn merge_additional_context(&self, context: Option<JsonObject>) -> Result<Value> {
632638
let context = context.map(Value::Object);
633-
let targeting = serde_json::to_value(self.get_targeting_attributes())?;
639+
let targeting = match serde_json::to_value(self.get_targeting_attributes()) {
640+
Ok(v) => v,
641+
Err(e) => return Err(NimbusError::JSONError("targeting = nimbus::stateful::nimbus_client::NimbusClient::merge_additional_context::serde_json::to_value".into(), e.to_string()))
642+
};
634643
let context = match context {
635644
Some(v) => v.defaults(&targeting)?,
636645
None => targeting,

components/nimbus/src/stateful/persistence.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,10 @@ impl SingleStore {
157157
key: &str,
158158
persisted_data: &T,
159159
) -> Result<()> {
160-
let persisted_json = serde_json::to_string(persisted_data)?;
160+
let persisted_json = match serde_json::to_string(persisted_data) {
161+
Ok(v) => v,
162+
Err(e) => return Err(NimbusError::JSONError("persisted_json = nimbus::stateful::persistence::SingleStore::put::serde_json::to_string".into(), e.to_string()))
163+
};
161164
self.store
162165
.put(writer, key, &rkv::Value::Json(&persisted_json))?;
163166
Ok(())
@@ -187,7 +190,10 @@ impl SingleStore {
187190
match persisted_data {
188191
Some(data) => {
189192
if let rkv::Value::Json(data) = data {
190-
Ok(Some(serde_json::from_str::<T>(data)?))
193+
Ok(Some(match serde_json::from_str::<T>(data) {
194+
Ok(v) => v,
195+
Err(e) => return Err(NimbusError::JSONError("match persisted_data nimbus::stateful::persistence::SingleStore::get::serde_json::from_str".into(), e.to_string()))
196+
}))
191197
} else {
192198
Err(NimbusError::InvalidPersistedData)
193199
}
@@ -239,7 +245,10 @@ impl SingleStore {
239245
let mut iter = self.store.iter_start(reader)?;
240246
while let Some(Ok((_, data))) = iter.next() {
241247
if let rkv::Value::Json(data) = data {
242-
result.push(serde_json::from_str::<T>(data)?);
248+
result.push(match serde_json::from_str::<T>(data) {
249+
Ok(v) => v,
250+
Err(e) => return Err(NimbusError::JSONError("rkv::Value::Json(data) nimbus::stateful::persistence::SingleStore::collect_all::serde_json::from_str".into(), e.to_string()))
251+
});
243252
}
244253
}
245254
Ok(result)
@@ -510,7 +519,10 @@ impl Database {
510519
match persisted_data {
511520
Some(data) => {
512521
if let rkv::Value::Json(data) = data {
513-
Ok(Some(serde_json::from_str::<T>(data)?))
522+
Ok(Some(match serde_json::from_str::<T>(data) {
523+
Ok(v) => v,
524+
Err(e) => return Err(NimbusError::JSONError("rkv::Value::Json(data) nimbus::stateful::persistence::Database::get::serde_json::from_str".into(), e.to_string()))
525+
}))
514526
} else {
515527
Err(NimbusError::InvalidPersistedData)
516528
}
@@ -533,7 +545,10 @@ impl Database {
533545
let mut iter = self.get_store(store_id).store.iter_start(&reader)?;
534546
while let Some(Ok((_, data))) = iter.next() {
535547
if let rkv::Value::Json(data) = data {
536-
result.push(serde_json::from_str::<T>(data)?);
548+
result.push(match serde_json::from_str::<T>(data) {
549+
Ok(v) => v,
550+
Err(e) => return Err(NimbusError::JSONError("rkv::Value::Json(data) nimbus::stateful::persistence::Database::collect_all::serde_json::from_str".into(), e.to_string()))
551+
});
537552
}
538553
}
539554
Ok(result)

components/nimbus/src/stateless/cirrus_client.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,10 @@ impl CirrusClient {
9090
metrics_handler: Box<dyn MetricsHandler>,
9191
coenrolling_feature_ids: Vec<String>,
9292
) -> Result<Self> {
93-
let app_context: AppContext = serde_json::from_str(&app_context)?;
93+
let app_context: AppContext = match serde_json::from_str(&app_context) {
94+
Ok(v) => v,
95+
Err(e) => return Err(NimbusError::JSONError("app_context = nimbus::stateless::cirrus_client::CirrusClient::new::serde_json::from_str".into(), e.to_string()))
96+
};
9497
Ok(Self {
9598
app_context,
9699
coenrolling_feature_ids,
@@ -112,7 +115,10 @@ impl CirrusClient {
112115
request_context,
113116
is_user_participating,
114117
prev_enrollments,
115-
} = serde_json::from_str(request.as_str())?;
118+
} = match serde_json::from_str(request.as_str()) {
119+
Ok(v) => v,
120+
Err(e) => return Err(NimbusError::JSONError("EnrollmentRequest { .. } = nimbus::stateless::cirrus_client::CirrusClient::handle_enrollment::serde_json::from_str".into(), e.to_string()))
121+
};
116122
let client_id = if let Some(client_id) = client_id {
117123
client_id
118124
} else {
@@ -121,12 +127,15 @@ impl CirrusClient {
121127
));
122128
};
123129

124-
Ok(serde_json::to_string(&self.enroll(
130+
Ok(match serde_json::to_string(&self.enroll(
125131
client_id,
126132
request_context,
127133
is_user_participating,
128134
&prev_enrollments,
129-
)?)?)
135+
)?) {
136+
Ok(v) => v,
137+
Err(e) => return Err(NimbusError::JSONError("return nimbus::stateless::cirrus_client::CirrusClient::handle_enrollment::serde_json::to_string".into(), e.to_string()))
138+
})
130139
}
131140

132141
pub(crate) fn enroll(

components/nimbus/src/strings.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,15 @@ use serde_json::{value::Value, Map};
77

88
#[allow(dead_code)]
99
pub fn fmt<T: serde::Serialize>(template: &str, context: &T) -> Result<String> {
10-
let obj: Value = serde_json::to_value(context)?;
10+
let obj: Value = match serde_json::to_value(context) {
11+
Ok(v) => v,
12+
Err(e) => {
13+
return Err(NimbusError::JSONError(
14+
"obj = nimbus::strings::fmt::serde_json::to_value".into(),
15+
e.to_string(),
16+
))
17+
}
18+
};
1119

1220
fmt_with_value(template, &obj)
1321
}

components/nimbus/src/tests/stateful/client/test_http_client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ fn test_malformed_payload() {
6666
"#;
6767

6868
let result = parse_experiments(payload).unwrap_err();
69-
assert!(matches!(result, NimbusError::JSONError(_)));
69+
assert!(matches!(result, NimbusError::JSONError(_, _)));
7070
}
7171

7272
// This response body includes a matching schema version, a non-matching schema version,

components/nimbus/src/tests/stateful/test_evaluator.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ fn test_event_transform_sum_cnz_avg_avgnz_parameters() {
158158
&th,
159159
),
160160
Some(EnrollmentStatus::Error {
161-
reason: "EvaluationError: Custom error: JSON Error: invalid type: floating point `1.0`, expected a string"
161+
reason: "EvaluationError: Custom error: JSON Error: event = nimbus::stateful::behavior::EventQueryType::validate_counting_arguments::serde_json::from_value — invalid type: floating point `1.0`, expected a string"
162162
.to_string()
163163
})
164164
);
@@ -168,7 +168,7 @@ fn test_event_transform_sum_cnz_avg_avgnz_parameters() {
168168
&th,
169169
),
170170
Some(EnrollmentStatus::Error {
171-
reason: "EvaluationError: Custom error: JSON Error: invalid type: floating point `1.0`, expected a string"
171+
reason: "EvaluationError: Custom error: JSON Error: interval = nimbus::stateful::behavior::EventQueryType::validate_counting_arguments::serde_json::from_value — invalid type: floating point `1.0`, expected a string"
172172
.to_string()
173173
})
174174
);
@@ -234,7 +234,7 @@ fn test_event_transform_last_seen_parameters() {
234234
&th,
235235
),
236236
Some(EnrollmentStatus::Error {
237-
reason: "EvaluationError: Custom error: JSON Error: invalid type: floating point `1.0`, expected a string"
237+
reason: "EvaluationError: Custom error: JSON Error: event = nimbus::stateful::behavior::EventQueryType::validate_last_seen_arguments::serde_json::from_value — invalid type: floating point `1.0`, expected a string"
238238
.to_string()
239239
})
240240
);
@@ -244,7 +244,7 @@ fn test_event_transform_last_seen_parameters() {
244244
&th,
245245
),
246246
Some(EnrollmentStatus::Error {
247-
reason: "EvaluationError: Custom error: JSON Error: invalid type: floating point `1.0`, expected a string"
247+
reason: "EvaluationError: Custom error: JSON Error: interval = nimbus::stateful::behavior::EventQueryType::validate_last_seen_arguments::serde_json::from_value — invalid type: floating point `1.0`, expected a string"
248248
.to_string()
249249
})
250250
);

0 commit comments

Comments
 (0)