diff --git a/Cargo.lock b/Cargo.lock index d7bd16ba58e..a279bd5478a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -266,6 +266,8 @@ dependencies = [ "static_assertions", "tempfile", "thiserror", + "tracing", + "tracing-futures", ] [[package]] @@ -6305,6 +6307,7 @@ dependencies = [ "tower", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -6359,6 +6362,8 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" dependencies = [ + "futures", + "futures-task", "pin-project 1.0.10", "tracing", ] diff --git a/README.md b/README.md index 32ed0b4bb85..27d277a42e6 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,8 @@ Clear your local database using: `rm -rf ~/.fuel/db` The service relies on the environment variable `RUST_LOG`. For more information, check the [EnvFilter examples](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/struct.EnvFilter.html#examples) crate. +Human logging can be disabled with the environment variable `HUMAN_LOGGING=false` + ## Docker & Kubernetes ``` # Create Docker Image @@ -127,5 +129,5 @@ RET(REG_ONE), ``` $ cargo run --bin fuel-gql-cli -- transaction submit \ -"{\"Script\":{\"gas_price\":0,\"gas_limit\":1000000,\"maturity\":0,\"script\":[80,64,0,202,80,68,0,186,51,65,16,0,36,4,0,0],\"script_data\":[],\"inputs\":[],\"outputs\":[{\"Coin\":{\"to\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], \"amount\": 10, \"color\": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}}],\"witnesses\":[],\"receipts_root\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}}" +"{\"Script\":{\"byte_price\":0,\"gas_price\":0,\"gas_limit\":1000000,\"maturity\":0,\"script\":[80,64,0,202,80,68,0,186,51,65,16,0,36,4,0,0],\"script_data\":[],\"inputs\":[],\"outputs\":[],\"witnesses\":[],\"receipts_root\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}}" ``` diff --git a/deployment/charts/templates/fuel-core-deploy.yaml b/deployment/charts/templates/fuel-core-deploy.yaml index f313e4047da..98081ef246e 100644 --- a/deployment/charts/templates/fuel-core-deploy.yaml +++ b/deployment/charts/templates/fuel-core-deploy.yaml @@ -72,6 +72,9 @@ spec: volumeMounts: - name: {{ .Values.app.volume.pvname }} mountPath: "{{ .Values.app.volume.mountPath }}" + env: + - name: {{ .Values.app.human_logging }} + value: "false" volumes: - name: {{ .Values.app.volume.pvname }} persistentVolumeClaim: diff --git a/deployment/charts/values.yaml b/deployment/charts/values.yaml index e37b3ebefd8..2c1f6471182 100644 --- a/deployment/charts/values.yaml +++ b/deployment/charts/values.yaml @@ -8,6 +8,7 @@ app: httpport: 80 httpsport: 443 targetport: 4000 + human_logging: false image: repository: ${fuel_core_image_repository} tag: ${fuel_core_image_tag} diff --git a/fuel-core/Cargo.toml b/fuel-core/Cargo.toml index a016af3adbc..6489649a4ed 100644 --- a/fuel-core/Cargo.toml +++ b/fuel-core/Cargo.toml @@ -19,7 +19,7 @@ test = false [dependencies] anyhow = "1.0" -async-graphql = { version = "=2.9", features = ["chrono", "chrono-tz"] } +async-graphql = { version = "=2.9", features = ["chrono", "chrono-tz", "tracing"] } async-trait = "0.1" axum = { version = "0.4" } bincode = "1.3" @@ -56,10 +56,10 @@ strum_macros = "0.21" tempfile = "3.3" thiserror = "1.0.26" tokio = { version = "1.8", features = ["macros", "rt-multi-thread"] } -tower-http = { version = "0.2.1", features = ["set-header"] } +tower-http = { version = "0.2.1", features = ["set-header", "trace"] } tower-layer = "0.3" tracing = "0.1" -tracing-subscriber = { version = "0.2", features = ["env-filter"] } +tracing-subscriber = { version = "0.2", features = ["env-filter", "json"] } uuid = { version = "0.8", features = ["v4"] } [dev-dependencies] diff --git a/fuel-core/src/args.rs b/fuel-core/src/args.rs index bcd088b0e96..d1addc3bf26 100644 --- a/fuel-core/src/args.rs +++ b/fuel-core/src/args.rs @@ -1,5 +1,6 @@ use clap::Parser; use fuel_core::service::{Config, DbType, VMConfig}; +use std::str::FromStr; use std::{env, io, net, path::PathBuf}; use strum::VariantNames; use tracing_subscriber::filter::EnvFilter; @@ -8,6 +9,9 @@ lazy_static::lazy_static! { pub static ref DEFAULT_DB_PATH: PathBuf = dirs::home_dir().unwrap().join(".fuel").join("db"); } +pub const LOG_FILTER: &str = "RUST_LOG"; +pub const HUMAN_LOGGING: &str = "HUMAN_LOGGING"; + #[derive(Parser, Debug)] #[clap(name = "fuel-core", about = "Fuel client implementation", version)] pub struct Opt { @@ -44,15 +48,34 @@ pub struct Opt { impl Opt { pub fn exec(self) -> io::Result { - let filter = match env::var_os("RUST_LOG") { + let filter = match env::var_os(LOG_FILTER) { Some(_) => EnvFilter::try_from_default_env().expect("Invalid `RUST_LOG` provided"), None => EnvFilter::new("info"), }; - tracing_subscriber::fmt::Subscriber::builder() + let human_logging = env::var_os(HUMAN_LOGGING) + .map(|s| { + bool::from_str(s.to_str().unwrap()) + .expect("Expected `true` or `false` to be provided for `HUMAN_LOGGING`") + }) + .unwrap_or(true); + + let sub = tracing_subscriber::fmt::Subscriber::builder() .with_writer(std::io::stderr) - .with_env_filter(filter) - .init(); + .with_env_filter(filter); + + if human_logging { + // use pretty logs + sub.pretty().init(); + } else { + // use machine parseable structured logs + sub + // disable terminal colors + .with_ansi(false) + // use json + .json() + .init(); + } let Opt { ip, diff --git a/fuel-core/src/service/graph_api.rs b/fuel-core/src/service/graph_api.rs index 07871b77bd3..8fadf610ca0 100644 --- a/fuel-core/src/service/graph_api.rs +++ b/fuel-core/src/service/graph_api.rs @@ -2,7 +2,9 @@ use crate::database::Database; use crate::schema::{build_schema, dap, CoreSchema}; use crate::service::Config; use crate::tx_pool::TxPool; -use async_graphql::{http::playground_source, http::GraphQLPlaygroundConfig, Request, Response}; +use async_graphql::{ + extensions::Tracing, http::playground_source, http::GraphQLPlaygroundConfig, Request, Response, +}; use axum::routing::{get, post}; use axum::{ extract::Extension, @@ -22,7 +24,7 @@ use std::{ sync::Arc, }; use tokio::task::JoinHandle; -use tower_http::set_header::SetResponseHeaderLayer; +use tower_http::{set_header::SetResponseHeaderLayer, trace::TraceLayer}; use tracing::info; /// Spawns the api server for this node @@ -33,13 +35,14 @@ pub async fn start_server( ) -> Result<(SocketAddr, JoinHandle>), std::io::Error> { let network_addr = config.addr; let schema = build_schema().data(db).data(tx_pool).data(config); - let schema = dap::init(schema).finish(); + let schema = dap::init(schema).extension(Tracing).finish(); let router = Router::new() .route("/playground", get(graphql_playground)) .route("/graphql", post(graphql_handler).options(ok)) .route("/health", get(health)) .layer(Extension(schema)) + .layer(TraceLayer::new_for_http()) .layer(SetResponseHeaderLayer::<_>::overriding( ACCESS_CONTROL_ALLOW_ORIGIN, HeaderValue::from_static("*"),