Skip to content

Commit

Permalink
fix: improve error handling in main
Browse files Browse the repository at this point in the history
  • Loading branch information
hseeberger committed Oct 10, 2023
1 parent 5fdcaa5 commit e8614ae
Show file tree
Hide file tree
Showing 10 changed files with 201 additions and 80 deletions.
174 changes: 118 additions & 56 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ members = [
resolver = "2"

[workspace.package]
rust-version = "1.72.0"
edition = "2021"
authors = [ "Heiko Seeberger <[email protected]>" ]
license = "Apache-2.0"
Expand All @@ -27,6 +26,7 @@ opentelemetry-otlp = { version = "0.12", default-features = false, features =
prost = { version = "0.11" }
serde = { version = "1.0", features = [ "derive" ] }
serde_json = { version = "1.0" }
time = { version = "0.3", features = [ "formatting" ] }
tokio = { version = "1", features = [ "macros", "rt-multi-thread", "signal" ] }
tokio-stream = { version = "0.1", features = [ "fs" ] }
tonic = { version = "0.9" }
Expand Down
2 changes: 1 addition & 1 deletion hello-tracing-backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG RUST_VERSION=1.72.1
ARG RUST_VERSION=1.73.0

FROM rust:${RUST_VERSION}-bullseye AS builder
RUN apt-get update && \
Expand Down
39 changes: 30 additions & 9 deletions hello-tracing-backend/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,42 @@ mod api;

use anyhow::{Context, Result};
use configured::Configured;
use hello_tracing_common::tracing::{init_tracing, TracingConfig};
use hello_tracing_common::{
log_error,
tracing::{init_tracing, TracingConfig},
};
use serde::Deserialize;
use std::panic;
use tracing::{error, info};

#[tokio::main]
async fn main() -> Result<()> {
let config = Config::load().context("load configuration")?;
init_tracing(config.tracing.clone()).context("initialize tracing")?;
async fn main() {
// Load configuration first, because needed for tracing initialization.
let config = match Config::load().context("load configuration") {
Ok(config) => config,
Err(error) => {
log_error(error);
return;
}
};

info!(?config, "starting");
// If tracing initialization fails, nevertheless emit a structured log event.
if let Err(error) = init_tracing(config.tracing.clone()) {
log_error(error);
return;
}

let result = api::serve(config.api).await;
// Replace the default panic hook with one that uses structured logging at ERROR level.
panic::set_hook(Box::new(|panic| error!(%panic, "process panicked")));

if let Err(error) = result {
// Run and log any error.
if let Err(error) = run(config).await {
error!(
error = format!("{error:#}"),
backtrace = %error.backtrace(),
"hello-tracing-backend exited with ERROR"
"process exited with ERROR"
);
};
Ok(())
}

#[derive(Debug, Deserialize)]
Expand All @@ -31,3 +46,9 @@ struct Config {
api: api::Config,
tracing: TracingConfig,
}

async fn run(config: Config) -> Result<()> {
info!(?config, "starting");

api::serve(config.api).await
}
1 change: 1 addition & 0 deletions hello-tracing-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ opentelemetry-otlp = { workspace = true }
prost = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
time = { workspace = true }
tokio = { workspace = true }
tonic = { workspace = true }
tower = { workspace = true }
Expand Down
16 changes: 16 additions & 0 deletions hello-tracing-common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,18 @@
use serde_json::json;
use std::fmt::Display;
use time::{format_description::well_known::Rfc3339, OffsetDateTime};

pub mod otel;
pub mod tracing;

pub fn log_error(error: impl Display) {
let now = OffsetDateTime::now_utc().format(&Rfc3339).unwrap();
let error = serde_json::to_string(&json!({
"timestamp": now,
"level": "ERROR",
"message": "process exited with ERROR",
"error": format!("{error:#}")
}));
// Not using `eprintln!`, because `tracing_subscriber::fmt` uses stdout by default.
println!("{}", error.unwrap());
}
2 changes: 1 addition & 1 deletion hello-tracing-common/src/tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub fn init_tracing(config: TracingConfig) -> Result<()> {

tracing_subscriber::registry()
.with(EnvFilter::from_default_env())
.with(fmt::layer().json())
.with(fmt::layer().json().flatten_event(true))
.with(otlp_layer(config)?)
.try_init()
.context("initialize tracing subscriber")
Expand Down
2 changes: 1 addition & 1 deletion hello-tracing-gateway/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG RUST_VERSION=1.72.1
ARG RUST_VERSION=1.73.0

FROM rust:${RUST_VERSION}-bullseye AS builder
RUN apt-get update && \
Expand Down
2 changes: 1 addition & 1 deletion hello-tracing-gateway/proto
41 changes: 31 additions & 10 deletions hello-tracing-gateway/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,42 @@ mod backend;
use crate::backend::Backend;
use anyhow::{Context, Result};
use configured::Configured;
use hello_tracing_common::tracing::{init_tracing, TracingConfig};
use hello_tracing_common::{
log_error,
tracing::{init_tracing, TracingConfig},
};
use serde::Deserialize;
use std::panic;
use tracing::{error, info};

#[tokio::main]
async fn main() -> Result<()> {
let config = Config::load().context("load configuration")?;
init_tracing(config.tracing.clone()).context("initialize tracing")?;
async fn main() {
// Load configuration first, because needed for tracing initialization.
let config = match Config::load().context("load configuration") {
Ok(config) => config,
Err(error) => {
log_error(error);
return;
}
};

info!(?config, "starting");
// If tracing initialization fails, nevertheless emit a structured log event.
if let Err(error) = init_tracing(config.tracing.clone()) {
log_error(error);
return;
}

let backend = Backend::new(config.backend);
let result = api::serve(config.api, backend).await;
// Replace the default panic hook with one that uses structured logging at ERROR level.
panic::set_hook(Box::new(|panic| error!(%panic, "process panicked")));

if let Err(error) = result {
// Run and log any error.
if let Err(error) = run(config).await {
error!(
error = format!("{error:#}"),
backtrace = %error.backtrace(),
"hello-tracing-gateway exited with ERROR"
"process exited with ERROR"
);
};
Ok(())
}

#[derive(Debug, Deserialize)]
Expand All @@ -35,3 +49,10 @@ struct Config {
backend: backend::Config,
tracing: TracingConfig,
}

async fn run(config: Config) -> Result<()> {
info!(?config, "starting");

let backend = Backend::new(config.backend);
api::serve(config.api, backend).await
}

0 comments on commit e8614ae

Please sign in to comment.