migrate to tracing and remove log
This commit is contained in:
parent
d3a3b1e1f2
commit
88430a3e51
1
.env
1
.env
@ -5,4 +5,5 @@ ACTIX_DEMO_RUST_LOG=debug
|
||||
ACTIX_DEMO_TEST_RUST_LOG=debug
|
||||
ACTIX_DEMO_HTTP_HOST=127.0.0.1
|
||||
ACTIX_DEMO_HASH_COST=8
|
||||
ACTIX_DEMO_LOGGER_FORMAT=plain
|
||||
|
||||
|
194
Cargo.lock
generated
194
Cargo.lock
generated
@ -57,12 +57,10 @@ dependencies = [
|
||||
"diesel",
|
||||
"diesel_migrations",
|
||||
"dotenv",
|
||||
"env_logger",
|
||||
"envy",
|
||||
"futures",
|
||||
"lazy-regex",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"nanoid",
|
||||
"r2d2",
|
||||
"rand 0.8.3",
|
||||
@ -71,6 +69,12 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"timeago",
|
||||
"tracing",
|
||||
"tracing-actix-web",
|
||||
"tracing-bunyan-formatter",
|
||||
"tracing-futures",
|
||||
"tracing-log",
|
||||
"tracing-subscriber",
|
||||
"uuid",
|
||||
"validator",
|
||||
"validator_derive",
|
||||
@ -453,17 +457,6 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.7"
|
||||
@ -975,19 +968,6 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"humantime",
|
||||
"log",
|
||||
"regex",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "envy"
|
||||
version = "0.4.2"
|
||||
@ -1176,6 +1156,16 @@ dependencies = [
|
||||
"version_check 0.9.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gethostname"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e692e296bfac1d2533ef168d0b60ff5897b8b70a4009276834014dd8924cc028"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
@ -1319,12 +1309,6 @@ version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a1ce40d6fc9764887c2fdc7305c3dcc429ba11ff981c1509416afd5697e4437"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.2.3"
|
||||
@ -1529,6 +1513,15 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1"
|
||||
dependencies = [
|
||||
"regex-automata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matches"
|
||||
version = "0.1.8"
|
||||
@ -1700,6 +1693,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.0"
|
||||
@ -2179,6 +2178,16 @@ dependencies = [
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.23"
|
||||
@ -2359,6 +2368,15 @@ dependencies = [
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sharded-slab"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79c719719ee05df97490f80a45acfc99e5a30ce98a1e4fb67aee422745ae14e3"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.3.0"
|
||||
@ -2472,15 +2490,6 @@ dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.24"
|
||||
@ -2501,6 +2510,15 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "threadpool"
|
||||
version = "1.8.1"
|
||||
@ -2627,9 +2645,51 @@ dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"log",
|
||||
"pin-project-lite 0.2.6",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-actix-web"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc36fc2f840643e49d220d07cd7ca81bc31c7f6df25f164d4257971533dab354"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"futures",
|
||||
"tracing",
|
||||
"tracing-futures",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-bunyan-formatter"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dce1eae70720bd6bb3944f7cf501761aeae658bd1f9293aa373c71a195064910"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"gethostname",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.17"
|
||||
@ -2649,6 +2709,49 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"log",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-serde"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa5553bf0883ba7c9cbe493b085c29926bd41b66afc31ff72cf17ff4fb60dcd5"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"chrono",
|
||||
"lazy_static",
|
||||
"matchers",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sharded-slab",
|
||||
"smallvec",
|
||||
"thread_local",
|
||||
"tracing",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
"tracing-serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "trust-dns-proto"
|
||||
version = "0.19.7"
|
||||
@ -2959,15 +3062,6 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
|
@ -11,8 +11,6 @@ actix-files = "0.5.0"
|
||||
actix-http = "2.2.0"
|
||||
bytes = "1.0.1"
|
||||
futures = "0.3.14"
|
||||
log = "0.4.14"
|
||||
env_logger = "0.8.3"
|
||||
serde_json = "1.0.64"
|
||||
# json = "0.12.4"
|
||||
# listenfd = "0.3.3"
|
||||
@ -36,6 +34,12 @@ derive-new = "0.5.9"
|
||||
diesel_migrations = "1.4.0"
|
||||
actix-threadpool = "0.3.3"
|
||||
envy = "0.4"
|
||||
tracing = { version = "0.1" }
|
||||
tracing-log = "0.1.2"
|
||||
tracing-subscriber = { version = "0.2.18", features = ["fmt", "registry", "env-filter"] }
|
||||
tracing-futures = "0.2.5"
|
||||
tracing-actix-web = "0.2.1"
|
||||
tracing-bunyan-formatter = "0.2.4"
|
||||
|
||||
[dependencies.build-info]
|
||||
version = "=0.0.23"
|
||||
|
@ -44,7 +44,7 @@ impl ResponseError for DomainError {
|
||||
})
|
||||
}
|
||||
DomainError::DbError { source: _ } => {
|
||||
log::error!("{}", err);
|
||||
tracing::error!("{}", err);
|
||||
HttpResponse::InternalServerError().json(ErrorModel {
|
||||
// error_code: 500,
|
||||
success: false,
|
||||
@ -52,7 +52,7 @@ impl ResponseError for DomainError {
|
||||
})
|
||||
}
|
||||
DomainError::DbPoolError { source: _ } => {
|
||||
log::error!("{}", err);
|
||||
tracing::error!("{}", err);
|
||||
HttpResponse::InternalServerError().json(ErrorModel {
|
||||
// error_code: 500,
|
||||
success: false,
|
||||
@ -67,14 +67,14 @@ impl ResponseError for DomainError {
|
||||
})
|
||||
}
|
||||
DomainError::EntityDoesNotExistError { message: _ } => {
|
||||
HttpResponse::Accepted().json(ErrorModel {
|
||||
HttpResponse::NotFound().json(ErrorModel {
|
||||
// error_code: 400,
|
||||
success: false,
|
||||
reason: err.to_string(),
|
||||
})
|
||||
}
|
||||
DomainError::ThreadPoolError { message: _ } => {
|
||||
log::error!("{}", err);
|
||||
tracing::error!("{}", err);
|
||||
HttpResponse::InternalServerError().json(ErrorModel {
|
||||
// error_code: 400,
|
||||
success: false,
|
||||
@ -82,7 +82,7 @@ impl ResponseError for DomainError {
|
||||
})
|
||||
}
|
||||
DomainError::AuthError { message: _ } => {
|
||||
HttpResponse::Accepted().json(ErrorModel {
|
||||
HttpResponse::Forbidden().json(ErrorModel {
|
||||
// error_code: 400,
|
||||
success: false,
|
||||
reason: err.to_string(),
|
||||
|
22
src/lib.rs
22
src/lib.rs
@ -16,21 +16,31 @@ mod utils;
|
||||
|
||||
use actix_files as fs;
|
||||
use actix_identity::{CookieIdentityPolicy, IdentityService};
|
||||
use actix_web::{cookie::SameSite, middleware, web, App, HttpServer};
|
||||
use actix_web::{middleware::Logger, web::ServiceConfig};
|
||||
use actix_web::web::ServiceConfig;
|
||||
use actix_web::{cookie::SameSite, web, App, HttpServer};
|
||||
use rand::Rng;
|
||||
use serde::Deserialize;
|
||||
use std::io;
|
||||
use tracing_actix_web::TracingLogger;
|
||||
|
||||
use types::DbPool;
|
||||
|
||||
build_info::build_info!(pub fn get_build_info);
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum LoggerFormat {
|
||||
Json,
|
||||
Plain,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct EnvConfig {
|
||||
pub database_url: String,
|
||||
pub http_host: String,
|
||||
#[serde(default = "default_hash_cost")]
|
||||
pub hash_cost: u8,
|
||||
pub logger_format: LoggerFormat,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
@ -91,13 +101,9 @@ pub fn id_service(
|
||||
)
|
||||
}
|
||||
|
||||
pub fn app_logger() -> Logger {
|
||||
middleware::Logger::default()
|
||||
}
|
||||
|
||||
pub async fn run(addr: String, app_data: AppData) -> io::Result<()> {
|
||||
let bi = get_build_info();
|
||||
log::info!("Starting {} {}", bi.crate_info.name, bi.crate_info.version);
|
||||
tracing::info!("Starting {} {}", bi.crate_info.name, bi.crate_info.version);
|
||||
println!(
|
||||
r#"
|
||||
__ .__ .___
|
||||
@ -113,7 +119,7 @@ pub async fn run(addr: String, app_data: AppData) -> io::Result<()> {
|
||||
App::new()
|
||||
.configure(configure_app(app_data.clone()))
|
||||
.wrap(id_service(&private_key))
|
||||
.wrap(app_logger())
|
||||
.wrap(TracingLogger)
|
||||
};
|
||||
HttpServer::new(app).bind(addr)?.run().await
|
||||
}
|
||||
|
77
src/main.rs
77
src/main.rs
@ -1,9 +1,15 @@
|
||||
#![forbid(unsafe_code)]
|
||||
use actix_demo::{AppConfig, AppData, EnvConfig};
|
||||
use actix_demo::{AppConfig, AppData, EnvConfig, LoggerFormat};
|
||||
use diesel::{r2d2::ConnectionManager, SqliteConnection};
|
||||
use env_logger::Env;
|
||||
use io::ErrorKind;
|
||||
use std::io;
|
||||
use tracing::subscriber::set_global_default;
|
||||
use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer};
|
||||
use tracing_log::LogTracer;
|
||||
use tracing_subscriber::fmt::format::FmtSpan;
|
||||
use tracing_subscriber::{
|
||||
layer::SubscriberExt, EnvFilter, FmtSubscriber, Registry,
|
||||
};
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> io::Result<()> {
|
||||
@ -14,16 +20,6 @@ async fn main() -> io::Result<()> {
|
||||
)
|
||||
})?;
|
||||
|
||||
let _ = env_logger::try_init_from_env(
|
||||
Env::default().filter("ACTIX_DEMO_RUST_LOG"),
|
||||
)
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Failed to set up env logger: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
|
||||
let env_config = envy::prefixed("ACTIX_DEMO_")
|
||||
.from_env::<EnvConfig>()
|
||||
.map_err(|err| {
|
||||
@ -33,6 +29,8 @@ async fn main() -> io::Result<()> {
|
||||
)
|
||||
})?;
|
||||
|
||||
let _ = setup_logger(env_config.logger_format)?;
|
||||
|
||||
let connspec = &env_config.database_url;
|
||||
let manager = ConnectionManager::<SqliteConnection>::new(connspec);
|
||||
let pool = r2d2::Pool::builder().build(manager).map_err(|err| {
|
||||
@ -68,3 +66,58 @@ async fn main() -> io::Result<()> {
|
||||
|
||||
actix_demo::run(format!("{}:7800", env_config.http_host), app_data).await
|
||||
}
|
||||
|
||||
pub fn setup_logger(format: LoggerFormat) -> io::Result<()> {
|
||||
let env_filter =
|
||||
EnvFilter::try_from_env("ACTIX_DEMO_RUST_LOG").map_err(|err| {
|
||||
io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Failed to set up env filter: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
|
||||
let _ = LogTracer::init().map_err(|err| {
|
||||
io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Failed to set up log tracer: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
|
||||
let bi = actix_demo::get_build_info();
|
||||
|
||||
let _ = match format {
|
||||
LoggerFormat::Json => {
|
||||
let formatting_layer = BunyanFormattingLayer::new(
|
||||
format!("actix-demo-{}", bi.crate_info.version),
|
||||
// Output the formatted spans to stdout.
|
||||
std::io::stdout,
|
||||
);
|
||||
let subscriber = Registry::default()
|
||||
.with(env_filter)
|
||||
.with(JsonStorageLayer)
|
||||
.with(formatting_layer);
|
||||
let _ = set_global_default(subscriber).map_err(|err| {
|
||||
io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Failed to set subscriber: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
}
|
||||
|
||||
LoggerFormat::Plain => {
|
||||
let subscriber = FmtSubscriber::builder()
|
||||
.pretty()
|
||||
.with_span_events(FmtSpan::NEW)
|
||||
.with_span_events(FmtSpan::CLOSE)
|
||||
.with_env_filter(env_filter)
|
||||
.finish();
|
||||
let _ = set_global_default(subscriber).map_err(|err| {
|
||||
io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Failed to set subscriber: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ pub async fn login(
|
||||
response
|
||||
}
|
||||
|
||||
//TODO: fix the response
|
||||
#[get("/logout")]
|
||||
pub async fn logout(
|
||||
id: Identity,
|
||||
@ -45,7 +46,7 @@ pub async fn logout(
|
||||
) -> Result<HttpResponse, Error> {
|
||||
let maybe_identity = id.identity();
|
||||
let response = if let Some(identity) = maybe_identity {
|
||||
log::info!("Logging out {user}", user = identity);
|
||||
tracing::info!("Logging out {user}", user = identity);
|
||||
id.forget();
|
||||
HttpResponse::Found().header("location", "/").finish()
|
||||
} else {
|
||||
|
@ -7,11 +7,19 @@ use actix_web::error::ResponseError;
|
||||
use validator::Validate;
|
||||
|
||||
/// Finds user by UID.
|
||||
#[tracing::instrument(
|
||||
level = "debug",
|
||||
skip(app_data),
|
||||
fields(
|
||||
user_id = %user_id.0
|
||||
)
|
||||
)]
|
||||
pub async fn get_user(
|
||||
app_data: web::Data<AppData>,
|
||||
user_id: web::Path<i32>,
|
||||
) -> Result<HttpResponse, DomainError> {
|
||||
let u_id = user_id.into_inner();
|
||||
tracing::info!("Getting user with id {}", u_id);
|
||||
// use web::block to offload blocking Diesel code without blocking server thread
|
||||
let res = web::block(move || {
|
||||
let pool = &app_data.pool;
|
||||
@ -20,6 +28,7 @@ pub async fn get_user(
|
||||
})
|
||||
.await
|
||||
.map_err(|err| DomainError::new_thread_pool_error(err.to_string()))?;
|
||||
tracing::trace!("{:?}", res);
|
||||
if let Some(user) = res {
|
||||
Ok(HttpResponse::Ok().json(user))
|
||||
} else {
|
||||
@ -61,7 +70,7 @@ pub async fn get_all_users(
|
||||
.await
|
||||
.map_err(|err| DomainError::new_thread_pool_error(err.to_string()))?;
|
||||
|
||||
log::debug!("{:?}", users);
|
||||
tracing::debug!("{:?}", users);
|
||||
|
||||
if !users.is_empty() {
|
||||
Ok(HttpResponse::Ok().json(users))
|
||||
@ -87,7 +96,7 @@ pub async fn add_user(
|
||||
})
|
||||
.await
|
||||
.map(|user| {
|
||||
log::debug!("{:?}", user);
|
||||
tracing::debug!("{:?}", user);
|
||||
HttpResponse::Created().json(user)
|
||||
}),
|
||||
|
||||
|
@ -2,5 +2,3 @@ pub mod auth;
|
||||
pub mod regexs;
|
||||
pub use self::auth::*;
|
||||
pub use self::regexs::*;
|
||||
pub mod ops;
|
||||
pub use self::ops::*;
|
||||
|
@ -1,34 +0,0 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
pub trait LogErrorResult<T, E> {
|
||||
fn log_err(self) -> Result<T, E>;
|
||||
}
|
||||
impl<T, E: Display> LogErrorResult<T, E> for Result<T, E> {
|
||||
fn log_err(self) -> Result<T, E> {
|
||||
self.map_err(|err| {
|
||||
log::error!("{}", err.to_string());
|
||||
err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
trait ResultOps<T, E> {
|
||||
fn tap<U, F: FnOnce(T) -> U>(self, op: F) -> Result<T, E>;
|
||||
fn tap_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T, E>;
|
||||
}
|
||||
|
||||
impl<T: Clone, E: Clone> ResultOps<T, E> for Result<T, E> {
|
||||
fn tap<U, F: FnOnce(T) -> U>(self, op: F) -> Result<T, E> {
|
||||
self.map(|x| {
|
||||
op(x.clone());
|
||||
x
|
||||
})
|
||||
}
|
||||
|
||||
fn tap_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T, E> {
|
||||
self.map_err(|err| {
|
||||
op(err.clone());
|
||||
err
|
||||
})
|
||||
}
|
||||
}
|
@ -1,59 +1,92 @@
|
||||
extern crate actix_demo;
|
||||
use actix_demo::{AppConfig, AppData};
|
||||
use actix_demo::{AppConfig, AppData, EnvConfig};
|
||||
use actix_web::test;
|
||||
use actix_web::App;
|
||||
use diesel::SqliteConnection;
|
||||
|
||||
use diesel::r2d2::{self, ConnectionManager};
|
||||
use env_logger::Env;
|
||||
use std::io;
|
||||
use std::io::ErrorKind;
|
||||
use tracing::subscriber::set_global_default;
|
||||
use tracing_actix_web::TracingLogger;
|
||||
use tracing_log::LogTracer;
|
||||
use tracing_subscriber::fmt::{format::FmtSpan, Subscriber as FmtSubscriber};
|
||||
use tracing_subscriber::{layer::SubscriberExt, EnvFilter};
|
||||
|
||||
use actix_demo::configure_app;
|
||||
|
||||
use actix_http::Request;
|
||||
use actix_web::{dev as ax_dev, Error as AxError};
|
||||
|
||||
pub async fn test_app() -> impl ax_dev::Service<
|
||||
pub async fn test_app() -> io::Result<
|
||||
impl ax_dev::Service<
|
||||
Request = Request,
|
||||
Response = ax_dev::ServiceResponse<impl ax_dev::MessageBody>,
|
||||
Error = AxError,
|
||||
>,
|
||||
> {
|
||||
let _ = dotenv::dotenv()
|
||||
.map_err(|err| {
|
||||
let _ = dotenv::dotenv().map_err(|err| {
|
||||
io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Failed to set up env: {:?}", err),
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
let _ = env_logger::builder()
|
||||
.is_test(true)
|
||||
.parse_env(Env::default().filter("ACTIX_DEMO_TEST_RUST_LOG"))
|
||||
.try_init();
|
||||
})?;
|
||||
|
||||
let _ = envy::prefixed("ACTIX_DEMO_")
|
||||
.from_env::<EnvConfig>()
|
||||
.map_err(|err| {
|
||||
io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Failed to parse config: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
|
||||
let env_filter =
|
||||
EnvFilter::try_from_env("ACTIX_DEMO_RUST_LOG").map_err(|err| {
|
||||
io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Failed to set up env logger: {:?}", err),
|
||||
)
|
||||
})?;
|
||||
|
||||
let _ = LogTracer::init().map_err(|err| {
|
||||
io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Failed to set up log tracer: {:?}", err),
|
||||
)
|
||||
});
|
||||
|
||||
let subscriber = FmtSubscriber::builder()
|
||||
.pretty()
|
||||
.with_test_writer()
|
||||
.with_span_events(FmtSpan::NEW)
|
||||
.with_span_events(FmtSpan::CLOSE)
|
||||
.finish()
|
||||
.with(env_filter);
|
||||
|
||||
let _ = set_global_default(subscriber).map_err(|err| {
|
||||
io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Failed to set subscriber: {:?}", err),
|
||||
)
|
||||
});
|
||||
|
||||
let connspec = ":memory:";
|
||||
let manager = ConnectionManager::<SqliteConnection>::new(connspec);
|
||||
let pool = r2d2::Pool::builder()
|
||||
.build(manager)
|
||||
.map_err(|err| {
|
||||
let pool = r2d2::Pool::builder().build(manager).map_err(|err| {
|
||||
io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Failed to create pool: {:?}", err),
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
})?;
|
||||
|
||||
let _ = {
|
||||
let conn = &pool
|
||||
.get()
|
||||
.map_err(|err| {
|
||||
let conn = &pool.get().map_err(|err| {
|
||||
io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Failed to get connection: {:?}", err),
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
})?;
|
||||
|
||||
let migrations_dir = diesel_migrations::find_migrations_directory()
|
||||
.map_err(|err| {
|
||||
@ -61,8 +94,7 @@ pub async fn test_app() -> impl ax_dev::Service<
|
||||
ErrorKind::Other,
|
||||
format!("Error finding migrations dir: {:?}", err),
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
})?;
|
||||
let _ = diesel_migrations::run_pending_migrations_in_directory(
|
||||
conn,
|
||||
&migrations_dir,
|
||||
@ -73,17 +105,16 @@ pub async fn test_app() -> impl ax_dev::Service<
|
||||
ErrorKind::Other,
|
||||
format!("Error running migrations: {:?}", err),
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
})?;
|
||||
};
|
||||
|
||||
test::init_service(
|
||||
Ok(test::init_service(
|
||||
App::new()
|
||||
.configure(configure_app(AppData {
|
||||
config: AppConfig { hash_cost: 8 },
|
||||
pool,
|
||||
}))
|
||||
.wrap(actix_web::middleware::Logger::default()),
|
||||
.wrap(TracingLogger),
|
||||
)
|
||||
.await
|
||||
.await)
|
||||
}
|
||||
|
@ -12,10 +12,10 @@ mod tests {
|
||||
#[actix_rt::test]
|
||||
async fn get_build_info_should_succeed() {
|
||||
let req = test::TestRequest::get().uri("/api/build-info").to_request();
|
||||
let resp = common::test_app().await.call(req).await.unwrap();
|
||||
let resp = common::test_app().await.unwrap().call(req).await.unwrap();
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
let body: build_info::BuildInfo = test::read_body_json(resp).await;
|
||||
tracing::debug!("{:?}", body);
|
||||
assert_eq!(body, *get_build_info());
|
||||
log::debug!("{:?}", body);
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,10 @@ mod tests {
|
||||
#[actix_rt::test]
|
||||
async fn get_users_api_should_return_error_message_if_no_users_exist() {
|
||||
let req = test::TestRequest::get().uri("/api/users").to_request();
|
||||
let resp = common::test_app().await.call(req).await.unwrap();
|
||||
assert_eq!(resp.status(), StatusCode::ACCEPTED);
|
||||
let resp = common::test_app().await.unwrap().call(req).await.unwrap();
|
||||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||
let body: ErrorModel = test::read_body_json(resp).await;
|
||||
tracing::debug!("{:?}", body);
|
||||
assert_eq!(
|
||||
body,
|
||||
ErrorModel {
|
||||
@ -21,16 +22,16 @@ mod tests {
|
||||
reason: "Entity does not exist - No users available".to_owned()
|
||||
}
|
||||
);
|
||||
log::debug!("{:?}", body);
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn get_user_api_should_return_error_message_if_user_with_id_does_not_exist(
|
||||
) {
|
||||
let req = test::TestRequest::get().uri("/api/users/1").to_request();
|
||||
let resp = common::test_app().await.call(req).await.unwrap();
|
||||
assert_eq!(resp.status(), StatusCode::ACCEPTED);
|
||||
let resp = common::test_app().await.unwrap().call(req).await.unwrap();
|
||||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||
let body: ErrorModel = test::read_body_json(resp).await;
|
||||
tracing::debug!("{:?}", body);
|
||||
assert_eq!(
|
||||
body,
|
||||
ErrorModel {
|
||||
@ -39,6 +40,5 @@ mod tests {
|
||||
.to_owned()
|
||||
}
|
||||
);
|
||||
log::debug!("{:?}", body);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user