Skip to content

Commit 3e9cc6b

Browse files
majectymergify[bot]
authored andcommitted
Send an email when logging an error message
1 parent 7a81e14 commit 3e9cc6b

File tree

10 files changed

+596
-78
lines changed

10 files changed

+596
-78
lines changed

Cargo.lock

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

codechain/codechain.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,23 @@ args:
286286
value_name: PATH
287287
help: Specify the path for the network blacklist file.
288288
takes_value: true
289+
- no-email-alarm:
290+
long: no-email-alarm
291+
help: Do not use email alarm
292+
- email-alarm-to:
293+
long: email-alarm-to
294+
value_name: EMAIL
295+
help: Specify the email address to receive the alarm.
296+
takes_value: true
297+
conflicts_with:
298+
- no-email-alarm
299+
- email-alarm-sendgrid-key:
300+
long: email-alarm-sendgrid-key
301+
value_name: KEY
302+
help: Specify the sendgrid key which is used to send alarms.
303+
takes_value: true
304+
conflicts_with:
305+
- no-email-alarm
289306
subcommands:
290307
- account:
291308
about: account managing commands

codechain/config/presets/config.dev.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,6 @@ path = "snapshot"
5757
[stratum]
5858
disable = false
5959
port = 8008
60+
61+
[email_alarm]
62+
disable = true

codechain/config/presets/config.prod.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,6 @@ path = "snapshot"
5757
[stratum]
5858
disable = true
5959
port = 8008
60+
61+
[email_alarm]
62+
disable = true

codechain/run_node.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use ckey::{Address, NetworkId, PlatformAddress};
2828
use ckeystore::accounts_dir::RootDiskDirectory;
2929
use ckeystore::KeyStore;
3030
use clap::ArgMatches;
31-
use clogger::{self, LoggerConfig};
31+
use clogger::{self, EmailAlarmConfig, LoggerConfig};
3232
use cnetwork::{Filters, NetworkConfig, NetworkControl, NetworkService, RoutingTable, SocketAddr};
3333
use csync::{BlockSyncExtension, BlockSyncSender, SnapshotService, TransactionSyncExtension};
3434
use ctimer::TimerLoop;
@@ -238,7 +238,17 @@ pub fn run_node(matches: &ArgMatches) -> Result<(), String> {
238238
.expect("Current time should be later than unix epoch")
239239
.subsec_nanos() as usize,
240240
);
241-
clogger::init(&LoggerConfig::new(instance_id)).expect("Logger must be successfully initialized");
241+
let email_alarm_config = if !config.email_alarm.disable.unwrap() {
242+
match (&config.email_alarm.to, &config.email_alarm.sendgrid_key) {
243+
(Some(to), Some(sendgrid_key)) => Some(EmailAlarmConfig::new(to.to_string(), sendgrid_key.to_string())),
244+
(None, _) => return Err("email-alarm-to is not specified".to_string()),
245+
(_, None) => return Err("email-alarm-sendgrid-key is not specified".to_string()),
246+
}
247+
} else {
248+
None
249+
};
250+
clogger::init(&LoggerConfig::new(instance_id), &email_alarm_config)
251+
.expect("Logger must be successfully initialized");
242252

243253
let pf = load_password_file(&config.operating.password_path)?;
244254
let base_path = config.operating.base_path.as_ref().unwrap().clone();

codechain/subcommand/account_command.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub fn run_account_command(matches: &ArgMatches) -> Result<(), String> {
3636
return Ok(())
3737
}
3838

39-
clogger::init(&LoggerConfig::new(0)).expect("Logger must be successfully initialized");
39+
clogger::init(&LoggerConfig::new(0), &None).expect("Logger must be successfully initialized");
4040

4141
let keys_path = get_global_argument(matches, "keys-path").unwrap_or_else(|| DEFAULT_KEYS_PATH.into());
4242
let dir = RootDiskDirectory::create(keys_path).expect("Cannot read key path directory");

util/logger/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ env_logger = "0.6.0"
1010
lazy_static = "1.2"
1111
log = "0.4.6"
1212
parking_lot = "0.6.0"
13+
sendgrid = "0.8.1"
1314
serde = "1.0"
1415
serde_derive = "1.0"
1516
serde_json = "1.0"

util/logger/src/email.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use sendgrid::v3 as sendgrid;
2+
3+
pub struct EmailAlarmConfig {
4+
pub to: String,
5+
pub sendgrid_key: String,
6+
}
7+
8+
impl EmailAlarmConfig {
9+
pub fn new(to: String, sendgrid_key: String) -> Self {
10+
Self {
11+
to,
12+
sendgrid_key,
13+
}
14+
}
15+
}
16+
17+
pub struct EmailAlarm {
18+
pub to: String,
19+
pub sendgrid_key: String,
20+
}
21+
22+
impl EmailAlarm {
23+
pub fn new(config: &EmailAlarmConfig) -> Self {
24+
Self {
25+
to: config.to.clone(),
26+
sendgrid_key: config.sendgrid_key.clone(),
27+
}
28+
}
29+
30+
pub fn send(&self, log: &str) {
31+
let p = sendgrid::Personalization::new().add_to(sendgrid::Email::new().set_email(&self.to));
32+
let now = time::now_utc();
33+
let now = now.rfc3339();
34+
let m = sendgrid::Message::new()
35+
.set_from(sendgrid::Email::new().set_email("[email protected]"))
36+
// FIXME: fill the network id
37+
.set_subject(&format!("[error][?c][codechain] Error from CodeChain-{}", now))
38+
.add_content(sendgrid::Content::new().set_content_type("text/html").set_value(log))
39+
.add_personalization(p);
40+
let sender = sendgrid::Sender::new(self.sendgrid_key.clone());
41+
let send_result = sender.send(&m);
42+
if let Err(err) = send_result {
43+
eprintln!("Sent an email, but failed. returned error is {}", err);
44+
}
45+
}
46+
}

util/logger/src/lib.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ extern crate env_logger;
2020
extern crate lazy_static;
2121
extern crate log;
2222
extern crate parking_lot;
23+
extern crate sendgrid;
2324
extern crate serde;
2425
extern crate serde_derive;
2526
extern crate serde_json;
2627
extern crate time;
2728

29+
mod email;
2830
mod logger;
2931
mod macros;
3032
mod structured_logger;
@@ -36,8 +38,9 @@ use logger::Logger;
3638

3739
pub use log::Level;
3840

39-
pub fn init(config: &LoggerConfig) -> Result<(), SetLoggerError> {
40-
let logger = Logger::new(config);
41+
pub fn init(config: &LoggerConfig, email_alarm_config: &Option<EmailAlarmConfig>) -> Result<(), SetLoggerError> {
42+
let email_alarm = email_alarm_config.as_ref().map(EmailAlarm::new);
43+
let logger = Logger::new(config, email_alarm);
4144
log::set_max_level(logger.filter());
4245
log::set_boxed_logger(Box::new(logger))
4346
}
@@ -49,3 +52,6 @@ use lazy_static::lazy_static;
4952
lazy_static! {
5053
pub static ref SLOGGER: StructuredLogger = StructuredLogger::create();
5154
}
55+
56+
use email::EmailAlarm;
57+
pub use email::EmailAlarmConfig;

util/logger/src/logger.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ use time;
2121
use atty;
2222
use colored::Colorize;
2323
use env_logger::filter::{Builder as FilterBuilder, Filter};
24-
use log::{LevelFilter, Log, Metadata, Record};
24+
use log::{Level, LevelFilter, Log, Metadata, Record};
2525

26-
use crate::{structured_logger, SLOGGER};
26+
use crate::{email::EmailAlarm, structured_logger, SLOGGER};
2727

2828
pub struct Config {
2929
pub instance_id: usize,
@@ -41,10 +41,11 @@ pub struct Logger {
4141
instance_id: usize,
4242
filter: Filter,
4343
stderr_is_tty: bool,
44+
email_alarm: Option<EmailAlarm>,
4445
}
4546

4647
impl Logger {
47-
pub fn new(config: &Config) -> Self {
48+
pub fn new(config: &Config, email_alarm: Option<EmailAlarm>) -> Self {
4849
let mut builder = FilterBuilder::new();
4950
builder.filter(None, LevelFilter::Info);
5051

@@ -58,6 +59,7 @@ impl Logger {
5859
instance_id: config.instance_id,
5960
filter: builder.build(),
6061
stderr_is_tty,
62+
email_alarm,
6163
}
6264
}
6365

@@ -103,8 +105,14 @@ impl Log for Logger {
103105
target: log_target.to_string(),
104106
message: log_message.to_string(),
105107
timestamp,
106-
thread_name,
108+
thread_name: thread_name.clone(),
107109
});
110+
111+
if log_level == Level::Error {
112+
if let Some(email_alarm) = &self.email_alarm {
113+
email_alarm.send(&format!("{} {} {}", thread_name, log_target, log_message))
114+
}
115+
}
108116
}
109117
}
110118

0 commit comments

Comments
 (0)