Skip to content

Commit

Permalink
Implement proper logging instead of using println!() everywhere
Browse files Browse the repository at this point in the history
  • Loading branch information
Luflosi committed Apr 23, 2024
1 parent 25c22da commit b0c5c9d
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 18 deletions.
69 changes: 69 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ license = "AGPL-3.0-only"
[dependencies]
argon2 = { version = "0.5", features = ["std"] }
clap = { version = "4.5", features = ["derive"] }
env_logger = "0.11"
error-chain = "0.12"
log = "0.4"
serde = "1.0"
serde_derive = "1.0"
tokio = { version = "1", features = ["full"] }
Expand All @@ -24,6 +26,8 @@ unsafe_code = "forbid"

[lints.clippy]
enum_glob_use = "warn"
pedantic = "warn"
nursery = "warn"
pedantic = "warn"
print_stdout = "warn"
unwrap_used = "warn"
use_debug = "warn"
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ If you would like to see any of the following TODO items implemented, please fil
- Test on platforms other than `x86_64-linux`
- Use systemd socket activation for lower resource usage
- Support HTTP basic auth
- Implement proper logging with different log levels to reduce log spam
- Improve documentation
- Add some simpler tests in Rust in addition to the NixOS test
- Make use of the `ipv6lanprefix` sent by FRITZ!Boxes
Expand Down
32 changes: 32 additions & 0 deletions src/logging.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-FileCopyrightText: 2024 Luflosi <[email protected]>
// SPDX-License-Identifier: AGPL-3.0-only

use env_logger::{Builder, Env};
use std::io::Write;

pub fn setup() {
let env = Env::default().filter_or("RUST_LOG", "dyndnsd=info");

match std::env::var("RUST_LOG_STYLE") {
Ok(s) if s == "SYSTEMD" => Builder::from_env(env)
.format(|buf, record| {
for line in record.args().to_string().lines() {
writeln!(
buf,
"<{}>{}: {}",
match record.level() {
log::Level::Error => 3,
log::Level::Warn => 4,
log::Level::Info => 6,
log::Level::Debug | log::Level::Trace => 7,
},
record.target(),
line
)?;
}
Ok(())
})
.init(),
_ => env_logger::init_from_env(env),
}
}
16 changes: 10 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
// SPDX-FileCopyrightText: 2024 Luflosi <[email protected]>
// SPDX-License-Identifier: AGPL-3.0-only

mod config;
mod logging;
mod process;

#[macro_use]
extern crate error_chain;

use crate::config::Config;
use crate::process::{update, QueryParameters};
use clap::Parser;
use log::{error, info};
use warp::Filter;

mod config;
mod process;

#[derive(Parser, Debug)]
#[command(version)]
struct Args {
Expand All @@ -22,16 +24,18 @@ struct Args {

#[tokio::main]
async fn main() {
logging::setup();

let args = Args::parse();

let config = match Config::read(&args.config) {
Ok(v) => v,
Err(e) => {
eprintln!("ERROR: {e}");
error!("ERROR: {e}");

/////// look at the chain of errors... ///////
for e in e.iter().skip(1) {
eprintln!("caused by: {e}");
error!("caused by: {e}");
}

std::process::exit(1);
Expand All @@ -45,6 +49,6 @@ async fn main() {
.and(warp::query::<QueryParameters>())
.map(move |q: QueryParameters| update(&config, &q));

println!("Listening on {listen}");
info!("Listening on {listen}");
warp::serve(update).run(listen).await;
}
22 changes: 12 additions & 10 deletions src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use crate::config::{Config, User};
use argon2::{password_hash::PasswordVerifier, Argon2};
use log::{debug, error, info, trace, warn};
use serde_derive::Deserialize;
use std::io::Write;
use std::net::{Ipv4Addr, Ipv6Addr};
Expand All @@ -11,7 +12,7 @@ use warp::{http::StatusCode, Reply};

#[derive(Deserialize)]
pub struct QueryParameters {
domain: Option<String>,
domain: Option<String>, // Ignored, we use the username to determine the list of domains to be updated
user: String,
pass: String,
ipv4: Option<Ipv4Addr>,
Expand All @@ -36,7 +37,7 @@ fn build_command_string(config: &Config, user: &User, q: &QueryParameters) -> St
command.push_str(config.update_program.initial_stdin.as_str());
let domains = &user.domains;
for (domain, props) in domains {
println!("{domain:?} {props:?}");
trace!("Domain: {domain:?} {props:?}");
let ttl = &props.ttl.to_string();
if let Some(ipv4) = q.ipv4 {
let ipv4 = &ipv4.to_string();
Expand All @@ -53,7 +54,7 @@ fn build_command_string(config: &Config, user: &User, q: &QueryParameters) -> St
}
if let Some(prefix) = q.ipv6 {
if props.ipv6prefixlen == 0 {
println!("IPv6 prefix length for domain {domain} is zero, ignoring update to IPv6 address");
warn!("IPv6 prefix length for domain {domain} is zero, ignoring update to IPv6 address");
} else {
let assembled_addr =
splice_ipv6_addrs(props.ipv6prefixlen, prefix, props.ipv6suffix);
Expand All @@ -73,12 +74,13 @@ fn build_command_string(config: &Config, user: &User, q: &QueryParameters) -> St
command.push_str(config.update_program.stdin_per_zone_update.as_str());
}
command.push_str(config.update_program.final_stdin.as_str());
println!("{command}");
debug!("Commands for update program:\n{command}");
command
}

pub fn update(config: &Config, q: &QueryParameters) -> Result<impl Reply, impl Reply> {
println!("domain: {:?}, user: {:?}, pass: <redacted>, ipv4: {:?}, ipv6: {:?}, dualstack: {:?}, ipv6lanprefix: {:?}", &q.domain, &q.user, &q.ipv4, &q.ipv6, &q.dualstack, &q.ipv6lanprefix);
info!("Incoming request from user `{}`", &q.user);
debug!("domain: {:?}, user: {:?}, pass: <redacted>, ipv4: {:?}, ipv6: {:?}, dualstack: {:?}, ipv6lanprefix: {:?}", &q.domain, &q.user, &q.ipv4, &q.ipv6, &q.dualstack, &q.ipv6lanprefix);

let Some(user) = config.users.get(&q.user) else {
eprintln!("User {} does not exist.", q.user);
Expand All @@ -96,7 +98,7 @@ pub fn update(config: &Config, q: &QueryParameters) -> Result<impl Reply, impl R
));
};

println!("Authentication successful");
info!("Authentication successful");

let command = build_command_string(config, user, q);

Expand Down Expand Up @@ -137,20 +139,20 @@ pub fn update(config: &Config, q: &QueryParameters) -> Result<impl Reply, impl R

let status = output.status;
if !status.success() {
println!("The update program failed with {status}");
error!("The update program failed with {status}");
let stdout = String::from_utf8_lossy(&output.stdout);
if !stdout.is_empty() {
println!("and stdout: `{stdout}`");
error!("and stdout: `{stdout}`");
}
let stderr = String::from_utf8_lossy(&output.stderr);
if !stderr.is_empty() {
println!("and stderr: `{stderr}`");
error!("and stderr: `{stderr}`");
}
return Err(warp::reply::with_status(
"ERROR".to_string(),
StatusCode::INTERNAL_SERVER_ERROR,
));
}
println!("Success");
info!("Successfully processed update request");
Ok(warp::reply::with_status("ok".to_string(), StatusCode::OK))
}
5 changes: 5 additions & 0 deletions systemd/dyndnsd.service
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,10 @@ SystemCallFilter=~@privileged
Type=simple
UMask=0077

Environment="RUST_LOG_STYLE=SYSTEMD"

# Uncomment for maximum verbosity
#Environment="RUST_LOG=dyndnsd=trace"

[Install]
WantedBy=multi-user.target

0 comments on commit b0c5c9d

Please sign in to comment.