Skip to content

Commit c3325fd

Browse files
committed
primitives - targeting - eval - add Logging for TypeError
1 parent 913aad3 commit c3325fd

File tree

9 files changed

+100
-50
lines changed

9 files changed

+100
-50
lines changed

Cargo.lock

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

adview-manager/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ serde = {version = "^1.0", features = ['derive']}
1414
serde_json = "^1.0"
1515
reqwest = { version = "0.10", features = ["json"] }
1616
url = { version = "^2.1", features = ["serde"]}
17+
# Logging
18+
slog = { version = "^2.5.2" , features = ["max_level_trace"] }
1719
# Async
1820
async-std = "1.6"
1921
# Other

adview-manager/src/lib.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use lazy_static::lazy_static;
1313
use rand::Rng;
1414
use reqwest::StatusCode;
1515
use serde::{Deserialize, Serialize};
16+
use slog::{error, Logger};
1617
use std::{cmp::Ordering, collections::VecDeque, convert::TryFrom, sync::Arc};
1718
use thiserror::Error;
1819
use units_for_slot::response::UnitsWithPrice;
@@ -279,16 +280,22 @@ pub struct Manager {
279280
/// It always trims to HISTORY_LIMIT, removing the oldest (firstly inserted) elements from the History
280281
history: Arc<RwLock<VecDeque<HistoryEntry>>>,
281282
client: reqwest::Client,
283+
logger: Logger,
282284
}
283285

284286
impl Manager {
285-
pub fn new(options: Options, history: VecDeque<HistoryEntry>) -> Result<Self, Error> {
287+
pub fn new(
288+
options: Options,
289+
history: VecDeque<HistoryEntry>,
290+
logger: Logger,
291+
) -> Result<Self, Error> {
286292
let client = reqwest::Client::builder().build()?;
287293

288294
Ok(Self {
289295
options,
290296
history: Arc::new(RwLock::new(history)),
291297
client,
298+
logger,
292299
})
293300
}
294301

@@ -488,11 +495,13 @@ impl Manager {
488495
.collect(),
489496
};
490497

491-
// TODO: Logging for `eval_multiple`
492-
targeting::eval_multiple(
498+
let on_type_error = |error, rule| error!(&self.logger, "Rule evaluation error for {:?}", campaign_id; "error" => ?error, "rule" => ?rule);
499+
500+
targeting::eval_with_callback(
493501
&campaign.targeting_rules,
494502
&input::Input::Getter(campaign_input.clone()),
495503
&mut output,
504+
Some(on_type_error)
496505
);
497506

498507
output.show

primitives/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,16 @@ pub mod targeting_tag;
2121

2222
pub mod util {
2323
pub mod tests {
24+
use slog::{o, Discard, Drain, Logger};
25+
2426
pub mod prep_db;
2527
pub mod time;
28+
29+
pub fn discard_logger() -> Logger {
30+
let drain = Discard.fuse();
31+
32+
Logger::root(drain, o!())
33+
}
2634
}
2735

2836
pub mod logging;

primitives/src/targeting/eval.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -967,11 +967,11 @@ pub fn eval_multiple(
967967
rules: &[Rule],
968968
input: &Input,
969969
output: &mut Output,
970-
) -> Vec<Result<Option<Value>, Error>> {
970+
) -> Vec<Result<Option<Value>, (Error, Rule)>> {
971971
let mut results = vec![];
972972

973973
for rule in rules {
974-
results.push(rule.eval(input, output));
974+
results.push(rule.eval(input, output).map_err(|err| (err, rule.clone())));
975975

976976
if !output.show {
977977
break;
@@ -981,6 +981,29 @@ pub fn eval_multiple(
981981
results
982982
}
983983

984+
pub fn eval_with_callback<F: Fn(Error, Rule)>(
985+
rules: &[Rule],
986+
input: &Input,
987+
output: &mut Output,
988+
on_type_error: Option<F>,
989+
) {
990+
for result in eval_multiple(rules, input, output) {
991+
match (result, on_type_error.as_ref()) {
992+
(Ok(_), _) => {}
993+
(Err((Error::UnknownVariable, _)), _) => {}
994+
(Err((Error::TypeError, rule)), Some(on_type_error)) => {
995+
on_type_error(Error::TypeError, rule)
996+
}
997+
// skip any other case, including Error::TypeError if there is no passed function
998+
_ => {}
999+
}
1000+
1001+
if !output.show {
1002+
return;
1003+
}
1004+
}
1005+
}
1006+
9841007
enum MathOperator {
9851008
Division,
9861009
Multiplication,

sentry/src/analytics_recorder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub async fn record(
3535
} => {
3636
let divisor = BigNum::from(10u64.pow(18));
3737
// @Todo: Check this!
38-
let pay_amount = get_payout(&channel, event, &session)
38+
let pay_amount = get_payout(&logger, &channel, event, &session)
3939
.expect("should have payout")
4040
.map(|(_, payout)| payout)
4141
.unwrap_or_default()

sentry/src/event_aggregator.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,13 @@ impl EventAggregator {
144144
})?;
145145

146146
events.iter().for_each(|ev| {
147-
match event_reducer::reduce(&record.channel, &mut record.aggregate, ev, &session) {
147+
match event_reducer::reduce(
148+
&app.logger,
149+
&record.channel,
150+
&mut record.aggregate,
151+
ev,
152+
&session,
153+
) {
148154
Ok(_) => {}
149155
Err(err) => error!(&app.logger, "Event Reducer failed"; "error" => ?err ),
150156
}

sentry/src/event_reducer.rs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
use crate::payout::get_payout;
2-
use crate::Session;
3-
use primitives::sentry::{AggregateEvents, Event, EventAggregate};
4-
use primitives::{BigNum, Channel, ValidatorId};
1+
use crate::{payout::get_payout, Session};
2+
use primitives::{
3+
sentry::{AggregateEvents, Event, EventAggregate},
4+
BigNum, Channel, ValidatorId,
5+
};
6+
use slog::Logger;
57

68
pub(crate) fn reduce(
9+
logger: &Logger,
710
channel: &Channel,
811
initial_aggr: &mut EventAggregate,
912
ev: &Event,
@@ -13,8 +16,8 @@ pub(crate) fn reduce(
1316
match ev {
1417
Event::Impression { publisher, .. } => {
1518
let impression = initial_aggr.events.get(&event_type);
16-
let payout = get_payout(&channel, &ev, session)?;
17-
let merge = merge_impression_ev(
19+
let payout = get_payout(logger, &channel, &ev, session)?;
20+
let merge = merge_payable_event(
1821
impression,
1922
payout.unwrap_or_else(|| (*publisher, Default::default())),
2023
);
@@ -23,8 +26,8 @@ pub(crate) fn reduce(
2326
}
2427
Event::Click { publisher, .. } => {
2528
let clicks = initial_aggr.events.get(&event_type);
26-
let payout = get_payout(&channel, &ev, session)?;
27-
let merge = merge_impression_ev(
29+
let payout = get_payout(logger, &channel, &ev, session)?;
30+
let merge = merge_payable_event(
2831
clicks,
2932
payout.unwrap_or_else(|| (*publisher, Default::default())),
3033
);
@@ -46,38 +49,43 @@ pub(crate) fn reduce(
4649
Ok(())
4750
}
4851

49-
fn merge_impression_ev(
50-
impression: Option<&AggregateEvents>,
52+
/// payable_event is either an IMPRESSION or a CLICK
53+
fn merge_payable_event(
54+
payable_event: Option<&AggregateEvents>,
5155
payout: (ValidatorId, BigNum),
5256
) -> AggregateEvents {
53-
let mut impression = impression.map(Clone::clone).unwrap_or_default();
57+
let mut payable_event = payable_event.cloned().unwrap_or_default();
5458

55-
let event_count = impression
59+
let event_count = payable_event
5660
.event_counts
5761
.get_or_insert_with(Default::default)
5862
.entry(payout.0)
5963
.or_insert_with(|| 0.into());
6064

6165
*event_count += &1.into();
6266

63-
let event_payouts = impression
67+
let event_payouts = payable_event
6468
.event_payouts
6569
.entry(payout.0)
6670
.or_insert_with(|| 0.into());
6771
*event_payouts += &payout.1;
6872

69-
impression
73+
payable_event
7074
}
7175

7276
#[cfg(test)]
7377
mod test {
7478
use super::*;
7579
use chrono::Utc;
76-
use primitives::util::tests::prep_db::{DUMMY_CHANNEL, IDS};
80+
use primitives::util::tests::{
81+
discard_logger,
82+
prep_db::{DUMMY_CHANNEL, IDS},
83+
};
7784
use primitives::BigNum;
7885

7986
#[test]
8087
fn test_reduce() {
88+
let logger = discard_logger();
8189
let mut channel: Channel = DUMMY_CHANNEL.clone();
8290
channel.deposit_amount = 100.into();
8391
// make immutable again
@@ -104,7 +112,7 @@ mod test {
104112
};
105113

106114
for i in 0..101 {
107-
reduce(&channel, &mut event_aggr, &event, &session)
115+
reduce(&logger, &channel, &mut event_aggr, &event, &session)
108116
.expect(&format!("Should be able to reduce event #{}", i));
109117
}
110118

sentry/src/payout.rs

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@ use crate::Session;
22
use chrono::Utc;
33
use primitives::{
44
sentry::Event,
5-
targeting::{get_pricing_bounds, input, Error, Error as EvalError, Input, Output, Rule, eval_multiple},
5+
targeting::{eval_with_callback, get_pricing_bounds, input, Error, Output},
66
BigNum, Channel, ValidatorId,
77
};
8+
use slog::{error, Logger};
89
use std::{
910
cmp::{max, min},
1011
convert::TryFrom,
1112
};
1213

1314
type Result = std::result::Result<Option<(ValidatorId, BigNum)>, Error>;
1415

15-
pub fn get_payout(channel: &Channel, event: &Event, session: &Session) -> Result {
16+
pub fn get_payout(logger: &Logger, channel: &Channel, event: &Event, session: &Session) -> Result {
1617
let event_type = event.to_string();
1718

1819
match event {
@@ -77,7 +78,9 @@ pub fn get_payout(channel: &Channel, event: &Event, session: &Session) -> Result
7778
.collect(),
7879
};
7980

80-
eval_and_log(&targeting_rules, &input, &mut output);
81+
let on_type_error = |error, rule| error!(logger, "Rule evaluation error for {:?}", channel.id; "error" => ?error, "rule" => ?rule);
82+
83+
eval_with_callback(&targeting_rules, &input, &mut output, Some(on_type_error));
8184

8285
if output.show {
8386
let price = match output.price.get(&event_type) {
@@ -97,31 +100,19 @@ pub fn get_payout(channel: &Channel, event: &Event, session: &Session) -> Result
97100
}
98101
}
99102

100-
fn eval_and_log(/* logger: &Logger, channel_id: ChannelId, */rules: &[Rule], input: &Input, output: &mut Output) {
101-
for result in eval_multiple(rules, input, output) {
102-
match result {
103-
Ok(_) => {}
104-
Err(EvalError::UnknownVariable) => {}
105-
Err(EvalError::TypeError) => {
106-
todo!();
107-
// error!(logger, "`WARNING: rule for {:?} failing", channel_id; "rule" => rule, "err" => ?result)
108-
}
109-
}
110-
111-
if !output.show {
112-
return;
113-
}
114-
}
115-
}
116-
117103
#[cfg(test)]
118104
mod test {
119105
use super::*;
120106
use primitives::channel::{Pricing, PricingBounds};
121-
use primitives::util::tests::prep_db::{DUMMY_CHANNEL, IDS};
107+
use primitives::util::tests::{
108+
discard_logger,
109+
prep_db::{DUMMY_CHANNEL, IDS},
110+
};
122111

123112
#[test]
124113
fn get_event_payouts_pricing_bounds_impression_event() {
114+
let logger = discard_logger();
115+
125116
let mut channel = DUMMY_CHANNEL.clone();
126117
channel.deposit_amount = 100.into();
127118
channel.spec.min_per_impression = 8.into();
@@ -148,14 +139,15 @@ mod test {
148139
os: None,
149140
};
150141

151-
let payout = get_payout(&channel, &event, &session).expect("Should be OK");
142+
let payout = get_payout(&logger, &channel, &event, &session).expect("Should be OK");
152143

153144
let expected_option = Some((IDS["leader"], 8.into()));
154145
assert_eq!(expected_option, payout, "pricingBounds: impression event");
155146
}
156147

157148
#[test]
158149
fn get_event_payouts_pricing_bounds_click_event() {
150+
let logger = discard_logger();
159151
let mut channel = DUMMY_CHANNEL.clone();
160152
channel.deposit_amount = 100.into();
161153
channel.spec.min_per_impression = 8.into();
@@ -182,14 +174,15 @@ mod test {
182174
os: None,
183175
};
184176

185-
let payout = get_payout(&channel, &event, &session).expect("Should be OK");
177+
let payout = get_payout(&logger, &channel, &event, &session).expect("Should be OK");
186178

187179
let expected_option = Some((IDS["leader"], 23.into()));
188180
assert_eq!(expected_option, payout, "pricingBounds: click event");
189181
}
190182

191183
#[test]
192184
fn get_event_payouts_pricing_bounds_close_event() {
185+
let logger = discard_logger();
193186
let mut channel = DUMMY_CHANNEL.clone();
194187
channel.deposit_amount = 100.into();
195188
channel.spec.min_per_impression = 8.into();
@@ -211,7 +204,7 @@ mod test {
211204
os: None,
212205
};
213206

214-
let payout = get_payout(&channel, &event, &session).expect("Should be OK");
207+
let payout = get_payout(&logger, &channel, &event, &session).expect("Should be OK");
215208

216209
assert_eq!(None, payout, "pricingBounds: click event");
217210
}

0 commit comments

Comments
 (0)