diff --git a/Cargo.toml b/Cargo.toml index 7b4ac161..6d9fa877 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,10 +31,8 @@ figlet-rs = "0.1.3" config_rs = { package = "config", version = "0.11.0", features = ["toml"] } tracing = "0.1" -tracing-log = "0.1" tracing-appender = "0.2" -tracing-subscriber = { version = "0.3", features = ["registry", "env-filter"] } -tracing-bunyan-formatter = "0.3" +tracing-subscriber = { version = "0.3", features = ["json", "env-filter"] } tracing-actix-web = "0.2" fluent-templates = "0.6.1" diff --git a/config/settings.default.toml b/config/settings.default.toml index aea77e5e..3a4fb0ff 100644 --- a/config/settings.default.toml +++ b/config/settings.default.toml @@ -1,10 +1,12 @@ [app] name = "PageTop Application" description = "Developed with the amazing PageTop framework." -# Idioma (localización) predeterminado. -language = "en-US" # Tema predeterminado. theme = "Bootsier" +# Idioma (localización) predeterminado. +language = "en-US" +# Dirección predeterminada para el texto: "ltr", "rtl" o "auto". +direction = "ltr" # Rótulo al inicio: "Off", "Slant", "Small", "Speed" o "Starwars". startup_banner = "Small" @@ -18,6 +20,8 @@ rolling = "Daily" path = "log" # Prefijo para los archivos de traza (si rolling != "Stdout"). prefix = "tracing.log" +# Presentación de las trazas: "Json", "Full", "Compact" o "Pretty". +format = "Json" [webserver] # Configuración del servidor web. diff --git a/src/config/settings.rs b/src/config/settings.rs index 94097c3a..66ddbe42 100644 --- a/src/config/settings.rs +++ b/src/config/settings.rs @@ -42,7 +42,12 @@ pub static CONFIG: Lazy = Lazy::new(|| { /// componente, en una estructura similar a [`SETTINGS`] con tipos de variables /// seguros. Produce un *panic!* en caso de asignaciones no válidas. macro_rules! config_map { - ( $COMM:expr, $CONF:ident, $TYPE:tt $(, $key:expr => $value:expr)* ) => { + ( + $COMM:expr, + $CONF:ident, + $TYPE:tt + $(, $key:expr => $value:expr)* + ) => { $crate::doc_comment! { concat!($COMM), @@ -64,8 +69,9 @@ macro_rules! config_map { pub struct App { pub name : String, pub description : String, - pub language : String, pub theme : String, + pub language : String, + pub direction : String, pub startup_banner: String, pub run_mode : String, } @@ -76,6 +82,7 @@ pub struct Log { pub rolling : String, pub path : String, pub prefix : String, + pub format : String, } #[derive(Debug, Deserialize)] @@ -100,8 +107,9 @@ Ajustes globales y valores predeterminados para las secciones *\[app\]*, // [app] "app.name" => "PageTop Application", "app.description" => "Developed with the amazing PageTop framework.", - "app.language" => "en-US", "app.theme" => "Bootsier", + "app.language" => "en-US", + "app.direction" => "ltr", "app.startup_banner" => "Small", // [log] @@ -109,6 +117,7 @@ Ajustes globales y valores predeterminados para las secciones *\[app\]*, "log.rolling" => "Daily", "log.path" => "log", "log.prefix" => "tracing.log", + "log.format" => "json", // [webserver] "webserver.bind_address" => "localhost", diff --git a/src/core/server/main.rs b/src/core/server/main.rs index 2c8e2d37..fb9663b1 100644 --- a/src/core/server/main.rs +++ b/src/core/server/main.rs @@ -1,59 +1,11 @@ -use crate::{base, trace}; +use crate::{Lazy, base, locale, trace}; use crate::config::SETTINGS; use crate::core::{Server, all, server}; use crate::core::module::register_module; -use tracing_log::LogTracer; -use tracing_subscriber::{EnvFilter, Registry}; -use tracing_subscriber::layer::SubscriberExt; -use tracing::subscriber::set_global_default; -use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer}; -use tracing_actix_web::TracingLogger; - use actix_web::middleware::normalize; pub fn run(bootstrap: Option) -> Result { - // Inicia la traza de ejecución de la aplicación. - let env_filter = EnvFilter::try_new(&SETTINGS.log.tracing) - .unwrap_or(EnvFilter::new("Info")); - - let rolling = SETTINGS.log.rolling.to_lowercase(); - let (non_blocking, _guard) = match rolling.as_str() { - "stdout" => tracing_appender::non_blocking( - std::io::stdout() - ), - _ => tracing_appender::non_blocking({ - let path = &SETTINGS.log.path; - let prefix = &SETTINGS.log.prefix; - match rolling.as_str() { - "daily" => tracing_appender::rolling::daily(path, prefix), - "hourly" => tracing_appender::rolling::hourly(path, prefix), - "minutely" => tracing_appender::rolling::minutely(path, prefix), - "endless" => tracing_appender::rolling::never(path, prefix), - _ => { - println!( - "Rolling value \"{}\" not valid. Using \"daily\"", - rolling - ); - tracing_appender::rolling::daily(path, prefix) - } - } - }) - }; - let formatting_layer = BunyanFormattingLayer::new( - String::from(&SETTINGS.app.name), - non_blocking - ); - - let subscriber = Registry::default() - .with(env_filter) - .with(JsonStorageLayer) - .with(formatting_layer); - - set_global_default(subscriber).expect("Unable to setup subscriber!"); - - LogTracer::init().expect("Unable to setup log tracer!"); - // Imprime el rótulo (opcional) de bienvenida. if SETTINGS.app.startup_banner.to_lowercase() != "off" { let figfont = figlet_rs::FIGfont::from_content( @@ -63,9 +15,11 @@ pub fn run(bootstrap: Option) -> Result { "speed" => include_str!("figfonts/speed.flf"), "starwars" => include_str!("figfonts/starwars.flf"), _ => { - trace::warn!( - "FIGfont \"{}\" not found for banner. Using \"{}\"", - SETTINGS.app.startup_banner, "Small" + println!( + "FIGfont \"{}\" not found for banner. {}. {}.", + SETTINGS.app.startup_banner, + "Using \"Small\"", + "Check the settings file", ); include_str!("figfonts/small.flf") } @@ -78,6 +32,12 @@ pub fn run(bootstrap: Option) -> Result { ); } + // Traza de seguimiento. + Lazy::force(&trace::TRACING); + + // Identificador de idioma. + Lazy::force(&locale::LANGID); + // Ejecuta la función de inicio de la aplicación. if bootstrap != None { trace::debug!("Calling application bootstrap"); @@ -92,7 +52,7 @@ pub fn run(bootstrap: Option) -> Result { // Inicializa el servidor web. let server = server::HttpServer::new(|| { server::App::new() - .wrap(TracingLogger) + .wrap(tracing_actix_web::TracingLogger) .wrap(normalize::NormalizePath::new(normalize::TrailingSlash::Trim)) .configure(&all::themes) .configure(&all::modules) diff --git a/src/locale/locale.rs b/src/locale/locale.rs new file mode 100644 index 00000000..3638a6a4 --- /dev/null +++ b/src/locale/locale.rs @@ -0,0 +1,23 @@ +use crate::{Lazy, trace}; +use crate::config::SETTINGS; + +use unic_langid::LanguageIdentifier; + +/// Almacena el Identificador de Idioma Unicode ([Unicode Language Identifier] +/// (https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier)) de +/// la aplicación, obtenido de `SETTINGS.app.language`. +pub static LANGID: Lazy = Lazy::new(|| { + match SETTINGS.app.language.parse() { + Ok(language) => language, + Err(_) => { + trace::warn!( + "Failed to parse language \"{}\". {}. {}. {}.", + SETTINGS.app.language, + "Unicode Language Identifier not recognized", + "Using \"en-US\"", + "Check the settings file", + ); + "en-US".parse().unwrap() + } + } +}); diff --git a/src/locale/mod.rs b/src/locale/mod.rs index 6e64cc8f..e13d9f21 100644 --- a/src/locale/mod.rs +++ b/src/locale/mod.rs @@ -1,21 +1,12 @@ -use crate::Lazy; -use crate::config::SETTINGS; - -use unic_langid::LanguageIdentifier; - pub use fluent_templates::{static_loader as static_locale, Loader as Locale}; pub use fluent_templates; pub use fluent_templates::fluent_bundle::FluentValue; -/// Almacena el Identificador de Idioma Unicode ([Unicode Language Identifier] -/// (https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier)) de -/// la aplicación, obtenido de `SETTINGS.app.language`. -pub static LANGID: Lazy = Lazy::new(|| { - SETTINGS.app.language.parse().expect("Failed to parse.") -}); +mod locale; +pub use locale::LANGID; #[macro_export] -/// Permite integrar fácilmente localización en tus temas y módulos. +/// Permite integrar fácilmente localización en temas, módulos y componentes. macro_rules! localize { ( $DEF_LANGID:literal, $locales:literal $(, $core_locales:literal)? ) => { use $crate::locale::*; diff --git a/src/trace/mod.rs b/src/trace/mod.rs index f4af4116..8ffa8bcd 100644 --- a/src/trace/mod.rs +++ b/src/trace/mod.rs @@ -1 +1,5 @@ +pub use tracing::{Level, event, span}; pub use tracing::{debug, error, info, trace, warn}; + +mod trace; +pub use trace::TRACING; diff --git a/src/trace/trace.rs b/src/trace/trace.rs new file mode 100644 index 00000000..fd907461 --- /dev/null +++ b/src/trace/trace.rs @@ -0,0 +1,57 @@ +use crate::Lazy; +use crate::config::SETTINGS; + +use tracing_appender::non_blocking::WorkerGuard; +use tracing_subscriber::EnvFilter; + +pub static TRACING: Lazy = Lazy::new(|| { + let env_filter = EnvFilter::try_new(&SETTINGS.log.tracing) + .unwrap_or(EnvFilter::new("Info")); + + let rolling = SETTINGS.log.rolling.to_lowercase(); + let (non_blocking, guard) = match rolling.as_str() { + "stdout" => tracing_appender::non_blocking( + std::io::stdout() + ), + _ => tracing_appender::non_blocking({ + let path = &SETTINGS.log.path; + let prefix = &SETTINGS.log.prefix; + match rolling.as_str() { + "daily" => tracing_appender::rolling::daily(path, prefix), + "hourly" => tracing_appender::rolling::hourly(path, prefix), + "minutely" => tracing_appender::rolling::minutely(path, prefix), + "endless" => tracing_appender::rolling::never(path, prefix), + _ => { + println!( + "Rolling value \"{}\" not valid. {}. {}.", + SETTINGS.log.rolling, + "Using \"daily\"", + "Check the settings file", + ); + tracing_appender::rolling::daily(path, prefix) + } + } + }) + }; + let subscriber = tracing_subscriber::fmt() + .with_env_filter(env_filter) + .with_writer(non_blocking) + .with_ansi(rolling.as_str() == "stdout"); + match SETTINGS.log.format.to_lowercase().as_str() { + "json" => subscriber.json().init(), + "full" => subscriber.init(), + "compact" => subscriber.compact().init(), + "pretty" => subscriber.pretty().init(), + _ => { + println!( + "Tracing format \"{}\" not valid. {}. {}.", + SETTINGS.log.format, + "Using \"Full\"", + "Check the settings file", + ); + subscriber.init(); + } + } + + guard +});