Skip to content

Commit c8f3fcc

Browse files
authored
Reworking sentry (#154)
* update toolchain to nightly and fix `cargo clippy` installation error * fix clippy errors * update to `.await` and fix cargo errors/warnings * clean up some files * Clean up some files and some not needed dependencies * update .travis.yml to use latest nightly * follower - merge fix for `.await` * fix cargo fmt * add rust-toolchain for sentry only, until `.await` is merged * clean up `sentry` * make sentry build again * cargo-make 0.22.2 fixes the installation of clippy so remove the custom task override * update `futures-preview` to `alpha.19` * sentry - add the `adapter` along side `futures-preview`, `hyper`, `regex` and `tokio` * sentry - add the cli options, load config and make a 404 Not found response. * sentry - add `serde` & `serde_urlencoded` * sentry - routes - channel - list channel WIP * sentry - move `fn not_found` & `fn bad_request` to lib * sentry - Cargo.toml - add `unstable-stream` feature for `hyper` * sentry - more to channels list and channel create endpoints * sentry - fix some issues and clean up code * sentry - Cargo.toml - add `chrono` * primitives - remove channel::ChannelListParams * sentry - ChannelListQuery * sentry - better error response handling & move channel list & create code to own modules * sentry - Fix changes required because of the merge & `clippy` warnings * sentry - remove `rust-toolchain` * fix `rustfmt` * improve `Adapter`, `EthereumAdapter` & `DummyAdapter` * sentry - Application struct * Fix `EthereumAdapter` and fix `clippy` warnings * fix import * primitives - big_num - fix `clippy` warnings about `to_owned()` * primitives - add `slog` and impl own PrefixCompactFormat * primitives - re-export `slog_async::Async` & `slog_term::TermDecorator` * sentry - working logging for the `Application`: - use the re-exported from `primitives` `slog` structs & traits - Cargo.toml - remove `slog-term` & `slog-async` since we use the re-exported once * sentry - use `error!` for server error & suppress `clustered` warning for not using it now * Use patch instead of `git` url & branch in the `primitives` `Cargo.toml` * sentry - add listening to port on `Application::run` * sentry - add missing `info` import * Fix some merge problems and re-add the `Send` trait bound for the `Adapter`
1 parent 8908f6c commit c8f3fcc

File tree

22 files changed

+805
-528
lines changed

22 files changed

+805
-528
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ members = [
44
"adapter",
55
"primitives",
66
"validator_worker",
7-
# "sentry",
7+
"sentry",
88
"adview-manager",
9-
]
9+
]
10+
11+
[patch.crates-io]
12+
slog-term = { git = "https://github.com/slog-rs/term", branch = "master"}

adapter/src/dummy.rs

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use primitives::adapter::{Adapter, AdapterError, AdapterOptions, AdapterResult, Session};
1+
use primitives::adapter::{Adapter, AdapterError, AdapterResult, DummyAdapterOptions, Session};
22
use primitives::channel_validator::ChannelValidator;
33
use primitives::config::Config;
44
use primitives::Channel;
@@ -18,31 +18,18 @@ pub struct DummyAdapter {
1818
// check if a channel is valid
1919
impl ChannelValidator for DummyAdapter {}
2020

21-
impl Adapter for DummyAdapter {
22-
type Output = DummyAdapter;
23-
24-
fn init(opts: AdapterOptions, config: &Config) -> AdapterResult<DummyAdapter> {
25-
let (identity, authorization_tokens, session_tokens) = match opts {
26-
AdapterOptions::DummAdapter {
27-
dummy_identity,
28-
dummy_auth,
29-
dummy_auth_tokens,
30-
} => (dummy_identity, dummy_auth, dummy_auth_tokens),
31-
_ => {
32-
return Err(AdapterError::Configuration(
33-
"dummy_identity, dummy_auth, dummy_auth_tokens required".to_string(),
34-
))
35-
}
36-
};
37-
38-
Ok(Self {
39-
identity,
21+
impl DummyAdapter {
22+
pub fn init(opts: DummyAdapterOptions, config: &Config) -> Self {
23+
Self {
24+
identity: opts.dummy_identity,
4025
config: config.to_owned(),
41-
session_tokens,
42-
authorization_tokens,
43-
})
26+
session_tokens: opts.dummy_auth_tokens,
27+
authorization_tokens: opts.dummy_auth,
28+
}
4429
}
30+
}
4531

32+
impl Adapter for DummyAdapter {
4633
fn unlock(&mut self) -> AdapterResult<()> {
4734
Ok(())
4835
}

adapter/src/ethereum.rs

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use ethkey::{public_to_address, recover, verify_address, Address, Message, Passw
44
use ethstore::SafeAccount;
55
use lazy_static::lazy_static;
66
use primitives::{
7-
adapter::{Adapter, AdapterError, AdapterOptions, AdapterResult, Session},
7+
adapter::{Adapter, AdapterError, AdapterResult, KeystoreOptions, Session},
88
channel_validator::ChannelValidator,
99
config::Config,
1010
Channel,
@@ -49,22 +49,9 @@ pub struct EthereumAdapter {
4949
// check if a channel is valid
5050
impl ChannelValidator for EthereumAdapter {}
5151

52-
impl Adapter for EthereumAdapter {
53-
type Output = EthereumAdapter;
54-
55-
fn init(opts: AdapterOptions, config: &Config) -> AdapterResult<EthereumAdapter> {
56-
let (keystore_file, keystore_pwd) = match opts {
57-
AdapterOptions::EthereumAdapter(keystore_opts) => {
58-
(keystore_opts.keystore_file, keystore_opts.keystore_pwd)
59-
}
60-
_ => {
61-
return Err(AdapterError::Configuration(
62-
"Missing keystore json file or password".to_string(),
63-
))
64-
}
65-
};
66-
67-
let keystore_contents = fs::read_to_string(&keystore_file)
52+
impl EthereumAdapter {
53+
pub fn init(opts: KeystoreOptions, config: &Config) -> AdapterResult<EthereumAdapter> {
54+
let keystore_contents = fs::read_to_string(&opts.keystore_file)
6855
.map_err(|_| map_error("Invalid keystore location provided"))?;
6956

7057
let keystore_json: Value = serde_json::from_str(&keystore_contents)
@@ -82,14 +69,16 @@ impl Adapter for EthereumAdapter {
8269
Ok(Self {
8370
address,
8471
keystore_json,
85-
keystore_pwd: keystore_pwd.into(),
72+
keystore_pwd: opts.keystore_pwd.into(),
8673
session_tokens: HashMap::new(),
8774
authorization_tokens: HashMap::new(),
8875
wallet: None,
8976
config: config.to_owned(),
9077
})
9178
}
79+
}
9280

81+
impl Adapter for EthereumAdapter {
9382
fn unlock(&mut self) -> AdapterResult<()> {
9483
let account = SafeAccount::from_file(
9584
serde_json::from_value(self.keystore_json.clone())
@@ -414,9 +403,8 @@ mod test {
414403
keystore_file: "./test/resources/keystore.json".to_string(),
415404
keystore_pwd: "adexvalidator".to_string(),
416405
};
417-
let adapter_options = AdapterOptions::EthereumAdapter(keystore_options);
418406

419-
EthereumAdapter::init(adapter_options, &config).expect("should init ethereum adapter")
407+
EthereumAdapter::init(keystore_options, &config).expect("should init ethereum adapter")
420408
}
421409

422410
#[test]
@@ -473,8 +461,7 @@ mod test {
473461
let wallet = eth_adapter.wallet.clone();
474462
let response = ewt_sign(&wallet.unwrap(), &eth_adapter.keystore_pwd, &payload)
475463
.expect("failed to generate ewt signature");
476-
let expected =
477-
"eyJ0eXBlIjoiSldUIiwiYWxnIjoiRVRIIn0.eyJpZCI6ImF3ZXNvbWVWYWxpZGF0b3IiLCJlcmEiOjEwMDAwMCwiYWRkcmVzcyI6IjB4MmJEZUFGQUU1Mzk0MDY2OURhQTZGNTE5MzczZjY4NmMxZjNkMzM5MyJ9.gGw_sfnxirENdcX5KJQWaEt4FVRvfEjSLD4f3OiPrJIltRadeYP2zWy9T2GYcK5xxD96vnqAw4GebAW7rMlz4xw";
464+
let expected = "eyJ0eXBlIjoiSldUIiwiYWxnIjoiRVRIIn0.eyJpZCI6ImF3ZXNvbWVWYWxpZGF0b3IiLCJlcmEiOjEwMDAwMCwiYWRkcmVzcyI6IjB4MmJEZUFGQUU1Mzk0MDY2OURhQTZGNTE5MzczZjY4NmMxZjNkMzM5MyJ9.gGw_sfnxirENdcX5KJQWaEt4FVRvfEjSLD4f3OiPrJIltRadeYP2zWy9T2GYcK5xxD96vnqAw4GebAW7rMlz4xw";
478465
assert_eq!(response, expected, "generated wrong ewt signature");
479466

480467
let expected_verification_response = r#"VerifyPayload { from: "0x2bDeAFAE53940669DaA6F519373f686c1f3d3393", payload: Payload { id: "awesomeValidator", era: 100000, address: Some("0x2bDeAFAE53940669DaA6F519373f686c1f3d3393"), identity: None } }"#;

primitives/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ serde = { version = "^1.0", features = ['derive'] }
1212
serde_json = "1.0"
1313
serde-hex = "0.1.0"
1414
toml = "0.5"
15+
# Logging
16+
slog = { version = "^2.5.2" , features = ["max_level_trace"] }
17+
slog-term = "^2.4.1"
18+
slog-async = "^2.3.0"
1519
# Domain
1620
chrono = { version = "0.4", features = ["serde"] }
1721
time = "0.1.42"

primitives/src/adapter.rs

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::channel_validator::ChannelValidator;
2-
use crate::{Channel, Config};
2+
use crate::Channel;
33
use std::collections::HashMap;
44
use std::error::Error;
55
use std::fmt;
@@ -33,14 +33,10 @@ impl fmt::Display for AdapterError {
3333
}
3434
}
3535

36-
#[derive(Debug, Clone)]
37-
pub enum AdapterOptions {
38-
DummAdapter {
39-
dummy_identity: String,
40-
dummy_auth: HashMap<String, String>,
41-
dummy_auth_tokens: HashMap<String, String>,
42-
},
43-
EthereumAdapter(KeystoreOptions),
36+
pub struct DummyAdapterOptions {
37+
pub dummy_identity: String,
38+
pub dummy_auth: HashMap<String, String>,
39+
pub dummy_auth_tokens: HashMap<String, String>,
4440
}
4541

4642
#[derive(Debug, Clone)]
@@ -55,12 +51,7 @@ pub struct Session {
5551
pub uid: String,
5652
}
5753

58-
pub trait Adapter: ChannelValidator + Clone + Debug + Send {
59-
type Output;
60-
61-
/// Initialize adapter
62-
fn init(opts: AdapterOptions, config: &Config) -> AdapterResult<Self::Output>;
63-
54+
pub trait Adapter: ChannelValidator + Send + Clone + Debug {
6455
/// Unlock adapter
6556
fn unlock(&mut self) -> AdapterResult<()>;
6657

primitives/src/channel.rs

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -129,49 +129,6 @@ impl<'a> IntoIterator for &'a SpecValidators {
129129
}
130130
}
131131

132-
pub struct ChannelListParams {
133-
/// page to show, should be >= 1
134-
pub page: u64,
135-
/// channels limit per page, should be >= 1
136-
pub limit: u32,
137-
/// filters `valid_until` to be `>= valid_until_ge`
138-
pub valid_until_ge: DateTime<Utc>,
139-
/// filters the channels containing a specific validator if provided
140-
pub validator: Option<String>,
141-
/// Ensures that this struct can only be created by calling `new()`
142-
_secret: (),
143-
}
144-
145-
impl ChannelListParams {
146-
pub fn new(
147-
valid_until_ge: DateTime<Utc>,
148-
limit: u32,
149-
page: u64,
150-
validator: Option<&str>,
151-
) -> Result<Self, ChannelError> {
152-
if page < 1 {
153-
return Err(ChannelError::InvalidArgument(
154-
"Page should be >= 1".to_string(),
155-
));
156-
}
157-
158-
if limit < 1 {
159-
return Err(ChannelError::InvalidArgument(
160-
"Limit should be >= 1".to_string(),
161-
));
162-
}
163-
164-
let validator = validator.and_then(|s| if s.is_empty() { None } else { Some(s.into()) });
165-
Ok(Self {
166-
valid_until_ge,
167-
page,
168-
limit,
169-
validator,
170-
_secret: (),
171-
})
172-
}
173-
}
174-
175132
#[derive(Debug, PartialEq, Eq)]
176133
pub enum ChannelError {
177134
InvalidArgument(String),

primitives/src/util.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,118 @@ pub mod serde {
6666
}
6767
}
6868
}
69+
70+
pub mod logging {
71+
use slog::{Drain, OwnedKVList, Record, KV};
72+
use slog_term::{
73+
timestamp_local, CompactFormatSerializer, CountingWriter, Decorator, RecordDecorator,
74+
Serializer, ThreadSafeTimestampFn,
75+
};
76+
use std::cell::RefCell;
77+
use std::{io, io::Write};
78+
79+
pub use slog_async::Async;
80+
pub use slog_term::TermDecorator;
81+
82+
pub struct PrefixedCompactFormat<D>
83+
where
84+
D: Decorator,
85+
{
86+
decorator: D,
87+
history: RefCell<Vec<(Vec<u8>, Vec<u8>)>>,
88+
fn_timestamp: Box<dyn ThreadSafeTimestampFn<Output = io::Result<()>>>,
89+
prefix: String,
90+
}
91+
92+
impl<D> Drain for PrefixedCompactFormat<D>
93+
where
94+
D: Decorator,
95+
{
96+
type Ok = ();
97+
type Err = io::Error;
98+
99+
fn log(&self, record: &Record<'_>, values: &OwnedKVList) -> Result<Self::Ok, Self::Err> {
100+
self.format_compact(record, values)
101+
}
102+
}
103+
104+
impl<D> PrefixedCompactFormat<D>
105+
where
106+
D: Decorator,
107+
{
108+
pub fn new(prefix: &str, d: D) -> PrefixedCompactFormat<D> {
109+
Self {
110+
fn_timestamp: Box::new(timestamp_local),
111+
decorator: d,
112+
history: RefCell::new(vec![]),
113+
prefix: prefix.to_owned(),
114+
}
115+
}
116+
117+
fn format_compact(&self, record: &Record<'_>, values: &OwnedKVList) -> io::Result<()> {
118+
self.decorator.with_record(record, values, |decorator| {
119+
let indent = {
120+
let mut history_ref = self.history.borrow_mut();
121+
let mut serializer = CompactFormatSerializer::new(decorator, &mut *history_ref);
122+
123+
values.serialize(record, &mut serializer)?;
124+
125+
serializer.finish()?
126+
};
127+
128+
decorator.start_whitespace()?;
129+
130+
for _ in 0..indent {
131+
write!(decorator, " ")?;
132+
}
133+
134+
let comma_needed =
135+
print_msg_header(&self.prefix, &*self.fn_timestamp, decorator, record)?;
136+
{
137+
let mut serializer = Serializer::new(decorator, comma_needed, false);
138+
139+
record.kv().serialize(record, &mut serializer)?;
140+
141+
serializer.finish()?;
142+
}
143+
144+
decorator.start_whitespace()?;
145+
writeln!(decorator)?;
146+
147+
decorator.flush()?;
148+
149+
Ok(())
150+
})
151+
}
152+
}
153+
154+
pub fn print_msg_header(
155+
prefix: &str,
156+
fn_timestamp: &dyn ThreadSafeTimestampFn<Output = io::Result<()>>,
157+
mut rd: &mut dyn RecordDecorator,
158+
record: &Record<'_>,
159+
) -> io::Result<bool> {
160+
rd.start_timestamp()?;
161+
fn_timestamp(&mut rd)?;
162+
163+
rd.start_whitespace()?;
164+
write!(rd, " ")?;
165+
166+
rd.start_level()?;
167+
write!(rd, "{}", record.level().as_short_str())?;
168+
169+
rd.start_whitespace()?;
170+
write!(rd, " ")?;
171+
172+
rd.start_msg()?;
173+
write!(rd, "{}:", prefix)?;
174+
175+
rd.start_whitespace()?;
176+
write!(rd, " ")?;
177+
178+
rd.start_msg()?;
179+
let mut count_rd = CountingWriter::new(&mut rd);
180+
write!(count_rd, "{}", record.msg())?;
181+
Ok(count_rd.count() != 0)
182+
}
183+
}

sentry/Cargo.toml

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
[package]
22
name = "sentry"
33
version = "0.1.0"
4-
authors = ["Samparsky"]
4+
authors = ["Omidiora Samuel <[email protected]>"]
55
edition = "2018"
66

7-
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8-
97
[dependencies]
8+
# Futures
9+
futures-preview = { version = "=0.3.0-alpha.19", features = ["compat"]}
10+
# Primitives
1011
primitives = {path = "../primitives"}
12+
adapter = { version = "0.1", path = "../adapter" }
13+
chrono = { version = "0.4", features = ["serde"] }
1114
# CLI
1215
clap = "2.33.0"
16+
# Server
17+
tokio = "0.2.0-alpha.6"
18+
hyper = {version = "=0.13.0-alpha.4", features = ["unstable-stream"]}
19+
regex = "1"
1320
# Logger
1421
slog = { version = "^2.2.3" , features = ["max_level_trace"] }
15-
slog-term = "^2.4.0"
16-
slog-async = "^2.3.0"
17-
# Database
18-
diesel = { version = "1.3", features = ["postgres"] }
22+
# Serde
23+
serde = {version = "^1.0", features = ['derive']}
24+
serde_json = "^1.0"
25+
serde_urlencoded = "0.6.1"
File renamed without changes.

0 commit comments

Comments
 (0)