diff --git a/Cargo.lock b/Cargo.lock index be3454628c..4dd50297b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2265,6 +2265,7 @@ dependencies = [ "actix-web-prometheus", "ahash 0.8.11", "anyhow", + "arc-swap", "arrow", "arrow-json", "arrow-schema", @@ -5328,7 +5329,7 @@ dependencies = [ "rayon", "regex", "regex-syntax 0.8.3", - "reportserver", + "report_server", "reqwest 0.12.4", "rust-embed-for-web", "segment", @@ -6356,7 +6357,7 @@ dependencies = [ ] [[package]] -name = "reportserver" +name = "report_server" version = "0.1.0" dependencies = [ "actix-web", diff --git a/Cargo.toml b/Cargo.toml index b869fe12ed..b86677ec0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -159,7 +159,7 @@ zstd.workspace = true config.workspace = true infra.workspace = true ingester.workspace = true -reportserver.workspace = true +report_server.workspace = true chromiumoxide.workspace = true lettre.workspace = true @@ -173,7 +173,7 @@ float-cmp = "0.9" async-walkdir = "1.0.0" [workspace] -members = ["src/config", "src/infra", "src/ingester", "src/wal", "src/proto", "src/reportserver"] +members = ["src/config", "src/infra", "src/ingester", "src/wal", "src/proto", "src/report_server"] resolver = "2" [workspace.package] @@ -187,12 +187,13 @@ infra = { path = "src/infra" } ingester = { path = "src/ingester" } wal = { path = "src/wal" } proto = { path = "src/proto" } -reportserver = { path = "src/reportserver" } +report_server = { path = "src/report_server" } ahash = { version = "0.8", features = ["serde"] } actix-web = "4.5" actix-web-prometheus = { version = "0.1", features = ["process"] } anyhow = "1.0" +arc-swap = "1.7.1" argon2 = { version = "0.5", features = ["alloc", "password-hash"] } async-trait = "0.1" async-recursion = "1.0" diff --git a/build.rs b/build.rs index 03d6e93940..4a0196ac0f 100644 --- a/build.rs +++ b/build.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/cli/basic/cli.rs b/src/cli/basic/cli.rs index 499e032edc..625417bd2d 100644 --- a/src/cli/basic/cli.rs +++ b/src/cli/basic/cli.rs @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::{utils::file::set_permission, CONFIG}; +use config::utils::file::set_permission; use infra::file_list as infra_file_list; use crate::{ @@ -115,7 +115,7 @@ pub async fn cli() -> Result { if app.subcommand().is_none() { return Ok(false); } - + let cfg = config::get_config(); #[cfg(not(feature = "tokio-console"))] env_logger::init_from_env(env_logger::Env::new().default_filter_or("INFO")); @@ -142,13 +142,13 @@ pub async fn cli() -> Result { "root" => { let _ = users::update_user( meta::organization::DEFAULT_ORG, - CONFIG.auth.root_user_email.as_str(), + cfg.auth.root_user_email.as_str(), false, - CONFIG.auth.root_user_email.as_str(), + cfg.auth.root_user_email.as_str(), meta::user::UpdateUser { change_password: true, old_password: None, - new_password: Some(CONFIG.auth.root_user_password.clone()), + new_password: Some(cfg.auth.root_user_password.clone()), role: Some(meta::user::UserRole::Root), first_name: Some("root".to_owned()), last_name: Some("".to_owned()), diff --git a/src/cli/basic/mod.rs b/src/cli/basic/mod.rs index 2131ab39fd..c0ae357c90 100644 --- a/src/cli/basic/mod.rs +++ b/src/cli/basic/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/cli/data/cli.rs b/src/cli/data/cli.rs index 547e6c7e1d..53cfdbffca 100644 --- a/src/cli/data/cli.rs +++ b/src/cli/data/cli.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/cli/data/export.rs b/src/cli/data/export.rs index a83951c5d6..2422149d56 100644 --- a/src/cli/data/export.rs +++ b/src/cli/data/export.rs @@ -37,6 +37,7 @@ impl Context for Export { Err(_) => return Ok(false), }; + let cfg = config::get_config(); let table = c.stream_name; let query = search::Query { sql: format!("select * from {}", table), @@ -47,7 +48,7 @@ impl Context for Export { query_type: "".to_owned(), start_time: c.start_time, end_time: c.end_time, - sort_by: Some(format!("{} ASC", config::CONFIG.common.column_timestamp)), + sort_by: Some(format!("{} ASC", cfg.common.column_timestamp)), track_total_hits: false, query_context: None, uses_zo_fn: false, diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 6101b53b9c..40e03640e6 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/infra/cluster/etcd.rs b/src/common/infra/cluster/etcd.rs index 131a519786..33704d1720 100644 --- a/src/common/infra/cluster/etcd.rs +++ b/src/common/infra/cluster/etcd.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -15,9 +15,9 @@ use config::{ cluster::*, + get_config, meta::cluster::{Node, NodeStatus, Role}, utils::json, - CONFIG, }; use etcd_client::PutOptions; use infra::{ @@ -49,9 +49,12 @@ pub(crate) async fn register_and_keepalive() -> Result<()> { } let lease_id = unsafe { LOCAL_NODE_KEY_LEASE_ID }; - let ret = - etcd::keepalive_lease_id(lease_id, CONFIG.limit.node_heartbeat_ttl, is_offline) - .await; + let ret = etcd::keepalive_lease_id( + lease_id, + get_config().limit.node_heartbeat_ttl, + is_offline, + ) + .await; if ret.is_ok() { break; } @@ -77,8 +80,9 @@ pub(crate) async fn register_and_keepalive() -> Result<()> { /// Register to cluster async fn register() -> Result<()> { + let cfg = get_config(); // 1. create a cluster lock for node register - let locker = dist_lock::lock("/nodes/register", CONFIG.limit.node_heartbeat_ttl as u64).await?; + let locker = dist_lock::lock("/nodes/register", cfg.limit.node_heartbeat_ttl as u64).await?; // 2. watch node list tokio::task::spawn(async move { super::watch_node_list().await }); @@ -126,15 +130,15 @@ async fn register() -> Result<()> { } // 4. join the cluster - let key = format!("{}nodes/{}", &CONFIG.etcd.prefix, *LOCAL_NODE_UUID); + let key = format!("{}nodes/{}", &cfg.etcd.prefix, *LOCAL_NODE_UUID); let node = Node { id: new_node_id, uuid: LOCAL_NODE_UUID.clone(), - name: CONFIG.common.instance_name.clone(), - http_addr: format!("http://{}:{}", get_local_http_ip(), CONFIG.http.port), - grpc_addr: format!("http://{}:{}", get_local_grpc_ip(), CONFIG.grpc.port), + name: cfg.common.instance_name.clone(), + http_addr: format!("http://{}:{}", get_local_http_ip(), cfg.http.port), + grpc_addr: format!("http://{}:{}", get_local_grpc_ip(), cfg.grpc.port), role: LOCAL_NODE_ROLE.clone(), - cpu_num: CONFIG.limit.cpu_num as u64, + cpu_num: cfg.limit.cpu_num as u64, status: NodeStatus::Prepare, scheduled: true, broadcasted: false, @@ -155,10 +159,7 @@ async fn register() -> Result<()> { // register node to cluster let mut client = etcd::get_etcd_client().await.clone(); - let resp = match client - .lease_grant(CONFIG.limit.node_heartbeat_ttl, None) - .await - { + let resp = match client.lease_grant(cfg.limit.node_heartbeat_ttl, None).await { Ok(v) => v, Err(e) => { dist_lock::unlock(&locker).await?; @@ -193,6 +194,7 @@ pub(crate) async fn set_offline(new_lease_id: bool) -> Result<()> { /// set online to cluster pub(crate) async fn set_status(status: NodeStatus, new_lease_id: bool) -> Result<()> { + let cfg = get_config(); // set node status to online let node = match super::NODES.read().await.get(LOCAL_NODE_UUID.as_str()) { Some(node) => { @@ -203,11 +205,11 @@ pub(crate) async fn set_status(status: NodeStatus, new_lease_id: bool) -> Result None => Node { id: unsafe { LOCAL_NODE_ID }, uuid: LOCAL_NODE_UUID.clone(), - name: CONFIG.common.instance_name.clone(), - http_addr: format!("http://{}:{}", get_local_node_ip(), CONFIG.http.port), - grpc_addr: format!("http://{}:{}", get_local_node_ip(), CONFIG.grpc.port), + name: cfg.common.instance_name.clone(), + http_addr: format!("http://{}:{}", get_local_node_ip(), cfg.http.port), + grpc_addr: format!("http://{}:{}", get_local_node_ip(), cfg.grpc.port), role: LOCAL_NODE_ROLE.clone(), - cpu_num: CONFIG.limit.cpu_num as u64, + cpu_num: cfg.limit.cpu_num as u64, status: status.clone(), scheduled: true, broadcasted: false, @@ -223,7 +225,7 @@ pub(crate) async fn set_status(status: NodeStatus, new_lease_id: bool) -> Result // get new lease id let mut client = etcd::get_etcd_client().await.clone(); let resp = client - .lease_grant(CONFIG.limit.node_heartbeat_ttl, None) + .lease_grant(cfg.limit.node_heartbeat_ttl, None) .await?; let lease_id = resp.id(); // update local node key lease id @@ -232,7 +234,7 @@ pub(crate) async fn set_status(status: NodeStatus, new_lease_id: bool) -> Result } } - let key = format!("{}nodes/{}", &CONFIG.etcd.prefix, *LOCAL_NODE_UUID); + let key = format!("{}nodes/{}", &cfg.etcd.prefix, *LOCAL_NODE_UUID); let opt = PutOptions::new().with_lease(unsafe { LOCAL_NODE_KEY_LEASE_ID }); let mut client = etcd::get_etcd_client().await.clone(); if let Err(e) = client.put(key, val, Some(opt)).await { @@ -244,7 +246,7 @@ pub(crate) async fn set_status(status: NodeStatus, new_lease_id: bool) -> Result /// Leave cluster pub(crate) async fn leave() -> Result<()> { - let key = format!("{}nodes/{}", &CONFIG.etcd.prefix, *LOCAL_NODE_UUID); + let key = format!("{}nodes/{}", get_config().etcd.prefix, *LOCAL_NODE_UUID); let mut client = etcd::get_etcd_client().await.clone(); if let Err(e) = client.delete(key, None).await { return Err(Error::Message(format!("leave node error: {}", e))); @@ -254,7 +256,7 @@ pub(crate) async fn leave() -> Result<()> { } pub(crate) async fn update_local_node(node: &Node) -> Result<()> { - let key = format!("{}nodes/{}", &CONFIG.etcd.prefix, *LOCAL_NODE_UUID); + let key = format!("{}nodes/{}", get_config().etcd.prefix, *LOCAL_NODE_UUID); let opt = PutOptions::new().with_lease(unsafe { LOCAL_NODE_KEY_LEASE_ID }); let val = json::to_string(&node).unwrap(); let mut client = etcd::get_etcd_client().await.clone(); diff --git a/src/common/infra/cluster/mod.rs b/src/common/infra/cluster/mod.rs index 3dd5e732b8..d3759b1656 100644 --- a/src/common/infra/cluster/mod.rs +++ b/src/common/infra/cluster/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -17,12 +17,13 @@ use std::{cmp::min, ops::Bound, sync::Arc, time::Duration}; use config::{ cluster::*, + get_config, get_instance_id, meta::{ cluster::{Node, NodeStatus, Role}, meta_store::MetaStore, }, utils::{hash::Sum64, json}, - RwAHashMap, RwBTreeMap, CONFIG, INSTANCE_ID, + RwAHashMap, RwBTreeMap, }; use infra::{ db::{get_coordinator, Event}, @@ -51,7 +52,7 @@ pub async fn add_node_to_consistent_hash(node: &Node, role: &Role) { _ => return, }; let mut h = config::utils::hash::gxhash::new(); - for i in 0..CONFIG.limit.consistent_hash_vnodes { + for i in 0..get_config().limit.consistent_hash_vnodes { let key = format!("{}{}", node.uuid, i); let hash = h.sum64(&key); nodes.insert(hash, node.uuid.clone()); @@ -65,7 +66,7 @@ pub async fn remove_node_from_consistent_hash(node: &Node, role: &Role) { _ => return, }; let mut h = config::utils::hash::gxhash::new(); - for i in 0..CONFIG.limit.consistent_hash_vnodes { + for i in 0..get_config().limit.consistent_hash_vnodes { let key = format!("{}{}", node.uuid, i); let hash = h.sum64(&key); nodes.remove(&hash); @@ -94,16 +95,18 @@ pub async fn get_node_from_consistent_hash(key: &str, role: &Role) -> Option String { - if CONFIG.grpc.internal_grpc_token.is_empty() { - INSTANCE_ID.get("instance_id").unwrap().to_string() + let cfg = get_config(); + if cfg.grpc.internal_grpc_token.is_empty() { + get_instance_id() } else { - CONFIG.grpc.internal_grpc_token.clone() + cfg.grpc.internal_grpc_token.clone() } } /// Register and keepalive the node to cluster pub async fn register_and_keepalive() -> Result<()> { - if CONFIG.common.local_mode { + let cfg = get_config(); + if cfg.common.local_mode { let roles = load_local_node_role(); if !is_single_node(&roles) { panic!("Local mode only support NODE_ROLE=all"); @@ -116,14 +119,14 @@ pub async fn register_and_keepalive() -> Result<()> { return Ok(()); } - match CONFIG.common.cluster_coordinator.as_str().into() { + match cfg.common.cluster_coordinator.as_str().into() { MetaStore::Nats => nats::register_and_keepalive().await?, _ => etcd::register_and_keepalive().await?, }; // check node heatbeat tokio::task::spawn(async move { - let ttl_keep_alive = min(10, (CONFIG.limit.node_heartbeat_ttl / 2) as u64); + let ttl_keep_alive = min(10, (cfg.limit.node_heartbeat_ttl / 2) as u64); let client = reqwest::Client::new(); loop { time::sleep(time::Duration::from_secs(ttl_keep_alive)).await; @@ -137,33 +140,36 @@ pub async fn register_and_keepalive() -> Result<()> { } pub async fn set_online(new_lease_id: bool) -> Result<()> { - if CONFIG.common.local_mode { + let cfg = get_config(); + if cfg.common.local_mode { return Ok(()); } - match CONFIG.common.cluster_coordinator.as_str().into() { + match cfg.common.cluster_coordinator.as_str().into() { MetaStore::Nats => nats::set_online().await, _ => etcd::set_online(new_lease_id).await, } } pub async fn set_offline(new_lease_id: bool) -> Result<()> { - if CONFIG.common.local_mode { + let cfg = get_config(); + if cfg.common.local_mode { return Ok(()); } - match CONFIG.common.cluster_coordinator.as_str().into() { + match cfg.common.cluster_coordinator.as_str().into() { MetaStore::Nats => nats::set_offline().await, _ => etcd::set_offline(new_lease_id).await, } } pub async fn update_local_node(node: &Node) -> Result<()> { - if CONFIG.common.local_mode { + let cfg = get_config(); + if cfg.common.local_mode { return Ok(()); } - match CONFIG.common.cluster_coordinator.as_str().into() { + match cfg.common.cluster_coordinator.as_str().into() { MetaStore::Nats => nats::update_local_node(node).await, _ => etcd::update_local_node(node).await, } @@ -173,12 +179,12 @@ pub async fn leave() -> Result<()> { unsafe { LOCAL_NODE_STATUS = NodeStatus::Offline; } - - if CONFIG.common.local_mode { + let cfg = get_config(); + if cfg.common.local_mode { return Ok(()); } - match CONFIG.common.cluster_coordinator.as_str().into() { + match cfg.common.cluster_coordinator.as_str().into() { MetaStore::Nats => nats::leave().await, _ => etcd::leave().await, } @@ -207,7 +213,9 @@ async fn watch_node_list() -> Result<()> { let mut events = client.watch(key).await?; let events = Arc::get_mut(&mut events).unwrap(); log::info!("Start watching node_list"); + loop { + let cfg = get_config(); let ev = match events.recv().await { Some(ev) => ev, None => { @@ -238,7 +246,7 @@ async fn watch_node_list() -> Result<()> { continue; } log::info!("[CLUSTER] join {:?}", item_value); - if !CONFIG.common.meta_store_external && !broadcasted { + if !cfg.common.meta_store_external && !broadcasted { // The ingester need broadcast local file list to the new node if is_ingester(&LOCAL_NODE_ROLE) && (item_value.status.eq(&NodeStatus::Prepare) @@ -297,12 +305,13 @@ async fn watch_node_list() -> Result<()> { } async fn check_nodes_status(client: &reqwest::Client) -> Result<()> { + let cfg = get_config(); let nodes = get_cached_online_nodes().await.unwrap_or_default(); for node in nodes { if node.uuid.eq(LOCAL_NODE_UUID.as_str()) { continue; } - let url = format!("{}{}/healthz", node.http_addr, CONFIG.common.base_uri); + let url = format!("{}{}/healthz", node.http_addr, cfg.common.base_uri); let resp = client.get(url).timeout(HEALTH_CHECK_TIMEOUT).send().await; if resp.is_err() || !resp.unwrap().status().is_success() { log::error!("[CLUSTER] node {} health check failed", node.name); @@ -350,14 +359,15 @@ pub async fn get_cached_nodes(cond: fn(&Node) -> bool) -> Option> { #[inline(always)] pub fn load_local_mode_node() -> Node { + let cfg = get_config(); Node { id: 1, uuid: LOCAL_NODE_UUID.clone(), - name: CONFIG.common.instance_name.clone(), - http_addr: format!("http://127.0.0.1:{}", CONFIG.http.port), - grpc_addr: format!("http://127.0.0.1:{}", CONFIG.grpc.port), + name: cfg.common.instance_name.clone(), + http_addr: format!("http://127.0.0.1:{}", cfg.http.port), + grpc_addr: format!("http://127.0.0.1:{}", cfg.grpc.port), role: [Role::All].to_vec(), - cpu_num: CONFIG.limit.cpu_num as u64, + cpu_num: cfg.limit.cpu_num as u64, status: NodeStatus::Online, scheduled: true, broadcasted: false, diff --git a/src/common/infra/cluster/nats.rs b/src/common/infra/cluster/nats.rs index d271cac50d..7ac3a3aa52 100644 --- a/src/common/infra/cluster/nats.rs +++ b/src/common/infra/cluster/nats.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -17,9 +17,9 @@ use core::cmp::min; use config::{ cluster::*, + get_config, meta::cluster::{Node, NodeStatus, Role}, utils::json, - CONFIG, }; use infra::{ db::{get_coordinator, NEED_WATCH}, @@ -46,7 +46,7 @@ pub(crate) async fn register_and_keepalive() -> Result<()> { } } // after the node is online, keepalive - let ttl_keep_alive = min(10, (CONFIG.limit.node_heartbeat_ttl / 2) as u64); + let ttl_keep_alive = min(10, (get_config().limit.node_heartbeat_ttl / 2) as u64); loop { time::sleep(time::Duration::from_secs(ttl_keep_alive)).await; loop { @@ -72,8 +72,9 @@ pub(crate) async fn register_and_keepalive() -> Result<()> { /// Register to cluster async fn register() -> Result<()> { + let cfg = get_config(); // 1. create a cluster lock for node register - let locker = dist_lock::lock("/nodes/register", CONFIG.limit.node_heartbeat_ttl as u64).await?; + let locker = dist_lock::lock("/nodes/register", cfg.limit.node_heartbeat_ttl as u64).await?; // 2. watch node list task::spawn(async move { super::watch_node_list().await }); @@ -125,11 +126,11 @@ async fn register() -> Result<()> { let node = Node { id: new_node_id, uuid: LOCAL_NODE_UUID.clone(), - name: CONFIG.common.instance_name.clone(), - http_addr: format!("http://{}:{}", get_local_http_ip(), CONFIG.http.port), - grpc_addr: format!("http://{}:{}", get_local_grpc_ip(), CONFIG.grpc.port), + name: cfg.common.instance_name.clone(), + http_addr: format!("http://{}:{}", get_local_http_ip(), cfg.http.port), + grpc_addr: format!("http://{}:{}", get_local_grpc_ip(), cfg.grpc.port), role: LOCAL_NODE_ROLE.clone(), - cpu_num: CONFIG.limit.cpu_num as u64, + cpu_num: cfg.limit.cpu_num as u64, status: NodeStatus::Prepare, scheduled: true, broadcasted: false, @@ -172,6 +173,7 @@ pub(crate) async fn set_offline() -> Result<()> { /// set online to cluster pub(crate) async fn set_status(status: NodeStatus) -> Result<()> { + let cfg = get_config(); // set node status to online let node = match super::NODES.read().await.get(LOCAL_NODE_UUID.as_str()) { Some(node) => { @@ -182,11 +184,11 @@ pub(crate) async fn set_status(status: NodeStatus) -> Result<()> { None => Node { id: unsafe { LOCAL_NODE_ID }, uuid: LOCAL_NODE_UUID.clone(), - name: CONFIG.common.instance_name.clone(), - http_addr: format!("http://{}:{}", get_local_node_ip(), CONFIG.http.port), - grpc_addr: format!("http://{}:{}", get_local_node_ip(), CONFIG.grpc.port), + name: cfg.common.instance_name.clone(), + http_addr: format!("http://{}:{}", get_local_node_ip(), cfg.http.port), + grpc_addr: format!("http://{}:{}", get_local_node_ip(), cfg.grpc.port), role: LOCAL_NODE_ROLE.clone(), - cpu_num: CONFIG.limit.cpu_num as u64, + cpu_num: cfg.limit.cpu_num as u64, status: status.clone(), scheduled: true, broadcasted: false, diff --git a/src/common/infra/mod.rs b/src/common/infra/mod.rs index d0c05f6a3f..c1b23cd020 100644 --- a/src/common/infra/mod.rs +++ b/src/common/infra/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use ::config::{ider, INSTANCE_ID}; +use ::config::{cache_instance_id, ider}; use crate::service::db::instance; @@ -32,7 +32,7 @@ pub async fn init() -> Result<(), anyhow::Error> { id } }; - INSTANCE_ID.insert("instance_id".to_owned(), instance_id); + cache_instance_id(&instance_id); wal::init().await?; // because of asynchronous, we need to wait for a while diff --git a/src/common/infra/wal.rs b/src/common/infra/wal.rs index a4006b32af..db714e1971 100644 --- a/src/common/infra/wal.rs +++ b/src/common/infra/wal.rs @@ -19,11 +19,11 @@ use arrow::{ipc::writer::StreamWriter, record_batch::RecordBatch}; use arrow_schema::Schema; use chrono::{DateTime, Datelike, TimeZone, Utc}; use config::{ - ider, + get_config, ider, meta::stream::{PartitionTimeLevel, StreamType}, metrics, utils::asynchronism::file::get_file_contents, - CONFIG, FILE_EXT_ARROW, FILE_EXT_JSON, + FILE_EXT_ARROW, FILE_EXT_JSON, }; use hashbrown::HashMap; use once_cell::sync::Lazy; @@ -147,7 +147,7 @@ impl Default for Manager { impl Manager { pub fn new() -> Manager { - let size = CONFIG.limit.cpu_num; + let size = get_config().limit.cpu_num; let mut data = Vec::with_capacity(size); for _ in 0..size { data.push(RwLock::new(HashMap::>::default())); @@ -178,7 +178,7 @@ impl Manager { drop(manager); // check size & ttl - if file.size().await >= (CONFIG.limit.max_file_size_on_disk as i64) + if file.size().await >= (get_config().limit.max_file_size_on_disk as i64) || file.expired() <= Utc::now().timestamp() { let mut manager = locker.write().await; @@ -258,16 +258,16 @@ impl RwFile { schema: Option, ) -> RwFile { let use_arrow = schema.is_some(); - + let cfg = get_config(); let mut dir_path = if use_arrow { format!( "{}files/{}/{}/{}/", - &CONFIG.common.data_idx_dir, stream.org_id, stream.stream_type, stream.stream_name + &cfg.common.data_idx_dir, stream.org_id, stream.stream_type, stream.stream_name ) } else { format!( "{}files/{}/{}/{}/", - &CONFIG.common.data_wal_dir, stream.org_id, stream.stream_type, stream.stream_name + &cfg.common.data_wal_dir, stream.org_id, stream.stream_type, stream.stream_name ) }; // Hack for file_list @@ -308,7 +308,7 @@ impl RwFile { let time_now: DateTime = Utc::now(); let level_duration = partition_time_level.unwrap_or_default().duration(); - let ttl = if !CONFIG.limit.ignore_file_retention_by_stream && level_duration > 0 { + let ttl = if !cfg.limit.ignore_file_retention_by_stream && level_duration > 0 { let time_end_day = Utc .with_ymd_and_hms( time_now.year(), @@ -324,12 +324,12 @@ impl RwFile { if expired > time_end_day { // if the file expired time is tomorrow, it should be deleted at 23:59:59 + // 10min - time_end_day + CONFIG.limit.max_file_retention_time as i64 + time_end_day + cfg.limit.max_file_retention_time as i64 } else { expired } } else { - time_now.timestamp() + CONFIG.limit.max_file_retention_time as i64 + time_now.timestamp() + cfg.limit.max_file_retention_time as i64 }; RwFile { diff --git a/src/common/meta/alerts/destinations.rs b/src/common/meta/alerts/destinations.rs index 1b29414fa0..86be738c2f 100644 --- a/src/common/meta/alerts/destinations.rs +++ b/src/common/meta/alerts/destinations.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/alerts/mod.rs b/src/common/meta/alerts/mod.rs index 66e4869c88..2dd421ea0a 100644 --- a/src/common/meta/alerts/mod.rs +++ b/src/common/meta/alerts/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/alerts/templates.rs b/src/common/meta/alerts/templates.rs index 799edc9fbd..51f32dc500 100644 --- a/src/common/meta/alerts/templates.rs +++ b/src/common/meta/alerts/templates.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/authz.rs b/src/common/meta/authz.rs index 59d31bf85d..1dec9a8dc2 100644 --- a/src/common/meta/authz.rs +++ b/src/common/meta/authz.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/dashboards/mod.rs b/src/common/meta/dashboards/mod.rs index d22e022563..0633904282 100644 --- a/src/common/meta/dashboards/mod.rs +++ b/src/common/meta/dashboards/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/dashboards/reports.rs b/src/common/meta/dashboards/reports.rs index 4146de1e99..d95298b886 100644 --- a/src/common/meta/dashboards/reports.rs +++ b/src/common/meta/dashboards/reports.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/dashboards/v1/mod.rs b/src/common/meta/dashboards/v1/mod.rs index 78728f2f39..3ff0f0fd62 100644 --- a/src/common/meta/dashboards/v1/mod.rs +++ b/src/common/meta/dashboards/v1/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/dashboards/v2/mod.rs b/src/common/meta/dashboards/v2/mod.rs index 526f2ddadb..04ba7cb769 100644 --- a/src/common/meta/dashboards/v2/mod.rs +++ b/src/common/meta/dashboards/v2/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/dashboards/v3/mod.rs b/src/common/meta/dashboards/v3/mod.rs index 8518d4d8b0..e9ca542669 100644 --- a/src/common/meta/dashboards/v3/mod.rs +++ b/src/common/meta/dashboards/v3/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/functions.rs b/src/common/meta/functions.rs index 54fb87d6db..c56ec69211 100644 --- a/src/common/meta/functions.rs +++ b/src/common/meta/functions.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/ingestion.rs b/src/common/meta/ingestion.rs index 934a9d196f..8b54f392cb 100644 --- a/src/common/meta/ingestion.rs +++ b/src/common/meta/ingestion.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/maxmind/client.rs b/src/common/meta/maxmind/client.rs index 8eb7f31360..eab46b5f06 100644 --- a/src/common/meta/maxmind/client.rs +++ b/src/common/meta/maxmind/client.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/maxmind/mod.rs b/src/common/meta/maxmind/mod.rs index 61b29f0388..90d8a2d26e 100644 --- a/src/common/meta/maxmind/mod.rs +++ b/src/common/meta/maxmind/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/middleware_data.rs b/src/common/meta/middleware_data.rs index d9a69d443f..3d3bba211b 100644 --- a/src/common/meta/middleware_data.rs +++ b/src/common/meta/middleware_data.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/organization.rs b/src/common/meta/organization.rs index ee40d7fa51..656157f8c5 100644 --- a/src/common/meta/organization.rs +++ b/src/common/meta/organization.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -13,7 +13,6 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::CONFIG; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; @@ -99,7 +98,7 @@ pub struct RumIngestionResponse { } fn default_scrape_interval() -> u32 { - CONFIG.common.default_scrape_interval + config::get_config().common.default_scrape_interval } #[derive(Serialize, ToSchema, Deserialize, Debug, Clone)] diff --git a/src/common/meta/prom.rs b/src/common/meta/prom.rs index 56f880f69f..81456e7474 100644 --- a/src/common/meta/prom.rs +++ b/src/common/meta/prom.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/saved_view.rs b/src/common/meta/saved_view.rs index 5ae58db692..5dd31aece3 100644 --- a/src/common/meta/saved_view.rs +++ b/src/common/meta/saved_view.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/service.rs b/src/common/meta/service.rs index 428a55806d..61f8a0ce89 100644 --- a/src/common/meta/service.rs +++ b/src/common/meta/service.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/syslog.rs b/src/common/meta/syslog.rs index 103eb52055..b32d7933e8 100644 --- a/src/common/meta/syslog.rs +++ b/src/common/meta/syslog.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/meta/telemetry.rs b/src/common/meta/telemetry.rs index 4382c50b3c..3108725f1c 100644 --- a/src/common/meta/telemetry.rs +++ b/src/common/meta/telemetry.rs @@ -17,8 +17,9 @@ use std::collections::HashMap; use config::{ cluster::{is_single_node, load_local_node_role}, + get_config, get_instance_id, utils::json, - CONFIG, INSTANCE_ID, SIZE_IN_MB, TELEMETRY_CLIENT, + SIZE_IN_MB, TELEMETRY_CLIENT, }; use hashbrown::HashSet; use infra::{cache::stats, db as infra_db, schema::STREAM_SCHEMAS_LATEST}; @@ -53,7 +54,7 @@ impl Telemetry { data: Option>, send_zo_data: bool, ) { - if !CONFIG.common.telemetry_enabled { + if !get_config().common.telemetry_enabled { return; } log::info!("sending event {}", event); @@ -69,7 +70,7 @@ impl Telemetry { self.add_event(Track { user: segment::message::User::UserId { user_id: segment::message::User::AnonymousId { - anonymous_id: INSTANCE_ID.get("instance_id").unwrap().to_string(), + anonymous_id: get_instance_id(), } .to_string(), }, @@ -80,10 +81,7 @@ impl Telemetry { }); let res = TELEMETRY_CLIENT - .send( - INSTANCE_ID.get("instance_id").unwrap().to_string(), - Message::from(self.event.clone()), - ) + .send(get_instance_id(), Message::from(self.event.clone())) .await; if res.is_err() { @@ -109,7 +107,7 @@ pub fn get_base_info(data: &mut HashMap) -> HashMap) -> HashMap) -> HashMap. use config::{ + get_config, meta::stream::{FileKey, PartitionTimeLevel, StreamType}, utils::{file::get_file_meta, time::BASE_TIME}, - CONFIG, }; use infra::file_list as infra_file_list; @@ -26,7 +26,7 @@ use crate::{ }; pub async fn run(prefix: &str, from: &str, to: &str) -> Result<(), anyhow::Error> { - if get_file_meta(&CONFIG.common.data_wal_dir).is_err() { + if get_file_meta(&get_config().common.data_wal_dir).is_err() { // there is no local wal files, no need upgrade return Ok(()); } diff --git a/src/common/mod.rs b/src/common/mod.rs index aa2b22e63e..bd21a2e3f0 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/utils/auth.rs b/src/common/utils/auth.rs index 44712dacf6..28593c9c47 100644 --- a/src/common/utils/auth.rs +++ b/src/common/utils/auth.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -16,8 +16,6 @@ use actix_web::{dev::Payload, Error, FromRequest, HttpRequest}; use argon2::{password_hash::SaltString, Algorithm, Argon2, Params, PasswordHasher, Version}; use config::utils::json; -#[cfg(feature = "enterprise")] -use config::CONFIG; use futures::future::{ready, Ready}; #[cfg(feature = "enterprise")] @@ -177,11 +175,12 @@ impl FromRequest for AuthExtractor { let mut method = req.method().to_string(); let local_path = req.path().to_string(); - let path = - match local_path.strip_prefix(format!("{}/api/", CONFIG.common.base_uri).as_str()) { - Some(path) => path, - None => &local_path, - }; + let path = match local_path + .strip_prefix(format!("{}/api/", config::get_config().common.base_uri).as_str()) + { + Some(path) => path, + None => &local_path, + }; let path_columns = path.split('/').collect::>(); let url_len = path_columns.len(); diff --git a/src/common/utils/functions.rs b/src/common/utils/functions.rs index 84c8eedeb6..33fe5353ef 100644 --- a/src/common/utils/functions.rs +++ b/src/common/utils/functions.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/utils/mod.rs b/src/common/utils/mod.rs index fa7a8b7b65..f1e4b653d8 100644 --- a/src/common/utils/mod.rs +++ b/src/common/utils/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/utils/record_batch_parquet_ext.rs b/src/common/utils/record_batch_parquet_ext.rs index 3958f7ece7..74ea1011ac 100644 --- a/src/common/utils/record_batch_parquet_ext.rs +++ b/src/common/utils/record_batch_parquet_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/common/utils/stream.rs b/src/common/utils/stream.rs index 9808fc15c9..45850e83fe 100644 --- a/src/common/utils/stream.rs +++ b/src/common/utils/stream.rs @@ -20,9 +20,10 @@ use std::{ use actix_web::HttpResponse; use config::{ + get_config, meta::stream::{FileMeta, StreamType}, utils::{arrow::record_batches_to_json_rows, json}, - CONFIG, FILE_EXT_JSON, + FILE_EXT_JSON, }; use datafusion::{ arrow::{datatypes::Schema, record_batch::RecordBatch}, @@ -60,7 +61,7 @@ pub fn get_file_name_v1(org_id: &str, stream_name: &str, suffix: u32) -> String // "./data/openobserve/olympics/olympics#2022#09#13#13_1.json" format!( "{}{}/{}/{}/{}_{}{}", - &CONFIG.common.data_wal_dir, + get_config().common.data_wal_dir, org_id, StreamType::Logs, stream_name, @@ -84,7 +85,7 @@ pub async fn populate_file_meta( let sql = format!( "SELECT min({0}) as min, max({0}) as max, count({0}) as num_records FROM temp;", - CONFIG.common.column_timestamp + get_config().common.column_timestamp ); let df = ctx.sql(sql.as_str()).await?; let batches = df.collect().await?; diff --git a/src/common/utils/zo_logger.rs b/src/common/utils/zo_logger.rs index 9aa70de47b..f35d6d085b 100644 --- a/src/common/utils/zo_logger.rs +++ b/src/common/utils/zo_logger.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -16,7 +16,7 @@ use std::sync::Arc; use cloudevents::{Event, EventBuilder, EventBuilderV10}; -use config::{ider, utils::json, CONFIG}; +use config::{get_config, ider, utils::json}; use log::{Metadata, Record}; use once_cell::sync::Lazy; use reqwest::Client; @@ -35,7 +35,7 @@ pub struct ZoLogger { impl log::Log for ZoLogger { fn enabled(&self, _metadata: &Metadata) -> bool { - CONFIG.log.events_enabled + get_config().log.events_enabled } fn log(self: &ZoLogger, record: &Record) { @@ -59,7 +59,7 @@ impl log::Log for ZoLogger { let event = EventBuilderV10::new() .id(ider::generate()) .ty("debug_log") - .source(CONFIG.common.instance_name.clone()) + .source(get_config().common.instance_name.clone()) .data("application/json", payload) .build() .unwrap(); @@ -78,10 +78,11 @@ pub async fn send_logs() { let mut logs = LOGS.write().await; logs.push(val); - if logs.len() >= CONFIG.log.events_batch_size { + let cfg = get_config(); + if logs.len() >= cfg.log.events_batch_size { let old_logs = std::mem::take(&mut *logs); - let url = url::Url::parse(&CONFIG.log.events_url).unwrap(); - let auth = format!("Basic {}", &CONFIG.log.events_auth); + let url = url::Url::parse(&cfg.log.events_url).unwrap(); + let auth = format!("Basic {}", &cfg.log.events_auth); let cl = Arc::clone(&cl); tokio::task::spawn(async move { let _ = cl diff --git a/src/config/Cargo.toml b/src/config/Cargo.toml index 4263c88472..ec6a9d2859 100644 --- a/src/config/Cargo.toml +++ b/src/config/Cargo.toml @@ -8,6 +8,7 @@ license.workspace = true actix-web-prometheus.workspace = true ahash.workspace = true anyhow.workspace = true +arc-swap.workspace = true arrow.workspace = true arrow-json.workspace = true arrow-schema.workspace = true diff --git a/src/config/src/cluster.rs b/src/config/src/cluster.rs index df616357e5..28b1361068 100644 --- a/src/config/src/cluster.rs +++ b/src/config/src/cluster.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -18,9 +18,8 @@ use std::net::IpAddr; use once_cell::sync::Lazy; use crate::{ - ider, + get_config, ider, meta::cluster::{NodeStatus, Role}, - CONFIG, }; pub static mut LOCAL_NODE_ID: i32 = 0; @@ -36,8 +35,9 @@ pub fn load_local_node_uuid() -> String { #[inline(always)] pub fn get_local_http_ip() -> String { - if !CONFIG.http.addr.is_empty() { - CONFIG.http.addr.clone() + let cfg = get_config(); + if !cfg.http.addr.is_empty() { + cfg.http.addr.clone() } else { get_local_node_ip() } @@ -45,8 +45,9 @@ pub fn get_local_http_ip() -> String { #[inline(always)] pub fn get_local_grpc_ip() -> String { - if !CONFIG.grpc.addr.is_empty() { - CONFIG.grpc.addr.clone() + let cfg = get_config(); + if !cfg.grpc.addr.is_empty() { + cfg.grpc.addr.clone() } else { get_local_node_ip() } @@ -64,7 +65,7 @@ pub fn get_local_node_ip() -> String { #[inline(always)] pub fn load_local_node_role() -> Vec { - CONFIG + get_config() .common .node_role .clone() diff --git a/src/config/src/config.rs b/src/config/src/config.rs index f89b87ec4e..1de2b30898 100644 --- a/src/config/src/config.rs +++ b/src/config/src/config.rs @@ -13,8 +13,9 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use std::{cmp::max, collections::BTreeMap, path::Path, time::Duration}; +use std::{cmp::max, collections::BTreeMap, path::Path, sync::Arc, time::Duration}; +use arc_swap::ArcSwap; use chromiumoxide::{browser::BrowserConfig, handler::viewport::Viewport}; use dotenv_config::EnvConfig; use dotenvy::dotenv; @@ -69,7 +70,7 @@ pub static SQL_FULL_TEXT_SEARCH_FIELDS: Lazy> = Lazy::new(|| { _DEFAULT_SQL_FULL_TEXT_SEARCH_FIELDS .iter() .map(|s| s.to_string()), - CONFIG + get_config() .common .feature_fulltext_extra_fields .split(',') @@ -89,7 +90,7 @@ pub static SQL_FULL_TEXT_SEARCH_FIELDS: Lazy> = Lazy::new(|| { }); pub static QUICK_MODEL_FIELDS: Lazy> = Lazy::new(|| { - let mut fields = CONFIG + let mut fields = get_config() .common .feature_quick_mode_fields .split(',') @@ -111,7 +112,7 @@ const _DEFAULT_DISTINCT_FIELDS: [&str; 2] = ["service_name", "operation_name"]; pub static DISTINCT_FIELDS: Lazy> = Lazy::new(|| { let mut fields = chain( _DEFAULT_DISTINCT_FIELDS.iter().map(|s| s.to_string()), - CONFIG + get_config() .common .feature_distinct_extra_fields .split(',') @@ -134,7 +135,7 @@ const _DEFAULT_BLOOM_FILTER_FIELDS: [&str; 1] = ["trace_id"]; pub static BLOOM_FILTER_DEFAULT_FIELDS: Lazy> = Lazy::new(|| { let mut fields = chain( _DEFAULT_BLOOM_FILTER_FIELDS.iter().map(|s| s.to_string()), - CONFIG + get_config() .common .bloom_filter_default_fields .split(',') @@ -153,8 +154,8 @@ pub static BLOOM_FILTER_DEFAULT_FIELDS: Lazy> = Lazy::new(|| { fields }); -pub static CONFIG: Lazy = Lazy::new(init); -pub static INSTANCE_ID: Lazy> = Lazy::new(Default::default); +static CONFIG: Lazy> = Lazy::new(|| ArcSwap::from(Arc::new(init()))); +static INSTANCE_ID: Lazy> = Lazy::new(Default::default); pub static TELEMETRY_CLIENT: Lazy = Lazy::new(|| { segment::HttpClient::new( @@ -162,10 +163,27 @@ pub static TELEMETRY_CLIENT: Lazy = Lazy::new(|| { .connect_timeout(Duration::new(10, 0)) .build() .unwrap(), - CONFIG.common.telemetry_url.clone(), + CONFIG.load().common.telemetry_url.clone(), ) }); +pub fn get_config() -> Arc { + CONFIG.load().clone() +} + +pub fn refresh_config() -> Result<(), anyhow::Error> { + CONFIG.store(Arc::new(init())); + Ok(()) +} + +pub fn cache_instance_id(instance_id: &str) { + INSTANCE_ID.insert("instance_id".to_owned(), instance_id.to_owned()); +} + +pub fn get_instance_id() -> String { + INSTANCE_ID.get("instance_id").unwrap().clone() +} + static CHROME_LAUNCHER_OPTIONS: tokio::sync::OnceCell> = tokio::sync::OnceCell::const_new(); @@ -176,31 +194,32 @@ pub async fn get_chrome_launch_options() -> &'static Option { } async fn init_chrome_launch_options() -> Option { - if !CONFIG.chrome.chrome_enabled || !CONFIG.common.report_server_url.is_empty() { + let cfg = get_config(); + if !cfg.chrome.chrome_enabled || !cfg.common.report_server_url.is_empty() { None } else { let mut browser_config = BrowserConfig::builder() .window_size( - CONFIG.chrome.chrome_window_width, - CONFIG.chrome.chrome_window_height, + cfg.chrome.chrome_window_width, + cfg.chrome.chrome_window_height, ) .viewport(Viewport { - width: CONFIG.chrome.chrome_window_width, - height: CONFIG.chrome.chrome_window_height, + width: cfg.chrome.chrome_window_width, + height: cfg.chrome.chrome_window_height, device_scale_factor: Some(1.0), ..Viewport::default() }); - if CONFIG.chrome.chrome_with_head { + if cfg.chrome.chrome_with_head { browser_config = browser_config.with_head(); } - if CONFIG.chrome.chrome_no_sandbox { + if cfg.chrome.chrome_no_sandbox { browser_config = browser_config.no_sandbox(); } - if !CONFIG.chrome.chrome_path.is_empty() { - browser_config = browser_config.chrome_executable(CONFIG.chrome.chrome_path.as_str()); + if !cfg.chrome.chrome_path.is_empty() { + browser_config = browser_config.chrome_executable(cfg.chrome.chrome_path.as_str()); } else { panic!("Chrome path must be specified"); } @@ -209,15 +228,16 @@ async fn init_chrome_launch_options() -> Option { } pub static SMTP_CLIENT: Lazy>> = Lazy::new(|| { - if !CONFIG.smtp.smtp_enabled { + let cfg = get_config(); + if !cfg.smtp.smtp_enabled { None } else { - let tls_parameters = TlsParameters::new(CONFIG.smtp.smtp_host.clone()).unwrap(); + let tls_parameters = TlsParameters::new(cfg.smtp.smtp_host.clone()).unwrap(); let mut transport_builder = - AsyncSmtpTransport::::builder_dangerous(&CONFIG.smtp.smtp_host) - .port(CONFIG.smtp.smtp_port); + AsyncSmtpTransport::::builder_dangerous(&cfg.smtp.smtp_host) + .port(cfg.smtp.smtp_port); - let option = &CONFIG.smtp.smtp_encryption; + let option = &cfg.smtp.smtp_encryption; transport_builder = if option == "starttls" { transport_builder.tls(Tls::Required(tls_parameters)) } else if option == "ssltls" { @@ -226,18 +246,25 @@ pub static SMTP_CLIENT: Lazy>> = Lazy: transport_builder }; - if !CONFIG.smtp.smtp_username.is_empty() && !CONFIG.smtp.smtp_password.is_empty() { + if !cfg.smtp.smtp_username.is_empty() && !cfg.smtp.smtp_password.is_empty() { transport_builder = transport_builder.credentials(Credentials::new( - CONFIG.smtp.smtp_username.clone(), - CONFIG.smtp.smtp_password.clone(), + cfg.smtp.smtp_username.clone(), + cfg.smtp.smtp_password.clone(), )); } Some(transport_builder.build()) } }); -pub static BLOCKED_STREAMS: Lazy> = - Lazy::new(|| CONFIG.common.blocked_streams.split(',').collect()); +pub static BLOCKED_STREAMS: Lazy> = Lazy::new(|| { + let blocked_streams = get_config() + .common + .blocked_streams + .split(',') + .map(|x| x.to_string()) + .collect(); + blocked_streams +}); #[derive(EnvConfig)] pub struct Config { @@ -1448,13 +1475,15 @@ fn check_s3_config(cfg: &mut Config) -> Result<(), anyhow::Error> { #[inline] pub fn is_local_disk_storage() -> bool { - CONFIG.common.local_mode && CONFIG.common.local_mode_storage.eq("disk") + let cfg = get_config(); + cfg.common.local_mode && cfg.common.local_mode_storage.eq("disk") } #[inline] pub fn get_cluster_name() -> String { - if !CONFIG.common.cluster_name.is_empty() { - CONFIG.common.cluster_name.to_string() + let cfg = get_config(); + if !cfg.common.cluster_name.is_empty() { + cfg.common.cluster_name.to_string() } else { INSTANCE_ID.get("instance_id").unwrap().to_string() } diff --git a/src/config/src/ider.rs b/src/config/src/ider.rs index ad97f1c6fc..7d795230cc 100644 --- a/src/config/src/ider.rs +++ b/src/config/src/ider.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/lib.rs b/src/config/src/lib.rs index ec169126ba..c7347ef759 100644 --- a/src/config/src/lib.rs +++ b/src/config/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/meta/cluster.rs b/src/config/src/meta/cluster.rs index d7992c6834..ff42ae6ea1 100644 --- a/src/config/src/meta/cluster.rs +++ b/src/config/src/meta/cluster.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/meta/logger.rs b/src/config/src/meta/logger.rs index 7859dfc463..ca491af0ac 100644 --- a/src/config/src/meta/logger.rs +++ b/src/config/src/meta/logger.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -27,16 +27,15 @@ use tracing_subscriber::{ registry::LookupSpan, }; -use crate::CONFIG; - pub struct CustomTimeFormat; impl FormatTime for CustomTimeFormat { fn format_time(&self, w: &mut Writer<'_>) -> std::fmt::Result { - if CONFIG.log.local_time_format.is_empty() { + let cfg = crate::get_config(); + if cfg.log.local_time_format.is_empty() { write!(w, "{}", Utc::now().to_rfc3339()) } else { - write!(w, "{}", Local::now().format(&CONFIG.log.local_time_format)) + write!(w, "{}", Local::now().format(&cfg.log.local_time_format)) } } } diff --git a/src/config/src/meta/meta_store.rs b/src/config/src/meta/meta_store.rs index 566020bc10..a7c9dd7efd 100644 --- a/src/config/src/meta/meta_store.rs +++ b/src/config/src/meta/meta_store.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/meta/sql.rs b/src/config/src/meta/sql.rs index 83efc873f3..1e071fbf74 100644 --- a/src/config/src/meta/sql.rs +++ b/src/config/src/meta/sql.rs @@ -25,7 +25,7 @@ use sqlparser::{ parser::Parser, }; -use crate::CONFIG; +use crate::get_config; const MAX_LIMIT: usize = 100000; const MAX_OFFSET: usize = 100000; @@ -313,7 +313,7 @@ impl<'a> TryFrom> for Option<(i64, i64)> { Some(expr) => parse_expr_for_field( expr, &SqlOperator::And, - &CONFIG.common.column_timestamp, + &get_config().common.column_timestamp, &mut fields, )?, None => {} @@ -544,7 +544,7 @@ fn parse_expr_check_field_name(s: &str, field: &str) -> bool { if s == field { return true; } - if field == "*" && s != "_all" && s != CONFIG.common.column_timestamp.clone() { + if field == "*" && s != "_all" && s != get_config().common.column_timestamp.clone() { return true; } diff --git a/src/config/src/meta/stream.rs b/src/config/src/meta/stream.rs index 58aa315441..9d7b8f89a1 100644 --- a/src/config/src/meta/stream.rs +++ b/src/config/src/meta/stream.rs @@ -24,12 +24,11 @@ use utoipa::ToSchema; use super::usage::Stats; use crate::{ + get_config, utils::{ hash::{gxhash, Sum64}, - json, - json::{Map, Value}, + json::{self, Map, Value}, }, - CONFIG, }; #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize, ToSchema, Hash)] @@ -223,7 +222,7 @@ impl StreamStats { fn time_range(&self) -> (i64, i64) { assert!(self.doc_time_min <= self.doc_time_max); - let file_push_interval = Duration::try_seconds(CONFIG.limit.file_push_interval as _) + let file_push_interval = Duration::try_seconds(get_config().limit.file_push_interval as _) .unwrap() .num_microseconds() .unwrap(); diff --git a/src/config/src/meta/usage.rs b/src/config/src/meta/usage.rs index 7b7aea4a2a..c2ebc6fcdb 100644 --- a/src/config/src/meta/usage.rs +++ b/src/config/src/meta/usage.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/metrics.rs b/src/config/src/metrics.rs index c5b26f64cd..0a45f36203 100644 --- a/src/config/src/metrics.rs +++ b/src/config/src/metrics.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -21,8 +21,6 @@ use prometheus::{ CounterVec, HistogramOpts, HistogramVec, IntCounterVec, IntGaugeVec, Opts, Registry, }; -use crate::CONFIG; - pub const NAMESPACE: &str = "zo"; const HELP_SUFFIX: &str = "Please include 'organization, 'stream type', and 'stream' labels for this metric."; @@ -682,10 +680,11 @@ fn register_metrics(registry: &Registry) { } fn create_const_labels() -> HashMap { + let cfg = crate::config::get_config(); let mut labels = HashMap::new(); - labels.insert("cluster".to_string(), CONFIG.common.cluster_name.clone()); - labels.insert("instance".to_string(), CONFIG.common.instance_name.clone()); - labels.insert("role".to_string(), CONFIG.common.node_role.clone()); + labels.insert("cluster".to_string(), cfg.common.cluster_name.clone()); + labels.insert("instance".to_string(), cfg.common.instance_name.clone()); + labels.insert("role".to_string(), cfg.common.node_role.clone()); labels } @@ -694,7 +693,7 @@ pub fn create_prometheus_handler() -> PrometheusMetrics { register_metrics(®istry); PrometheusMetricsBuilder::new(NAMESPACE) - .endpoint(format!("{}/metrics", CONFIG.common.base_uri).as_str()) + .endpoint(format!("{}/metrics", crate::config::get_config().common.base_uri).as_str()) .const_labels(create_const_labels()) .registry(registry) .build() diff --git a/src/config/src/utils/asynchronism/mod.rs b/src/config/src/utils/asynchronism/mod.rs index 517385c0e9..a0f934d208 100644 --- a/src/config/src/utils/asynchronism/mod.rs +++ b/src/config/src/utils/asynchronism/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/utils/cgroup.rs b/src/config/src/utils/cgroup.rs index d08bd26dce..a60e773825 100644 --- a/src/config/src/utils/cgroup.rs +++ b/src/config/src/utils/cgroup.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/utils/flatten.rs b/src/config/src/utils/flatten.rs index b1cd712b31..a434246449 100644 --- a/src/config/src/utils/flatten.rs +++ b/src/config/src/utils/flatten.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/utils/hash/cityhash.rs b/src/config/src/utils/hash/cityhash.rs index f41ca9ffdc..a7f831ba70 100644 --- a/src/config/src/utils/hash/cityhash.rs +++ b/src/config/src/utils/hash/cityhash.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/utils/hash/fnv.rs b/src/config/src/utils/hash/fnv.rs index 6e8ee31dd2..d1ee05a179 100644 --- a/src/config/src/utils/hash/fnv.rs +++ b/src/config/src/utils/hash/fnv.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/utils/hash/gxhash.rs b/src/config/src/utils/hash/gxhash.rs index ab7be4d718..e504028b0e 100644 --- a/src/config/src/utils/hash/gxhash.rs +++ b/src/config/src/utils/hash/gxhash.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/utils/hash/mod.rs b/src/config/src/utils/hash/mod.rs index 134b708f16..c176be829f 100644 --- a/src/config/src/utils/hash/mod.rs +++ b/src/config/src/utils/hash/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/utils/hash/murmur3.rs b/src/config/src/utils/hash/murmur3.rs index 00f8f529e2..0cbf564dd3 100644 --- a/src/config/src/utils/hash/murmur3.rs +++ b/src/config/src/utils/hash/murmur3.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/utils/parquet.rs b/src/config/src/utils/parquet.rs index 04fbe3da67..b7d634549c 100644 --- a/src/config/src/utils/parquet.rs +++ b/src/config/src/utils/parquet.rs @@ -33,8 +33,9 @@ pub fn new_parquet_writer<'a>( full_text_search_fields: &'a [String], metadata: &'a FileMeta, ) -> AsyncArrowWriter<&'a mut Vec> { - let row_group_size = if CONFIG.limit.parquet_max_row_group_size > 0 { - CONFIG.limit.parquet_max_row_group_size + let cfg = get_config(); + let row_group_size = if cfg.limit.parquet_max_row_group_size > 0 { + cfg.limit.parquet_max_row_group_size } else { PARQUET_MAX_ROW_GROUP_SIZE }; @@ -46,11 +47,11 @@ pub fn new_parquet_writer<'a>( .set_dictionary_enabled(true) .set_encoding(Encoding::PLAIN) .set_column_dictionary_enabled( - CONFIG.common.column_timestamp.as_str().into(), + cfg.common.column_timestamp.as_str().into(), false, ) .set_column_encoding( - CONFIG.common.column_timestamp.as_str().into(), + cfg.common.column_timestamp.as_str().into(), Encoding::DELTA_BINARY_PACKED, ) .set_key_value_metadata(Some(vec![ @@ -70,9 +71,9 @@ pub fn new_parquet_writer<'a>( } // Bloom filter stored by row_group, so if the num_rows can limit to row_group_size let num_rows = min(metadata.records as u64, row_group_size as u64); - if CONFIG.common.bloom_filter_enabled { + if cfg.common.bloom_filter_enabled { // if bloom_filter_on_all_fields is true, then use all string fields - let fields = if CONFIG.common.bloom_filter_on_all_fields { + let fields = if cfg.common.bloom_filter_on_all_fields { schema .fields() .iter() diff --git a/src/config/src/utils/rand.rs b/src/config/src/utils/rand.rs index 3a1ab3e1d4..f428fc5435 100644 --- a/src/config/src/utils/rand.rs +++ b/src/config/src/utils/rand.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/utils/schema.rs b/src/config/src/utils/schema.rs index 92c49f6b1b..d1f106393e 100644 --- a/src/config/src/utils/schema.rs +++ b/src/config/src/utils/schema.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/utils/schema_ext.rs b/src/config/src/utils/schema_ext.rs index 26f1c04618..3040cdd997 100644 --- a/src/config/src/utils/schema_ext.rs +++ b/src/config/src/utils/schema_ext.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/utils/str.rs b/src/config/src/utils/str.rs index a8d78706c1..d247422309 100644 --- a/src/config/src/utils/str.rs +++ b/src/config/src/utils/str.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/config/src/utils/time.rs b/src/config/src/utils/time.rs index 51c860dc8d..d9e02678ab 100644 --- a/src/config/src/utils/time.rs +++ b/src/config/src/utils/time.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/grpc/auth/mod.rs b/src/handler/grpc/auth/mod.rs index 2cb29350b6..bba8b5ff5e 100644 --- a/src/handler/grpc/auth/mod.rs +++ b/src/handler/grpc/auth/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -13,7 +13,6 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::CONFIG; use http_auth_basic::Credentials; use tonic::{metadata::MetadataValue, Request, Status}; @@ -26,10 +25,9 @@ use crate::common::{ }; pub fn check_auth(req: Request<()>) -> Result, Status> { + let cfg = config::get_config(); let metadata = req.metadata(); - if !metadata.contains_key(&CONFIG.grpc.org_header_key) - && !metadata.contains_key("authorization") - { + if !metadata.contains_key(&cfg.grpc.org_header_key) && !metadata.contains_key("authorization") { return Err(Status::unauthenticated("No valid auth token")); } @@ -43,11 +41,11 @@ pub fn check_auth(req: Request<()>) -> Result, Status> { if token.eq(get_internal_grpc_token().as_str()) { Ok(req) } else { - let org_id = metadata.get(&CONFIG.grpc.org_header_key); + let org_id = metadata.get(&cfg.grpc.org_header_key); if org_id.is_none() { return Err(Status::invalid_argument(format!( "Please specify organization id with header key '{}' ", - &CONFIG.grpc.org_header_key + &cfg.grpc.org_header_key ))); } @@ -92,14 +90,14 @@ pub fn check_auth(req: Request<()>) -> Result, Status> { #[cfg(test)] mod tests { - use config::INSTANCE_ID; + use config::cache_instance_id; use super::*; use crate::common::meta::user::User; #[tokio::test] async fn test_check_no_auth() { - INSTANCE_ID.insert("instance_id".to_owned(), "instance".to_string()); + cache_instance_id("instance"); ROOT_USER.insert( "root".to_string(), User { @@ -128,7 +126,7 @@ mod tests { #[tokio::test] async fn test_check_auth() { - INSTANCE_ID.insert("instance_id".to_owned(), "instance".to_string()); + cache_instance_id("instance"); ROOT_USER.insert( "root".to_string(), User { @@ -155,7 +153,7 @@ mod tests { #[tokio::test] async fn test_check_err_auth() { - INSTANCE_ID.insert("instance_id".to_owned(), "instance".to_string()); + cache_instance_id("instance"); ROOT_USER.insert( "root".to_string(), User { diff --git a/src/handler/grpc/request/event.rs b/src/handler/grpc/request/event.rs index 3f2b8eafe5..5af904fa5c 100644 --- a/src/handler/grpc/request/event.rs +++ b/src/handler/grpc/request/event.rs @@ -16,10 +16,10 @@ use chrono::{Duration, Utc}; use config::{ cluster::{is_compactor, is_querier, LOCAL_NODE_ROLE, LOCAL_NODE_UUID}, + get_config, meta::{cluster::Role, stream::FileKey}, metrics, utils::parquet::read_recordbatch_from_bytes, - CONFIG, }; use hashbrown::HashSet; use infra::{file_list as infra_file_list, schema::STREAM_SCHEMAS_FIELDS}; @@ -57,11 +57,11 @@ impl Event for Eventer { .filter(|v| v.deleted) .map(|v| v.key.clone()) .collect::>(); - + let cfg = get_config(); // Warning: external meta store should not accept any file list // querier and compactor can accept add new files // ingester only accept remove old files - if !CONFIG.common.meta_store_external { + if !cfg.common.meta_store_external { if is_querier(&LOCAL_NODE_ROLE) || is_compactor(&LOCAL_NODE_ROLE) { if let Err(e) = infra_file_list::batch_add(&put_items).await { // metrics @@ -89,7 +89,7 @@ impl Event for Eventer { } // cache latest files for querier - if CONFIG.memory_cache.cache_latest_files && is_querier(&LOCAL_NODE_ROLE) { + if cfg.memory_cache.cache_latest_files && is_querier(&LOCAL_NODE_ROLE) { let mut cached_field_stream = HashSet::new(); for item in put_items.iter() { let Some(node) = get_node_from_consistent_hash(&item.key, &Role::Querier).await @@ -102,7 +102,7 @@ impl Event for Eventer { if infra::cache::file_data::download("download", &item.key) .await .is_ok() - && CONFIG.limit.quick_mode_file_list_enabled + && cfg.limit.quick_mode_file_list_enabled { let columns = item.key.split('/').collect::>(); if columns[2] != "logs" { @@ -138,7 +138,7 @@ async fn cache_latest_fields(stream: &str, file: &str) -> Result<(), anyhow::Err drop(fr); if field_cache_time - + Duration::try_seconds(CONFIG.limit.quick_mode_file_list_interval) + + Duration::try_seconds(get_config().limit.quick_mode_file_list_interval) .unwrap() .num_microseconds() .unwrap() diff --git a/src/handler/grpc/request/file_list.rs b/src/handler/grpc/request/file_list.rs index 5d71f4fef6..6de00d7ace 100644 --- a/src/handler/grpc/request/file_list.rs +++ b/src/handler/grpc/request/file_list.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/grpc/request/logs.rs b/src/handler/grpc/request/logs.rs index b0ef913b16..7c00413340 100644 --- a/src/handler/grpc/request/logs.rs +++ b/src/handler/grpc/request/logs.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -14,7 +14,6 @@ // along with this program. If not, see . use async_trait::async_trait; -use config::CONFIG; use opentelemetry_proto::tonic::collector::logs::v1::{ logs_service_server::LogsService, ExportLogsServiceRequest, ExportLogsServiceResponse, }; @@ -29,21 +28,22 @@ impl LogsService for LogsServer { &self, request: tonic::Request, ) -> Result, tonic::Status> { + let cfg = config::get_config(); let metadata = request.metadata().clone(); let msg = format!( "Please specify organization id with header key '{}' ", - &CONFIG.grpc.org_header_key + &cfg.grpc.org_header_key ); - if !metadata.contains_key(&CONFIG.grpc.org_header_key) { + if !metadata.contains_key(&cfg.grpc.org_header_key) { return Err(Status::invalid_argument(msg)); } let in_req = request.into_inner(); - let org_id = metadata.get(&CONFIG.grpc.org_header_key); + let org_id = metadata.get(&cfg.grpc.org_header_key); if org_id.is_none() { return Err(Status::invalid_argument(msg)); } - let stream_name = metadata.get(&CONFIG.grpc.stream_header_key); + let stream_name = metadata.get(&cfg.grpc.stream_header_key); let mut in_stream_name: Option<&str> = None; if let Some(stream_name) = stream_name { in_stream_name = Some(stream_name.to_str().unwrap()); diff --git a/src/handler/grpc/request/metrics/ingester.rs b/src/handler/grpc/request/metrics/ingester.rs index 4a5d8f8477..a9181e3947 100644 --- a/src/handler/grpc/request/metrics/ingester.rs +++ b/src/handler/grpc/request/metrics/ingester.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -14,7 +14,6 @@ // along with this program. If not, see . use async_trait::async_trait; -use config::CONFIG; use opentelemetry_proto::tonic::collector::metrics::v1::{ metrics_service_server::MetricsService, ExportMetricsServiceRequest, ExportMetricsServiceResponse, @@ -30,17 +29,18 @@ impl MetricsService for Ingester { &self, request: tonic::Request, ) -> Result, tonic::Status> { + let cfg = config::get_config(); let metadata = request.metadata().clone(); let msg = format!( "Please specify organization id with header key '{}' ", - &CONFIG.grpc.org_header_key + &cfg.grpc.org_header_key ); - if !metadata.contains_key(&CONFIG.grpc.org_header_key) { + if !metadata.contains_key(&cfg.grpc.org_header_key) { return Err(Status::invalid_argument(msg)); } let in_req = request.into_inner(); - let org_id = metadata.get(&CONFIG.grpc.org_header_key); + let org_id = metadata.get(&cfg.grpc.org_header_key); if org_id.is_none() { return Err(Status::invalid_argument(msg)); } diff --git a/src/handler/grpc/request/metrics/mod.rs b/src/handler/grpc/request/metrics/mod.rs index b8f1b86327..f2821e34ca 100644 --- a/src/handler/grpc/request/metrics/mod.rs +++ b/src/handler/grpc/request/metrics/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/grpc/request/metrics/querier.rs b/src/handler/grpc/request/metrics/querier.rs index 0fc2a96d2f..d8a5cede31 100644 --- a/src/handler/grpc/request/metrics/querier.rs +++ b/src/handler/grpc/request/metrics/querier.rs @@ -23,7 +23,6 @@ use config::{ parquet::{parse_time_range_from_filename, read_metadata_from_bytes}, schema_ext::SchemaExt, }, - CONFIG, }; use infra::errors; use opentelemetry::global; @@ -150,20 +149,21 @@ impl Metrics for Querier { } // get parquet files - let wal_dir = match std::path::Path::new(&CONFIG.common.data_wal_dir).canonicalize() { - Ok(path) => { - let mut path = path.to_str().unwrap().to_string(); - // Hack for windows - if path.starts_with("\\\\?\\") { - path = path[4..].to_string(); - path = path.replace('\\', "/"); + let wal_dir = + match std::path::Path::new(&config::get_config().common.data_wal_dir).canonicalize() { + Ok(path) => { + let mut path = path.to_str().unwrap().to_string(); + // Hack for windows + if path.starts_with("\\\\?\\") { + path = path[4..].to_string(); + path = path.replace('\\', "/"); + } + path } - path - } - Err(_) => { - return Ok(Response::new(resp)); - } - }; + Err(_) => { + return Ok(Response::new(resp)); + } + }; let pattern = format!("{wal_dir}/files/{org_id}/metrics/{stream_name}/"); let files = scan_files(&pattern, "parquet", None).unwrap_or_default(); diff --git a/src/handler/grpc/request/mod.rs b/src/handler/grpc/request/mod.rs index e7e2d3809c..918a4e09a4 100644 --- a/src/handler/grpc/request/mod.rs +++ b/src/handler/grpc/request/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/grpc/request/traces.rs b/src/handler/grpc/request/traces.rs index e5a35873cb..7957cff0ed 100644 --- a/src/handler/grpc/request/traces.rs +++ b/src/handler/grpc/request/traces.rs @@ -13,7 +13,6 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::CONFIG; use opentelemetry_proto::tonic::collector::trace::v1::{ trace_service_server::TraceService, ExportTraceServiceRequest, ExportTraceServiceResponse, }; @@ -30,22 +29,23 @@ impl TraceService for TraceServer { &self, request: tonic::Request, ) -> Result, tonic::Status> { + let cfg = config::get_config(); let metadata = request.metadata().clone(); let msg = format!( "Please specify organization id with header key '{}' ", - &CONFIG.grpc.org_header_key + &cfg.grpc.org_header_key ); - if !metadata.contains_key(&CONFIG.grpc.org_header_key) { + if !metadata.contains_key(&cfg.grpc.org_header_key) { return Err(Status::invalid_argument(msg)); } let in_req = request.into_inner(); - let org_id = metadata.get(&CONFIG.grpc.org_header_key); + let org_id = metadata.get(&cfg.grpc.org_header_key); if org_id.is_none() { return Err(Status::invalid_argument(msg)); } - let stream_name = metadata.get(&CONFIG.grpc.stream_header_key); + let stream_name = metadata.get(&cfg.grpc.stream_header_key); let mut in_stream_name: Option<&str> = None; if let Some(stream_name) = stream_name { in_stream_name = Some(stream_name.to_str().unwrap()); diff --git a/src/handler/grpc/request/usage.rs b/src/handler/grpc/request/usage.rs index 0a6a388971..bfe720e357 100644 --- a/src/handler/grpc/request/usage.rs +++ b/src/handler/grpc/request/usage.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -14,7 +14,6 @@ // along with this program. If not, see . use async_trait::async_trait; -use config::CONFIG; use proto::cluster_rpc::{usage_server::Usage, UsageRequest, UsageResponse}; use tonic::{Request, Response, Status}; @@ -30,7 +29,7 @@ impl Usage for UsageServerImpl { let metadata = request.metadata().clone(); let req = request.into_inner(); let report_to_stream = req.stream_name; - let report_to_org_id = metadata.get(&CONFIG.grpc.org_header_key); + let report_to_org_id = metadata.get(&config::get_config().grpc.org_header_key); let in_data = req.data.unwrap_or_default(); let resp = crate::service::logs::otlp_grpc::usage_ingest( report_to_org_id.unwrap().to_str().unwrap(), diff --git a/src/handler/http/auth/jwt.rs b/src/handler/http/auth/jwt.rs index bced55778f..7722473ee0 100644 --- a/src/handler/http/auth/jwt.rs +++ b/src/handler/http/auth/jwt.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -16,7 +16,7 @@ use std::str::FromStr; #[cfg(feature = "enterprise")] -use config::CONFIG; +use config::get_config; #[cfg(feature = "enterprise")] use jsonwebtoken::TokenData; #[cfg(feature = "enterprise")] @@ -220,7 +220,7 @@ pub async fn process_token( &org.name, &user_email, org.role.clone(), - &CONFIG.auth.root_user_email, + &get_config().auth.root_user_email, ) .await { @@ -239,8 +239,12 @@ pub async fn process_token( } for org in orgs_removed { - match users::remove_user_from_org(&org.name, &user_email, &CONFIG.auth.root_user_email) - .await + match users::remove_user_from_org( + &org.name, + &user_email, + &get_config().auth.root_user_email, + ) + .await { Ok(_) => { log::info!("User removed from the organization {}", org.name); @@ -264,7 +268,7 @@ pub async fn process_token( &org.name, &user_email, false, - &CONFIG.auth.root_user_email, + &get_config().auth.root_user_email, crate::common::meta::user::UpdateUser { role: Some(org.role.clone()), ..Default::default() diff --git a/src/handler/http/auth/mod.rs b/src/handler/http/auth/mod.rs index fdd5ca3edd..7a692e52d7 100644 --- a/src/handler/http/auth/mod.rs +++ b/src/handler/http/auth/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/auth/token.rs b/src/handler/http/auth/token.rs index e448002f1d..f063225170 100644 --- a/src/handler/http/auth/token.rs +++ b/src/handler/http/auth/token.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -20,8 +20,6 @@ use actix_web::{ http::{header, Method}, }; #[cfg(feature = "enterprise")] -use config::CONFIG; -#[cfg(feature = "enterprise")] use o2_enterprise::enterprise::{common::infra::config::O2_CONFIG, dex::service::auth::get_jwks}; use crate::common::utils::auth::AuthExtractor; @@ -44,7 +42,7 @@ pub async fn token_validator( let path = match req .request() .path() - .strip_prefix(format!("{}/api/", CONFIG.common.base_uri).as_str()) + .strip_prefix(format!("{}/api/", config::get_config().common.base_uri).as_str()) { Some(path) => path, None => req.request().path(), diff --git a/src/handler/http/auth/validator.rs b/src/handler/http/auth/validator.rs index 07e0241ced..e95e4b14d8 100644 --- a/src/handler/http/auth/validator.rs +++ b/src/handler/http/auth/validator.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -20,7 +20,7 @@ use actix_web::{ web, Error, }; use actix_web_httpauth::extractors::basic::BasicAuth; -use config::{utils::base64, CONFIG}; +use config::{get_config, utils::base64}; use crate::{ common::{ @@ -45,10 +45,11 @@ pub async fn validator( auth_info: AuthExtractor, path_prefix: &str, ) -> Result { + let cfg = get_config(); let path = match req .request() .path() - .strip_prefix(format!("{}{}", CONFIG.common.base_uri, path_prefix).as_str()) + .strip_prefix(format!("{}{}", cfg.common.base_uri, path_prefix).as_str()) { Some(path) => path, None => req.request().path(), @@ -244,10 +245,11 @@ pub async fn validator_aws( req: ServiceRequest, _credentials: Option, ) -> Result { + let cfg = get_config(); let path = req .request() .path() - .strip_prefix(format!("{}/aws/", CONFIG.common.base_uri).as_str()) + .strip_prefix(format!("{}/aws/", cfg.common.base_uri).as_str()) .unwrap_or(req.request().path()); match req.headers().get("X-Amz-Firehose-Access-Key") { @@ -288,10 +290,11 @@ pub async fn validator_gcp( req: ServiceRequest, _credentials: Option, ) -> Result { + let cfg = get_config(); let path = req .request() .path() - .strip_prefix(format!("{}/gcp/", CONFIG.common.base_uri).as_str()) + .strip_prefix(format!("{}/gcp/", cfg.common.base_uri).as_str()) .unwrap_or(req.request().path()); let query = @@ -332,7 +335,7 @@ pub async fn validator_rum( let path = req .request() .path() - .strip_prefix(format!("{}/rum/v1/", CONFIG.common.base_uri).as_str()) + .strip_prefix(format!("{}/rum/v1/", get_config().common.base_uri).as_str()) .unwrap_or(req.request().path()); // After this previous path clean we should get only the diff --git a/src/handler/http/mod.rs b/src/handler/http/mod.rs index 0f719e9acd..169c50d469 100644 --- a/src/handler/http/mod.rs +++ b/src/handler/http/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/authz/fga.rs b/src/handler/http/request/authz/fga.rs index 1c7da1ce38..1af9f0d63e 100644 --- a/src/handler/http/request/authz/fga.rs +++ b/src/handler/http/request/authz/fga.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/authz/mod.rs b/src/handler/http/request/authz/mod.rs index 56306869ee..70b14e0c9b 100644 --- a/src/handler/http/request/authz/mod.rs +++ b/src/handler/http/request/authz/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/enrichment_table/mod.rs b/src/handler/http/request/enrichment_table/mod.rs index 01b7ac44cd..7df00c10af 100644 --- a/src/handler/http/request/enrichment_table/mod.rs +++ b/src/handler/http/request/enrichment_table/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -17,7 +17,7 @@ use std::io::Error; use actix_multipart::Multipart; use actix_web::{post, web, HttpRequest, HttpResponse}; -use config::{CONFIG, SIZE_IN_MB}; +use config::SIZE_IN_MB; use hashbrown::HashMap; use crate::{ @@ -62,10 +62,11 @@ pub async fn save_enrichment_table( / SIZE_IN_MB } }; - if content_length > CONFIG.limit.enrichment_table_limit as f64 { + let cfg = config::get_config(); + if content_length > cfg.limit.enrichment_table_limit as f64 { return Ok(MetaHttpResponse::bad_request(format!( "exceeds allowed limit of {} mb", - CONFIG.limit.enrichment_table_limit + cfg.limit.enrichment_table_limit ))); } match content_type { diff --git a/src/handler/http/request/functions/mod.rs b/src/handler/http/request/functions/mod.rs index 7b38abe53d..a84fcb1819 100644 --- a/src/handler/http/request/functions/mod.rs +++ b/src/handler/http/request/functions/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/kv/mod.rs b/src/handler/http/request/kv/mod.rs index 394ce14e07..4f702f99d5 100644 --- a/src/handler/http/request/kv/mod.rs +++ b/src/handler/http/request/kv/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/logs/ingest.rs b/src/handler/http/request/logs/ingest.rs index 83f757424a..ef69de8048 100644 --- a/src/handler/http/request/logs/ingest.rs +++ b/src/handler/http/request/logs/ingest.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -16,7 +16,6 @@ use std::io::Error; use actix_web::{http, post, web, HttpRequest, HttpResponse}; -use config::CONFIG; use crate::{ common::meta::{ @@ -288,7 +287,7 @@ pub async fn otlp_logs_write( let user_email = req.headers().get("user_id").unwrap().to_str().unwrap(); let in_stream_name = req .headers() - .get(&CONFIG.grpc.stream_header_key) + .get(&config::get_config().grpc.stream_header_key) .map(|header| header.to_str().unwrap()); if content_type.eq(CONTENT_TYPE_PROTO) { // log::info!("otlp::logs_proto_handler"); diff --git a/src/handler/http/request/logs/mod.rs b/src/handler/http/request/logs/mod.rs index ad13676aa2..9558bd7dd9 100644 --- a/src/handler/http/request/logs/mod.rs +++ b/src/handler/http/request/logs/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/metrics/ingest.rs b/src/handler/http/request/metrics/ingest.rs index 534f94ca2f..92f168e18b 100644 --- a/src/handler/http/request/metrics/ingest.rs +++ b/src/handler/http/request/metrics/ingest.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/metrics/mod.rs b/src/handler/http/request/metrics/mod.rs index ad13676aa2..9558bd7dd9 100644 --- a/src/handler/http/request/metrics/mod.rs +++ b/src/handler/http/request/metrics/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/mod.rs b/src/handler/http/request/mod.rs index a6d90a009a..7dbe9029a0 100644 --- a/src/handler/http/request/mod.rs +++ b/src/handler/http/request/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/organization/es.rs b/src/handler/http/request/organization/es.rs index 209ce15c31..b0df5bd770 100644 --- a/src/handler/http/request/organization/es.rs +++ b/src/handler/http/request/organization/es.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/organization/mod.rs b/src/handler/http/request/organization/mod.rs index 11b6935ae2..774581604a 100644 --- a/src/handler/http/request/organization/mod.rs +++ b/src/handler/http/request/organization/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/organization/settings.rs b/src/handler/http/request/organization/settings.rs index 24585e31a1..339b724029 100644 --- a/src/handler/http/request/organization/settings.rs +++ b/src/handler/http/request/organization/settings.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/prom/mod.rs b/src/handler/http/request/prom/mod.rs index ae9897e59f..ea8648f7be 100644 --- a/src/handler/http/request/prom/mod.rs +++ b/src/handler/http/request/prom/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/rum/ingest.rs b/src/handler/http/request/rum/ingest.rs index 9c48eec291..f86bcd0414 100644 --- a/src/handler/http/request/rum/ingest.rs +++ b/src/handler/http/request/rum/ingest.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/rum/mod.rs b/src/handler/http/request/rum/mod.rs index ad13676aa2..9558bd7dd9 100644 --- a/src/handler/http/request/rum/mod.rs +++ b/src/handler/http/request/rum/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/search/mod.rs b/src/handler/http/request/search/mod.rs index 3b660591fd..9cf619dfce 100644 --- a/src/handler/http/request/search/mod.rs +++ b/src/handler/http/request/search/mod.rs @@ -18,14 +18,14 @@ use std::{collections::HashMap, io::Error}; use actix_web::{get, http::StatusCode, post, web, HttpRequest, HttpResponse}; use chrono::Duration; use config::{ - ider, + get_config, ider, meta::{ stream::StreamType, usage::{RequestStats, UsageType}, }, metrics, utils::{base64, json}, - CONFIG, DISTINCT_FIELDS, + DISTINCT_FIELDS, }; use infra::{errors, schema::STREAM_SCHEMAS_LATEST}; use opentelemetry::{global, trace::TraceContextExt}; @@ -123,13 +123,14 @@ pub async fn search( let start = std::time::Instant::now(); let org_id = org_id.into_inner(); + let cfg = get_config(); let mut http_span = None; - let trace_id = if CONFIG.common.tracing_enabled { + let trace_id = if cfg.common.tracing_enabled { let ctx = global::get_text_map_propagator(|propagator| { propagator.extract(&RequestHeaderExtractor::new(in_req.headers())) }); ctx.span().span_context().trace_id().to_string() - } else if CONFIG.common.tracing_search_enabled { + } else if cfg.common.tracing_search_enabled { let span = tracing::info_span!("/api/{org_id}/_search", org_id = org_id.clone()); let trace_id = span.context().span().span_context().trace_id().to_string(); http_span = Some(span); @@ -219,13 +220,14 @@ pub async fn search( } } + let cfg = get_config(); // get a local search queue lock #[cfg(not(feature = "enterprise"))] let locker = SearchService::QUEUE_LOCKER.clone(); #[cfg(not(feature = "enterprise"))] let locker = locker.lock().await; #[cfg(not(feature = "enterprise"))] - if !CONFIG.common.feature_query_queue_enabled { + if !cfg.common.feature_query_queue_enabled { drop(locker); } #[cfg(not(feature = "enterprise"))] @@ -241,7 +243,7 @@ pub async fn search( Some(user_id.to_str().unwrap().to_string()), &req, ); - let search_res = if !CONFIG.common.tracing_enabled && CONFIG.common.tracing_search_enabled { + let search_res = if !cfg.common.tracing_enabled && cfg.common.tracing_search_enabled { search_fut.instrument(http_span.unwrap()).await } else { search_fut.await @@ -388,14 +390,14 @@ pub async fn around( ) -> Result { let start = std::time::Instant::now(); let (org_id, stream_name) = path.into_inner(); - + let cfg = get_config(); let mut http_span = None; - let trace_id = if CONFIG.common.tracing_enabled { + let trace_id = if cfg.common.tracing_enabled { let ctx = global::get_text_map_propagator(|propagator| { propagator.extract(&RequestHeaderExtractor::new(in_req.headers())) }); ctx.span().span_context().trace_id().to_string() - } else if CONFIG.common.tracing_search_enabled { + } else if cfg.common.tracing_search_enabled { let span = tracing::info_span!( "/api/{org_id}/{stream_name}/_around", org_id = org_id.clone(), @@ -468,7 +470,7 @@ pub async fn around( #[cfg(not(feature = "enterprise"))] let locker = locker.lock().await; #[cfg(not(feature = "enterprise"))] - if !CONFIG.common.feature_query_queue_enabled { + if !cfg.common.feature_query_queue_enabled { drop(locker); } #[cfg(not(feature = "enterprise"))] @@ -501,7 +503,7 @@ pub async fn around( size: around_size / 2, start_time: around_start_time, end_time: around_key, - sort_by: Some(format!("{} DESC", CONFIG.common.column_timestamp)), + sort_by: Some(format!("{} DESC", cfg.common.column_timestamp)), sql_mode: "".to_string(), quick_mode: false, query_type: "".to_string(), @@ -525,7 +527,7 @@ pub async fn around( .ok() .map(|v| v.to_string()); let search_fut = SearchService::search(&trace_id, &org_id, stream_type, user_id.clone(), &req); - let search_res = if !CONFIG.common.tracing_enabled && CONFIG.common.tracing_search_enabled { + let search_res = if !cfg.common.tracing_enabled && cfg.common.tracing_search_enabled { search_fut.instrument(http_span.clone().unwrap()).await } else { search_fut.await @@ -580,7 +582,7 @@ pub async fn around( size: around_size / 2, start_time: around_key, end_time: around_end_time, - sort_by: Some(format!("{} ASC", CONFIG.common.column_timestamp)), + sort_by: Some(format!("{} ASC", cfg.common.column_timestamp)), sql_mode: "".to_string(), quick_mode: false, query_type: "".to_string(), @@ -597,7 +599,7 @@ pub async fn around( timeout, }; let search_fut = SearchService::search(&trace_id, &org_id, stream_type, user_id, &req); - let search_res = if !CONFIG.common.tracing_enabled && CONFIG.common.tracing_search_enabled { + let search_res = if !cfg.common.tracing_enabled && cfg.common.tracing_search_enabled { search_fut.instrument(http_span.unwrap()).await } else { search_fut.await @@ -769,13 +771,15 @@ pub async fn values( Some(v) => v.to_str().unwrap(), None => "", }; + + let cfg = get_config(); let mut http_span = None; - let trace_id = if CONFIG.common.tracing_enabled { + let trace_id = if cfg.common.tracing_enabled { let ctx = global::get_text_map_propagator(|propagator| { propagator.extract(&RequestHeaderExtractor::new(in_req.headers())) }); ctx.span().span_context().trace_id().to_string() - } else if CONFIG.common.tracing_search_enabled { + } else if cfg.common.tracing_search_enabled { let span = tracing::info_span!( "/api/{org_id}/{stream_name}/_values", org_id = org_id.clone(), @@ -879,9 +883,10 @@ async fn values_v1( } } + let cfg = get_config(); let default_sql = format!( "SELECT {} FROM \"{stream_name}\"", - CONFIG.common.column_timestamp + cfg.common.column_timestamp ); let mut query_sql = match query.get("filter") { None => default_sql, @@ -919,7 +924,7 @@ async fn values_v1( query_sql = RE_ONLY_SELECT .replace( &query_sql, - format!("SELECT {} ", CONFIG.common.column_timestamp).as_str(), + format!("SELECT {} ", cfg.common.column_timestamp).as_str(), ) .to_string() }; @@ -965,7 +970,7 @@ async fn values_v1( #[cfg(not(feature = "enterprise"))] let locker = locker.lock().await; #[cfg(not(feature = "enterprise"))] - if !CONFIG.common.feature_query_queue_enabled { + if !cfg.common.feature_query_queue_enabled { drop(locker); } #[cfg(not(feature = "enterprise"))] @@ -1028,7 +1033,7 @@ async fn values_v1( Some(user_id.to_string()), &req, ); - let search_res = if !CONFIG.common.tracing_enabled && CONFIG.common.tracing_search_enabled { + let search_res = if !cfg.common.tracing_enabled && cfg.common.tracing_search_enabled { search_fut.instrument(http_span.unwrap()).await } else { search_fut.await @@ -1203,13 +1208,14 @@ async fn values_v2( .get("timeout") .map_or(0, |v| v.parse::().unwrap_or(0)); + let cfg = get_config(); // get a local search queue lock #[cfg(not(feature = "enterprise"))] let locker = SearchService::QUEUE_LOCKER.clone(); #[cfg(not(feature = "enterprise"))] let locker = locker.lock().await; #[cfg(not(feature = "enterprise"))] - if !CONFIG.common.feature_query_queue_enabled { + if !cfg.common.feature_query_queue_enabled { drop(locker); } #[cfg(not(feature = "enterprise"))] @@ -1249,7 +1255,7 @@ async fn values_v2( Some(user_id.to_string()), &req, ); - let search_res = if !CONFIG.common.tracing_enabled && CONFIG.common.tracing_search_enabled { + let search_res = if !cfg.common.tracing_enabled && cfg.common.tracing_search_enabled { search_fut.instrument(http_span.unwrap()).await } else { search_fut.await @@ -1393,14 +1399,14 @@ pub async fn search_partition( body: web::Bytes, ) -> Result { let start = std::time::Instant::now(); - + let cfg = get_config(); let mut http_span = None; - let trace_id = if CONFIG.common.tracing_enabled { + let trace_id = if cfg.common.tracing_enabled { let ctx = global::get_text_map_propagator(|propagator| { propagator.extract(&RequestHeaderExtractor::new(in_req.headers())) }); ctx.span().span_context().trace_id().to_string() - } else if CONFIG.common.tracing_search_enabled { + } else if cfg.common.tracing_search_enabled { let span = tracing::info_span!("/api/{org_id}/_search_partition", org_id = org_id.clone()); let trace_id = span.context().span().span_context().trace_id().to_string(); http_span = Some(span); @@ -1425,7 +1431,7 @@ pub async fn search_partition( } let search_fut = SearchService::search_partition(&trace_id, &org_id, stream_type, &req); - let search_res = if !CONFIG.common.tracing_enabled && CONFIG.common.tracing_search_enabled { + let search_res = if !cfg.common.tracing_enabled && cfg.common.tracing_search_enabled { search_fut.instrument(http_span.unwrap()).await } else { search_fut.await diff --git a/src/handler/http/request/search/saved_view.rs b/src/handler/http/request/search/saved_view.rs index b10785438b..d32111be48 100644 --- a/src/handler/http/request/search/saved_view.rs +++ b/src/handler/http/request/search/saved_view.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/status/mod.rs b/src/handler/http/request/status/mod.rs index b12a6c2374..0d15c17215 100644 --- a/src/handler/http/request/status/mod.rs +++ b/src/handler/http/request/status/mod.rs @@ -25,9 +25,10 @@ use actix_web::{ use arrow_schema::Schema; use config::{ cluster::{is_ingester, LOCAL_NODE_ROLE, LOCAL_NODE_UUID}, + get_config, get_instance_id, meta::cluster::NodeStatus, utils::{json, schema_ext::SchemaExt}, - CONFIG, INSTANCE_ID, QUICK_MODEL_FIELDS, SQL_FULL_TEXT_SEARCH_FIELDS, + QUICK_MODEL_FIELDS, SQL_FULL_TEXT_SEARCH_FIELDS, }; use hashbrown::HashMap; use infra::{ @@ -216,60 +217,62 @@ pub async fn zo_config() -> Result { #[cfg(not(feature = "enterprise"))] let build_type = "opensource"; + let cfg = get_config(); Ok(HttpResponse::Ok().json(ConfigResponse { version: VERSION.to_string(), - instance: INSTANCE_ID.get("instance_id").unwrap().to_string(), + instance: get_instance_id(), commit_hash: COMMIT_HASH.to_string(), build_date: BUILD_DATE.to_string(), build_type: build_type.to_string(), - telemetry_enabled: CONFIG.common.telemetry_enabled, + telemetry_enabled: cfg.common.telemetry_enabled, default_fts_keys: SQL_FULL_TEXT_SEARCH_FIELDS .iter() .map(|s| s.to_string()) .collect(), default_quick_mode_fields: QUICK_MODEL_FIELDS.to_vec(), default_functions: DEFAULT_FUNCTIONS.to_vec(), - sql_base64_enabled: CONFIG.common.ui_sql_base64_enabled, - timestamp_column: CONFIG.common.column_timestamp.clone(), + sql_base64_enabled: cfg.common.ui_sql_base64_enabled, + timestamp_column: cfg.common.column_timestamp.clone(), syslog_enabled: *SYSLOG_ENABLED.read(), - data_retention_days: CONFIG.compact.data_retention_days, - restricted_routes_on_empty_data: CONFIG.common.restricted_routes_on_empty_data, + data_retention_days: cfg.compact.data_retention_days, + restricted_routes_on_empty_data: cfg.common.restricted_routes_on_empty_data, sso_enabled, native_login_enabled, rbac_enabled, super_cluster_enabled, - query_on_stream_selection: CONFIG.common.query_on_stream_selection, - show_stream_stats_doc_num: CONFIG.common.show_stream_dates_doc_num, + query_on_stream_selection: cfg.common.query_on_stream_selection, + show_stream_stats_doc_num: cfg.common.show_stream_dates_doc_num, custom_logo_text, custom_slack_url: custom_slack_url.to_string(), custom_docs_url: custom_docs_url.to_string(), custom_logo_img: logo, custom_hide_menus: custom_hide_menus.to_string(), rum: Rum { - enabled: CONFIG.rum.enabled, - client_token: CONFIG.rum.client_token.to_string(), - application_id: CONFIG.rum.application_id.to_string(), - site: CONFIG.rum.site.to_string(), - service: CONFIG.rum.service.to_string(), - env: CONFIG.rum.env.to_string(), - version: CONFIG.rum.version.to_string(), - organization_identifier: CONFIG.rum.organization_identifier.to_string(), - api_version: CONFIG.rum.api_version.to_string(), - insecure_http: CONFIG.rum.insecure_http, + enabled: cfg.rum.enabled, + client_token: cfg.rum.client_token.to_string(), + application_id: cfg.rum.application_id.to_string(), + site: cfg.rum.site.to_string(), + service: cfg.rum.service.to_string(), + env: cfg.rum.env.to_string(), + version: cfg.rum.version.to_string(), + organization_identifier: cfg.rum.organization_identifier.to_string(), + api_version: cfg.rum.api_version.to_string(), + insecure_http: cfg.rum.insecure_http, }, - meta_org: CONFIG.common.usage_org.to_string(), - quick_mode_enabled: CONFIG.limit.quick_mode_enabled, - user_defined_schemas_enabled: CONFIG.common.allow_user_defined_schemas, - all_fields_name: CONFIG.common.all_fields_name.to_string(), + meta_org: cfg.common.usage_org.to_string(), + quick_mode_enabled: cfg.limit.quick_mode_enabled, + user_defined_schemas_enabled: cfg.common.allow_user_defined_schemas, + all_fields_name: cfg.common.all_fields_name.to_string(), })) } #[get("/status")] pub async fn cache_status() -> Result { + let cfg = get_config(); let mut stats: HashMap<&str, json::Value> = HashMap::default(); stats.insert("LOCAL_NODE_UUID", json::json!(LOCAL_NODE_UUID.clone())); - stats.insert("LOCAL_NODE_NAME", json::json!(&CONFIG.common.instance_name)); - stats.insert("LOCAL_NODE_ROLE", json::json!(&CONFIG.common.node_role)); + stats.insert("LOCAL_NODE_NAME", json::json!(&cfg.common.instance_name)); + stats.insert("LOCAL_NODE_ROLE", json::json!(&cfg.common.node_role)); let nodes = cluster::get_cached_online_nodes().await; stats.insert("NODE_LIST", json::json!(nodes)); @@ -318,6 +321,17 @@ pub async fn cache_status() -> Result { Ok(HttpResponse::Ok().json(stats)) } +#[get("")] +pub async fn config_reload() -> Result { + if let Err(e) = config::refresh_config() { + return Ok( + HttpResponse::InternalServerError().json(serde_json::json!({"status": e.to_string()})) + ); + } + let status = "succcessfully reloaded config"; + Ok(HttpResponse::Ok().json(serde_json::json!({"status": status}))) +} + async fn get_stream_schema_status() -> (usize, usize, usize) { let mut stream_num = 0; let mut stream_schema_num = 0; @@ -424,15 +438,16 @@ pub async fn redirect(req: HttpRequest) -> Result { }) .unwrap(); + let cfg = get_config(); let mut auth_cookie = Cookie::new("auth_tokens", tokens); auth_cookie.set_expires( cookie::time::OffsetDateTime::now_utc() - + cookie::time::Duration::seconds(CONFIG.auth.cookie_max_age), + + cookie::time::Duration::seconds(cfg.auth.cookie_max_age), ); auth_cookie.set_http_only(true); - auth_cookie.set_secure(CONFIG.auth.cookie_secure_only); + auth_cookie.set_secure(cfg.auth.cookie_secure_only); auth_cookie.set_path("/"); - if CONFIG.auth.cookie_same_site_lax { + if cfg.auth.cookie_same_site_lax { auth_cookie.set_same_site(SameSite::Lax); } else { auth_cookie.set_same_site(SameSite::None); @@ -462,6 +477,7 @@ pub async fn dex_login() -> Result { #[cfg(feature = "enterprise")] #[get("/dex_refresh")] async fn refresh_token_with_dex(req: actix_web::HttpRequest) -> HttpResponse { + let cfg = get_config(); let token = if let Some(cookie) = req.cookie("auth_tokens") { let auth_tokens: AuthTokens = json::from_str(cookie.value()).unwrap_or_default(); @@ -498,12 +514,12 @@ async fn refresh_token_with_dex(req: actix_web::HttpRequest) -> HttpResponse { let mut auth_cookie = Cookie::new("auth_tokens", tokens); auth_cookie.set_expires( cookie::time::OffsetDateTime::now_utc() - + cookie::time::Duration::seconds(CONFIG.auth.cookie_max_age), + + cookie::time::Duration::seconds(cfg.auth.cookie_max_age), ); auth_cookie.set_http_only(true); - auth_cookie.set_secure(CONFIG.auth.cookie_secure_only); + auth_cookie.set_secure(cfg.auth.cookie_secure_only); auth_cookie.set_path("/"); - if CONFIG.auth.cookie_same_site_lax { + if cfg.auth.cookie_same_site_lax { auth_cookie.set_same_site(SameSite::Lax); } else { auth_cookie.set_same_site(SameSite::None); @@ -516,12 +532,12 @@ async fn refresh_token_with_dex(req: actix_web::HttpRequest) -> HttpResponse { let mut auth_cookie = Cookie::new("auth_tokens", tokens); auth_cookie.set_expires( cookie::time::OffsetDateTime::now_utc() - + cookie::time::Duration::seconds(CONFIG.auth.cookie_max_age), + + cookie::time::Duration::seconds(cfg.auth.cookie_max_age), ); auth_cookie.set_http_only(true); - auth_cookie.set_secure(CONFIG.auth.cookie_secure_only); + auth_cookie.set_secure(cfg.auth.cookie_secure_only); auth_cookie.set_path("/"); - if CONFIG.auth.cookie_same_site_lax { + if cfg.auth.cookie_same_site_lax { auth_cookie.set_same_site(SameSite::Lax); } else { auth_cookie.set_same_site(SameSite::None); @@ -548,16 +564,17 @@ async fn logout(req: actix_web::HttpRequest) -> HttpResponse { } }; + let cfg = get_config(); let tokens = json::to_string(&AuthTokens::default()).unwrap(); let mut auth_cookie = Cookie::new("auth_tokens", tokens); auth_cookie.set_expires( cookie::time::OffsetDateTime::now_utc() - + cookie::time::Duration::seconds(CONFIG.auth.cookie_max_age), + + cookie::time::Duration::seconds(cfg.auth.cookie_max_age), ); auth_cookie.set_http_only(true); - auth_cookie.set_secure(CONFIG.auth.cookie_secure_only); + auth_cookie.set_secure(cfg.auth.cookie_secure_only); auth_cookie.set_path("/"); - if CONFIG.auth.cookie_same_site_lax { + if cfg.auth.cookie_same_site_lax { auth_cookie.set_same_site(SameSite::Lax); } else { auth_cookie.set_same_site(SameSite::None); diff --git a/src/handler/http/request/syslog/mod.rs b/src/handler/http/request/syslog/mod.rs index 9fd5351c40..b16d24d00f 100644 --- a/src/handler/http/request/syslog/mod.rs +++ b/src/handler/http/request/syslog/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/http/request/traces/mod.rs b/src/handler/http/request/traces/mod.rs index c35fed9d7b..0bb0a44ee6 100644 --- a/src/handler/http/request/traces/mod.rs +++ b/src/handler/http/request/traces/mod.rs @@ -16,7 +16,7 @@ use std::{collections::HashMap, io::Error}; use actix_web::{get, http, post, web, HttpRequest, HttpResponse}; -use config::{ider, meta::stream::StreamType, metrics, utils::json, CONFIG}; +use config::{get_config, ider, meta::stream::StreamType, metrics, utils::json}; use infra::errors; use opentelemetry::{global, trace::TraceContextExt}; use serde::Serialize; @@ -76,7 +76,7 @@ async fn handle_req( let content_type = req.headers().get("Content-Type").unwrap().to_str().unwrap(); let in_stream_name = req .headers() - .get(&CONFIG.grpc.stream_header_key) + .get(&get_config().grpc.stream_header_key) .map(|header| header.to_str().unwrap()); if content_type.eq(CONTENT_TYPE_PROTO) { otlp_http::traces_proto(&org_id, **thread_id, body, in_stream_name).await @@ -136,14 +136,14 @@ pub async fn get_latest_traces( ) -> Result { let start = std::time::Instant::now(); let (org_id, stream_name) = path.into_inner(); - + let cfg = get_config(); let mut http_span = None; - let trace_id = if CONFIG.common.tracing_enabled { + let trace_id = if cfg.common.tracing_enabled { let ctx = global::get_text_map_propagator(|propagator| { propagator.extract(&RequestHeaderExtractor::new(in_req.headers())) }); ctx.span().span_context().trace_id().to_string() - } else if CONFIG.common.tracing_search_enabled { + } else if cfg.common.tracing_search_enabled { let span = tracing::info_span!( "/api/{org_id}/{stream_name}/traces/latest", org_id = org_id.clone(), @@ -221,13 +221,14 @@ pub async fn get_latest_traces( .get("timeout") .map_or(0, |v| v.parse::().unwrap_or(0)); + let cfg = get_config(); // get a local search queue lock #[cfg(not(feature = "enterprise"))] let locker = SearchService::QUEUE_LOCKER.clone(); #[cfg(not(feature = "enterprise"))] let locker = locker.lock().await; #[cfg(not(feature = "enterprise"))] - if !CONFIG.common.feature_query_queue_enabled { + if !cfg.common.feature_query_queue_enabled { drop(locker); } #[cfg(not(feature = "enterprise"))] @@ -239,7 +240,7 @@ pub async fn get_latest_traces( // search let query_sql = format!( "SELECT trace_id, min({}) as zo_sql_timestamp, min(start_time) as trace_start_time, max(end_time) as trace_end_time FROM {stream_name}", - CONFIG.common.column_timestamp + cfg.common.column_timestamp ); let query_sql = if filter.is_empty() { format!("{query_sql} GROUP BY trace_id ORDER BY zo_sql_timestamp DESC") @@ -279,7 +280,7 @@ pub async fn get_latest_traces( .map(|v| v.to_string()); let search_fut = SearchService::search(&trace_id, &org_id, stream_type, user_id.clone(), &req); - let search_res = if !CONFIG.common.tracing_enabled && CONFIG.common.tracing_search_enabled { + let search_res = if !cfg.common.tracing_enabled && cfg.common.tracing_search_enabled { search_fut.instrument(http_span.clone().unwrap()).await } else { search_fut.await @@ -360,7 +361,7 @@ pub async fn get_latest_traces( .join("','"); let query_sql = format!( "SELECT {}, trace_id, start_time, end_time, duration, service_name, operation_name, span_status FROM {stream_name} WHERE trace_id IN ('{}') ORDER BY {} ASC", - CONFIG.common.column_timestamp, trace_ids, CONFIG.common.column_timestamp, + cfg.common.column_timestamp, trace_ids, cfg.common.column_timestamp, ); req.query.from = 0; req.query.size = 9999; @@ -372,7 +373,7 @@ pub async fn get_latest_traces( loop { let search_fut = SearchService::search(&trace_id, &org_id, stream_type, user_id.clone(), &req); - let search_res = if !CONFIG.common.tracing_enabled && CONFIG.common.tracing_search_enabled { + let search_res = if !cfg.common.tracing_enabled && cfg.common.tracing_search_enabled { search_fut.instrument(http_span.clone().unwrap()).await } else { search_fut.await diff --git a/src/handler/http/request/users/mod.rs b/src/handler/http/request/users/mod.rs index 50a86603c1..740867ac76 100644 --- a/src/handler/http/request/users/mod.rs +++ b/src/handler/http/request/users/mod.rs @@ -21,8 +21,8 @@ use actix_web::{ post, put, web, HttpRequest, HttpResponse, }; use config::{ + get_config, utils::{base64, json}, - CONFIG, }; use strum::IntoEnumIterator; @@ -275,6 +275,7 @@ pub async fn authentication( } }; if resp.status { + let cfg = get_config(); let access_token = format!( "Basic {}", base64::encode(&format!("{}:{}", auth.name, auth.password)) @@ -287,12 +288,12 @@ pub async fn authentication( let mut auth_cookie = cookie::Cookie::new("auth_tokens", tokens); auth_cookie.set_expires( cookie::time::OffsetDateTime::now_utc() - + cookie::time::Duration::seconds(CONFIG.auth.cookie_max_age), + + cookie::time::Duration::seconds(cfg.auth.cookie_max_age), ); auth_cookie.set_http_only(true); - auth_cookie.set_secure(CONFIG.auth.cookie_secure_only); + auth_cookie.set_secure(cfg.auth.cookie_secure_only); auth_cookie.set_path("/"); - if CONFIG.auth.cookie_same_site_lax { + if cfg.auth.cookie_same_site_lax { auth_cookie.set_same_site(cookie::SameSite::Lax); } else { auth_cookie.set_same_site(cookie::SameSite::None); @@ -311,6 +312,7 @@ pub async fn get_auth(_req: HttpRequest) -> Result { use crate::handler::http::auth::validator::ID_TOKEN_HEADER; + let cfg = get_config(); let mut resp = SignInResponse::default(); if let Some(auth_header) = _req.headers().get("Authorization") { if let Ok(auth_header) = auth_header.to_str() { @@ -351,21 +353,21 @@ pub async fn get_auth(_req: HttpRequest) -> Result { let mut auth_cookie = cookie::Cookie::new("auth_tokens", tokens); auth_cookie.set_expires( cookie::time::OffsetDateTime::now_utc() - + cookie::time::Duration::seconds(CONFIG.auth.cookie_max_age), + + cookie::time::Duration::seconds(cfg.auth.cookie_max_age), ); auth_cookie.set_http_only(true); - auth_cookie.set_secure(CONFIG.auth.cookie_secure_only); + auth_cookie.set_secure(cfg.auth.cookie_secure_only); auth_cookie.set_path("/"); - if CONFIG.auth.cookie_same_site_lax { + if cfg.auth.cookie_same_site_lax { auth_cookie.set_same_site(cookie::SameSite::Lax); } else { auth_cookie.set_same_site(cookie::SameSite::None); } let url = format!( "{}{}/web/cb#id_token={}.{}", - CONFIG.common.web_url, - CONFIG.common.base_uri, + cfg.common.web_url, + cfg.common.base_uri, ID_TOKEN_HEADER, base64::encode(&id_token.to_string()) ); diff --git a/src/handler/http/router/mod.rs b/src/handler/http/router/mod.rs index 2a19e62908..4a207285c9 100644 --- a/src/handler/http/router/mod.rs +++ b/src/handler/http/router/mod.rs @@ -24,7 +24,7 @@ use actix_web::{ }; use actix_web_httpauth::middleware::HttpAuthentication; use actix_web_lab::middleware::{from_fn, Next}; -use config::CONFIG; +use config::get_config; use futures::FutureExt; use utoipa::OpenApi; use utoipa_swagger_ui::SwaggerUi; @@ -84,7 +84,7 @@ async fn audit_middleware( next: Next, ) -> Result, actix_web::Error> { let method = req.method().to_string(); - let prefix = format!("{}/api/", CONFIG.common.base_uri); + let prefix = format!("{}/api/", get_config().common.base_uri); let path = req.path().strip_prefix(&prefix).unwrap().to_string(); let path_columns = path.split('/').collect::>(); let path_len = path_columns.len(); @@ -219,7 +219,7 @@ pub fn get_basic_routes(cfg: &mut web::ServiceConfig) { cfg.service( SwaggerUi::new("/swagger/{_:.*}") .url( - format!("{}/api-doc/openapi.json", CONFIG.common.base_uri), + format!("{}/api-doc/openapi.json", get_config().common.base_uri), openapi::ApiDoc::openapi(), ) .url("/api-doc/openapi.json", openapi::ApiDoc::openapi()), @@ -227,13 +227,14 @@ pub fn get_basic_routes(cfg: &mut web::ServiceConfig) { cfg.service(web::redirect("/swagger", "/swagger/")); cfg.service(web::redirect("/docs", "/swagger/")); - if CONFIG.common.ui_enabled { + if get_config().common.ui_enabled { cfg.service(web::redirect("/", "./web/")); cfg.service(web::redirect("/web", "./web/")); cfg.service( web::scope("/web") .wrap_fn(|req, srv| { - let prefix = format!("{}/web/", CONFIG.common.base_uri); + let cfg = get_config(); + let prefix = format!("{}/web/", cfg.common.base_uri); let path = req.path().strip_prefix(&prefix).unwrap().to_string(); srv.call(req).map(move |res| { @@ -272,9 +273,10 @@ pub fn get_config_routes(cfg: &mut web::ServiceConfig) { let cors = get_cors(); cfg.service( web::scope("/config") - .wrap(cors) + .wrap(cors.clone()) .service(status::zo_config) - .service(status::logout), + .service(status::logout) + .service(web::scope("/reload").service(status::config_reload)), ); } @@ -288,13 +290,13 @@ pub fn get_config_routes(cfg: &mut web::ServiceConfig) { .service(status::redirect) .service(status::dex_login) .service(status::refresh_token_with_dex) - .service(status::logout), + .service(status::logout) + .service(web::scope("/reload").service(status::config_reload)), ); } pub fn get_service_routes(cfg: &mut web::ServiceConfig) { let cors = get_cors(); - // set server header #[cfg(feature = "enterprise")] let server = format!( @@ -302,10 +304,10 @@ pub fn get_service_routes(cfg: &mut web::ServiceConfig) { o2_enterprise::enterprise::common::infra::config::O2_CONFIG .super_cluster .region, - CONFIG.common.instance_name_short + get_config().common.instance_name_short ); #[cfg(not(feature = "enterprise"))] - let server = CONFIG.common.instance_name_short.to_string(); + let server = get_config().common.instance_name_short.to_string(); cfg.service( web::scope("/api") diff --git a/src/handler/http/router/openapi.rs b/src/handler/http/router/openapi.rs index 5a1b2bfb5d..da824ec73e 100644 --- a/src/handler/http/router/openapi.rs +++ b/src/handler/http/router/openapi.rs @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::{meta::stream::StreamType, CONFIG}; +use config::{get_config, meta::stream::StreamType}; use utoipa::{openapi::security::SecurityScheme, Modify, OpenApi}; use crate::{common::meta, handler::http::request}; @@ -246,8 +246,9 @@ pub struct SecurityAddon; impl Modify for SecurityAddon { fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) { - if !CONFIG.common.base_uri.is_empty() { - openapi.servers = Some(vec![utoipa::openapi::Server::new(&CONFIG.common.base_uri)]); + let cfg = get_config(); + if !cfg.common.base_uri.is_empty() { + openapi.servers = Some(vec![utoipa::openapi::Server::new(&cfg.common.base_uri)]); } let components = openapi.components.as_mut().unwrap(); components.add_security_scheme( diff --git a/src/handler/http/router/ui.rs b/src/handler/http/router/ui.rs index bb9f50e979..98f8ca6119 100644 --- a/src/handler/http/router/ui.rs +++ b/src/handler/http/router/ui.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/mod.rs b/src/handler/mod.rs index dd4f8f53d2..2672bc5ad8 100644 --- a/src/handler/mod.rs +++ b/src/handler/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/handler/tcp_udp/mod.rs b/src/handler/tcp_udp/mod.rs index 071b90e1ac..c36e121a5a 100644 --- a/src/handler/tcp_udp/mod.rs +++ b/src/handler/tcp_udp/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/infra/src/cache/file_data/disk.rs b/src/infra/src/cache/file_data/disk.rs index e111e0d684..6f1313b297 100644 --- a/src/infra/src/cache/file_data/disk.rs +++ b/src/infra/src/cache/file_data/disk.rs @@ -22,12 +22,11 @@ use std::{ use async_recursion::async_recursion; use bytes::Bytes; use config::{ - is_local_disk_storage, metrics, + get_config, is_local_disk_storage, metrics, utils::{ asynchronism::file::*, hash::{gxhash, Sum32}, }, - CONFIG, }; use once_cell::sync::Lazy; use tokio::{fs, sync::RwLock}; @@ -36,8 +35,9 @@ use super::CacheStrategy; use crate::storage; static FILES: Lazy>> = Lazy::new(|| { - let mut files = Vec::with_capacity(CONFIG.disk_cache.bucket_num); - for _ in 0..CONFIG.disk_cache.bucket_num { + let cfg = get_config(); + let mut files = Vec::with_capacity(cfg.disk_cache.bucket_num); + for _ in 0..cfg.disk_cache.bucket_num { files.push(RwLock::new(FileData::new())); } files @@ -59,22 +59,24 @@ impl Default for FileData { impl FileData { pub fn new() -> FileData { + let cfg = get_config(); FileData::with_capacity_and_cache_strategy( - CONFIG.disk_cache.max_size, - &CONFIG.disk_cache.cache_strategy, + cfg.disk_cache.max_size, + &cfg.disk_cache.cache_strategy, ) } pub fn with_capacity_and_cache_strategy(max_size: usize, strategy: &str) -> FileData { + let cfg = get_config(); FileData { max_size, cur_size: 0, root_dir: format!( "{}{}", - CONFIG.common.data_cache_dir, + cfg.common.data_cache_dir, storage::format_key("", true) ), - multi_dir: CONFIG + multi_dir: cfg .disk_cache .multi_dir .split(',') @@ -114,7 +116,7 @@ impl FileData { // cache is full, need release some space let need_release_size = min( self.max_size, - max(CONFIG.disk_cache.release_size, data_size * 100), + max(get_config().disk_cache.release_size, data_size * 100), ); self.gc(trace_id, need_release_size).await?; } @@ -210,6 +212,7 @@ impl FileData { } pub async fn init() -> Result<(), anyhow::Error> { + let cfg = get_config(); for file in FILES.iter() { let root_dir = file.read().await.root_dir.clone(); std::fs::create_dir_all(&root_dir).expect("create cache dir success"); @@ -226,12 +229,11 @@ pub async fn init() -> Result<(), anyhow::Error> { }); tokio::task::spawn(async move { - if CONFIG.disk_cache.gc_interval == 0 { + if cfg.disk_cache.gc_interval == 0 { return; } - let mut interval = tokio::time::interval(tokio::time::Duration::from_secs( - config::CONFIG.disk_cache.gc_interval, - )); + let mut interval = + tokio::time::interval(tokio::time::Duration::from_secs(cfg.disk_cache.gc_interval)); interval.tick().await; // the first tick is immediate loop { if let Err(e) = gc().await { @@ -245,7 +247,7 @@ pub async fn init() -> Result<(), anyhow::Error> { #[inline] pub async fn get(file: &str, range: Option>) -> Option { - if !CONFIG.disk_cache.enabled { + if !get_config().disk_cache.enabled { return None; } let idx = get_bucket_idx(file); @@ -255,7 +257,7 @@ pub async fn get(file: &str, range: Option>) -> Option { #[inline] pub async fn exist(file: &str) -> bool { - if !CONFIG.disk_cache.enabled { + if !get_config().disk_cache.enabled { return false; } let idx = get_bucket_idx(file); @@ -265,7 +267,7 @@ pub async fn exist(file: &str) -> bool { #[inline] pub async fn set(trace_id: &str, file: &str, data: Bytes) -> Result<(), anyhow::Error> { - if !CONFIG.disk_cache.enabled || is_local_disk_storage() { + if !get_config().disk_cache.enabled || is_local_disk_storage() { return Ok(()); } let idx = get_bucket_idx(file); @@ -318,7 +320,7 @@ async fn load(root_dir: &PathBuf, scan_dir: &PathBuf) -> Result<(), anyhow::Erro .unwrap() .replace('\\', "/"); - if !CONFIG.disk_cache.multi_dir.is_empty() { + if !get_config().disk_cache.multi_dir.is_empty() { file_key = file_key.split('/').skip(1).collect::>().join("/"); } // check file already exists @@ -352,18 +354,19 @@ async fn load(root_dir: &PathBuf, scan_dir: &PathBuf) -> Result<(), anyhow::Erro } async fn gc() -> Result<(), anyhow::Error> { - if !CONFIG.disk_cache.enabled || is_local_disk_storage() { + let cfg = get_config(); + if !cfg.disk_cache.enabled || is_local_disk_storage() { return Ok(()); } for file in FILES.iter() { let r = file.read().await; - if r.cur_size + CONFIG.disk_cache.release_size < r.max_size { + if r.cur_size + cfg.disk_cache.release_size < r.max_size { drop(r); continue; } drop(r); let mut w = file.write().await; - w.gc("global", CONFIG.disk_cache.gc_size).await?; + w.gc("global", cfg.disk_cache.gc_size).await?; drop(w); } Ok(()) @@ -419,11 +422,12 @@ pub async fn download(trace_id: &str, file: &str) -> Result<(), anyhow::Error> { } fn get_bucket_idx(file: &str) -> usize { - if CONFIG.disk_cache.bucket_num <= 1 { + let cfg = get_config(); + if cfg.disk_cache.bucket_num <= 1 { 0 } else { let h = gxhash::new().sum32(file); - (h as usize) % CONFIG.disk_cache.bucket_num + (h as usize) % cfg.disk_cache.bucket_num } } @@ -450,7 +454,7 @@ mod tests { async fn test_lru_cache_get_file() { let trace_id = "session_123"; let mut file_data = - FileData::with_capacity_and_cache_strategy(CONFIG.disk_cache.max_size, "lru"); + FileData::with_capacity_and_cache_strategy(get_config().disk_cache.max_size, "lru"); let file_key = "files/default/logs/olympics/2022/10/03/10/6982652937134804993_2_1.parquet"; let content = Bytes::from("Some text"); @@ -510,7 +514,7 @@ mod tests { async fn test_fifo_cache_get_file() { let trace_id = "session_123"; let mut file_data = - FileData::with_capacity_and_cache_strategy(CONFIG.disk_cache.max_size, "fifo"); + FileData::with_capacity_and_cache_strategy(get_config().disk_cache.max_size, "fifo"); let file_key = "files/default/logs/olympics/2022/10/03/10/6982652937134804993_2_1.parquet"; let content = Bytes::from("Some text"); @@ -561,7 +565,7 @@ mod tests { let trace_id = "session_123"; let mut file_data = - FileData::with_capacity_and_cache_strategy(CONFIG.disk_cache.max_size, "lru"); + FileData::with_capacity_and_cache_strategy(get_config().disk_cache.max_size, "lru"); file_data.multi_dir = multi_dir; let file_key = "files/default/logs/olympics/2022/10/03/10/6982652937134804993_2_1.parquet"; let content = Bytes::from("Some text"); diff --git a/src/infra/src/cache/file_data/memory.rs b/src/infra/src/cache/file_data/memory.rs index 86224bd5bb..1627b863bf 100644 --- a/src/infra/src/cache/file_data/memory.rs +++ b/src/infra/src/cache/file_data/memory.rs @@ -20,9 +20,9 @@ use std::{ use bytes::Bytes; use config::{ - metrics, + get_config, metrics, utils::hash::{gxhash, Sum32}, - RwHashMap, CONFIG, + RwHashMap, }; use once_cell::sync::Lazy; use tokio::sync::RwLock; @@ -31,15 +31,17 @@ use super::CacheStrategy; use crate::storage; static FILES: Lazy>> = Lazy::new(|| { - let mut files = Vec::with_capacity(CONFIG.memory_cache.bucket_num); - for _ in 0..CONFIG.memory_cache.bucket_num { + let cfg = get_config(); + let mut files = Vec::with_capacity(cfg.memory_cache.bucket_num); + for _ in 0..cfg.memory_cache.bucket_num { files.push(RwLock::new(FileData::new())); } files }); static DATA: Lazy>> = Lazy::new(|| { - let mut datas = Vec::with_capacity(CONFIG.memory_cache.bucket_num); - for _ in 0..CONFIG.memory_cache.bucket_num { + let cfg = get_config(); + let mut datas = Vec::with_capacity(cfg.memory_cache.bucket_num); + for _ in 0..cfg.memory_cache.bucket_num { datas.push(Default::default()); } datas @@ -59,9 +61,10 @@ impl Default for FileData { impl FileData { pub fn new() -> FileData { + let cfg = get_config(); FileData::with_capacity_and_cache_strategy( - CONFIG.memory_cache.max_size, - &CONFIG.memory_cache.cache_strategy, + cfg.memory_cache.max_size, + &cfg.memory_cache.cache_strategy, ) } @@ -97,7 +100,7 @@ impl FileData { // cache is full, need release some space let need_release_size = min( self.max_size, - max(CONFIG.memory_cache.release_size, data_size * 100), + max(get_config().memory_cache.release_size, data_size * 100), ); self.gc(trace_id, need_release_size).await?; } @@ -180,16 +183,18 @@ impl FileData { } pub async fn init() -> Result<(), anyhow::Error> { + let cfg = get_config(); + for file in FILES.iter() { _ = file.read().await.get("", None).await; } tokio::task::spawn(async move { - if CONFIG.memory_cache.gc_interval == 0 { + if cfg.memory_cache.gc_interval == 0 { return; } let mut interval = tokio::time::interval(tokio::time::Duration::from_secs( - config::CONFIG.memory_cache.gc_interval, + cfg.memory_cache.gc_interval, )); interval.tick().await; // the first tick is immediate loop { @@ -204,7 +209,7 @@ pub async fn init() -> Result<(), anyhow::Error> { #[inline] pub async fn get(file: &str, range: Option>) -> Option { - if !CONFIG.memory_cache.enabled { + if !get_config().memory_cache.enabled { return None; } let idx = get_bucket_idx(file); @@ -214,7 +219,7 @@ pub async fn get(file: &str, range: Option>) -> Option { #[inline] pub async fn exist(file: &str) -> bool { - if !CONFIG.memory_cache.enabled { + if !get_config().memory_cache.enabled { return false; } let idx = get_bucket_idx(file); @@ -224,7 +229,7 @@ pub async fn exist(file: &str) -> bool { #[inline] pub async fn set(trace_id: &str, file: &str, data: Bytes) -> Result<(), anyhow::Error> { - if !CONFIG.memory_cache.enabled { + if !get_config().memory_cache.enabled { return Ok(()); } let idx = get_bucket_idx(file); @@ -236,19 +241,20 @@ pub async fn set(trace_id: &str, file: &str, data: Bytes) -> Result<(), anyhow:: } async fn gc() -> Result<(), anyhow::Error> { - if !CONFIG.memory_cache.enabled { + let cfg = get_config(); + if !cfg.memory_cache.enabled { return Ok(()); } for file in FILES.iter() { let r = file.read().await; - if r.cur_size + CONFIG.memory_cache.release_size < r.max_size { + if r.cur_size + cfg.memory_cache.release_size < r.max_size { drop(r); continue; } drop(r); let mut w = file.write().await; - w.gc("global", CONFIG.memory_cache.gc_size).await?; + w.gc("global", cfg.memory_cache.gc_size).await?; drop(w); } @@ -305,11 +311,12 @@ pub async fn download(trace_id: &str, file: &str) -> Result<(), anyhow::Error> { } fn get_bucket_idx(file: &str) -> usize { - if CONFIG.memory_cache.bucket_num <= 1 { + let cfg = get_config(); + if cfg.memory_cache.bucket_num <= 1 { 0 } else { let h = gxhash::new().sum32(file); - (h as usize) % CONFIG.memory_cache.bucket_num + (h as usize) % cfg.memory_cache.bucket_num } } @@ -336,7 +343,7 @@ mod tests { async fn test_lru_cache_get_file() { let trace_id = "session_123"; let mut file_data = - FileData::with_capacity_and_cache_strategy(CONFIG.memory_cache.max_size, "lru"); + FileData::with_capacity_and_cache_strategy(get_config().memory_cache.max_size, "lru"); let file_key = "files/default/logs/olympics/2022/10/03/10/6982652937134804993_2_1.parquet"; let content = Bytes::from("Some text"); @@ -397,7 +404,7 @@ mod tests { async fn test_fifo_cache_get_file() { let trace_id = "session_123"; let mut file_data = - FileData::with_capacity_and_cache_strategy(CONFIG.memory_cache.max_size, "fifo"); + FileData::with_capacity_and_cache_strategy(get_config().memory_cache.max_size, "fifo"); let file_key = "files/default/logs/olympics/2022/10/03/10/6982652937134804993_2_1.parquet"; let content = Bytes::from("Some text"); diff --git a/src/infra/src/cache/file_data/mod.rs b/src/infra/src/cache/file_data/mod.rs index 770a8e4da5..fe83f3a50e 100644 --- a/src/infra/src/cache/file_data/mod.rs +++ b/src/infra/src/cache/file_data/mod.rs @@ -102,9 +102,10 @@ pub async fn init() -> Result<(), anyhow::Error> { } pub async fn download(trace_id: &str, file: &str) -> Result<(), anyhow::Error> { - if config::CONFIG.memory_cache.enabled { + let cfg = config::get_config(); + if cfg.memory_cache.enabled { memory::download(trace_id, file).await - } else if config::CONFIG.disk_cache.enabled { + } else if cfg.disk_cache.enabled { disk::download(trace_id, file).await } else { Ok(()) diff --git a/src/infra/src/cache/stats.rs b/src/infra/src/cache/stats.rs index 45310d6317..2a93836edb 100644 --- a/src/infra/src/cache/stats.rs +++ b/src/infra/src/cache/stats.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/infra/src/cache/tmpfs.rs b/src/infra/src/cache/tmpfs.rs index 4ad7cc3887..c5baba7c1b 100644 --- a/src/infra/src/cache/tmpfs.rs +++ b/src/infra/src/cache/tmpfs.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/infra/src/db/etcd.rs b/src/infra/src/db/etcd.rs index 03a2d42d1b..0ec6fac8ea 100644 --- a/src/infra/src/db/etcd.rs +++ b/src/infra/src/db/etcd.rs @@ -23,7 +23,7 @@ use std::{ use async_trait::async_trait; use bytes::Bytes; -use config::{cluster, CONFIG}; +use config::{cluster, get_config}; use etcd_client::{ Certificate, DeleteOptions, EventType, GetOptions, Identity, SortOrder, SortTarget, TlsOptions, }; @@ -47,7 +47,8 @@ pub async fn get_etcd_client() -> &'static etcd_client::Client { } pub async fn init() { - if CONFIG.common.local_mode || CONFIG.common.cluster_coordinator.to_lowercase() == "nats" { + let cfg = get_config(); + if cfg.common.local_mode || cfg.common.cluster_coordinator.to_lowercase() == "nats" { return; } // enable keep alive for auth token @@ -91,7 +92,7 @@ impl Etcd { impl Default for Etcd { fn default() -> Self { - Self::new(&CONFIG.etcd.prefix) + Self::new(&get_config().etcd.prefix) } } @@ -228,20 +229,21 @@ impl super::Db for Etcd { } async fn list(&self, prefix: &str) -> Result> { + let cfg = get_config(); let mut result = HashMap::default(); let key = format!("{}{}", self.prefix, prefix); let mut client = get_etcd_client().await.clone(); let mut opt = GetOptions::new() .with_prefix() .with_sort(SortTarget::Key, SortOrder::Ascend) - .with_limit(CONFIG.etcd.load_page_size); + .with_limit(cfg.etcd.load_page_size); let mut resp = client.get(key.clone(), Some(opt.clone())).await?; let mut first_call = true; let mut have_next = true; let mut last_key = String::new(); loop { let kvs_num = resp.kvs().len() as i64; - if kvs_num < CONFIG.etcd.load_page_size { + if kvs_num < cfg.etcd.load_page_size { have_next = false; } for kv in resp.kvs() { @@ -272,20 +274,21 @@ impl super::Db for Etcd { } async fn list_keys(&self, prefix: &str) -> Result> { + let cfg = get_config(); let mut result = Vec::new(); let key = format!("{}{}", self.prefix, prefix); let mut client = get_etcd_client().await.clone(); let mut opt = GetOptions::new() .with_prefix() .with_sort(SortTarget::Key, SortOrder::Ascend) - .with_limit(CONFIG.etcd.load_page_size); + .with_limit(cfg.etcd.load_page_size); let mut resp = client.get(key.clone(), Some(opt.clone())).await?; let mut first_call = true; let mut have_next = true; let mut last_key = String::new(); loop { let kvs_num = resp.kvs().len() as i64; - if kvs_num < CONFIG.etcd.load_page_size { + if kvs_num < cfg.etcd.load_page_size { have_next = false; } for kv in resp.kvs() { @@ -316,20 +319,21 @@ impl super::Db for Etcd { } async fn list_values(&self, prefix: &str) -> Result> { + let cfg = get_config(); let mut result = Vec::new(); let key = format!("{}{}", self.prefix, prefix); let mut client = get_etcd_client().await.clone(); let mut opt = GetOptions::new() .with_prefix() .with_sort(SortTarget::Key, SortOrder::Ascend) - .with_limit(CONFIG.etcd.load_page_size); + .with_limit(cfg.etcd.load_page_size); let mut resp = client.get(key.clone(), Some(opt.clone())).await?; let mut first_call = true; let mut have_next = true; let mut last_key = String::new(); loop { let kvs_num = resp.kvs().len() as i64; - if kvs_num < CONFIG.etcd.load_page_size { + if kvs_num < cfg.etcd.load_page_size { have_next = false; } for kv in resp.kvs() { @@ -363,6 +367,7 @@ impl super::Db for Etcd { prefix: &str, start_dt: Option<(i64, i64)>, ) -> Result> { + let cfg = get_config(); if start_dt.is_none() || start_dt == Some((0, 0)) { let vals = self.list_values(prefix).await?; return Ok(vals.into_iter().map(|v| (0, v)).collect()); @@ -375,14 +380,14 @@ impl super::Db for Etcd { let mut opt = GetOptions::new() .with_prefix() .with_sort(SortTarget::Key, SortOrder::Ascend) - .with_limit(CONFIG.etcd.load_page_size); + .with_limit(cfg.etcd.load_page_size); let mut resp = client.get(key.clone(), Some(opt.clone())).await?; let mut first_call = true; let mut have_next = true; let mut last_key = String::new(); loop { let kvs_num = resp.kvs().len() as i64; - if kvs_num < CONFIG.etcd.load_page_size { + if kvs_num < cfg.etcd.load_page_size { have_next = false; } for kv in resp.kvs() { @@ -500,29 +505,30 @@ pub async fn create_table() -> Result<()> { } pub async fn connect() -> etcd_client::Client { - if CONFIG.common.print_key_config { - log::info!("Etcd init config: {:?}", CONFIG.etcd); + let cfg = get_config(); + if cfg.common.print_key_config { + log::info!("Etcd init cfg: {:?}", cfg.etcd); } let mut opts = etcd_client::ConnectOptions::new() - .with_timeout(core::time::Duration::from_secs(CONFIG.etcd.command_timeout)) - .with_connect_timeout(core::time::Duration::from_secs(CONFIG.etcd.connect_timeout)); - if !&CONFIG.etcd.user.is_empty() { - opts = opts.with_user(&CONFIG.etcd.user, &CONFIG.etcd.password); + .with_timeout(core::time::Duration::from_secs(cfg.etcd.command_timeout)) + .with_connect_timeout(core::time::Duration::from_secs(cfg.etcd.connect_timeout)); + if !&cfg.etcd.user.is_empty() { + opts = opts.with_user(&cfg.etcd.user, &cfg.etcd.password); } - if CONFIG.etcd.cert_auth { - let server_root_ca_cert = tokio::fs::read(&CONFIG.etcd.ca_file).await.unwrap(); + if cfg.etcd.cert_auth { + let server_root_ca_cert = tokio::fs::read(&cfg.etcd.ca_file).await.unwrap(); let server_root_ca_cert = Certificate::from_pem(server_root_ca_cert); - let client_cert = tokio::fs::read(&CONFIG.etcd.cert_file).await.unwrap(); - let client_key = tokio::fs::read(&CONFIG.etcd.key_file).await.unwrap(); + let client_cert = tokio::fs::read(&cfg.etcd.cert_file).await.unwrap(); + let client_key = tokio::fs::read(&cfg.etcd.key_file).await.unwrap(); let client_identity = Identity::from_pem(client_cert, client_key); let tls = TlsOptions::new() - .domain_name(&CONFIG.etcd.domain_name) + .domain_name(&cfg.etcd.domain_name) .ca_certificate(server_root_ca_cert) .identity(client_identity); opts = opts.with_tls(tls); } - let addrs = CONFIG.etcd.addr.split(',').collect::>(); + let addrs = cfg.etcd.addr.split(',').collect::>(); etcd_client::Client::connect(addrs, Some(opts)) .await .expect("Etcd connect failed") @@ -534,7 +540,7 @@ pub async fn keepalive_connection() -> Result<()> { break; } let mut client = get_etcd_client().await.clone(); - let key = format!("{}healthz", &CONFIG.etcd.prefix); + let key = format!("{}healthz", get_config().etcd.prefix); let key = key.as_str(); client.put(key, "OK", None).await?; let mut interval = time::interval(time::Duration::from_secs(60)); @@ -616,7 +622,7 @@ pub(crate) struct Locker { impl Locker { pub(crate) fn new(key: &str) -> Self { Self { - key: format!("{}locker{}", &CONFIG.etcd.prefix, key), + key: format!("{}locker{}", get_config().etcd.prefix, key), lock_id: "".to_string(), state: Arc::new(AtomicU8::new(0)), } @@ -624,14 +630,15 @@ impl Locker { /// lock with timeout, 0 means use default timeout, unit: second pub(crate) async fn lock(&mut self, timeout: u64) -> Result<()> { + let cfg = get_config(); let mut client = get_etcd_client().await.clone(); let mut last_err = None; let timeout = if timeout == 0 { - CONFIG.etcd.lock_wait_timeout + cfg.etcd.lock_wait_timeout } else { timeout }; - let mut n = timeout / CONFIG.etcd.command_timeout; + let mut n = timeout / cfg.etcd.command_timeout; if n < 1 { n = 1; } @@ -686,7 +693,7 @@ mod tests { #[tokio::test] async fn test_etcd_count() { - if CONFIG.common.local_mode { + if get_config().common.local_mode { return; } let client = Etcd::default(); diff --git a/src/infra/src/db/mod.rs b/src/infra/src/db/mod.rs index 5baffbb5e0..5033c61869 100644 --- a/src/infra/src/db/mod.rs +++ b/src/infra/src/db/mod.rs @@ -17,7 +17,7 @@ use std::sync::Arc; use async_trait::async_trait; use bytes::Bytes; -use config::{meta::meta_store::MetaStore, CONFIG}; +use config::{get_config, meta::meta_store::MetaStore}; use hashbrown::HashMap; use tokio::sync::{mpsc, OnceCell}; @@ -57,13 +57,14 @@ pub async fn init() -> Result<()> { } async fn default() -> Box { - if !CONFIG.common.local_mode - && (CONFIG.common.meta_store == "sled" || CONFIG.common.meta_store == "sqlite") + let cfg = get_config(); + if !cfg.common.local_mode + && (cfg.common.meta_store == "sled" || cfg.common.meta_store == "sqlite") { panic!("cluster mode is not supported for ZO_META_STORE=sqlite"); } - match CONFIG.common.meta_store.as_str().into() { + match cfg.common.meta_store.as_str().into() { MetaStore::Sqlite => Box::::default(), MetaStore::Etcd => Box::::default(), MetaStore::Nats => Box::::default(), @@ -73,13 +74,14 @@ async fn default() -> Box { } async fn init_cluster_coordinator() -> Box { - if CONFIG.common.local_mode { - match CONFIG.common.meta_store.as_str().into() { + let cfg = get_config(); + if cfg.common.local_mode { + match cfg.common.meta_store.as_str().into() { MetaStore::Sqlite => Box::::default(), _ => Box::::default(), } } else { - match CONFIG.common.cluster_coordinator.as_str().into() { + match cfg.common.cluster_coordinator.as_str().into() { MetaStore::Nats => Box::::default(), _ => Box::::default(), } @@ -87,7 +89,7 @@ async fn init_cluster_coordinator() -> Box { } async fn init_super_cluster() -> Box { - if CONFIG.common.local_mode { + if get_config().common.local_mode { panic!("super cluster is not supported in local mode"); } Box::new(nats::NatsDb::super_cluster()) @@ -95,7 +97,7 @@ async fn init_super_cluster() -> Box { pub async fn create_table() -> Result<()> { // check db dir - std::fs::create_dir_all(&CONFIG.common.data_db_dir)?; + std::fs::create_dir_all(&get_config().common.data_db_dir)?; // create for meta store let cluster_coordinator = get_coordinator().await; cluster_coordinator.create_table().await?; diff --git a/src/infra/src/db/mysql.rs b/src/infra/src/db/mysql.rs index 296d3da60c..b9d9d44159 100644 --- a/src/infra/src/db/mysql.rs +++ b/src/infra/src/db/mysql.rs @@ -17,7 +17,6 @@ use std::{str::FromStr, sync::Arc}; use async_trait::async_trait; use bytes::Bytes; -use config::CONFIG; use hashbrown::HashMap; use once_cell::sync::Lazy; use sqlx::{ @@ -31,13 +30,14 @@ use crate::errors::*; pub static CLIENT: Lazy> = Lazy::new(connect); fn connect() -> Pool { - let db_opts = MySqlConnectOptions::from_str(&CONFIG.common.meta_mysql_dsn) + let cfg = config::get_config(); + let db_opts = MySqlConnectOptions::from_str(&cfg.common.meta_mysql_dsn) .expect("mysql connect options create failed") .disable_statement_logging(); MySqlPoolOptions::new() - .min_connections(CONFIG.limit.sql_min_db_connections) - .max_connections(CONFIG.limit.sql_max_db_connections) + .min_connections(cfg.limit.sql_min_db_connections) + .max_connections(cfg.limit.sql_max_db_connections) .connect_lazy_with(db_opts) } @@ -164,7 +164,8 @@ impl super::Db for MysqlDb { let lock_key = format!("get_for_update_{}", key); let lock_sql = format!( "SELECT GET_LOCK('{}', {})", - lock_key, CONFIG.limit.meta_transaction_lock_timeout + lock_key, + config::get_config().limit.meta_transaction_lock_timeout ); let unlock_sql = format!("SELECT RELEASE_LOCK('{}')", lock_key); let mut lock_tx = lock_pool.begin().await?; diff --git a/src/infra/src/db/nats.rs b/src/infra/src/db/nats.rs index 7a083f3483..1d007f60a7 100644 --- a/src/infra/src/db/nats.rs +++ b/src/infra/src/db/nats.rs @@ -24,7 +24,7 @@ use std::{ use async_nats::{jetstream, Client, ServerAddr}; use async_trait::async_trait; use bytes::Bytes; -use config::{cluster, ider, utils::base64, CONFIG}; +use config::{cluster, get_config, ider, utils::base64}; use futures::{StreamExt, TryStreamExt}; use hashbrown::HashMap; use tokio::{ @@ -50,20 +50,21 @@ async fn get_bucket_by_key<'a>( prefix: &'a str, key: &'a str, ) -> Result<(jetstream::kv::Store, &'a str)> { + let cfg = get_config(); let client = get_nats_client().await.clone(); let jetstream = jetstream::new(client); let key = key.trim_start_matches('/'); let bucket_name = key.split('/').next().unwrap(); let mut bucket = jetstream::kv::Config { bucket: format!("{}{}", prefix, bucket_name), - num_replicas: CONFIG.nats.replicas, + num_replicas: cfg.nats.replicas, history: 3, ..Default::default() }; if bucket_name == "nodes" || bucket_name == "clusters" { // if changed ttl need recreate the bucket // CMD: nats kv del -f o2_nodes - bucket.max_age = Duration::from_secs(CONFIG.limit.node_heartbeat_ttl as u64); + bucket.max_age = Duration::from_secs(cfg.limit.node_heartbeat_ttl as u64); } let kv = jetstream.create_key_value(bucket).await?; Ok((kv, key.trim_start_matches(bucket_name))) @@ -127,7 +128,7 @@ impl NatsDb { impl Default for NatsDb { fn default() -> Self { - Self::new(&CONFIG.nats.prefix) + Self::new(&get_config().nats.prefix) } } @@ -321,13 +322,14 @@ impl super::Db for NatsDb { if keys_len == 0 { return Ok(HashMap::new()); } + let values = futures::stream::iter(keys) .map(|key| async move { let encoded_key = key_encode(&key); let value = bucket.get(&encoded_key).await?; Ok::<(String, Option), Error>((key, value)) }) - .buffer_unordered(CONFIG.limit.cpu_num) + .buffer_unordered(get_config().limit.cpu_num) .try_collect::)>>() .await .map_err(|e| Error::Message(e.to_string()))?; @@ -385,7 +387,7 @@ impl super::Db for NatsDb { let value = bucket.get(&encoded_key).await?; Ok::, Error>(value) }) - .buffer_unordered(CONFIG.limit.cpu_num) + .buffer_unordered(get_config().limit.cpu_num) .try_collect::>>() .await .map_err(|e| Error::Message(e.to_string()))?; @@ -441,7 +443,7 @@ impl super::Db for NatsDb { let value = bucket.get(&encoded_key).await?; Ok::, Error>(value.map(|value| (start_dt, value))) }) - .buffer_unordered(CONFIG.limit.cpu_num) + .buffer_unordered(get_config().limit.cpu_num) .try_collect::>>() .await .map_err(|e| Error::Message(e.to_string()))?; @@ -530,19 +532,17 @@ pub async fn create_table() -> Result<()> { } pub async fn connect() -> async_nats::Client { - if CONFIG.common.print_key_config { - log::info!("Nats init config: {:?}", CONFIG.nats); + let cfg = get_config(); + if cfg.common.print_key_config { + log::info!("Nats init get_config(): {:?}", cfg.nats); } let mut opts = async_nats::ConnectOptions::new() - .connection_timeout(Duration::from_secs(CONFIG.nats.connect_timeout)); - if !CONFIG.nats.user.is_empty() { - opts = opts.user_and_password( - CONFIG.nats.user.to_string(), - CONFIG.nats.password.to_string(), - ); + .connection_timeout(Duration::from_secs(cfg.nats.connect_timeout)); + if !cfg.nats.user.is_empty() { + opts = opts.user_and_password(cfg.nats.user.to_string(), cfg.nats.password.to_string()); } - let addrs = CONFIG + let addrs = cfg .nats .addr .split(',') @@ -578,9 +578,10 @@ impl Locker { /// lock with timeout, 0 means use default timeout, unit: second pub(crate) async fn lock(&mut self, timeout: u64) -> Result<()> { - let (bucket, new_key) = get_bucket_by_key(&CONFIG.nats.prefix, &self.key).await?; + let cfg = get_config(); + let (bucket, new_key) = get_bucket_by_key(&cfg.nats.prefix, &self.key).await?; let timeout = if timeout == 0 { - CONFIG.nats.lock_wait_timeout + cfg.nats.lock_wait_timeout } else { timeout }; @@ -636,7 +637,9 @@ impl Locker { if self.state.load(Ordering::SeqCst) != 1 { return Ok(()); } - let (bucket, new_key) = get_bucket_by_key(&CONFIG.nats.prefix, &self.key).await?; + + let cfg = get_config(); + let (bucket, new_key) = get_bucket_by_key(&cfg.nats.prefix, &self.key).await?; let key = key_encode(new_key); let ret = bucket.get(&key).await?; let Some(ret) = ret else { diff --git a/src/infra/src/db/postgres.rs b/src/infra/src/db/postgres.rs index 641a807cf1..4eddfdff7a 100644 --- a/src/infra/src/db/postgres.rs +++ b/src/infra/src/db/postgres.rs @@ -17,7 +17,7 @@ use std::{str::FromStr, sync::Arc}; use async_trait::async_trait; use bytes::Bytes; -use config::{utils::hash::Sum32, CONFIG}; +use config::utils::hash::Sum32; use hashbrown::HashMap; use once_cell::sync::Lazy; use sqlx::{ @@ -31,13 +31,14 @@ use crate::errors::*; pub static CLIENT: Lazy> = Lazy::new(connect); fn connect() -> Pool { - let db_opts = PgConnectOptions::from_str(&CONFIG.common.meta_postgres_dsn) + let cfg = config::get_config(); + let db_opts = PgConnectOptions::from_str(&cfg.common.meta_postgres_dsn) .expect("postgres connect options create failed") .disable_statement_logging(); PgPoolOptions::new() - .min_connections(CONFIG.limit.sql_min_db_connections) - .max_connections(CONFIG.limit.sql_max_db_connections) + .min_connections(cfg.limit.sql_min_db_connections) + .max_connections(cfg.limit.sql_max_db_connections) .connect_lazy_with(db_opts) } diff --git a/src/infra/src/db/sqlite.rs b/src/infra/src/db/sqlite.rs index 2cbcb6847a..21fa1de9d3 100644 --- a/src/infra/src/db/sqlite.rs +++ b/src/infra/src/db/sqlite.rs @@ -17,7 +17,7 @@ use std::{str::FromStr, sync::Arc, time::Duration}; use async_trait::async_trait; use bytes::Bytes; -use config::{cluster, FxIndexMap, CONFIG}; +use config::{cluster, FxIndexMap}; use hashbrown::HashMap; use once_cell::sync::Lazy; use sqlx::{ @@ -45,8 +45,9 @@ static WATCHERS: Lazy>> = type EventChannel = Arc>; fn connect_rw() -> Pool { - let url = format!("{}{}", CONFIG.common.data_db_dir, "metadata.sqlite"); - if !CONFIG.common.local_mode && std::path::Path::new(&url).exists() { + let cfg = config::get_config(); + let url = format!("{}{}", cfg.common.data_db_dir, "metadata.sqlite"); + if !cfg.common.local_mode && std::path::Path::new(&url).exists() { std::fs::remove_file(&url).expect("remove file sqlite failed"); _ = std::fs::remove_file(format!("{url}-shm")); _ = std::fs::remove_file(format!("{url}-wal")); @@ -68,7 +69,9 @@ fn connect_rw() -> Pool { } fn connect_ro() -> Pool { - let url = format!("{}{}", CONFIG.common.data_db_dir, "metadata.sqlite"); + let cfg = config::get_config(); + + let url = format!("{}{}", cfg.common.data_db_dir, "metadata.sqlite"); let db_opts = SqliteConnectOptions::from_str(&url) .expect("sqlite connect options create failed") .journal_mode(SqliteJournalMode::Wal) @@ -78,8 +81,8 @@ fn connect_ro() -> Pool { // .disable_statement_logging() .read_only(true); SqlitePoolOptions::new() - .min_connections(CONFIG.limit.sql_min_db_connections) - .max_connections(CONFIG.limit.sql_max_db_connections) + .min_connections(cfg.limit.sql_min_db_connections) + .max_connections(cfg.limit.sql_max_db_connections) .acquire_timeout(Duration::from_secs(30)) .connect_lazy_with(db_opts) } @@ -109,7 +112,7 @@ impl SqliteDbChannel { break; } }; - if CONFIG.common.print_key_event { + if config::get_config().common.print_key_event { log::info!("[SQLITE] watch event: {:?}", event); } for (prefix, tx) in WATCHERS.read().await.iter() { diff --git a/src/infra/src/dist_lock.rs b/src/infra/src/dist_lock.rs index 3ebbe5d533..d50df48df2 100644 --- a/src/infra/src/dist_lock.rs +++ b/src/infra/src/dist_lock.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -13,8 +13,6 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::CONFIG; - use crate::{ db::{etcd, nats}, errors::Result, @@ -30,10 +28,11 @@ enum LockerStore { /// lock key in etcd, wait_ttl is 0 means wait forever #[inline(always)] pub async fn lock(key: &str, wait_ttl: u64) -> Result> { - if CONFIG.common.local_mode { + let cfg = config::get_config(); + if cfg.common.local_mode { return Ok(None); } - match CONFIG.common.cluster_coordinator.as_str() { + match cfg.common.cluster_coordinator.as_str() { "nats" => { let mut lock = nats::Locker::new(key); lock.lock(wait_ttl).await?; diff --git a/src/infra/src/errors/grpc.rs b/src/infra/src/errors/grpc.rs index 94d640a6ed..d886a4018b 100644 --- a/src/infra/src/errors/grpc.rs +++ b/src/infra/src/errors/grpc.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/infra/src/errors/mod.rs b/src/infra/src/errors/mod.rs index 8fb27e2f46..538e8bc1bb 100644 --- a/src/infra/src/errors/mod.rs +++ b/src/infra/src/errors/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/infra/src/file_list/mod.rs b/src/infra/src/file_list/mod.rs index c90923a60b..0c131e8946 100644 --- a/src/infra/src/file_list/mod.rs +++ b/src/infra/src/file_list/mod.rs @@ -14,12 +14,9 @@ // along with this program. If not, see . use async_trait::async_trait; -use config::{ - meta::{ - meta_store::MetaStore, - stream::{FileKey, FileMeta, PartitionTimeLevel, StreamStats, StreamType}, - }, - CONFIG, +use config::meta::{ + meta_store::MetaStore, + stream::{FileKey, FileMeta, PartitionTimeLevel, StreamStats, StreamType}, }; use once_cell::sync::Lazy; @@ -32,7 +29,7 @@ pub mod sqlite; static CLIENT: Lazy> = Lazy::new(connect); pub fn connect() -> Box { - match CONFIG.common.meta_store.as_str().into() { + match config::get_config().common.meta_store.as_str().into() { MetaStore::Sqlite => Box::::default(), MetaStore::Etcd => Box::::default(), MetaStore::Nats => Box::::default(), diff --git a/src/infra/src/queue/mod.rs b/src/infra/src/queue/mod.rs index 0e75b6eeeb..cd45797c3b 100644 --- a/src/infra/src/queue/mod.rs +++ b/src/infra/src/queue/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -17,7 +17,7 @@ use std::sync::Arc; use async_trait::async_trait; use bytes::Bytes; -use config::{meta::meta_store::MetaStore, CONFIG}; +use config::meta::meta_store::MetaStore; use tokio::sync::{mpsc, OnceCell}; use crate::errors::{Error, Result}; @@ -41,14 +41,14 @@ pub async fn init() -> Result<()> { } async fn default() -> Box { - match CONFIG.common.queue_store.as_str().into() { + match config::get_config().common.queue_store.as_str().into() { MetaStore::Nats => Box::::default(), _ => Box::::default(), } } async fn init_super_cluster() -> Box { - if CONFIG.common.local_mode { + if config::get_config().common.local_mode { panic!("super cluster is not supported in local mode"); } Box::new(nats::NatsQueue::super_cluster()) diff --git a/src/infra/src/queue/nats.rs b/src/infra/src/queue/nats.rs index 1e200ade1b..1b1d9fc9cb 100644 --- a/src/infra/src/queue/nats.rs +++ b/src/infra/src/queue/nats.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -18,7 +18,7 @@ use std::{cmp::max, sync::Arc, time::Duration}; use async_nats::jetstream; use async_trait::async_trait; use bytes::Bytes; -use config::{get_cluster_name, CONFIG}; +use config::get_cluster_name; use futures::TryStreamExt; use tokio::{sync::mpsc, task::JoinHandle}; @@ -47,13 +47,14 @@ impl NatsQueue { impl Default for NatsQueue { fn default() -> Self { - Self::new(&CONFIG.nats.prefix) + Self::new(&config::get_config().nats.prefix) } } #[async_trait] impl super::Queue for NatsQueue { async fn create(&self, topic: &str) -> Result<()> { + let cfg = config::get_config(); let client = get_nats_client().await.clone(); let jetstream = jetstream::new(client); let topic_name = format!("{}{}", self.prefix, topic); @@ -61,8 +62,8 @@ impl super::Queue for NatsQueue { name: topic_name.to_string(), subjects: vec![topic_name.to_string(), format!("{}.*", topic_name)], retention: jetstream::stream::RetentionPolicy::Limits, - max_age: Duration::from_secs(60 * 60 * 24 * max(1, CONFIG.nats.queue_max_age)), - num_replicas: CONFIG.nats.replicas, + max_age: Duration::from_secs(60 * 60 * 24 * max(1, cfg.nats.queue_max_age)), + num_replicas: cfg.nats.replicas, ..Default::default() }; _ = jetstream.get_or_create_stream(config).await?; diff --git a/src/infra/src/queue/nop.rs b/src/infra/src/queue/nop.rs index 306ee5d5e5..60f938db01 100644 --- a/src/infra/src/queue/nop.rs +++ b/src/infra/src/queue/nop.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/infra/src/scheduler/mod.rs b/src/infra/src/scheduler/mod.rs index 8ddd7c0e4f..6427cddae0 100644 --- a/src/infra/src/scheduler/mod.rs +++ b/src/infra/src/scheduler/mod.rs @@ -14,7 +14,7 @@ // along with this program. If not, see . use async_trait::async_trait; -use config::{meta::meta_store::MetaStore, CONFIG}; +use config::meta::meta_store::MetaStore; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; @@ -28,7 +28,7 @@ static CLIENT: Lazy> = Lazy::new(connect); pub const TRIGGERS_KEY: &str = "/triggers/"; pub fn connect() -> Box { - match CONFIG.common.meta_store.as_str().into() { + match config::get_config().common.meta_store.as_str().into() { MetaStore::MySQL => Box::::default(), MetaStore::PostgreSQL => Box::::default(), _ => Box::::default(), diff --git a/src/infra/src/scheduler/mysql.rs b/src/infra/src/scheduler/mysql.rs index 9b78de13e2..2e7ffc4abd 100644 --- a/src/infra/src/scheduler/mysql.rs +++ b/src/infra/src/scheduler/mysql.rs @@ -16,7 +16,6 @@ use async_trait::async_trait; use bytes::Bytes; use chrono::Duration; -use config::CONFIG; use sqlx::Row; use super::{Trigger, TriggerId, TriggerModule, TriggerStatus, TRIGGERS_KEY}; @@ -284,7 +283,7 @@ FOR UPDATE; ) .bind(TriggerStatus::Waiting) .bind(now) - .bind(CONFIG.limit.scheduler_max_retries) + .bind(config::get_config().limit.scheduler_max_retries) .bind(true) .bind(false) .bind(concurrency) @@ -397,7 +396,7 @@ WHERE id IN (?); let pool = CLIENT.clone(); sqlx::query(r#"DELETE FROM scheduled_jobs WHERE status = ? OR retries >= ?;"#) .bind(TriggerStatus::Completed) - .bind(CONFIG.limit.scheduler_max_retries) + .bind(config::get_config().limit.scheduler_max_retries) .execute(&pool) .await?; Ok(()) diff --git a/src/infra/src/scheduler/postgres.rs b/src/infra/src/scheduler/postgres.rs index 2229071abb..f9611cd8e8 100644 --- a/src/infra/src/scheduler/postgres.rs +++ b/src/infra/src/scheduler/postgres.rs @@ -16,7 +16,6 @@ use async_trait::async_trait; use bytes::Bytes; use chrono::Duration; -use config::CONFIG; use sqlx::Row; use super::{Trigger, TriggerModule, TriggerStatus, TRIGGERS_KEY}; @@ -294,7 +293,7 @@ RETURNING *;"#; .bind(report_max_time) .bind(TriggerStatus::Waiting) .bind(now) - .bind(CONFIG.limit.scheduler_max_retries) + .bind(config::get_config().limit.scheduler_max_retries) .bind(true) .bind(false) .bind(concurrency) @@ -361,7 +360,7 @@ WHERE org = $1 AND module = $2 AND module_key = $3;"#; let pool = CLIENT.clone(); sqlx::query(r#"DELETE FROM scheduled_jobs WHERE status = $1 OR retries >= $2;"#) .bind(TriggerStatus::Completed) - .bind(CONFIG.limit.scheduler_max_retries) + .bind(config::get_config().limit.scheduler_max_retries) .execute(&pool) .await?; Ok(()) diff --git a/src/infra/src/scheduler/sqlite.rs b/src/infra/src/scheduler/sqlite.rs index 78d519b70d..20e02983ba 100644 --- a/src/infra/src/scheduler/sqlite.rs +++ b/src/infra/src/scheduler/sqlite.rs @@ -15,7 +15,7 @@ use async_trait::async_trait; use chrono::Duration; -use config::{utils::json, CONFIG}; +use config::utils::json; use sqlx::Row; use super::{Trigger, TriggerModule, TriggerStatus, TRIGGERS_KEY}; @@ -311,7 +311,7 @@ RETURNING *;"#; .bind(report_max_time) .bind(TriggerStatus::Waiting) .bind(now) - .bind(CONFIG.limit.scheduler_max_retries) + .bind(config::get_config().limit.scheduler_max_retries) .bind(true) .bind(false) .bind(concurrency) @@ -367,7 +367,7 @@ WHERE org = $1 AND module = $2 AND module_key = $3;"#; let client = client.lock().await; sqlx::query(r#"DELETE FROM scheduled_jobs WHERE status = $1 OR retries >= $2;"#) .bind(TriggerStatus::Completed) - .bind(CONFIG.limit.scheduler_max_retries) + .bind(config::get_config().limit.scheduler_max_retries) .execute(&*client) .await?; Ok(()) diff --git a/src/infra/src/schema/history/mod.rs b/src/infra/src/schema/history/mod.rs index f17077b973..8997e29995 100644 --- a/src/infra/src/schema/history/mod.rs +++ b/src/infra/src/schema/history/mod.rs @@ -14,10 +14,7 @@ // along with this program. If not, see . use async_trait::async_trait; -use config::{ - meta::{meta_store::MetaStore, stream::StreamType}, - CONFIG, -}; +use config::meta::{meta_store::MetaStore, stream::StreamType}; use datafusion::arrow::datatypes::Schema; use once_cell::sync::Lazy; @@ -30,7 +27,7 @@ pub mod sqlite; static CLIENT: Lazy> = Lazy::new(connect); pub fn connect() -> Box { - match CONFIG.common.meta_store.as_str().into() { + match config::get_config().common.meta_store.as_str().into() { MetaStore::Sqlite => Box::::default(), MetaStore::Etcd => Box::::default(), MetaStore::Nats => Box::::default(), diff --git a/src/infra/src/schema/mod.rs b/src/infra/src/schema/mod.rs index 1e6360126c..9105afd6c6 100644 --- a/src/infra/src/schema/mod.rs +++ b/src/infra/src/schema/mod.rs @@ -17,9 +17,10 @@ use std::collections::HashMap; use chrono::Utc; use config::{ + get_config, meta::stream::{PartitionTimeLevel, StreamSettings, StreamType}, utils::{json, schema_ext::SchemaExt}, - RwAHashMap, CONFIG, + RwAHashMap, }; use datafusion::arrow::datatypes::{DataType, Field, Schema}; use futures::{StreamExt, TryStreamExt}; @@ -121,8 +122,9 @@ pub async fn get_versions( let key = mk_key(org_id, stream_type, stream_name); let cache_key = key.strip_prefix("/schema/").unwrap(); + let cfg = get_config(); let (min_ts, max_ts) = time_range.unwrap_or((0, 0)); - if CONFIG.common.schema_cache_compress_enabled { + if cfg.common.schema_cache_compress_enabled { let mut last_schema_index = None; let r = STREAM_SCHEMAS_COMPRESSED.read().await; if let Some(versions) = r.get(cache_key) { @@ -154,7 +156,7 @@ pub async fn get_versions( let mut schemas: Vec = json::from_slice(&de_bytes)?; Ok::, Error>(schemas.pop()) }) - .buffer_unordered(CONFIG.limit.cpu_num) + .buffer_unordered(cfg.limit.cpu_num) .try_collect::>>() .await .map_err(|e| Error::Message(e.to_string()))?; @@ -250,13 +252,14 @@ pub fn unwrap_partition_time_level( if level != PartitionTimeLevel::Unset { level } else { + let cfg = get_config(); match stream_type { - StreamType::Logs => PartitionTimeLevel::from(CONFIG.limit.logs_file_retention.as_str()), + StreamType::Logs => PartitionTimeLevel::from(cfg.limit.logs_file_retention.as_str()), StreamType::Metrics => { - PartitionTimeLevel::from(CONFIG.limit.metrics_file_retention.as_str()) + PartitionTimeLevel::from(cfg.limit.metrics_file_retention.as_str()) } StreamType::Traces => { - PartitionTimeLevel::from(CONFIG.limit.traces_file_retention.as_str()) + PartitionTimeLevel::from(cfg.limit.traces_file_retention.as_str()) } _ => PartitionTimeLevel::default(), } @@ -608,7 +611,7 @@ pub fn get_merge_schema_changes( Some(idx) => { let existing_field = &merged_fields[*idx]; if existing_field.data_type() != item_data_type { - if !CONFIG.common.widening_schema_evolution { + if !get_config().common.widening_schema_evolution { field_datatype_delta.push(existing_field.as_ref().clone()); } else if is_widening_conversion(existing_field.data_type(), item_data_type) { is_schema_changed = true; diff --git a/src/infra/src/storage/local.rs b/src/infra/src/storage/local.rs index 5656142409..0f2b91be6f 100644 --- a/src/infra/src/storage/local.rs +++ b/src/infra/src/storage/local.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -17,7 +17,7 @@ use std::ops::Range; use async_trait::async_trait; use bytes::Bytes; -use config::{metrics, CONFIG}; +use config::metrics; use futures::stream::BoxStream; use object_store::{ limit::LimitStore, local::LocalFileSystem, path::Path, Error, GetOptions, GetResult, @@ -43,7 +43,7 @@ impl Local { impl Default for Local { fn default() -> Self { - Local::new(&CONFIG.common.data_stream_dir, true) + Local::new(&config::get_config().common.data_stream_dir, true) } } diff --git a/src/infra/src/storage/mod.rs b/src/infra/src/storage/mod.rs index 5ee5e4b77f..f9d236a215 100644 --- a/src/infra/src/storage/mod.rs +++ b/src/infra/src/storage/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::{is_local_disk_storage, metrics, CONFIG}; +use config::{get_config, is_local_disk_storage, metrics}; use futures::{StreamExt, TryStreamExt}; use object_store::ObjectStore; use once_cell::sync::Lazy; @@ -40,7 +40,7 @@ pub static LOCAL_WAL: Lazy> = Lazy::new(local_wal); /// ``` fn default() -> Box { if is_local_disk_storage() { - std::fs::create_dir_all(&CONFIG.common.data_stream_dir) + std::fs::create_dir_all(&get_config().common.data_stream_dir) .expect("create stream data dir success"); Box::::default() } else { @@ -49,13 +49,15 @@ fn default() -> Box { } fn local_cache() -> Box { - std::fs::create_dir_all(&CONFIG.common.data_cache_dir).expect("create cache dir success"); - Box::new(local::Local::new(&CONFIG.common.data_cache_dir, true)) + let cfg = get_config(); + std::fs::create_dir_all(&cfg.common.data_cache_dir).expect("create cache dir success"); + Box::new(local::Local::new(&cfg.common.data_cache_dir, true)) } fn local_wal() -> Box { - std::fs::create_dir_all(&CONFIG.common.data_wal_dir).expect("create wal dir success"); - Box::new(local::Local::new(&CONFIG.common.data_wal_dir, false)) + let cfg = get_config(); + std::fs::create_dir_all(&cfg.common.data_wal_dir).expect("create wal dir success"); + Box::new(local::Local::new(&cfg.common.data_wal_dir, false)) } pub async fn list(prefix: &str) -> Result, anyhow::Error> { @@ -92,7 +94,7 @@ pub async fn del(files: &[&str]) -> Result<(), anyhow::Error> { .collect::>(); let files_stream = futures::stream::iter(files); files_stream - .for_each_concurrent(CONFIG.limit.cpu_num, |file| async move { + .for_each_concurrent(get_config().limit.cpu_num, |file| async move { match DEFAULT.delete(&(file.as_str().into())).await { Ok(_) => { log::debug!("Deleted object: {}", file); @@ -115,12 +117,13 @@ pub async fn del(files: &[&str]) -> Result<(), anyhow::Error> { } pub fn format_key(key: &str, with_prefix: bool) -> String { + let cfg = get_config(); if !is_local_disk_storage() && with_prefix - && !CONFIG.s3.bucket_prefix.is_empty() - && !key.starts_with(&CONFIG.s3.bucket_prefix) + && !cfg.s3.bucket_prefix.is_empty() + && !key.starts_with(&cfg.s3.bucket_prefix) { - format!("{}{}", CONFIG.s3.bucket_prefix, key) + format!("{}{}", cfg.s3.bucket_prefix, key) } else { key.to_string() } diff --git a/src/infra/src/storage/remote.rs b/src/infra/src/storage/remote.rs index 933a58abf5..62cf6070c9 100644 --- a/src/infra/src/storage/remote.rs +++ b/src/infra/src/storage/remote.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -17,7 +17,7 @@ use std::ops::Range; use async_trait::async_trait; use bytes::Bytes; -use config::{metrics, CONFIG}; +use config::{get_config, metrics}; use futures::stream::BoxStream; use object_store::{ limit::LimitStore, path::Path, Error, GetOptions, GetResult, ListResult, MultipartId, @@ -227,77 +227,80 @@ impl ObjectStore for Remote { } fn init_aws_config() -> object_store::Result { + let cfg = get_config(); let mut opts = object_store::ClientOptions::default() - .with_connect_timeout(std::time::Duration::from_secs(CONFIG.s3.connect_timeout)) - .with_timeout(std::time::Duration::from_secs(CONFIG.s3.request_timeout)) - .with_allow_invalid_certificates(CONFIG.s3.allow_invalid_certificates) + .with_connect_timeout(std::time::Duration::from_secs(cfg.s3.connect_timeout)) + .with_timeout(std::time::Duration::from_secs(cfg.s3.request_timeout)) + .with_allow_invalid_certificates(cfg.s3.allow_invalid_certificates) .with_allow_http(true); - if CONFIG.s3.feature_http1_only { + if cfg.s3.feature_http1_only { opts = opts.with_http1_only(); } - if CONFIG.s3.feature_http2_only { + if cfg.s3.feature_http2_only { opts = opts.with_http2_only(); } - let force_hosted_style = - CONFIG.s3.feature_force_hosted_style || CONFIG.s3.feature_force_path_style; + let force_hosted_style = cfg.s3.feature_force_hosted_style || cfg.s3.feature_force_path_style; let mut builder = object_store::aws::AmazonS3Builder::from_env() .with_client_options(opts) - .with_bucket_name(&CONFIG.s3.bucket_name) + .with_bucket_name(&cfg.s3.bucket_name) .with_virtual_hosted_style_request(force_hosted_style); - if !CONFIG.s3.server_url.is_empty() { - builder = builder.with_endpoint(&CONFIG.s3.server_url); + if !cfg.s3.server_url.is_empty() { + builder = builder.with_endpoint(&cfg.s3.server_url); } - if !CONFIG.s3.region_name.is_empty() { - builder = builder.with_region(&CONFIG.s3.region_name); + if !cfg.s3.region_name.is_empty() { + builder = builder.with_region(&cfg.s3.region_name); } - if !CONFIG.s3.access_key.is_empty() { - builder = builder.with_access_key_id(&CONFIG.s3.access_key); + if !cfg.s3.access_key.is_empty() { + builder = builder.with_access_key_id(&cfg.s3.access_key); } - if !CONFIG.s3.secret_key.is_empty() { - builder = builder.with_secret_access_key(&CONFIG.s3.secret_key); + if !cfg.s3.secret_key.is_empty() { + builder = builder.with_secret_access_key(&cfg.s3.secret_key); } builder.build() } fn init_azure_config() -> object_store::Result { + let cfg = get_config(); let mut builder = object_store::azure::MicrosoftAzureBuilder::from_env() .with_client_options( object_store::ClientOptions::default() - .with_connect_timeout(std::time::Duration::from_secs(CONFIG.s3.connect_timeout)) - .with_timeout(std::time::Duration::from_secs(CONFIG.s3.request_timeout)) - .with_allow_invalid_certificates(CONFIG.s3.allow_invalid_certificates), + .with_connect_timeout(std::time::Duration::from_secs(cfg.s3.connect_timeout)) + .with_timeout(std::time::Duration::from_secs(cfg.s3.request_timeout)) + .with_allow_invalid_certificates(cfg.s3.allow_invalid_certificates), ) - .with_container_name(&CONFIG.s3.bucket_name); - if !CONFIG.s3.access_key.is_empty() { - builder = builder.with_account(&CONFIG.s3.access_key); + .with_container_name(&cfg.s3.bucket_name); + if !cfg.s3.access_key.is_empty() { + builder = builder.with_account(&cfg.s3.access_key); } - if !CONFIG.s3.secret_key.is_empty() { - builder = builder.with_access_key(&CONFIG.s3.secret_key); + if !cfg.s3.secret_key.is_empty() { + builder = builder.with_access_key(&cfg.s3.secret_key); } builder.build() } fn init_gcp_config() -> object_store::Result { + let cfg = get_config(); let mut builder = object_store::gcp::GoogleCloudStorageBuilder::from_env() .with_client_options( object_store::ClientOptions::default() - .with_connect_timeout(std::time::Duration::from_secs(CONFIG.s3.connect_timeout)) - .with_timeout(std::time::Duration::from_secs(CONFIG.s3.request_timeout)) - .with_allow_invalid_certificates(CONFIG.s3.allow_invalid_certificates), + .with_connect_timeout(std::time::Duration::from_secs(cfg.s3.connect_timeout)) + .with_timeout(std::time::Duration::from_secs(cfg.s3.request_timeout)) + .with_allow_invalid_certificates(cfg.s3.allow_invalid_certificates), ) - .with_bucket_name(&CONFIG.s3.bucket_name); - if !CONFIG.s3.access_key.is_empty() { - builder = builder.with_service_account_path(&CONFIG.s3.access_key); + .with_bucket_name(&cfg.s3.bucket_name); + if !cfg.s3.access_key.is_empty() { + builder = builder.with_service_account_path(&cfg.s3.access_key); } builder.build() } fn init_client() -> Box { - if CONFIG.common.print_key_config { - log::info!("s3 init config: {:?}", CONFIG.s3); + let cfg = get_config(); + if cfg.common.print_key_config { + log::info!("s3 init config: {:?}", cfg.s3); } - match CONFIG.s3.provider.as_str() { + match cfg.s3.provider.as_str() { "aws" | "s3" => match init_aws_config() { Ok(client) => Box::new(client), Err(e) => { @@ -319,7 +322,7 @@ fn init_client() -> Box { _ => match init_aws_config() { Ok(client) => Box::new(client), Err(e) => { - panic!("{} init config error: {:?}", CONFIG.s3.provider, e); + panic!("{} init config error: {:?}", cfg.s3.provider, e); } }, } diff --git a/src/ingester/bin/wal-reader.rs b/src/ingester/bin/wal-reader.rs index 22e353be4b..498ae07e2a 100644 --- a/src/ingester/bin/wal-reader.rs +++ b/src/ingester/bin/wal-reader.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/ingester/src/entry.rs b/src/ingester/src/entry.rs index d4f3ace5f7..109ab3025b 100644 --- a/src/ingester/src/entry.rs +++ b/src/ingester/src/entry.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -21,10 +21,7 @@ use std::{ use arrow::{array::Int64Array, record_batch::RecordBatch}; use arrow_schema::Schema; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; -use config::{ - utils::record_batch_ext::{convert_json_to_record_batch, RecordBatchExt}, - CONFIG, -}; +use config::utils::record_batch_ext::{convert_json_to_record_batch, RecordBatchExt}; use snafu::ResultExt; use crate::errors::*; @@ -132,23 +129,24 @@ impl RecordBatchEntry { data_json_size: usize, data_arrow_size: usize, ) -> Arc { - let (min_ts, max_ts) = match data.column_by_name(&CONFIG.common.column_timestamp) { - None => (0, 0), - Some(v) => { - let v = v.as_any().downcast_ref::().unwrap(); - let mut min_v = v.value(0); - let mut max_v = v.value(0); - for v in v.values() { - if &min_v > v { - min_v = *v; - } - if &max_v < v { - max_v = *v; + let (min_ts, max_ts) = + match data.column_by_name(&config::get_config().common.column_timestamp) { + None => (0, 0), + Some(v) => { + let v = v.as_any().downcast_ref::().unwrap(); + let mut min_v = v.value(0); + let mut max_v = v.value(0); + for v in v.values() { + if &min_v > v { + min_v = *v; + } + if &max_v < v { + max_v = *v; + } } + (min_v, max_v) } - (min_v, max_v) - } - }; + }; Arc::new(Self { data, data_json_size, diff --git a/src/ingester/src/errors.rs b/src/ingester/src/errors.rs index bb5f37465c..566ea4bd16 100644 --- a/src/ingester/src/errors.rs +++ b/src/ingester/src/errors.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/ingester/src/immutable.rs b/src/ingester/src/immutable.rs index 2a909a4a96..89102736ad 100644 --- a/src/ingester/src/immutable.rs +++ b/src/ingester/src/immutable.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -16,7 +16,7 @@ use std::{path::PathBuf, sync::Arc}; use arrow_schema::Schema; -use config::{metrics, CONFIG}; +use config::metrics; use futures::future::join_all; use once_cell::sync::Lazy; use snafu::ResultExt; @@ -116,7 +116,9 @@ pub(crate) async fn persist() -> Result<()> { drop(r); let mut tasks = Vec::with_capacity(paths.len()); - let semaphore = Arc::new(Semaphore::new(CONFIG.limit.file_move_thread_num)); + let semaphore = Arc::new(Semaphore::new( + config::get_config().limit.file_move_thread_num, + )); for path in paths { let permit = semaphore.clone().acquire_owned().await.unwrap(); let task: task::JoinHandle>> = diff --git a/src/ingester/src/lib.rs b/src/ingester/src/lib.rs index d6b3d524be..f98628cbf2 100644 --- a/src/ingester/src/lib.rs +++ b/src/ingester/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -43,7 +43,7 @@ pub async fn init() -> errors::Result<()> { tokio::task::spawn(async move { // immutable persist every 10 (default) seconds let mut interval = tokio::time::interval(tokio::time::Duration::from_secs( - config::CONFIG.limit.mem_persist_interval, + config::get_config().limit.mem_persist_interval, )); interval.tick().await; // the first tick is immediate loop { @@ -60,7 +60,7 @@ pub async fn init() -> errors::Result<()> { // start a job to flush memtable to immutable tokio::task::spawn(async move { let mut interval = tokio::time::interval(tokio::time::Duration::from_secs( - config::CONFIG.limit.max_file_retention_time, + config::get_config().limit.max_file_retention_time, )); interval.tick().await; // the first tick is immediate loop { diff --git a/src/ingester/src/memtable.rs b/src/ingester/src/memtable.rs index 3e97cc3f63..8c7b1db691 100644 --- a/src/ingester/src/memtable.rs +++ b/src/ingester/src/memtable.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/ingester/src/partition.rs b/src/ingester/src/partition.rs index ebc93b0815..95a3ef93d4 100644 --- a/src/ingester/src/partition.rs +++ b/src/ingester/src/partition.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -23,7 +23,6 @@ use config::{ parquet::{generate_filename_with_time_range, new_parquet_writer}, schema_ext::SchemaExt, }, - CONFIG, }; use snafu::ResultExt; use tokio::{fs::OpenOptions, io::AsyncWriteExt}; @@ -78,7 +77,8 @@ impl Partition { stream_type: &str, stream_name: &str, ) -> Result<(usize, Vec<(PathBuf, PersistStat)>)> { - let base_path = PathBuf::from(&CONFIG.common.data_wal_dir); + let cfg = config::get_config(); + let base_path = PathBuf::from(&cfg.common.data_wal_dir); let mut path = base_path.clone(); path.push("files"); path.push(org_id); @@ -110,7 +110,7 @@ impl Partition { }; // write into parquet buf let (bloom_filter_fields, full_text_search_fields) = - if self.schema.fields().len() > CONFIG.limit.file_move_fields_limit { + if self.schema.fields().len() > cfg.limit.file_move_fields_limit { let bloom_filter_fields = infra::schema::get_stream_setting_bloom_filter_fields(self.schema.as_ref()) .unwrap(); diff --git a/src/ingester/src/rwmap.rs b/src/ingester/src/rwmap.rs index c6f847faf3..996ffb6297 100644 --- a/src/ingester/src/rwmap.rs +++ b/src/ingester/src/rwmap.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/ingester/src/stream.rs b/src/ingester/src/stream.rs index a691cbb821..284d939d15 100644 --- a/src/ingester/src/stream.rs +++ b/src/ingester/src/stream.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/ingester/src/wal.rs b/src/ingester/src/wal.rs index 179440ccfb..bc66234028 100644 --- a/src/ingester/src/wal.rs +++ b/src/ingester/src/wal.rs @@ -21,10 +21,7 @@ use std::{ }; use async_walkdir::WalkDir; -use config::{ - utils::{schema::infer_json_schema_from_values, schema_ext::SchemaExt}, - CONFIG, -}; +use config::utils::{schema::infer_json_schema_from_values, schema_ext::SchemaExt}; use futures::StreamExt; use snafu::ResultExt; @@ -48,8 +45,9 @@ use crate::{errors::*, immutable, memtable, writer::WriterKey}; // 4. the process is killed before step 5, so there are some .parquet files and have lock file, the // files actually wrote to disk completely, need to continue step 5 pub(crate) async fn check_uncompleted_parquet_files() -> Result<()> { + let cfg = config::get_config(); // 1. get all .lock files - let wal_dir = PathBuf::from(&CONFIG.common.data_wal_dir).join("logs"); + let wal_dir = PathBuf::from(&cfg.common.data_wal_dir).join("logs"); // create wal dir if not exists create_dir_all(&wal_dir).context(OpenDirSnafu { path: wal_dir.clone(), @@ -90,7 +88,7 @@ pub(crate) async fn check_uncompleted_parquet_files() -> Result<()> { } // 4. delete all the .par files - let parquet_dir = PathBuf::from(&CONFIG.common.data_wal_dir).join("files"); + let parquet_dir = PathBuf::from(&cfg.common.data_wal_dir).join("files"); // create wal dir if not exists create_dir_all(&parquet_dir).context(OpenDirSnafu { path: parquet_dir.clone(), @@ -105,7 +103,7 @@ pub(crate) async fn check_uncompleted_parquet_files() -> Result<()> { // replay wal files to create immutable pub(crate) async fn replay_wal_files() -> Result<()> { - let wal_dir = PathBuf::from(&CONFIG.common.data_wal_dir).join("logs"); + let wal_dir = PathBuf::from(&config::get_config().common.data_wal_dir).join("logs"); create_dir_all(&wal_dir).context(OpenDirSnafu { path: wal_dir.clone(), })?; diff --git a/src/ingester/src/writer.rs b/src/ingester/src/writer.rs index 821e224ce3..7c5a42221a 100644 --- a/src/ingester/src/writer.rs +++ b/src/ingester/src/writer.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -23,7 +23,7 @@ use std::{ use arrow_schema::Schema; use chrono::{Duration, Utc}; -use config::{metrics, CONFIG}; +use config::{get_config, metrics}; use once_cell::sync::Lazy; use snafu::ResultExt; use tokio::sync::{Mutex, RwLock}; @@ -39,8 +39,9 @@ use crate::{ }; static WRITERS: Lazy>>> = Lazy::new(|| { - let writer_num = if CONFIG.common.feature_per_thread_lock { - CONFIG.limit.http_worker_num + let cfg = get_config(); + let writer_num = if cfg.common.feature_per_thread_lock { + cfg.limit.http_worker_num } else { 1 }; @@ -65,7 +66,7 @@ pub fn check_memtable_size() -> Result<()> { let total_mem_size = metrics::INGEST_MEMTABLE_ARROW_BYTES .with_label_values(&[]) .get(); - if total_mem_size >= CONFIG.limit.mem_table_max_size as i64 { + if total_mem_size >= get_config().limit.mem_table_max_size as i64 { Err(Error::MemoryTableOverflowError {}) } else { Ok(()) @@ -88,9 +89,10 @@ pub async fn read_from_memtable( stream_name: &str, time_range: Option<(i64, i64)>, ) -> Result, Vec>)>> { + let cfg = get_config(); let key = WriterKey::new(org_id, stream_type); - let writer_num = if CONFIG.common.feature_per_thread_lock { - CONFIG.limit.http_worker_num + let writer_num = if cfg.common.feature_per_thread_lock { + cfg.limit.http_worker_num } else { 1 }; @@ -137,9 +139,10 @@ pub async fn flush_all() -> Result<()> { impl Writer { pub(crate) fn new(thread_id: usize, key: WriterKey) -> Self { let now = Utc::now().timestamp_micros(); + let cfg = get_config(); let next_seq = AtomicU64::new(now as u64); let wal_id = next_seq.fetch_add(1, Ordering::SeqCst); - let wal_dir = PathBuf::from(&CONFIG.common.data_wal_dir) + let wal_dir = PathBuf::from(&cfg.common.data_wal_dir) .join("logs") .join(thread_id.to_string()); log::info!( @@ -158,7 +161,7 @@ impl Writer { &key.org_id, &key.stream_type, wal_id, - CONFIG.limit.max_file_size_on_disk as u64, + cfg.limit.max_file_size_on_disk as u64, ) .expect("wal file create error"), )), @@ -187,11 +190,12 @@ impl Writer { if self.check_wal_threshold(wal.size(), entry_bytes.len()) || self.check_mem_threshold(self.memtable.read().await.size(), entry.data_size) { + let cfg = get_config(); // sync wal before rotation wal.sync().context(WalSnafu)?; // rotation wal let wal_id = self.next_seq.fetch_add(1, Ordering::SeqCst); - let wal_dir = PathBuf::from(&CONFIG.common.data_wal_dir) + let wal_dir = PathBuf::from(&cfg.common.data_wal_dir) .join("logs") .join(self.thread_id.to_string()); log::info!( @@ -206,7 +210,7 @@ impl Writer { &self.key.org_id, &self.key.stream_type, wal_id, - CONFIG.limit.max_file_size_on_disk as u64, + cfg.limit.max_file_size_on_disk as u64, ) .context(WalSnafu)?; let old_wal = std::mem::replace(&mut *wal, new_wal); @@ -285,11 +289,12 @@ impl Writer { /// Check if the wal file size is over the threshold or the file is too old fn check_wal_threshold(&self, written_size: (usize, usize), data_size: usize) -> bool { + let cfg = get_config(); let (compressed_size, _uncompressed_size) = written_size; compressed_size > 0 - && (compressed_size + data_size > CONFIG.limit.max_file_size_on_disk + && (compressed_size + data_size > cfg.limit.max_file_size_on_disk || self.created_at.load(Ordering::Relaxed) - + Duration::try_seconds(CONFIG.limit.max_file_retention_time as i64) + + Duration::try_seconds(cfg.limit.max_file_retention_time as i64) .unwrap() .num_microseconds() .unwrap() @@ -298,10 +303,11 @@ impl Writer { /// Check if the memtable size is over the threshold fn check_mem_threshold(&self, written_size: (usize, usize), data_size: usize) -> bool { + let cfg = get_config(); let (json_size, arrow_size) = written_size; json_size > 0 - && (json_size + data_size > CONFIG.limit.max_file_size_in_memory - || arrow_size + data_size > CONFIG.limit.max_file_size_in_memory) + && (json_size + data_size > cfg.limit.max_file_size_in_memory + || arrow_size + data_size > cfg.limit.max_file_size_in_memory) } } diff --git a/src/job/alert_manager.rs b/src/job/alert_manager.rs index e8d78e1843..97d7602300 100644 --- a/src/job/alert_manager.rs +++ b/src/job/alert_manager.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::{cluster, config::CONFIG}; +use config::{cluster, get_config}; #[cfg(feature = "enterprise")] use o2_enterprise::enterprise::common::infra::config::O2_CONFIG; use tokio::time; @@ -25,13 +25,14 @@ pub async fn run() -> Result<(), anyhow::Error> { return Ok(()); } + let cfg = get_config(); log::info!( "Spawning embedded report server {}", - CONFIG.report_server.enable_report_server + cfg.report_server.enable_report_server ); - if CONFIG.report_server.enable_report_server { + if cfg.report_server.enable_report_server { tokio::task::spawn(async move { - if let Err(e) = reportserver::spawn_server().await { + if let Err(e) = report_server::spawn_server().await { log::error!("report server failed to spawn {}", e); } }); @@ -77,7 +78,7 @@ async fn run_schedule_jobs() -> Result<(), anyhow::Error> { async fn clean_complete_jobs() -> Result<(), anyhow::Error> { let mut interval = time::interval(time::Duration::from_secs( - CONFIG.limit.scheduler_clean_interval, + get_config().limit.scheduler_clean_interval, )); interval.tick().await; // trigger the first run loop { @@ -90,7 +91,7 @@ async fn clean_complete_jobs() -> Result<(), anyhow::Error> { async fn watch_timeout_jobs() -> Result<(), anyhow::Error> { let mut interval = time::interval(time::Duration::from_secs( - CONFIG.limit.scheduler_watch_interval, + get_config().limit.scheduler_watch_interval, )); interval.tick().await; // trigger the first run loop { diff --git a/src/job/compact.rs b/src/job/compact.rs index bdf23aa8d1..d25cbf2cc2 100644 --- a/src/job/compact.rs +++ b/src/job/compact.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -17,8 +17,8 @@ use std::sync::Arc; use config::{ cluster::{is_compactor, LOCAL_NODE_ROLE}, + get_config, meta::stream::FileKey, - CONFIG, }; use tokio::{ sync::{mpsc, Mutex}, @@ -35,14 +35,15 @@ pub async fn run() -> Result<(), anyhow::Error> { return Ok(()); } - if !CONFIG.compact.enabled { + let cfg = get_config(); + if !cfg.compact.enabled { return Ok(()); } - let (tx, rx) = mpsc::channel::<(MergeSender, MergeBatch)>(CONFIG.limit.file_move_thread_num); + let (tx, rx) = mpsc::channel::<(MergeSender, MergeBatch)>(cfg.limit.file_move_thread_num); let rx = Arc::new(Mutex::new(rx)); // start merge workers - for thread_id in 0..CONFIG.limit.file_move_thread_num { + for thread_id in 0..cfg.limit.file_move_thread_num { let rx = rx.clone(); tokio::spawn(async move { loop { @@ -100,7 +101,7 @@ pub async fn run() -> Result<(), anyhow::Error> { /// Merge small files async fn run_merge(tx: mpsc::Sender<(MergeSender, MergeBatch)>) -> Result<(), anyhow::Error> { - let mut interval = time::interval(time::Duration::from_secs(CONFIG.compact.interval)); + let mut interval = time::interval(time::Duration::from_secs(get_config().compact.interval)); interval.tick().await; // trigger the first run loop { interval.tick().await; @@ -117,7 +118,7 @@ async fn run_merge(tx: mpsc::Sender<(MergeSender, MergeBatch)>) -> Result<(), an /// Deletion for data retention async fn run_retention() -> Result<(), anyhow::Error> { - let mut interval = time::interval(time::Duration::from_secs(CONFIG.compact.interval + 1)); + let mut interval = time::interval(time::Duration::from_secs(get_config().compact.interval + 1)); interval.tick().await; // trigger the first run loop { interval.tick().await; @@ -134,7 +135,7 @@ async fn run_retention() -> Result<(), anyhow::Error> { /// Delete files based on the file_file_deleted in the database async fn run_delay_deletion() -> Result<(), anyhow::Error> { - let mut interval = time::interval(time::Duration::from_secs(CONFIG.compact.interval + 2)); + let mut interval = time::interval(time::Duration::from_secs(get_config().compact.interval + 2)); interval.tick().await; // trigger the first run loop { interval.tick().await; @@ -151,7 +152,7 @@ async fn run_delay_deletion() -> Result<(), anyhow::Error> { async fn run_sync_to_db() -> Result<(), anyhow::Error> { let mut interval = time::interval(time::Duration::from_secs( - CONFIG.compact.sync_to_db_interval, + get_config().compact.sync_to_db_interval, )); interval.tick().await; // trigger the first run loop { diff --git a/src/job/file_list.rs b/src/job/file_list.rs index abf47983cf..de977c705e 100644 --- a/src/job/file_list.rs +++ b/src/job/file_list.rs @@ -17,9 +17,9 @@ use std::{fs, path::Path}; use config::{ cluster::{is_compactor, is_ingester, is_querier, LOCAL_NODE_ROLE}, + get_config, meta::stream::StreamType, utils::file::scan_files, - CONFIG, }; use infra::storage; use tokio::time; @@ -30,7 +30,8 @@ use crate::{ }; pub async fn run() -> Result<(), anyhow::Error> { - if CONFIG.common.local_mode || CONFIG.common.meta_store_external { + let cfg = get_config(); + if cfg.common.local_mode || cfg.common.meta_store_external { return Ok(()); } @@ -45,7 +46,9 @@ pub async fn run_move_file_to_s3() -> Result<(), anyhow::Error> { return Ok(()); // not an ingester, no need to init job } - let mut interval = time::interval(time::Duration::from_secs(CONFIG.limit.file_push_interval)); + let mut interval = time::interval(time::Duration::from_secs( + get_config().limit.file_push_interval, + )); interval.tick().await; // trigger the first run loop { interval.tick().await; @@ -57,11 +60,10 @@ pub async fn run_move_file_to_s3() -> Result<(), anyhow::Error> { // upload compressed file_list to storage & delete moved files from local pub async fn move_file_list_to_storage(check_in_use: bool) -> Result<(), anyhow::Error> { - let data_dir = Path::new(&CONFIG.common.data_wal_dir) - .canonicalize() - .unwrap(); + let cfg = get_config(); + let data_dir = Path::new(&cfg.common.data_wal_dir).canonicalize().unwrap(); - let pattern = format!("{}file_list/", &CONFIG.common.data_wal_dir); + let pattern = format!("{}file_list/", &cfg.common.data_wal_dir); let files = scan_files(&pattern, "json", None).unwrap_or_default(); for file in files { @@ -147,7 +149,9 @@ async fn _run_sync_s3_to_cache() -> Result<(), anyhow::Error> { return Ok(()); // only querier or compactor need to sync } - let mut interval = time::interval(time::Duration::from_secs(CONFIG.s3.sync_to_cache_interval)); + let mut interval = time::interval(time::Duration::from_secs( + get_config().s3.sync_to_cache_interval, + )); interval.tick().await; // trigger the first run loop { interval.tick().await; diff --git a/src/job/files/mod.rs b/src/job/files/mod.rs index f890cabbb3..4524d3e43b 100644 --- a/src/job/files/mod.rs +++ b/src/job/files/mod.rs @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::{cluster, ider, meta::stream::StreamType, CONFIG, FILE_EXT_PARQUET}; +use config::{cluster, ider, meta::stream::StreamType, FILE_EXT_PARQUET}; use tokio::time; pub mod broadcast; @@ -41,7 +41,7 @@ async fn clean_empty_dirs() -> Result<(), anyhow::Error> { interval.tick().await; let last_updated = std::time::SystemTime::now() - std::time::Duration::from_secs(3600); if let Err(e) = config::utils::asynchronism::file::clean_empty_dirs( - &CONFIG.common.data_wal_dir, + &config::get_config().common.data_wal_dir, Some(last_updated), ) .await diff --git a/src/job/files/parquet.rs b/src/job/files/parquet.rs index e0756ea9f5..134ae253e8 100644 --- a/src/job/files/parquet.rs +++ b/src/job/files/parquet.rs @@ -23,7 +23,7 @@ use arrow_schema::{DataType, Schema, SchemaRef}; use bytes::Bytes; use chrono::{Duration, Utc}; use config::{ - cluster, + cluster, get_config, meta::stream::{FileKey, FileMeta, PartitionTimeLevel, StreamType}, metrics, utils::{ @@ -37,7 +37,7 @@ use config::{ }, schema_ext::SchemaExt, }, - FxIndexMap, CONFIG, DEFAULT_INDEX_TRIM_CHARS, INDEX_MIN_CHAR_LEN, + FxIndexMap, DEFAULT_INDEX_TRIM_CHARS, INDEX_MIN_CHAR_LEN, }; use datafusion::{datasource::MemTable, prelude::*}; use hashbrown::HashSet; @@ -70,11 +70,12 @@ use crate::{ static PROCESSING_FILES: Lazy>> = Lazy::new(|| RwLock::new(HashSet::new())); pub async fn run() -> Result<(), anyhow::Error> { + let cfg = get_config(); let (tx, rx) = - tokio::sync::mpsc::channel::<(String, Vec)>(CONFIG.limit.file_move_thread_num); + tokio::sync::mpsc::channel::<(String, Vec)>(cfg.limit.file_move_thread_num); let rx = Arc::new(Mutex::new(rx)); // move files - for thread_id in 0..CONFIG.limit.file_move_thread_num { + for thread_id in 0..cfg.limit.file_move_thread_num { let rx = rx.clone(); tokio::spawn(async move { loop { @@ -98,7 +99,7 @@ pub async fn run() -> Result<(), anyhow::Error> { } // prepare files - let mut interval = time::interval(time::Duration::from_secs(CONFIG.limit.file_push_interval)); + let mut interval = time::interval(time::Duration::from_secs(cfg.limit.file_push_interval)); interval.tick().await; // trigger the first run loop { if cluster::is_offline() { @@ -123,14 +124,13 @@ pub async fn run() -> Result<(), anyhow::Error> { } async fn prepare_files() -> Result>, anyhow::Error> { + let cfg = get_config(); let start = std::time::Instant::now(); - let wal_dir = Path::new(&CONFIG.common.data_wal_dir) - .canonicalize() - .unwrap(); + let wal_dir = Path::new(&cfg.common.data_wal_dir).canonicalize().unwrap(); let pattern = wal_dir.join("files/"); let files = - scan_files(&pattern, "parquet", Some(CONFIG.limit.file_push_limit)).unwrap_or_default(); + scan_files(&pattern, "parquet", Some(cfg.limit.file_push_limit)).unwrap_or_default(); if files.is_empty() { return Ok(FxIndexMap::default()); } @@ -220,9 +220,8 @@ async fn move_files( // log::debug!("[INGESTER:JOB:{thread_id}] check deletion for partition: {}", prefix); - let wal_dir = Path::new(&CONFIG.common.data_wal_dir) - .canonicalize() - .unwrap(); + let cfg = get_config(); + let wal_dir = Path::new(&cfg.common.data_wal_dir).canonicalize().unwrap(); // check if we are allowed to ingest or just delete the file if db::compact::retention::is_deleting_stream(&org_id, stream_type, &stream_name, None) { @@ -289,16 +288,16 @@ async fn move_files( .sum::(); if total_original_size < std::cmp::min( - CONFIG.limit.max_file_size_on_disk as i64, - CONFIG.compact.max_file_size as i64, + cfg.limit.max_file_size_on_disk as i64, + cfg.compact.max_file_size as i64, ) - && (CONFIG.limit.file_move_fields_limit == 0 - || group_schema_field_num < CONFIG.limit.file_move_fields_limit) + && (cfg.limit.file_move_fields_limit == 0 + || group_schema_field_num < cfg.limit.file_move_fields_limit) { let mut has_expired_files = false; // not enough files to upload, check if some files are too old let min_ts = Utc::now().timestamp_micros() - - Duration::try_seconds(CONFIG.limit.max_file_retention_time as i64) + - Duration::try_seconds(cfg.limit.max_file_retention_time as i64) .unwrap() .num_microseconds() .unwrap(); @@ -445,6 +444,7 @@ async fn merge_files( return Ok((String::from(""), FileMeta::default(), Vec::new())); } + let cfg = get_config(); let mut new_file_size: i64 = 0; let mut new_file_list = Vec::new(); let mut deleted_files = Vec::new(); @@ -454,9 +454,9 @@ async fn merge_files( for file in files_with_size.iter() { if new_file_size > 0 - && ((new_file_size + file.meta.original_size > CONFIG.compact.max_file_size as i64) - || (CONFIG.limit.file_move_fields_limit > 0 - && group_schema_field_num > CONFIG.limit.file_move_fields_limit)) + && ((new_file_size + file.meta.original_size > cfg.compact.max_file_size as i64) + || (cfg.limit.file_move_fields_limit > 0 + && group_schema_field_num > cfg.limit.file_move_fields_limit)) { break; } @@ -617,7 +617,7 @@ async fn merge_files( let buf = Bytes::from(buf); match storage::put(&new_file_key, buf).await { Ok(_) => { - if CONFIG.common.inverted_index_enabled && stream_type != StreamType::Index { + if cfg.common.inverted_index_enabled && stream_type != StreamType::Index { generate_index_on_ingester( inverted_idx_batches, new_file_key.clone(), @@ -680,7 +680,7 @@ pub(crate) async fn generate_index_on_ingester( let recs: Vec = json_rows.into_iter().map(json::Value::Object).collect(); for record_val in recs { let timestamp: i64 = record_val - .get(&CONFIG.common.column_timestamp) + .get(&get_config().common.column_timestamp) .unwrap() .as_i64() .unwrap(); @@ -782,6 +782,7 @@ async fn prepare_index_record_batches( return Ok(vec![]); } + let cfg = get_config(); // filter null columns let schema = batches.first().unwrap().schema(); let batches = batches.iter().collect::>(); @@ -796,7 +797,7 @@ async fn prepare_index_record_batches( } let schema = new_batch.schema(); if schema.fields().is_empty() - || (schema.fields().len() == 1 && schema.field(0).name() == &CONFIG.common.column_timestamp) + || (schema.fields().len() == 1 && schema.field(0).name() == &cfg.common.column_timestamp) { return Ok(vec![]); } @@ -816,7 +817,7 @@ async fn prepare_index_record_batches( let index_df = ctx.table("_tbl_raw_data").await?; let column_name = column.name(); - let split_chars = &CONFIG.common.inverted_index_split_chars; + let split_chars = &cfg.common.inverted_index_split_chars; let remove_chars_btrim = DEFAULT_INDEX_TRIM_CHARS; let lower_case_expr = lower(concat(vec![col(column_name), lit("")])); let split_arr = STRING_TO_ARRAY_V2_UDF.call(vec![lower_case_expr, lit(split_chars)]); diff --git a/src/job/metrics.rs b/src/job/metrics.rs index b9ceef7648..3f0fb834b2 100644 --- a/src/job/metrics.rs +++ b/src/job/metrics.rs @@ -16,11 +16,10 @@ use std::path::Path; use config::{ - cluster, + cluster, get_config, meta::{cluster::Role, stream::StreamType}, metrics, utils::file::scan_files, - CONFIG, }; use hashbrown::HashMap; use infra::{cache, db::get_db}; @@ -54,21 +53,23 @@ pub async fn run() -> Result<(), anyhow::Error> { } async fn load_query_cache_limit_bytes() -> Result<(), anyhow::Error> { + let cfg = get_config(); metrics::QUERY_MEMORY_CACHE_LIMIT_BYTES .with_label_values(&[]) - .set(CONFIG.memory_cache.max_size as i64); + .set(cfg.memory_cache.max_size as i64); metrics::QUERY_DISK_CACHE_LIMIT_BYTES .with_label_values(&[]) - .set(CONFIG.disk_cache.max_size as i64); + .set(cfg.disk_cache.max_size as i64); Ok(()) } async fn load_ingest_wal_used_bytes() -> Result<(), anyhow::Error> { - let data_dir = match Path::new(&CONFIG.common.data_wal_dir).canonicalize() { + let cfg = get_config(); + let data_dir = match Path::new(&cfg.common.data_wal_dir).canonicalize() { Ok(path) => path, Err(_) => return Ok(()), }; - let pattern = format!("{}files/", &CONFIG.common.data_wal_dir); + let pattern = format!("{}files/", &cfg.common.data_wal_dir); let files = scan_files(pattern, "parquet", None).unwrap_or_default(); let mut sizes = HashMap::new(); for file in files { @@ -110,7 +111,7 @@ async fn update_metadata_metrics() -> Result<(), anyhow::Error> { .with_label_values(&[]) .set(stats.keys_count); - if CONFIG.common.local_mode { + if get_config().common.local_mode { metrics::META_NUM_NODES.with_label_values(&["all"]).set(1); } else { metrics::META_NUM_NODES.reset(); diff --git a/src/job/mmdb_downloader.rs b/src/job/mmdb_downloader.rs index cd56ccbbbb..2ad1e5ca60 100644 --- a/src/job/mmdb_downloader.rs +++ b/src/job/mmdb_downloader.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -15,7 +15,7 @@ use std::{cmp::min, path::Path}; -use config::{CONFIG, MMDB_ASN_FILE_NAME, MMDB_CITY_FILE_NAME}; +use config::{MMDB_ASN_FILE_NAME, MMDB_CITY_FILE_NAME}; use futures::stream::StreamExt; use once_cell::sync::Lazy; use reqwest::Client; @@ -33,11 +33,10 @@ use crate::{ static CLIENT_INITIALIZED: Lazy = Lazy::new(|| true); pub async fn run() -> Result<(), anyhow::Error> { - std::fs::create_dir_all(&CONFIG.common.mmdb_data_dir)?; + let cfg = config::get_config(); + std::fs::create_dir_all(&cfg.common.mmdb_data_dir)?; // should run it every 24 hours - let mut interval = time::interval(time::Duration::from_secs( - CONFIG.common.mmdb_update_duration, - )); + let mut interval = time::interval(time::Duration::from_secs(cfg.common.mmdb_update_duration)); loop { interval.tick().await; @@ -46,13 +45,15 @@ pub async fn run() -> Result<(), anyhow::Error> { } async fn run_download_files() { + let cfg = config::get_config(); + // send request and await response let client = reqwest::Client::new(); - let city_fname = format!("{}{}", &CONFIG.common.mmdb_data_dir, MMDB_CITY_FILE_NAME); - let asn_fname = format!("{}{}", &CONFIG.common.mmdb_data_dir, MMDB_ASN_FILE_NAME); + let city_fname = format!("{}{}", &cfg.common.mmdb_data_dir, MMDB_CITY_FILE_NAME); + let asn_fname = format!("{}{}", &cfg.common.mmdb_data_dir, MMDB_ASN_FILE_NAME); let download_city_files = - is_digest_different(&city_fname, &CONFIG.common.mmdb_geolite_citydb_sha256_url) + is_digest_different(&city_fname, &cfg.common.mmdb_geolite_citydb_sha256_url) .await .unwrap_or_else(|e| { log::error!("Error checking digest difference: {e}"); @@ -60,7 +61,7 @@ async fn run_download_files() { }); let download_asn_files = - is_digest_different(&asn_fname, &CONFIG.common.mmdb_geolite_asndb_sha256_url) + is_digest_different(&asn_fname, &cfg.common.mmdb_geolite_asndb_sha256_url) .await .unwrap_or_else(|e| { log::error!("Error checking digest difference: {e}"); @@ -68,14 +69,14 @@ async fn run_download_files() { }); if download_city_files { - match download_file(&client, &CONFIG.common.mmdb_geolite_citydb_url, &city_fname).await { + match download_file(&client, &cfg.common.mmdb_geolite_citydb_url, &city_fname).await { Ok(()) => {} Err(e) => log::error!("failed to download the files {}", e), } } if download_asn_files { - match download_file(&client, &CONFIG.common.mmdb_geolite_asndb_url, &asn_fname).await { + match download_file(&client, &cfg.common.mmdb_geolite_asndb_url, &asn_fname).await { Ok(()) => {} Err(e) => log::error!("failed to download the files {}", e), } diff --git a/src/job/mod.rs b/src/job/mod.rs index 3c19520d2d..0398752996 100644 --- a/src/job/mod.rs +++ b/src/job/mod.rs @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::{cluster, CONFIG}; +use config::cluster; use infra::file_list as infra_file_list; #[cfg(feature = "enterprise")] use o2_enterprise::enterprise::common::infra::config::O2_CONFIG; @@ -44,11 +44,12 @@ pub async fn init() -> Result<(), anyhow::Error> { ) .expect("Email regex is valid"); + let cfg = config::get_config(); // init root user if !db::user::root_user_exists().await { - if CONFIG.auth.root_user_email.is_empty() - || !email_regex.is_match(&CONFIG.auth.root_user_email) - || CONFIG.auth.root_user_password.is_empty() + if cfg.auth.root_user_email.is_empty() + || !email_regex.is_match(&cfg.auth.root_user_email) + || cfg.auth.root_user_password.is_empty() { panic!( "Please set root user email-id & password using ZO_ROOT_USER_EMAIL & ZO_ROOT_USER_PASSWORD environment variables. This can also indicate an invalid email ID. Email ID must comply with ([a-z0-9_+]([a-z0-9_+.-]*[a-z0-9_+])?)@([a-z0-9]+([\\-\\.]{{1}}[a-z0-9]+)*\\.[a-z]{{2,6}})" @@ -57,8 +58,8 @@ pub async fn init() -> Result<(), anyhow::Error> { let _ = users::create_root_user( DEFAULT_ORG, UserRequest { - email: CONFIG.auth.root_user_email.clone(), - password: CONFIG.auth.root_user_password.clone(), + email: cfg.auth.root_user_email.clone(), + password: cfg.auth.root_user_password.clone(), role: crate::common::meta::user::UserRole::Root, first_name: "root".to_owned(), last_name: "".to_owned(), @@ -68,7 +69,7 @@ pub async fn init() -> Result<(), anyhow::Error> { .await; } - if !CONFIG.common.mmdb_disable_download { + if !cfg.common.mmdb_disable_download { // Try to download the mmdb files, if its not disabled. tokio::task::spawn(async move { mmdb_downloader::run().await }); } @@ -89,7 +90,7 @@ pub async fn init() -> Result<(), anyhow::Error> { } // telemetry run - if CONFIG.common.telemetry_enabled && cluster::is_querier(&cluster::LOCAL_NODE_ROLE) { + if cfg.common.telemetry_enabled && cluster::is_querier(&cluster::LOCAL_NODE_ROLE) { tokio::task::spawn(async move { telemetry::run().await }); } @@ -154,7 +155,7 @@ pub async fn init() -> Result<(), anyhow::Error> { } // cache file list - if !CONFIG.common.meta_store_external { + if !cfg.common.meta_store_external { if cluster::is_ingester(&cluster::LOCAL_NODE_ROLE) { // load the wal file_list into memory db::file_list::local::load_wal_in_cache() @@ -194,10 +195,10 @@ pub async fn init() -> Result<(), anyhow::Error> { // check wal directory if cluster::is_ingester(&cluster::LOCAL_NODE_ROLE) { // create wal dir - if let Err(e) = std::fs::create_dir_all(&CONFIG.common.data_wal_dir) { + if let Err(e) = std::fs::create_dir_all(&cfg.common.data_wal_dir) { log::error!("Failed to create wal dir: {}", e); } - if let Err(e) = std::fs::create_dir_all(&CONFIG.common.data_idx_dir) { + if let Err(e) = std::fs::create_dir_all(&cfg.common.data_idx_dir) { log::error!("Failed to create wal dir: {}", e); } } diff --git a/src/job/prom.rs b/src/job/prom.rs index 629887c0d9..d7faaecae0 100644 --- a/src/job/prom.rs +++ b/src/job/prom.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::{cluster, CONFIG}; +use config::cluster; use hashbrown::HashMap; use tokio::time::{self, Duration}; @@ -27,13 +27,12 @@ pub async fn run() -> Result<(), anyhow::Error> { return Ok(()); // not an ingester, no need to init job } - if !CONFIG.common.metrics_dedup_enabled { + let cfg = config::get_config(); + if !cfg.common.metrics_dedup_enabled { return Ok(()); } - let mut interval = time::interval(Duration::from_secs( - CONFIG.limit.metrics_leader_push_interval, - )); + let mut interval = time::interval(Duration::from_secs(cfg.limit.metrics_leader_push_interval)); interval.tick().await; // trigger the first run let mut last_leaders: HashMap = HashMap::new(); // maintain the last state diff --git a/src/job/stats.rs b/src/job/stats.rs index e1a489dc01..687c84e6fc 100644 --- a/src/job/stats.rs +++ b/src/job/stats.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -15,7 +15,7 @@ use config::{ cluster::{is_compactor, is_querier}, - CONFIG, + get_config, }; use tokio::time; @@ -29,13 +29,14 @@ pub async fn run() -> Result<(), anyhow::Error> { } async fn _usage_report_stats() -> Result<(), anyhow::Error> { - if !is_compactor(&super::cluster::LOCAL_NODE_ROLE) || !CONFIG.common.usage_enabled { + let cfg = get_config(); + if !is_compactor(&super::cluster::LOCAL_NODE_ROLE) || !cfg.common.usage_enabled { return Ok(()); } // should run it every 10 minutes let mut interval = time::interval(time::Duration::from_secs( - CONFIG.limit.calculate_stats_interval, + cfg.limit.calculate_stats_interval, )); interval.tick().await; // trigger the first run loop { @@ -48,14 +49,15 @@ async fn _usage_report_stats() -> Result<(), anyhow::Error> { // get stats from file_list to update stream_stats async fn file_list_update_stats() -> Result<(), anyhow::Error> { - if (CONFIG.common.meta_store_external || !is_querier(&super::cluster::LOCAL_NODE_ROLE)) + let cfg = get_config(); + if (cfg.common.meta_store_external || !is_querier(&super::cluster::LOCAL_NODE_ROLE)) && !is_compactor(&super::cluster::LOCAL_NODE_ROLE) { return Ok(()); } let mut interval = time::interval(time::Duration::from_secs( - CONFIG.limit.calculate_stats_interval, + cfg.limit.calculate_stats_interval, )); interval.tick().await; // trigger the first run loop { @@ -84,7 +86,7 @@ async fn cache_stream_stats() -> Result<(), anyhow::Error> { // should run it every minute let mut interval = time::interval(time::Duration::from_secs(std::cmp::min( - CONFIG.limit.calculate_stats_interval, + get_config().limit.calculate_stats_interval, 60, ))); interval.tick().await; // trigger the first run diff --git a/src/job/syslog_server.rs b/src/job/syslog_server.rs index feeb491944..dcb6721446 100644 --- a/src/job/syslog_server.rs +++ b/src/job/syslog_server.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -18,7 +18,6 @@ use std::{ net::{SocketAddr, TcpStream}, }; -use config::CONFIG; use once_cell::sync::Lazy; use tokio::{ net::{TcpListener, UdpSocket}, @@ -38,10 +37,11 @@ pub static BROADCASTER: Lazy>> = Lazy::new(|| { }); pub async fn run(start_srv: bool, is_init: bool) -> Result<(), anyhow::Error> { + let cfg = config::get_config(); let server_running = *SYSLOG_ENABLED.read(); let bind_addr = "0.0.0.0"; - let tcp_addr: SocketAddr = format!("{bind_addr}:{}", CONFIG.tcp.tcp_port).parse()?; - let udp_addr: SocketAddr = format!("{bind_addr}:{}", CONFIG.tcp.udp_port).parse()?; + let tcp_addr: SocketAddr = format!("{bind_addr}:{}", cfg.tcp.tcp_port).parse()?; + let udp_addr: SocketAddr = format!("{bind_addr}:{}", cfg.tcp.udp_port).parse()?; if (!server_running || is_init) && start_srv { log::info!("Starting TCP UDP server"); let tcp_listener: TcpListener = TcpListener::bind(tcp_addr).await?; diff --git a/src/job/telemetry.rs b/src/job/telemetry.rs index f1ffc091aa..dc211ac1e8 100644 --- a/src/job/telemetry.rs +++ b/src/job/telemetry.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -13,18 +13,18 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::CONFIG; use tokio::time; use crate::common::meta::telemetry::Telemetry; pub async fn run() -> Result<(), anyhow::Error> { - if !CONFIG.common.telemetry_enabled { + let cfg = config::get_config(); + if !cfg.common.telemetry_enabled { return Ok(()); } let mut interval = time::interval(time::Duration::from_secs( - (CONFIG.common.telemetry_heartbeat).try_into().unwrap(), + (cfg.common.telemetry_heartbeat).try_into().unwrap(), )); interval.tick().await; loop { diff --git a/src/main.rs b/src/main.rs index 386a317b70..3073d9be4e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,7 +29,7 @@ use actix_web::{dev::ServerHandle, http::KeepAlive, middleware, web, App, HttpSe use actix_web_opentelemetry::RequestTracing; use config::{ cluster::{is_router, LOCAL_NODE_ROLE}, - CONFIG, + get_config, }; use log::LevelFilter; use openobserve::{ @@ -91,16 +91,17 @@ use tracing_subscriber::{ #[tokio::main] async fn main() -> Result<(), anyhow::Error> { + let cfg = get_config(); #[cfg(feature = "tokio-console")] console_subscriber::ConsoleLayer::builder() .retention(Duration::from_secs( - CONFIG.tokio_console.tokio_console_retention, + cfg.tokio_console.tokio_console_retention, )) .server_addr( format!( "{}:{}", - CONFIG.tokio_console.tokio_console_server_addr, - CONFIG.tokio_console.tokio_console_server_port + cfg.tokio_console.tokio_console_server_addr, + cfg.tokio_console.tokio_console_server_port ) .as_str() .parse::()?, @@ -118,22 +119,21 @@ async fn main() -> Result<(), anyhow::Error> { // setup profiling #[cfg(feature = "profiling")] - let agent = if !CONFIG.profiling.enabled { + let agent = if !cfg.profiling.enabled { None } else { - let agent = - PyroscopeAgent::builder(&CONFIG.profiling.server_url, &CONFIG.profiling.project_name) - .tags( - [ - ("role", CONFIG.common.node_role.as_str()), - ("instance", CONFIG.common.instance_name.as_str()), - ("version", VERSION), - ] - .to_vec(), - ) - .backend(pprof_backend(PprofConfig::new().sample_rate(100))) - .build() - .expect("Failed to setup pyroscope agent"); + let agent = PyroscopeAgent::builder(&cfg.profiling.server_url, &cfg.profiling.project_name) + .tags( + [ + ("role", cfg.common.node_role.as_str()), + ("instance", cfg.common.instance_name.as_str()), + ("version", VERSION), + ] + .to_vec(), + ) + .backend(pprof_backend(PprofConfig::new().sample_rate(100))) + .build() + .expect("Failed to setup pyroscope agent"); #[cfg(feature = "profiling")] let agent_running = agent.start().expect("Failed to start pyroscope agent"); Some(agent_running) @@ -151,17 +151,15 @@ async fn main() -> Result<(), anyhow::Error> { let enable_tokio_console = false; let _guard: Option = if enable_tokio_console { None - } else if CONFIG.log.events_enabled { + } else if cfg.log.events_enabled { let logger = zo_logger::ZoLogger { sender: zo_logger::EVENT_SENDER.clone(), }; log::set_boxed_logger(Box::new(logger)).map(|()| { - log::set_max_level( - LevelFilter::from_str(&CONFIG.log.level).unwrap_or(LevelFilter::Info), - ) + log::set_max_level(LevelFilter::from_str(&cfg.log.level).unwrap_or(LevelFilter::Info)) })?; None - } else if CONFIG.common.tracing_enabled || CONFIG.common.tracing_search_enabled { + } else if cfg.common.tracing_enabled || cfg.common.tracing_search_enabled { enable_tracing()?; None } else { @@ -171,10 +169,10 @@ async fn main() -> Result<(), anyhow::Error> { log::info!("Starting OpenObserve {}", VERSION); log::info!( "System info: CPU cores {}, MEM total {} MB, Disk total {} GB, free {} GB", - CONFIG.limit.cpu_num, - CONFIG.limit.mem_total / 1024 / 1024, - CONFIG.limit.disk_total / 1024 / 1024 / 1024, - CONFIG.limit.disk_free / 1024 / 1024 / 1024, + cfg.limit.cpu_num, + cfg.limit.mem_total / 1024 / 1024, + cfg.limit.disk_total / 1024 / 1024 / 1024, + cfg.limit.disk_free / 1024 / 1024 / 1024, ); // it must be initialized before the server starts @@ -225,10 +223,10 @@ async fn main() -> Result<(), anyhow::Error> { .await .expect("EnrichmentTables cache failed"); - if CONFIG.log.events_enabled { + if cfg.log.events_enabled { tokio::task::spawn(async move { zo_logger::send_logs().await }); } - if CONFIG.common.telemetry_enabled { + if cfg.common.telemetry_enabled { tokio::task::spawn(async move { meta::telemetry::Telemetry::new() .event("OpenObserve - Starting server", None, false) @@ -237,7 +235,7 @@ async fn main() -> Result<(), anyhow::Error> { } // init http server - if !CONFIG.common.tracing_enabled && CONFIG.common.tracing_search_enabled { + if !cfg.common.tracing_enabled && cfg.common.tracing_search_enabled { if let Err(e) = init_http_server_without_tracing().await { log::error!("HTTP server runs failed: {}", e); } @@ -269,7 +267,7 @@ async fn main() -> Result<(), anyhow::Error> { _ = db.close().await; // stop telemetry - if CONFIG.common.telemetry_enabled { + if cfg.common.telemetry_enabled { meta::telemetry::Telemetry::new() .event("OpenObserve - Server stopped", None, false) .await; @@ -290,12 +288,13 @@ fn init_common_grpc_server( shutdown_rx: oneshot::Receiver<()>, stopped_tx: oneshot::Sender<()>, ) -> Result<(), anyhow::Error> { - let ip = if !CONFIG.grpc.addr.is_empty() { - CONFIG.grpc.addr.clone() + let cfg = get_config(); + let ip = if !cfg.grpc.addr.is_empty() { + cfg.grpc.addr.clone() } else { "0.0.0.0".to_string() }; - let gaddr: SocketAddr = format!("{}:{}", ip, CONFIG.grpc.port).parse()?; + let gaddr: SocketAddr = format!("{}:{}", ip, cfg.grpc.port).parse()?; let event_svc = EventServer::new(Eventer) .send_compressed(CompressionEncoding::Gzip) .accept_compressed(CompressionEncoding::Gzip); @@ -349,12 +348,13 @@ fn init_router_grpc_server( shutdown_rx: oneshot::Receiver<()>, stopped_tx: oneshot::Sender<()>, ) -> Result<(), anyhow::Error> { - let gaddr: SocketAddr = format!("0.0.0.0:{}", CONFIG.grpc.port).parse()?; + let cfg = get_config(); + let gaddr: SocketAddr = format!("0.0.0.0:{}", cfg.grpc.port).parse()?; let logs_svc = LogsServiceServer::new(router::grpc::ingest::logs::LogsServer) .send_compressed(CompressionEncoding::Gzip) .accept_compressed(CompressionEncoding::Gzip) - .max_decoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024) - .max_encoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024); + .max_decoding_message_size(cfg.grpc.max_message_size * 1024 * 1024) + .max_encoding_message_size(cfg.grpc.max_message_size * 1024 * 1024); let metrics_svc = MetricsServiceServer::new(router::grpc::ingest::metrics::MetricsServer) .send_compressed(CompressionEncoding::Gzip) .accept_compressed(CompressionEncoding::Gzip); @@ -381,24 +381,26 @@ fn init_router_grpc_server( } async fn init_http_server() -> Result<(), anyhow::Error> { + let cfg = get_config(); // metrics let prometheus = config::metrics::create_prometheus_handler(); let thread_id = Arc::new(AtomicU16::new(0)); - let haddr: SocketAddr = if CONFIG.http.ipv6_enabled { - format!("[::]:{}", CONFIG.http.port).parse()? + let haddr: SocketAddr = if cfg.http.ipv6_enabled { + format!("[::]:{}", cfg.http.port).parse()? } else { - let ip = if !CONFIG.http.addr.is_empty() { - CONFIG.http.addr.clone() + let ip = if !cfg.http.addr.is_empty() { + cfg.http.addr.clone() } else { "0.0.0.0".to_string() }; - format!("{}:{}", ip, CONFIG.http.port).parse()? + format!("{}:{}", ip, cfg.http.port).parse()? }; let server = HttpServer::new(move || { + let cfg = get_config(); let local_id = thread_id.load(Ordering::SeqCst) as usize; - if CONFIG.common.feature_per_thread_lock { + if cfg.common.feature_per_thread_lock { thread_id.fetch_add(1, Ordering::SeqCst); } log::info!( @@ -409,14 +411,14 @@ async fn init_http_server() -> Result<(), anyhow::Error> { let mut app = App::new().wrap(prometheus.clone()); if is_router(&LOCAL_NODE_ROLE) { let client = awc::Client::builder() - .connector(awc::Connector::new().limit(CONFIG.route.max_connections)) - .timeout(Duration::from_secs(CONFIG.route.timeout)) + .connector(awc::Connector::new().limit(cfg.route.max_connections)) + .timeout(Duration::from_secs(cfg.route.timeout)) .disable_redirects() .finish(); app = app .service( - // if `CONFIG.common.base_uri` is empty, scope("") still works as expected. - web::scope(&CONFIG.common.base_uri) + // if `cfg.common.base_uri` is empty, scope("") still works as expected. + web::scope(&cfg.common.base_uri) .service(router::http::config) .service(router::http::config_paths) .service(router::http::api) @@ -429,7 +431,7 @@ async fn init_http_server() -> Result<(), anyhow::Error> { .app_data(web::Data::new(client)) } else { app = app.service( - web::scope(&CONFIG.common.base_uri) + web::scope(&cfg.common.base_uri) .configure(get_config_routes) .configure(get_service_routes) .configure(get_other_service_routes) @@ -437,8 +439,8 @@ async fn init_http_server() -> Result<(), anyhow::Error> { .configure(get_proxy_routes), ) } - app.app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) // size is in bytes + app.app_data(web::JsonConfig::default().limit(cfg.limit.req_json_limit)) + .app_data(web::PayloadConfig::new(cfg.limit.req_payload_limit)) // size is in bytes .app_data(web::Data::new(local_id%10)) .wrap(middleware::Compress::default()) .wrap(middleware::Logger::new( @@ -448,17 +450,15 @@ async fn init_http_server() -> Result<(), anyhow::Error> { }) .keep_alive(KeepAlive::Timeout(Duration::from_secs(max( 15, - CONFIG.limit.keep_alive, + cfg.limit.keep_alive, )))) - .client_request_timeout(Duration::from_secs(max(5, CONFIG.limit.request_timeout))) - .shutdown_timeout(max(1, CONFIG.limit.shutdown_timeout)) + .client_request_timeout(Duration::from_secs(max(5, cfg.limit.request_timeout))) + .shutdown_timeout(max(1, cfg.limit.shutdown_timeout)) .bind(haddr)?; let server = server - .workers(CONFIG.limit.http_worker_num) - .worker_max_blocking_threads( - CONFIG.limit.http_worker_num * CONFIG.limit.http_worker_max_blocking, - ) + .workers(cfg.limit.http_worker_num) + .worker_max_blocking_threads(cfg.limit.http_worker_num * cfg.limit.http_worker_max_blocking) .disable_signals() .run(); let handle = server.handle(); @@ -470,24 +470,26 @@ async fn init_http_server() -> Result<(), anyhow::Error> { } async fn init_http_server_without_tracing() -> Result<(), anyhow::Error> { + let cfg = get_config(); // metrics let prometheus = config::metrics::create_prometheus_handler(); let thread_id = Arc::new(AtomicU16::new(0)); - let haddr: SocketAddr = if CONFIG.http.ipv6_enabled { - format!("[::]:{}", CONFIG.http.port).parse()? + let haddr: SocketAddr = if cfg.http.ipv6_enabled { + format!("[::]:{}", cfg.http.port).parse()? } else { - let ip = if !CONFIG.http.addr.is_empty() { - CONFIG.http.addr.clone() + let ip = if !cfg.http.addr.is_empty() { + cfg.http.addr.clone() } else { "0.0.0.0".to_string() }; - format!("{}:{}", ip, CONFIG.http.port).parse()? + format!("{}:{}", ip, cfg.http.port).parse()? }; let server = HttpServer::new(move || { + let cfg = get_config(); let local_id = thread_id.load(Ordering::SeqCst) as usize; - if CONFIG.common.feature_per_thread_lock { + if cfg.common.feature_per_thread_lock { thread_id.fetch_add(1, Ordering::SeqCst); } log::info!( @@ -498,14 +500,14 @@ async fn init_http_server_without_tracing() -> Result<(), anyhow::Error> { let mut app = App::new().wrap(prometheus.clone()); if is_router(&LOCAL_NODE_ROLE) { let client = awc::Client::builder() - .connector(awc::Connector::new().limit(CONFIG.route.max_connections)) - .timeout(Duration::from_secs(CONFIG.route.timeout)) + .connector(awc::Connector::new().limit(cfg.route.max_connections)) + .timeout(Duration::from_secs(cfg.route.timeout)) .disable_redirects() .finish(); app = app .service( - // if `CONFIG.common.base_uri` is empty, scope("") still works as expected. - web::scope(&CONFIG.common.base_uri) + // if `cfg.common.base_uri` is empty, scope("") still works as expected. + web::scope(&cfg.common.base_uri) .service(router::http::config) .service(router::http::config_paths) .service(router::http::api) @@ -518,7 +520,7 @@ async fn init_http_server_without_tracing() -> Result<(), anyhow::Error> { .app_data(web::Data::new(client)) } else { app = app.service( - web::scope(&CONFIG.common.base_uri) + web::scope(&cfg.common.base_uri) .configure(get_config_routes) .configure(get_service_routes) .configure(get_other_service_routes) @@ -526,8 +528,8 @@ async fn init_http_server_without_tracing() -> Result<(), anyhow::Error> { .configure(get_proxy_routes), ) } - app.app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) // size is in bytes + app.app_data(web::JsonConfig::default().limit(cfg.limit.req_json_limit)) + .app_data(web::PayloadConfig::new(cfg.limit.req_payload_limit)) // size is in bytes .app_data(web::Data::new(local_id%10)) .wrap(middleware::Compress::default()) .wrap(middleware::Logger::new( @@ -536,17 +538,15 @@ async fn init_http_server_without_tracing() -> Result<(), anyhow::Error> { }) .keep_alive(KeepAlive::Timeout(Duration::from_secs(max( 15, - CONFIG.limit.keep_alive, + cfg.limit.keep_alive, )))) - .client_request_timeout(Duration::from_secs(max(5, CONFIG.limit.request_timeout))) - .shutdown_timeout(max(1, CONFIG.limit.shutdown_timeout)) + .client_request_timeout(Duration::from_secs(max(5, cfg.limit.request_timeout))) + .shutdown_timeout(max(1, cfg.limit.shutdown_timeout)) .bind(haddr)?; let server = server - .workers(CONFIG.limit.http_worker_num) - .worker_max_blocking_threads( - CONFIG.limit.http_worker_num * CONFIG.limit.http_worker_max_blocking, - ) + .workers(cfg.limit.http_worker_num) + .worker_max_blocking_threads(cfg.limit.http_worker_num * cfg.limit.http_worker_max_blocking) .disable_signals() .run(); let handle = server.handle(); @@ -605,21 +605,21 @@ async fn graceful_shutdown(handle: ServerHandle) { pub(crate) fn setup_logs() -> tracing_appender::non_blocking::WorkerGuard { use tracing_subscriber::fmt::writer::BoxMakeWriter; - let (writer, guard) = if CONFIG.log.file_dir.is_empty() { + let cfg = get_config(); + let (writer, guard) = if cfg.log.file_dir.is_empty() { let (non_blocking, _guard) = tracing_appender::non_blocking(std::io::stdout()); (BoxMakeWriter::new(non_blocking), _guard) } else { - let file_name_prefix = if CONFIG.log.file_name_prefix.is_empty() { - format!("o2.{}.log", CONFIG.common.instance_name.as_str()) + let file_name_prefix = if cfg.log.file_name_prefix.is_empty() { + format!("o2.{}.log", cfg.common.instance_name.as_str()) } else { - CONFIG.log.file_name_prefix.to_string() + cfg.log.file_name_prefix.to_string() }; - let file_appender = - tracing_appender::rolling::daily(&CONFIG.log.file_dir, file_name_prefix); + let file_appender = tracing_appender::rolling::daily(&cfg.log.file_dir, file_name_prefix); let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender); (BoxMakeWriter::new(non_blocking), _guard) }; - let layer = if CONFIG.log.json_format { + let layer = if cfg.log.json_format { Layer::default() .with_writer(writer) .with_timer(config::meta::logger::CustomTimeFormat) @@ -649,28 +649,29 @@ pub(crate) fn setup_logs() -> tracing_appender::non_blocking::WorkerGuard { } fn enable_tracing() -> Result<(), anyhow::Error> { + let cfg = get_config(); opentelemetry::global::set_text_map_propagator(TraceContextPropagator::new()); let mut headers = HashMap::new(); headers.insert( - CONFIG.common.tracing_header_key.clone(), - CONFIG.common.tracing_header_value.clone(), + cfg.common.tracing_header_key.clone(), + cfg.common.tracing_header_value.clone(), ); let tracer = opentelemetry_otlp::new_pipeline() .tracing() .with_exporter( opentelemetry_otlp::new_exporter() .http() - .with_endpoint(&CONFIG.common.otel_otlp_url) + .with_endpoint(&cfg.common.otel_otlp_url) .with_headers(headers), ) .with_trace_config(sdktrace::config().with_resource(Resource::new(vec![ - KeyValue::new("service.name", CONFIG.common.node_role.as_str()), - KeyValue::new("service.instance", CONFIG.common.instance_name.as_str()), + KeyValue::new("service.name", cfg.common.node_role.to_string()), + KeyValue::new("service.instance", cfg.common.instance_name.to_string()), KeyValue::new("service.version", VERSION), ]))) .install_batch(opentelemetry_sdk::runtime::Tokio)?; - let layer = if CONFIG.log.json_format { + let layer = if cfg.log.json_format { tracing_subscriber::fmt::layer() .with_ansi(false) .json() @@ -680,7 +681,7 @@ fn enable_tracing() -> Result<(), anyhow::Error> { }; Registry::default() - .with(tracing_subscriber::EnvFilter::new(&CONFIG.log.level)) + .with(tracing_subscriber::EnvFilter::new(&cfg.log.level)) .with(layer) .with(tracing_opentelemetry::layer().with_tracer(tracer)) .init(); diff --git a/src/proto/build.rs b/src/proto/build.rs index 0a01ffa5a2..8e51828d79 100644 --- a/src/proto/build.rs +++ b/src/proto/build.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/reportserver/Cargo.toml b/src/report_server/Cargo.toml similarity index 94% rename from src/reportserver/Cargo.toml rename to src/report_server/Cargo.toml index b2709f63ed..3727e81520 100644 --- a/src/reportserver/Cargo.toml +++ b/src/report_server/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "reportserver" +name = "report_server" version.workspace = true edition.workspace = true license.workspace = true diff --git a/src/reportserver/src/lib.rs b/src/report_server/src/lib.rs similarity index 100% rename from src/reportserver/src/lib.rs rename to src/report_server/src/lib.rs diff --git a/src/reportserver/src/models.rs b/src/report_server/src/models.rs similarity index 100% rename from src/reportserver/src/models.rs rename to src/report_server/src/models.rs diff --git a/src/reportserver/src/report.rs b/src/report_server/src/report.rs similarity index 92% rename from src/reportserver/src/report.rs rename to src/report_server/src/report.rs index 1a080b9efc..386ad57e2e 100644 --- a/src/reportserver/src/report.rs +++ b/src/report_server/src/report.rs @@ -6,7 +6,7 @@ use chromiumoxide::{ handler::viewport::Viewport, Page, }; -use config::CONFIG; +use config::get_config; use futures::StreamExt; use lettre::{ message::{header::ContentType, MultiPart, SinglePart}, @@ -31,32 +31,33 @@ pub async fn get_chrome_launch_options() -> &'static BrowserConfig { } async fn init_chrome_launch_options() -> BrowserConfig { + let cfg = get_config(); let mut browser_config = BrowserConfig::builder() .window_size( - CONFIG.chrome.chrome_window_width, - CONFIG.chrome.chrome_window_height, + cfg.chrome.chrome_window_width, + cfg.chrome.chrome_window_height, ) .viewport(Viewport { - width: CONFIG.chrome.chrome_window_width, - height: CONFIG.chrome.chrome_window_height, + width: cfg.chrome.chrome_window_width, + height: cfg.chrome.chrome_window_height, device_scale_factor: Some(1.0), ..Viewport::default() }); - if CONFIG.chrome.chrome_with_head { + if cfg.chrome.chrome_with_head { browser_config = browser_config.with_head(); } - if CONFIG.chrome.chrome_no_sandbox { + if cfg.chrome.chrome_no_sandbox { browser_config = browser_config.no_sandbox(); } - if !CONFIG.chrome.chrome_path.is_empty() { - browser_config = browser_config.chrome_executable(CONFIG.chrome.chrome_path.as_str()); + if !cfg.chrome.chrome_path.is_empty() { + browser_config = browser_config.chrome_executable(cfg.chrome.chrome_path.as_str()); } else { let mut should_download = false; - if !CONFIG.chrome.chrome_check_default { + if !cfg.chrome.chrome_check_default { should_download = true; } else { // Check if chrome is available on default paths @@ -70,14 +71,14 @@ async fn init_chrome_launch_options() -> BrowserConfig { should_download = true; } } - if should_download && !CONFIG.chrome.chrome_auto_download { + if should_download && !cfg.chrome.chrome_auto_download { should_download = false; log::error!("Chrome binary could not be detected"); } if should_download { // Download known good chrome version - let download_path = &CONFIG.chrome.chrome_download_path; + let download_path = &cfg.chrome.chrome_download_path; log::info!("fetching chrome at: {download_path}"); tokio::fs::create_dir_all(download_path).await.unwrap(); let fetcher = BrowserFetcher::new( @@ -111,12 +112,13 @@ async fn init_chrome_launch_options() -> BrowserConfig { } pub static SMTP_CLIENT: Lazy> = Lazy::new(|| { - let tls_parameters = TlsParameters::new(CONFIG.smtp.smtp_host.clone()).unwrap(); + let cfg = get_config(); + let tls_parameters = TlsParameters::new(cfg.smtp.smtp_host.clone()).unwrap(); let mut transport_builder = - AsyncSmtpTransport::::builder_dangerous(&CONFIG.smtp.smtp_host) - .port(CONFIG.smtp.smtp_port); + AsyncSmtpTransport::::builder_dangerous(&cfg.smtp.smtp_host) + .port(cfg.smtp.smtp_port); - let option = &CONFIG.smtp.smtp_encryption; + let option = &cfg.smtp.smtp_encryption; transport_builder = if option == "starttls" { transport_builder.tls(Tls::Required(tls_parameters)) } else if option == "ssltls" { @@ -125,10 +127,10 @@ pub static SMTP_CLIENT: Lazy> = Lazy::new(|| transport_builder }; - if !CONFIG.smtp.smtp_username.is_empty() && !CONFIG.smtp.smtp_password.is_empty() { + if !cfg.smtp.smtp_username.is_empty() && !cfg.smtp.smtp_password.is_empty() { transport_builder = transport_builder.credentials(Credentials::new( - CONFIG.smtp.smtp_username.clone(), - CONFIG.smtp.smtp_password.clone(), + cfg.smtp.smtp_username.clone(), + cfg.smtp.smtp_password.clone(), )); } transport_builder.build() @@ -378,7 +380,7 @@ pub async fn send_email( pub async fn wait_for_panel_data_load(page: &Page) -> Result<(), anyhow::Error> { let start = std::time::Instant::now(); - let timeout = std::time::Duration::from_secs(CONFIG.chrome.chrome_sleep_secs.into()); + let timeout = std::time::Duration::from_secs(get_config().chrome.chrome_sleep_secs.into()); loop { if page .find_element("span#dashboardVariablesAndPanelsDataLoaded") diff --git a/src/reportserver/src/router.rs b/src/report_server/src/router.rs similarity index 92% rename from src/reportserver/src/router.rs rename to src/report_server/src/router.rs index 7a66b4d840..878f918e31 100644 --- a/src/reportserver/src/router.rs +++ b/src/report_server/src/router.rs @@ -1,7 +1,6 @@ use std::{collections::HashMap, io::Error}; use actix_web::{get, http::StatusCode, put, web, HttpRequest, HttpResponse as ActixHttpResponse}; -use config::CONFIG; use serde::{Deserialize, Serialize}; use crate::{ @@ -65,11 +64,13 @@ pub async fn send_report( Some(v) => v, None => "Europe/London", }; + + let cfg = config::get_config(); let (pdf_data, email_dashboard_url) = match generate_report( &report.dashboards[0], &org_id, - &CONFIG.report_server.user_email, - &CONFIG.report_server.user_password, + &cfg.report_server.user_email, + &cfg.report_server.user_password, &report.email_details.dashb_url, timezone, ) @@ -90,8 +91,8 @@ pub async fn send_report( ..report.email_details }, models::SmtpConfig { - from_email: CONFIG.smtp.smtp_from_email.to_string(), - reply_to: CONFIG.smtp.smtp_reply_to.to_string(), + from_email: cfg.smtp.smtp_from_email.to_string(), + reply_to: cfg.smtp.smtp_reply_to.to_string(), client: &SMTP_CLIENT, }, ) diff --git a/src/reportserver/src/server.rs b/src/report_server/src/server.rs similarity index 85% rename from src/reportserver/src/server.rs rename to src/report_server/src/server.rs index 55033a4a6c..17c5b0d1d6 100644 --- a/src/reportserver/src/server.rs +++ b/src/report_server/src/server.rs @@ -1,7 +1,6 @@ use std::net::SocketAddr; use actix_web::{dev::ServerHandle, middleware, web, App, HttpServer}; -use config::CONFIG; use crate::router::{healthz, send_report}; @@ -11,22 +10,23 @@ pub async fn spawn_server() -> Result<(), anyhow::Error> { log::info!("starting o2 chrome server"); - if CONFIG.report_server.user_email.is_empty() || CONFIG.report_server.user_password.is_empty() { + let cfg = config::get_config(); + if cfg.report_server.user_email.is_empty() || cfg.report_server.user_password.is_empty() { log::error!("Missing ZO_REPORT_USER_EMAIL or ZO_REPORT_USER_PASSWORD env vars"); return Err(anyhow::anyhow!( "Please set ZO_REPORT_USER_EMAIL and ZO_REPORT_USER_PASSWORD to use report server" )); } - let haddr: SocketAddr = if CONFIG.report_server.ipv6_enabled { - format!("[::]:{}", CONFIG.report_server.port).parse()? + let haddr: SocketAddr = if cfg.report_server.ipv6_enabled { + format!("[::]:{}", cfg.report_server.port).parse()? } else { - let ip = if !CONFIG.report_server.addr.is_empty() { - CONFIG.report_server.addr.clone() + let ip = if !cfg.report_server.addr.is_empty() { + cfg.report_server.addr.clone() } else { "0.0.0.0".to_string() }; - format!("{}:{}", ip, CONFIG.report_server.port).parse()? + format!("{}:{}", ip, cfg.report_server.port).parse()? }; log::info!("starting Report server at: {}", haddr); let server = HttpServer::new(move || { diff --git a/src/router/grpc/ingest/logs.rs b/src/router/grpc/ingest/logs.rs index e67ef56b19..40ec36bf6c 100644 --- a/src/router/grpc/ingest/logs.rs +++ b/src/router/grpc/ingest/logs.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -14,7 +14,6 @@ // along with this program. If not, see . use async_trait::async_trait; -use config::CONFIG; use opentelemetry_proto::tonic::collector::logs::v1::{ logs_service_client::LogsServiceClient, logs_service_server::LogsService, ExportLogsServiceRequest, ExportLogsServiceResponse, @@ -35,11 +34,12 @@ impl LogsService for LogsServer { ) -> Result, Status> { let (metadata, extensions, message) = request.into_parts(); + let cfg = config::get_config(); // basic validation - if !metadata.contains_key(&CONFIG.grpc.org_header_key) { + if !metadata.contains_key(&cfg.grpc.org_header_key) { return Err(Status::invalid_argument(format!( "Please specify organization id with header key '{}' ", - &CONFIG.grpc.org_header_key + &cfg.grpc.org_header_key ))); } diff --git a/src/router/grpc/ingest/metrics.rs b/src/router/grpc/ingest/metrics.rs index 42ee6ee01c..984f693b98 100644 --- a/src/router/grpc/ingest/metrics.rs +++ b/src/router/grpc/ingest/metrics.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -14,7 +14,6 @@ // along with this program. If not, see . use async_trait::async_trait; -use config::CONFIG; use opentelemetry_proto::tonic::collector::metrics::v1::{ metrics_service_client::MetricsServiceClient, metrics_service_server::MetricsService, ExportMetricsServiceRequest, ExportMetricsServiceResponse, @@ -35,11 +34,12 @@ impl MetricsService for MetricsServer { ) -> Result, Status> { let (metadata, extensions, message) = request.into_parts(); + let cfg = config::get_config(); // basic validation - if !metadata.contains_key(&CONFIG.grpc.org_header_key) { + if !metadata.contains_key(&cfg.grpc.org_header_key) { return Err(Status::invalid_argument(format!( "Please specify organization id with header key '{}' ", - &CONFIG.grpc.org_header_key + &cfg.grpc.org_header_key ))); } diff --git a/src/router/grpc/ingest/mod.rs b/src/router/grpc/ingest/mod.rs index 442f4e7e7a..85140df7e4 100644 --- a/src/router/grpc/ingest/mod.rs +++ b/src/router/grpc/ingest/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::{utils::rand::get_rand_element, RwAHashMap, CONFIG}; +use config::{utils::rand::get_rand_element, RwAHashMap}; use once_cell::sync::Lazy; use tonic::{transport::Channel, Status}; @@ -37,7 +37,9 @@ pub(crate) async fn get_ingester_channel() -> Result { // cache miss, connect to ingester let channel = Channel::from_shared(grpc_addr.clone()) .unwrap() - .connect_timeout(std::time::Duration::from_secs(CONFIG.grpc.connect_timeout)) + .connect_timeout(std::time::Duration::from_secs( + config::get_config().grpc.connect_timeout, + )) .connect() .await .map_err(|err| { @@ -56,12 +58,13 @@ pub(crate) async fn get_ingester_channel() -> Result { } async fn get_rand_ingester_addr() -> Result { + let cfg = config::get_config(); let nodes = cluster::get_cached_online_ingester_nodes().await; if nodes.is_none() || nodes.as_ref().unwrap().is_empty() { - if !CONFIG.route.ingester_srv_url.is_empty() { + if !cfg.route.ingester_srv_url.is_empty() { Ok(format!( "http://{}:{}", - CONFIG.route.ingester_srv_url, CONFIG.grpc.port + cfg.route.ingester_srv_url, cfg.grpc.port )) } else { Err(tonic::Status::internal( diff --git a/src/router/grpc/ingest/traces.rs b/src/router/grpc/ingest/traces.rs index 6d5de555d9..3878d7f849 100644 --- a/src/router/grpc/ingest/traces.rs +++ b/src/router/grpc/ingest/traces.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -14,7 +14,6 @@ // along with this program. If not, see . use async_trait::async_trait; -use config::CONFIG; use opentelemetry_proto::tonic::collector::trace::v1::{ trace_service_client::TraceServiceClient, trace_service_server::TraceService, ExportTraceServiceRequest, ExportTraceServiceResponse, @@ -35,11 +34,12 @@ impl TraceService for TraceServer { ) -> Result, Status> { let (metadata, extensions, message) = request.into_parts(); + let cfg = config::get_config(); // basic validation - if !metadata.contains_key(&CONFIG.grpc.org_header_key) { + if !metadata.contains_key(&cfg.grpc.org_header_key) { return Err(Status::invalid_argument(format!( "Please specify organization id with header key '{}' ", - &CONFIG.grpc.org_header_key + &cfg.grpc.org_header_key ))); } diff --git a/src/router/grpc/mod.rs b/src/router/grpc/mod.rs index ad13676aa2..9558bd7dd9 100644 --- a/src/router/grpc/mod.rs +++ b/src/router/grpc/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/router/http/mod.rs b/src/router/http/mod.rs index 9e82bde06b..6cc89aefa8 100644 --- a/src/router/http/mod.rs +++ b/src/router/http/mod.rs @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use ::config::{meta::cluster::Role, utils::rand::get_rand_element, CONFIG}; +use ::config::{get_config, meta::cluster::Role, utils::rand::get_rand_element}; use actix_web::{http::Error, route, web, HttpRequest, HttpResponse}; use crate::common::infra::cluster; @@ -173,7 +173,11 @@ async fn dispatch( } // set body - let body = match resp.body().limit(CONFIG.limit.req_payload_limit).await { + let body = match resp + .body() + .limit(get_config().limit.req_payload_limit) + .await + { Ok(b) => b, Err(e) => { log::error!("{}: {}", new_url.value, e); @@ -200,12 +204,13 @@ async fn get_url(path: &str) -> URLDetails { cluster::get_cached_online_ingester_nodes().await }; if nodes.is_none() || nodes.as_ref().unwrap().is_empty() { - if node_type == Role::Ingester && !CONFIG.route.ingester_srv_url.is_empty() { + let cfg = get_config(); + if node_type == Role::Ingester && !cfg.route.ingester_srv_url.is_empty() { return URLDetails { is_error: false, value: format!( "http://{}:{}{}", - CONFIG.route.ingester_srv_url, CONFIG.http.port, path + cfg.route.ingester_srv_url, cfg.http.port, path ), }; } diff --git a/src/router/mod.rs b/src/router/mod.rs index b003afa861..0cfb601e64 100644 --- a/src/router/mod.rs +++ b/src/router/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/alerts/alert_manager.rs b/src/service/alerts/alert_manager.rs index 5324d1d0c6..3197988807 100644 --- a/src/service/alerts/alert_manager.rs +++ b/src/service/alerts/alert_manager.rs @@ -17,11 +17,11 @@ use std::str::FromStr; use chrono::{Duration, FixedOffset, Utc}; use config::{ + get_config, meta::{ stream::StreamType, usage::{TriggerData, TriggerDataStatus, TriggerDataType}, }, - CONFIG, }; use cron::Schedule; @@ -32,14 +32,15 @@ use crate::{ pub async fn run() -> Result<(), anyhow::Error> { log::debug!("Pulling jobs from scheduler"); + let cfg = get_config(); // Scheduler pulls only those triggers that match the conditions- // - trigger.next_run_at <= now // - !(trigger.is_realtime && !trigger.is_silenced) // - trigger.status == "Waiting" let triggers = db::scheduler::pull( - CONFIG.limit.alert_schedule_concurrency, - CONFIG.limit.alert_schedule_timeout, - CONFIG.limit.report_schedule_timeout, + cfg.limit.alert_schedule_concurrency, + cfg.limit.alert_schedule_timeout, + cfg.limit.report_schedule_timeout, ) .await?; @@ -174,7 +175,7 @@ async fn handle_alert_triggers(trigger: db::scheduler::Trigger) -> Result<(), an &new_trigger.org, &new_trigger.module_key ); - if trigger.retries + 1 >= CONFIG.limit.scheduler_max_retries { + if trigger.retries + 1 >= get_config().limit.scheduler_max_retries { // It has been tried the maximum time, just update the // next_run_at to the next expected trigger time log::debug!( @@ -324,7 +325,7 @@ async fn handle_report_triggers(trigger: db::scheduler::Trigger) -> Result<(), a } Err(e) => { log::error!("Error sending report to subscribers: {e}"); - if trigger.retries + 1 >= CONFIG.limit.scheduler_max_retries && !run_once { + if trigger.retries + 1 >= get_config().limit.scheduler_max_retries && !run_once { // It has been tried the maximum time, just update the // next_run_at to the next expected trigger time log::debug!( diff --git a/src/service/alerts/destinations.rs b/src/service/alerts/destinations.rs index 3841b4924b..9c0225ad0a 100644 --- a/src/service/alerts/destinations.rs +++ b/src/service/alerts/destinations.rs @@ -14,7 +14,6 @@ // along with this program. If not, see . use actix_web::http; -use config::CONFIG; use crate::{ common::{ @@ -51,7 +50,7 @@ pub async fn save( anyhow::anyhow!("Atleast one alert destination email is required"), )); } - if !CONFIG.smtp.smtp_enabled { + if !config::get_config().smtp.smtp_enabled { return Err(( http::StatusCode::INTERNAL_SERVER_ERROR, anyhow::anyhow!("SMTP not configured"), diff --git a/src/service/alerts/mod.rs b/src/service/alerts/mod.rs index e6e4db1a13..8deb71fc57 100644 --- a/src/service/alerts/mod.rs +++ b/src/service/alerts/mod.rs @@ -22,13 +22,13 @@ use actix_web::http; use arrow_schema::DataType; use chrono::{Duration, Local, TimeZone, Utc}; use config::{ - ider, + get_config, ider, meta::stream::StreamType, utils::{ base64, json::{Map, Value}, }, - CONFIG, SMTP_CLIENT, + SMTP_CLIENT, }; use cron::Schedule; use lettre::{message::SinglePart, AsyncTransport, Message}; @@ -90,7 +90,8 @@ pub async fn save( Schedule::from_str(&alert.trigger_condition.cron)?; } else if alert.trigger_condition.frequency == 0 { // default frequency is 60 seconds - alert.trigger_condition.frequency = std::cmp::max(10, CONFIG.limit.alert_schedule_interval); + alert.trigger_condition.frequency = + std::cmp::max(10, get_config().limit.alert_schedule_interval); } if alert.name.is_empty() || alert.stream_name.is_empty() { @@ -613,14 +614,15 @@ async fn build_sql(alert: &Alert, conditions: &[Condition]) -> Result format!("approx_percentile_cont(\"{}\", 0.99)", agg.having.column), }; + let cfg = get_config(); if let Some(group) = agg.group_by.as_ref() { if !group.is_empty() { sql = format!( "SELECT {}, {} AS alert_agg_value, MIN({}) as zo_sql_min_time, MAX({}) AS zo_sql_max_time FROM \"{}\" {} GROUP BY {} HAVING {}", group.join(", "), func_expr, - CONFIG.common.column_timestamp, - CONFIG.common.column_timestamp, + cfg.common.column_timestamp, + cfg.common.column_timestamp, alert.stream_name, where_sql, group.join(", "), @@ -632,8 +634,8 @@ async fn build_sql(alert: &Alert, conditions: &[Condition]) -> Result Result<(), anyhow::Error> { - if !CONFIG.smtp.smtp_enabled { + let cfg = get_config(); + if !cfg.smtp.smtp_enabled { return Err(anyhow::anyhow!("SMTP configuration not enabled")); } @@ -875,15 +878,15 @@ pub async fn send_email_notification( } let mut email = Message::builder() - .from(CONFIG.smtp.smtp_from_email.parse()?) + .from(cfg.smtp.smtp_from_email.parse()?) .subject(format!("Openobserve Alert - {}", alert_name)); for recepient in recepients { email = email.to(recepient.parse()?); } - if !CONFIG.smtp.smtp_reply_to.is_empty() { - email = email.reply_to(CONFIG.smtp.smtp_reply_to.parse()?); + if !cfg.smtp.smtp_reply_to.is_empty() { + email = email.reply_to(cfg.smtp.smtp_reply_to.parse()?); } let email = email.singlepart(SinglePart::html(msg)).unwrap(); @@ -918,7 +921,7 @@ fn process_row_template(tpl: &String, alert: &Alert, rows: &[Map] process_variable_replace(&mut resp, key, &VarValue::Str(&value)); // calculate start and end time - if key == &CONFIG.common.column_timestamp { + if key == &get_config().common.column_timestamp { let val = value.parse::().unwrap_or_default(); if alert_start_time == 0 || val < alert_start_time { alert_start_time = val; @@ -1003,6 +1006,7 @@ async fn process_dest_template( rows: &[Map], rows_tpl_val: &[String], ) -> String { + let cfg = get_config(); // format values let alert_count = rows.len(); let mut vars = HashMap::with_capacity(rows.len()); @@ -1023,7 +1027,7 @@ async fn process_dest_template( // calculate start and end time let mut alert_start_time = 0; let mut alert_end_time = 0; - if let Some(values) = vars.get(&CONFIG.common.column_timestamp) { + if let Some(values) = vars.get(&cfg.common.column_timestamp) { for val in values { let val = val.parse::().unwrap_or_default(); if alert_start_time == 0 || val < alert_start_time { @@ -1122,8 +1126,8 @@ async fn process_dest_template( // http://localhost:5080/web/metrics?stream=zo_http_response_time_bucket&from=1705248000000000&to=1705334340000000&query=em9faHR0cF9yZXNwb25zZV90aW1lX2J1Y2tldHt9&org_identifier=default format!( "{}{}/web/metrics?stream_type={}&stream={}&stream_value={}&from={}&to={}&query={}&org_identifier={}", - CONFIG.common.web_url, - CONFIG.common.base_uri, + cfg.common.web_url, + cfg.common.base_uri, alert.stream_type, alert.stream_name, alert.stream_name, @@ -1151,8 +1155,8 @@ async fn process_dest_template( // http://localhost:5080/web/logs?stream_type=logs&stream=test&from=1708416534519324&to=1708416597898186&sql_mode=true&query=U0VMRUNUICogRlJPTSAidGVzdCIgd2hlcmUgbGV2ZWwgPSAnaW5mbyc=&org_identifier=default format!( "{}{}/web/logs?stream_type={}&stream={}&stream_value={}&from={}&to={}&sql_mode=true&query={}&org_identifier={}", - CONFIG.common.web_url, - CONFIG.common.base_uri, + cfg.common.web_url, + cfg.common.base_uri, alert.stream_type, alert.stream_name, alert.stream_name, diff --git a/src/service/compact/file_list.rs b/src/service/compact/file_list.rs index 97d7485b33..7ac1c77dc7 100644 --- a/src/service/compact/file_list.rs +++ b/src/service/compact/file_list.rs @@ -20,7 +20,7 @@ use std::{ use bytes::Buf; use chrono::{DateTime, Datelike, Duration, TimeZone, Timelike, Utc}; -use config::{cluster::LOCAL_NODE_UUID, ider, meta::stream::FileKey, utils::json, CONFIG}; +use config::{cluster::LOCAL_NODE_UUID, ider, meta::stream::FileKey, utils::json}; use hashbrown::HashMap; use infra::{dist_lock, schema::STREAM_SCHEMAS_LATEST, storage}; use tokio::sync::{RwLock, Semaphore}; @@ -223,7 +223,9 @@ async fn merge_file_list(offset: i64) -> Result<(), anyhow::Error> { // filter deleted file keys let filter_file_keys: Arc>> = Arc::new(RwLock::new(HashMap::new())); - let semaphore = std::sync::Arc::new(Semaphore::new(CONFIG.limit.file_move_thread_num)); + let semaphore = std::sync::Arc::new(Semaphore::new( + config::get_config().limit.file_move_thread_num, + )); let mut tasks = Vec::new(); for file in file_list.clone() { let filter_file_keys = filter_file_keys.clone(); diff --git a/src/service/compact/file_list_deleted.rs b/src/service/compact/file_list_deleted.rs index 9807983b7f..47a4ccc54e 100644 --- a/src/service/compact/file_list_deleted.rs +++ b/src/service/compact/file_list_deleted.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -17,7 +17,6 @@ use std::io::{BufRead, BufReader}; use bytes::Buf; use chrono::{DateTime, Duration, TimeZone, Utc}; -use config::CONFIG; use futures::future::try_join_all; use hashbrown::HashMap; use infra::{file_list as infra_file_list, storage}; @@ -84,7 +83,7 @@ async fn query_deleted( time_max: i64, limit: i64, ) -> Result>, anyhow::Error> { - if CONFIG.common.meta_store_external { + if config::get_config().common.meta_store_external { query_deleted_from_table(org_id, time_min, time_max, limit).await } else { query_deleted_from_s3(org_id, time_min, time_max, limit).await @@ -160,8 +159,9 @@ pub async fn load_prefix_from_s3( } log::info!("Load file_list_deleted gets {} files", files_num); - let mut tasks = Vec::with_capacity(CONFIG.limit.query_thread_num + 1); - let chunk_size = std::cmp::max(1, files_num / CONFIG.limit.query_thread_num); + let cfg = config::get_config(); + let mut tasks = Vec::with_capacity(cfg.limit.query_thread_num + 1); + let chunk_size = std::cmp::max(1, files_num / cfg.limit.query_thread_num); for chunk in files.chunks(chunk_size) { let chunk = chunk.to_vec(); let task: tokio::task::JoinHandle>, anyhow::Error>> = diff --git a/src/service/compact/merge.rs b/src/service/compact/merge.rs index ba07fc2dd7..dd77e3ff73 100644 --- a/src/service/compact/merge.rs +++ b/src/service/compact/merge.rs @@ -21,7 +21,7 @@ use bytes::Bytes; use chrono::{DateTime, Datelike, Duration, TimeZone, Timelike, Utc}; use config::{ cluster::LOCAL_NODE_UUID, - ider, + get_config, ider, meta::stream::{FileKey, FileMeta, PartitionTimeLevel, StreamStats, StreamType}, metrics, utils::{ @@ -31,7 +31,7 @@ use config::{ }, record_batch_ext::format_recordbatch_by_schema, }, - CONFIG, FILE_EXT_PARQUET, + FILE_EXT_PARQUET, }; use hashbrown::HashSet; use infra::{ @@ -167,6 +167,7 @@ pub async fn merge_by_stream( .unwrap() .timestamp_micros(); + let cfg = get_config(); // check offset let time_now: DateTime = Utc::now(); let time_now_hour = Utc @@ -186,16 +187,16 @@ pub async fn merge_by_stream( // -- second period, the last hour file list upload to storage // -- third period, we can do the merge, so, at least 3 times of // max_file_retention_time - if (CONFIG.compact.step_secs < 3600 + if (cfg.compact.step_secs < 3600 && time_now.timestamp_micros() - offset - <= Duration::try_seconds(CONFIG.limit.max_file_retention_time as i64) + <= Duration::try_seconds(cfg.limit.max_file_retention_time as i64) .unwrap() .num_microseconds() .unwrap()) - || (CONFIG.compact.step_secs >= 3600 + || (cfg.compact.step_secs >= 3600 && (offset >= time_now_hour || time_now.timestamp_micros() - offset - <= Duration::try_seconds(CONFIG.limit.max_file_retention_time as i64) + <= Duration::try_seconds(cfg.limit.max_file_retention_time as i64) .unwrap() .num_microseconds() .unwrap() @@ -230,8 +231,8 @@ pub async fn merge_by_stream( .map_err(|e| anyhow::anyhow!("query file list failed: {}", e))?; // check lookback files - if CONFIG.compact.lookback_hours > 0 { - let lookback_offset = Duration::try_hours(CONFIG.compact.lookback_hours) + if cfg.compact.lookback_hours > 0 { + let lookback_offset = Duration::try_hours(cfg.compact.lookback_hours) .unwrap() .num_microseconds() .unwrap(); @@ -268,11 +269,11 @@ pub async fn merge_by_stream( if files.is_empty() { // this hour is no data, and check if pass allowed_upto, then just write new // offset if offset > 0 && offset_time_hour + - // Duration::try_hours(CONFIG.limit.allowed_upto).unwrap().num_microseconds().unwrap() < + // Duration::try_hours(cfg.limit.allowed_upto).unwrap().num_microseconds().unwrap() < // time_now_hour { -- no check it // } let offset = offset - + Duration::try_seconds(CONFIG.compact.step_secs) + + Duration::try_seconds(cfg.compact.step_secs) .unwrap() .num_microseconds() .unwrap(); @@ -300,7 +301,7 @@ pub async fn merge_by_stream( let mut stream_stats = StreamStats::default(); // use mutiple threads to merge - let semaphore = std::sync::Arc::new(Semaphore::new(CONFIG.limit.file_move_thread_num)); + let semaphore = std::sync::Arc::new(Semaphore::new(cfg.limit.file_move_thread_num)); let mut tasks = Vec::with_capacity(partition_files_with_size.len()); for (prefix, files_with_size) in partition_files_with_size.into_iter() { let org_id = org_id.to_string(); @@ -308,6 +309,7 @@ pub async fn merge_by_stream( let permit = semaphore.clone().acquire_owned().await.unwrap(); let worker_tx = worker_tx.clone(); let task: JoinHandle> = tokio::task::spawn(async move { + let cfg = get_config(); // sort by file size let mut files_with_size = files_with_size.to_owned(); files_with_size.sort_by(|a, b| a.meta.original_size.cmp(&b.meta.original_size)); @@ -323,7 +325,7 @@ pub async fn merge_by_stream( let mut new_file_list = Vec::new(); let mut new_file_size = 0; for file in files_with_size.iter() { - if new_file_size + file.meta.original_size > CONFIG.compact.max_file_size as i64 { + if new_file_size + file.meta.original_size > cfg.compact.max_file_size as i64 { if new_file_list.len() <= 1 { break; // no files need to merge } @@ -445,7 +447,7 @@ pub async fn merge_by_stream( // write new offset let offset = offset - + Duration::try_seconds(CONFIG.compact.step_secs) + + Duration::try_seconds(cfg.compact.step_secs) .unwrap() .num_microseconds() .unwrap(); @@ -503,8 +505,9 @@ pub async fn merge_files( let mut total_records = 0; let mut new_file_list = Vec::new(); let mut deleted_files = Vec::new(); + let cfg = get_config(); for file in files_with_size.iter() { - if new_file_size + file.meta.original_size > CONFIG.compact.max_file_size as i64 { + if new_file_size + file.meta.original_size > cfg.compact.max_file_size as i64 { break; } new_file_size += file.meta.original_size; @@ -585,7 +588,7 @@ pub async fn merge_files( let schema_latest_id = schema_versions.len() - 1; let bloom_filter_fields = get_stream_setting_bloom_filter_fields(&schema_latest).unwrap(); let full_text_search_fields = get_stream_setting_fts_fields(&schema_latest).unwrap(); - if CONFIG.common.widening_schema_evolution && schema_versions.len() > 1 { + if cfg.common.widening_schema_evolution && schema_versions.len() > 1 { for file in &new_file_list { // get the schema version of the file let schema_ver_id = match db::schema::filter_schema_version_id( @@ -735,7 +738,7 @@ pub async fn merge_files( // upload file match storage::put(&new_file_key, buf.clone()).await { Ok(_) => { - if CONFIG.common.inverted_index_enabled && stream_type == StreamType::Logs { + if cfg.common.inverted_index_enabled && stream_type == StreamType::Logs { let (index_file_name, filemeta) = generate_index_on_compactor( &retain_file_list, inverted_idx_batches, @@ -788,7 +791,7 @@ async fn write_file_list(org_id: &str, events: &[FileKey]) -> Result<(), anyhow: if events.is_empty() { return Ok(()); } - if CONFIG.common.meta_store_external { + if get_config().common.meta_store_external { write_file_list_db_only(org_id, events).await } else { write_file_list_s3(org_id, events).await @@ -833,7 +836,7 @@ async fn write_file_list_db_only(org_id: &str, events: &[FileKey]) -> Result<(), continue; } // send broadcast to other nodes - if CONFIG.memory_cache.cache_latest_files { + if get_config().memory_cache.cache_latest_files { if let Err(e) = db::file_list::broadcast::send(events, None).await { log::error!("[COMPACT] send broadcast for file_list failed: {}", e); } @@ -925,10 +928,8 @@ pub fn generate_inverted_idx_recordbatch( stream_type: StreamType, full_text_search_fields: &[String], ) -> Vec { - if !CONFIG.common.inverted_index_enabled - || batches.is_empty() - || stream_type != StreamType::Logs - { + let cfg = get_config(); + if !cfg.common.inverted_index_enabled || batches.is_empty() || stream_type != StreamType::Logs { return Vec::new(); } @@ -948,8 +949,8 @@ pub fn generate_inverted_idx_recordbatch( return Vec::new(); } // add _timestamp column to columns_to_index - if !inverted_idx_columns.contains(&CONFIG.common.column_timestamp) { - inverted_idx_columns.push(CONFIG.common.column_timestamp.to_string()); + if !inverted_idx_columns.contains(&cfg.common.column_timestamp) { + inverted_idx_columns.push(cfg.common.column_timestamp.to_string()); } let mut inverted_idx_batches = Vec::with_capacity(batches.len()); @@ -1029,7 +1030,7 @@ pub async fn merge_parquet_files( // 3. sort concatenated record batch by timestamp col in desc order let sort_indices = arrow::compute::sort_to_indices( concatenated_record_batch - .column_by_name(&CONFIG.common.column_timestamp) + .column_by_name(&get_config().common.column_timestamp) .ok_or_else(|| { log::error!( "[INGESTER:JOB:{thread_id}] merge small files failed to find _timestamp column from merged record batch.", diff --git a/src/service/compact/mod.rs b/src/service/compact/mod.rs index b21a4d5f2b..f89bf3a202 100644 --- a/src/service/compact/mod.rs +++ b/src/service/compact/mod.rs @@ -18,8 +18,8 @@ use std::sync::Arc; use chrono::{Datelike, Duration, TimeZone, Timelike, Utc}; use config::{ cluster::LOCAL_NODE_UUID, + get_config, meta::{cluster::Role, stream::StreamType}, - CONFIG, }; use infra::dist_lock; use once_cell::sync::Lazy; @@ -41,10 +41,11 @@ pub(crate) static QUEUE_LOCKER: Lazy>> = /// compactor retention run steps: pub async fn run_retention() -> Result<(), anyhow::Error> { + let cfg = get_config(); // check data retention - if CONFIG.compact.data_retention_days > 0 { + if cfg.compact.data_retention_days > 0 { let now = Utc::now(); - let date = now - Duration::try_days(CONFIG.compact.data_retention_days).unwrap(); + let date = now - Duration::try_days(cfg.compact.data_retention_days).unwrap(); let data_lifecycle_end = date.format("%Y-%m-%d").to_string(); let orgs = db::schema::list_organizations_from_cache().await; @@ -181,7 +182,8 @@ pub async fn run_retention() -> Result<(), anyhow::Error> { pub async fn run_merge( worker_tx: mpsc::Sender<(merge::MergeSender, merge::MergeBatch)>, ) -> Result<(), anyhow::Error> { - let semaphore = std::sync::Arc::new(Semaphore::new(CONFIG.limit.file_move_thread_num)); + let cfg = get_config(); + let semaphore = std::sync::Arc::new(Semaphore::new(cfg.limit.file_move_thread_num)); let orgs = db::schema::list_organizations_from_cache().await; let stream_types = [ StreamType::Logs, @@ -193,8 +195,7 @@ pub async fn run_merge( ]; for org_id in orgs { // check backlist - if !db::file_list::BLOCKED_ORGS.is_empty() - && db::file_list::BLOCKED_ORGS.contains(&org_id.as_str()) + if !db::file_list::BLOCKED_ORGS.is_empty() && db::file_list::BLOCKED_ORGS.contains(&org_id) { continue; } @@ -271,7 +272,7 @@ pub async fn run_merge( } // after compact, compact file list from storage - if !CONFIG.common.meta_store_external { + if !cfg.common.meta_store_external { let last_file_list_offset = db::compact::file_list::get_offset().await?; if let Err(e) = file_list::run(last_file_list_offset).await { log::error!("[COMPACTOR] merge file list error: {}", e); @@ -286,7 +287,8 @@ pub async fn run_merge( /// 2. delete files from storage pub async fn run_delay_deletion() -> Result<(), anyhow::Error> { let now = Utc::now(); - let time_max = now - Duration::try_hours(CONFIG.compact.delete_files_delay_hours).unwrap(); + let time_max = + now - Duration::try_hours(get_config().compact.delete_files_delay_hours).unwrap(); let time_max = Utc .with_ymd_and_hms( time_max.year(), diff --git a/src/service/compact/retention.rs b/src/service/compact/retention.rs index f66198c8bf..a59f83992f 100644 --- a/src/service/compact/retention.rs +++ b/src/service/compact/retention.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -21,10 +21,9 @@ use std::{ use chrono::{DateTime, Duration, TimeZone, Utc}; use config::{ cluster::LOCAL_NODE_UUID, - ider, is_local_disk_storage, + get_config, ider, is_local_disk_storage, meta::stream::{FileKey, FileMeta, PartitionTimeLevel, StreamStats, StreamType}, utils::{json, time::BASE_TIME}, - CONFIG, }; use infra::{cache, dist_lock, file_list as infra_file_list, storage}; @@ -106,10 +105,11 @@ pub async fn delete_all( let start_time = BASE_TIME.timestamp_micros(); let end_time = Utc::now().timestamp_micros(); + let cfg = get_config(); if is_local_disk_storage() { let data_dir = format!( "{}files/{org_id}/{stream_type}/{stream_name}", - CONFIG.common.data_stream_dir + cfg.common.data_stream_dir ); let path = std::path::Path::new(&data_dir); if path.exists() { @@ -129,7 +129,7 @@ pub async fn delete_all( true, ) .await?; - if CONFIG.compact.data_retention_history { + if cfg.compact.data_retention_history { // only store the file_list into history, don't delete files if let Err(e) = infra_file_list::batch_add_history(&files).await { log::error!("[COMPACT] file_list batch_add_history failed: {}", e); @@ -208,11 +208,12 @@ pub async fn delete_by_date( DateTime::parse_from_rfc3339(&format!("{}T00:00:00Z", date_range.1))?.with_timezone(&Utc); let time_range = { (date_start.timestamp_micros(), date_end.timestamp_micros()) }; + let cfg = get_config(); if is_local_disk_storage() { while date_start <= date_end { let data_dir = format!( "{}files/{org_id}/{stream_type}/{stream_name}/{}", - CONFIG.common.data_stream_dir, + cfg.common.data_stream_dir, date_start.format("%Y/%m/%d") ); let path = std::path::Path::new(&data_dir); @@ -234,7 +235,7 @@ pub async fn delete_by_date( true, ) .await?; - if CONFIG.compact.data_retention_history { + if cfg.compact.data_retention_history { // only store the file_list into history, don't delete files if let Err(e) = infra_file_list::batch_add_history(&files).await { log::error!("[COMPACT] file_list batch_add_history failed: {}", e); @@ -358,7 +359,7 @@ async fn write_file_list( file_list_days: HashSet, hours_files: HashMap>, ) -> Result<(), anyhow::Error> { - if CONFIG.common.meta_store_external { + if get_config().common.meta_store_external { write_file_list_db_only(org_id, hours_files).await } else { write_file_list_s3(org_id, file_list_days, hours_files).await diff --git a/src/service/compact/stats.rs b/src/service/compact/stats.rs index 05976e77b9..5f8c8ca399 100644 --- a/src/service/compact/stats.rs +++ b/src/service/compact/stats.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::{cluster::LOCAL_NODE_UUID, CONFIG}; +use config::cluster::LOCAL_NODE_UUID; use infra::{dist_lock, file_list as infra_file_list}; use tokio::time; @@ -27,7 +27,9 @@ pub async fn update_stats_from_file_list() -> Result, anyhow: } // before starting, set current node to lock the job - if CONFIG.common.meta_store_external && (node.is_empty() || LOCAL_NODE_UUID.ne(&node)) { + if config::get_config().common.meta_store_external + && (node.is_empty() || LOCAL_NODE_UUID.ne(&node)) + { offset = match update_stats_lock_node().await { Ok(Some(offset)) => offset, Ok(None) => return Ok(None), diff --git a/src/service/dashboards/folders.rs b/src/service/dashboards/folders.rs index 35c70c15c7..a6e7ce7faf 100644 --- a/src/service/dashboards/folders.rs +++ b/src/service/dashboards/folders.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/dashboards/mod.rs b/src/service/dashboards/mod.rs index 4367ff5088..cacddb1028 100644 --- a/src/service/dashboards/mod.rs +++ b/src/service/dashboards/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/dashboards/reports.rs b/src/service/dashboards/reports.rs index 38efdd83e8..df893adfb8 100644 --- a/src/service/dashboards/reports.rs +++ b/src/service/dashboards/reports.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -17,7 +17,7 @@ use std::{str::FromStr, time::Duration}; use actix_web::http; use chromiumoxide::{browser::Browser, cdp::browser_protocol::page::PrintToPdfParams, Page}; -use config::{get_chrome_launch_options, CONFIG, SMTP_CLIENT}; +use config::{get_chrome_launch_options, get_config, SMTP_CLIENT}; use cron::Schedule; use futures::{future::try_join_all, StreamExt}; use lettre::{ @@ -46,20 +46,19 @@ pub async fn save( mut report: Report, create: bool, ) -> Result<(), anyhow::Error> { - if CONFIG.common.report_server_url.is_empty() { + let cfg = get_config(); + if cfg.common.report_server_url.is_empty() { // Check if SMTP is enabled, otherwise don't save the report - if !CONFIG.smtp.smtp_enabled { + if !cfg.smtp.smtp_enabled { return Err(anyhow::anyhow!("SMTP configuration not enabled")); } // Check if Chrome is enabled, otherwise don't save the report - if !CONFIG.chrome.chrome_enabled || CONFIG.chrome.chrome_path.is_empty() { + if !cfg.chrome.chrome_enabled || cfg.chrome.chrome_path.is_empty() { return Err(anyhow::anyhow!("Chrome not enabled")); } - if CONFIG.common.report_user_name.is_empty() - || CONFIG.common.report_user_password.is_empty() - { + if cfg.common.report_user_name.is_empty() || cfg.common.report_user_password.is_empty() { return Err(anyhow::anyhow!("Report username and password ENVs not set")); } } @@ -240,7 +239,8 @@ impl Report { return Err(anyhow::anyhow!("Atleast one dashboard is required")); } - if !CONFIG.common.report_server_url.is_empty() { + let cfg = get_config(); + if !cfg.common.report_server_url.is_empty() { let mut recepients = vec![]; for recepient in &self.destinations { match recepient { @@ -255,17 +255,17 @@ impl Report { recepients, name: self.name.clone(), message: self.message.clone(), - dashb_url: format!("{}{}/web", CONFIG.common.web_url, CONFIG.common.base_uri), + dashb_url: format!("{}{}/web", cfg.common.web_url, cfg.common.base_uri), }, }; let url = url::Url::parse(&format!( "{}/{}/reports/{}/send", - &CONFIG.common.report_server_url, &self.org_id, &self.name + &cfg.common.report_server_url, &self.org_id, &self.name )) .unwrap(); match Client::builder() - .danger_accept_invalid_certs(CONFIG.common.report_server_skip_tls_verify) + .danger_accept_invalid_certs(cfg.common.report_server_skip_tls_verify) .build() .unwrap() .put(url) @@ -295,8 +295,8 @@ impl Report { let report = generate_report( dashboard, &self.org_id, - &CONFIG.common.report_user_name, - &CONFIG.common.report_user_password, + &cfg.common.report_user_name, + &cfg.common.report_user_password, &self.timezone, ) .await?; @@ -306,7 +306,8 @@ impl Report { /// Sends emails to the [`Report`] recepients. Currently only one pdf data is supported. async fn send_email(&self, pdf_data: &[u8], dashb_url: String) -> Result<(), anyhow::Error> { - if !CONFIG.smtp.smtp_enabled { + let cfg = get_config(); + if !cfg.smtp.smtp_enabled { return Err(anyhow::anyhow!("SMTP configuration not enabled")); } @@ -318,15 +319,15 @@ impl Report { } let mut email = Message::builder() - .from(CONFIG.smtp.smtp_from_email.parse()?) + .from(cfg.smtp.smtp_from_email.parse()?) .subject(format!("Openobserve Report - {}", &self.title)); for recepient in recepients { email = email.to(recepient.parse()?); } - if !CONFIG.smtp.smtp_reply_to.is_empty() { - email = email.reply_to(CONFIG.smtp.smtp_reply_to.parse()?); + if !cfg.smtp.smtp_reply_to.is_empty() { + email = email.reply_to(cfg.smtp.smtp_reply_to.parse()?); } let email = email @@ -364,8 +365,9 @@ async fn generate_report( user_pass: &str, timezone: &str, ) -> Result<(Vec, String), anyhow::Error> { + let cfg = get_config(); // Check if Chrome is enabled, otherwise don't save the report - if !CONFIG.chrome.chrome_enabled { + if !cfg.chrome.chrome_enabled { return Err(anyhow::anyhow!("Chrome not enabled")); } @@ -396,7 +398,7 @@ async fn generate_report( } }); - let web_url = format!("{}{}/web", CONFIG.common.web_url, CONFIG.common.base_uri); + let web_url = format!("{}{}/web", cfg.common.web_url, cfg.common.base_uri); log::debug!("Navigating to web url: {}", &web_url); let page = browser .new_page(&format!("{web_url}/login?login_as_internal_user=true")) @@ -548,7 +550,7 @@ async fn generate_report( async fn wait_for_panel_data_load(page: &Page) -> Result<(), anyhow::Error> { let start = std::time::Instant::now(); - let timeout = Duration::from_secs(CONFIG.chrome.chrome_sleep_secs.into()); + let timeout = Duration::from_secs(get_config().chrome.chrome_sleep_secs.into()); log::info!("waiting for headless data to load"); loop { if page diff --git a/src/service/db/alerts/destinations.rs b/src/service/db/alerts/destinations.rs index 10ae3ec8ab..1d666ecac0 100644 --- a/src/service/db/alerts/destinations.rs +++ b/src/service/db/alerts/destinations.rs @@ -91,7 +91,7 @@ pub async fn watch() -> Result<(), anyhow::Error> { match ev { db::Event::Put(ev) => { let item_key = ev.key.strip_prefix(key).unwrap(); - let item_value: Destination = if config::CONFIG.common.meta_store_external { + let item_value: Destination = if config::get_config().common.meta_store_external { match db::get(&ev.key).await { Ok(val) => match json::from_slice(&val) { Ok(val) => val, diff --git a/src/service/db/alerts/mod.rs b/src/service/db/alerts/mod.rs index 1b68db80c6..d84fdf5b14 100644 --- a/src/service/db/alerts/mod.rs +++ b/src/service/db/alerts/mod.rs @@ -155,7 +155,7 @@ pub async fn watch() -> Result<(), anyhow::Error> { db::Event::Put(ev) => { let item_key = ev.key.strip_prefix(key).unwrap(); let stream_key = item_key[0..item_key.rfind('/').unwrap()].to_string(); - let item_value: Alert = if config::CONFIG.common.meta_store_external { + let item_value: Alert = if config::get_config().common.meta_store_external { match db::get(&ev.key).await { Ok(val) => match json::from_slice(&val) { Ok(val) => val, diff --git a/src/service/db/alerts/templates.rs b/src/service/db/alerts/templates.rs index 0509d29f9a..fb800fb6ea 100644 --- a/src/service/db/alerts/templates.rs +++ b/src/service/db/alerts/templates.rs @@ -103,7 +103,7 @@ pub async fn watch() -> Result<(), anyhow::Error> { match ev { db::Event::Put(ev) => { let item_key = ev.key.strip_prefix(key).unwrap(); - let item_value: Template = if config::CONFIG.common.meta_store_external { + let item_value: Template = if config::get_config().common.meta_store_external { match db::get(&ev.key).await { Ok(val) => match json::from_slice(&val) { Ok(val) => val, diff --git a/src/service/db/compact/file_list.rs b/src/service/db/compact/file_list.rs index 68fea90a93..79bd4151ad 100644 --- a/src/service/db/compact/file_list.rs +++ b/src/service/db/compact/file_list.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/db/compact/files.rs b/src/service/db/compact/files.rs index 3afcfbf9b1..b495005705 100644 --- a/src/service/db/compact/files.rs +++ b/src/service/db/compact/files.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/db/compact/mod.rs b/src/service/db/compact/mod.rs index 99939ce2fd..9d475a5cea 100644 --- a/src/service/db/compact/mod.rs +++ b/src/service/db/compact/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/db/compact/organization.rs b/src/service/db/compact/organization.rs index 160897dea3..d80d3fe772 100644 --- a/src/service/db/compact/organization.rs +++ b/src/service/db/compact/organization.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/db/compact/retention.rs b/src/service/db/compact/retention.rs index 0b290e596d..4da403d1b0 100644 --- a/src/service/db/compact/retention.rs +++ b/src/service/db/compact/retention.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/db/compact/stats.rs b/src/service/db/compact/stats.rs index f9ecfcd192..5b5c56d481 100644 --- a/src/service/db/compact/stats.rs +++ b/src/service/db/compact/stats.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -15,14 +15,12 @@ use std::sync::atomic::{AtomicI64, Ordering}; -use config::CONFIG; - use crate::service::db; static LOCAL_OFFSET: AtomicI64 = AtomicI64::new(0); pub async fn get_offset() -> (i64, String) { - if !CONFIG.common.meta_store_external { + if !config::get_config().common.meta_store_external { let offset = LOCAL_OFFSET.load(Ordering::Relaxed); return (offset, String::from("")); } @@ -43,7 +41,7 @@ pub async fn get_offset() -> (i64, String) { } pub async fn set_offset(offset: i64, node: Option<&str>) -> Result<(), anyhow::Error> { - if !CONFIG.common.meta_store_external { + if !config::get_config().common.meta_store_external { LOCAL_OFFSET.store(offset, Ordering::Release); return Ok(()); } diff --git a/src/service/db/dashboards/folders.rs b/src/service/db/dashboards/folders.rs index 41fa96e8f0..8ab91f9490 100644 --- a/src/service/db/dashboards/folders.rs +++ b/src/service/db/dashboards/folders.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/db/dashboards/mod.rs b/src/service/db/dashboards/mod.rs index 9b87a3ecf7..719b27e070 100644 --- a/src/service/db/dashboards/mod.rs +++ b/src/service/db/dashboards/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/db/dashboards/reports.rs b/src/service/db/dashboards/reports.rs index eaef4b79ff..d335bed84e 100644 --- a/src/service/db/dashboards/reports.rs +++ b/src/service/db/dashboards/reports.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -145,7 +145,7 @@ pub async fn watch() -> Result<(), anyhow::Error> { match ev { db::Event::Put(ev) => { let item_key = ev.key.strip_prefix(key).unwrap(); - let item_value: Report = if config::CONFIG.common.meta_store_external { + let item_value: Report = if config::get_config().common.meta_store_external { match db::get(&ev.key).await { Ok(val) => match json::from_slice(&val) { Ok(val) => val, diff --git a/src/service/db/file_list/broadcast.rs b/src/service/db/file_list/broadcast.rs index 01d56ccfe7..cf74063cbc 100644 --- a/src/service/db/file_list/broadcast.rs +++ b/src/service/db/file_list/broadcast.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -17,11 +17,11 @@ use std::sync::Arc; use config::{ cluster::{is_compactor, is_ingester, is_querier, LOCAL_NODE_UUID}, + get_config, meta::{ cluster::{Node, NodeStatus}, stream::FileKey, }, - CONFIG, }; use hashbrown::HashMap; use once_cell::sync::Lazy; @@ -38,7 +38,8 @@ type EventChannel = Arc>>; /// send an event to broadcast, will create a new channel for each nodes pub async fn send(items: &[FileKey], node_uuid: Option) -> Result<(), anyhow::Error> { - if CONFIG.common.local_mode || items.is_empty() { + let cfg = get_config(); + if cfg.common.local_mode || items.is_empty() { return Ok(()); } let nodes = if let Some(node_uuid) = node_uuid { @@ -62,7 +63,7 @@ pub async fn send(items: &[FileKey], node_uuid: Option) -> Result<(), an continue; } // if meta_store_external is true, only send to querier - if CONFIG.common.meta_store_external && !is_querier(&node.role) { + if cfg.common.meta_store_external && !is_querier(&node.role) { continue; } if !is_querier(&node.role) && !is_compactor(&node.role) && !is_ingester(&node.role) { @@ -70,7 +71,7 @@ pub async fn send(items: &[FileKey], node_uuid: Option) -> Result<(), an } let node_uuid = node.uuid.clone(); let node_addr = node.grpc_addr.clone(); - if CONFIG.common.print_key_event { + if cfg.common.print_key_event { items.iter().for_each(|item| { log::info!( "[broadcast] send event to node[{}]: file: {}, deleted: {}", @@ -148,13 +149,14 @@ async fn send_to_node( tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; tokio::task::yield_now().await; } + let cfg = get_config(); // connect to the node let token: MetadataValue<_> = cluster::get_internal_grpc_token() .parse() .expect("parse internal grpc token faile"); let channel = match Channel::from_shared(node.grpc_addr.clone()) .unwrap() - .connect_timeout(std::time::Duration::from_secs(CONFIG.grpc.connect_timeout)) + .connect_timeout(std::time::Duration::from_secs(cfg.grpc.connect_timeout)) .connect() .await { @@ -177,11 +179,12 @@ async fn send_to_node( Ok(req) }, ); + client = client .send_compressed(CompressionEncoding::Gzip) .accept_compressed(CompressionEncoding::Gzip) - .max_decoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024) - .max_encoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024); + .max_decoding_message_size(cfg.grpc.max_message_size * 1024 * 1024) + .max_encoding_message_size(cfg.grpc.max_message_size * 1024 * 1024); loop { let items = match rx.recv().await { Some(v) => v, diff --git a/src/service/db/file_list/local.rs b/src/service/db/file_list/local.rs index b5f097dff0..54b397d531 100644 --- a/src/service/db/file_list/local.rs +++ b/src/service/db/file_list/local.rs @@ -21,7 +21,6 @@ use config::{ asynchronism::file::get_file_contents, file::scan_files, json, parquet::parse_file_key_columns, }, - CONFIG, }; use infra::file_list as infra_file_list; use once_cell::sync::Lazy; @@ -48,8 +47,9 @@ pub async fn set(key: &str, meta: Option, deleted: bool) -> Result<(), } } + let cfg = config::get_config(); // write into local cache for s3 - if !CONFIG.common.meta_store_external { + if !cfg.common.meta_store_external { let mut write_buf = json::to_vec(&file_data)?; write_buf.push(b'\n'); let file = wal::get_or_create( @@ -63,7 +63,7 @@ pub async fn set(key: &str, meta: Option, deleted: bool) -> Result<(), } // notify other nodes - if !CONFIG.common.meta_store_external || CONFIG.memory_cache.cache_latest_files { + if !cfg.common.meta_store_external || cfg.memory_cache.cache_latest_files { let mut q = BROADCAST_QUEUE.write().await; q.push(file_data); } @@ -74,7 +74,7 @@ pub async fn set(key: &str, meta: Option, deleted: bool) -> Result<(), /// need to load wal file_list when the ingester async fn get_in_wal() -> Result, anyhow::Error> { let mut result = Vec::with_capacity(1024); - let pattern = format!("{}file_list/", &CONFIG.common.data_wal_dir); + let pattern = format!("{}file_list/", &config::get_config().common.data_wal_dir); let files = scan_files(&pattern, "json", None).unwrap_or_default(); let mut line_no = 0; for file in files { diff --git a/src/service/db/file_list/mod.rs b/src/service/db/file_list/mod.rs index ef407dce0b..49987d4019 100644 --- a/src/service/db/file_list/mod.rs +++ b/src/service/db/file_list/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::{meta::stream::FileMeta, RwHashMap, RwHashSet, CONFIG}; +use config::{meta::stream::FileMeta, RwHashMap, RwHashSet}; use dashmap::{DashMap, DashSet}; use infra::{cache, file_list}; use once_cell::sync::Lazy; @@ -28,8 +28,14 @@ pub static DEPULICATE_FILES: Lazy> = pub static DELETED_FILES: Lazy> = Lazy::new(|| DashMap::with_capacity_and_hasher(64, Default::default())); -pub static BLOCKED_ORGS: Lazy> = - Lazy::new(|| CONFIG.compact.blocked_orgs.split(',').collect()); +pub static BLOCKED_ORGS: Lazy> = Lazy::new(|| { + config::get_config() + .compact + .blocked_orgs + .split(',') + .map(|x| x.to_string()) + .collect() +}); pub async fn progress( key: &str, @@ -53,7 +59,7 @@ pub async fn progress( ); } // update stream stats realtime - if CONFIG.common.local_mode { + if config::get_config().common.local_mode { if let Err(e) = cache::stats::incr_stream_stats(key, data.unwrap()) { log::error!( "service:db:file_list: add {}, incr_stream_stats error: {}", diff --git a/src/service/db/file_list/remote.rs b/src/service/db/file_list/remote.rs index c3a62841cf..3c056245c5 100644 --- a/src/service/db/file_list/remote.rs +++ b/src/service/db/file_list/remote.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -21,7 +21,7 @@ use std::{ use bytes::Buf; use chrono::{DateTime, Duration, TimeZone, Utc}; -use config::{meta::stream::FileKey, utils::json, CONFIG}; +use config::{meta::stream::FileKey, utils::json}; use futures::future::try_join_all; use infra::{cache::stats, file_list as infra_file_list, storage}; use once_cell::sync::Lazy; @@ -53,8 +53,9 @@ pub async fn cache(prefix: &str, force: bool) -> Result<(), anyhow::Error> { return Ok(()); } - let mut tasks = Vec::with_capacity(CONFIG.limit.query_thread_num + 1); - let chunk_size = std::cmp::max(1, files_num / CONFIG.limit.query_thread_num); + let cfg = config::get_config(); + let mut tasks = Vec::with_capacity(cfg.limit.query_thread_num + 1); + let chunk_size = std::cmp::max(1, files_num / cfg.limit.query_thread_num); for chunk in files.chunks(chunk_size) { let chunk = chunk.to_vec(); let task: tokio::task::JoinHandle> = @@ -181,7 +182,7 @@ async fn process_file(file: &str) -> Result, anyhow::Error> { if !super::BLOCKED_ORGS.is_empty() { let columns = item.key.split('/').collect::>(); let org_id = columns.get(1).unwrap_or(&""); - if super::BLOCKED_ORGS.contains(org_id) { + if super::BLOCKED_ORGS.contains(&org_id.to_string()) { // log::error!("Load file_list skip blacklist org: {}", org_id); continue; } @@ -195,7 +196,7 @@ async fn process_file(file: &str) -> Result, anyhow::Error> { continue; } // check duplicate files - if CONFIG.common.feature_filelist_dedup_enabled { + if config::get_config().common.feature_filelist_dedup_enabled { if super::DEPULICATE_FILES.contains(&item.key) { continue; } diff --git a/src/service/db/functions.rs b/src/service/db/functions.rs index 095dfc49a4..138f83974e 100644 --- a/src/service/db/functions.rs +++ b/src/service/db/functions.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -15,7 +15,7 @@ use std::sync::Arc; -use config::{utils::json, CONFIG}; +use config::utils::json; use crate::{ common::{ @@ -88,7 +88,7 @@ pub async fn watch() -> Result<(), anyhow::Error> { db::Event::Put(ev) => { let item_key = ev.key.strip_prefix(key).unwrap(); let org_id = &item_key[0..item_key.find('/').unwrap()]; - let item_value: Transform = if CONFIG.common.meta_store_external { + let item_value: Transform = if config::get_config().common.meta_store_external { match db::get(&ev.key).await { Ok(val) => match json::from_slice(&val) { Ok(val) => val, diff --git a/src/service/db/instance.rs b/src/service/db/instance.rs index 97b41b3208..82f4ebe571 100644 --- a/src/service/db/instance.rs +++ b/src/service/db/instance.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/db/kv.rs b/src/service/db/kv.rs index ec5ae587df..efcac0e876 100644 --- a/src/service/db/kv.rs +++ b/src/service/db/kv.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -15,8 +15,6 @@ use std::sync::Arc; -use config::CONFIG; - use crate::{common::infra::config::KVS, service::db}; fn mk_keys(org_id: &str, key: &str) -> (String, String) { @@ -79,7 +77,7 @@ pub async fn watch() -> Result<(), anyhow::Error> { match ev { db::Event::Put(ev) => { let item_key = ev.key.strip_prefix(key).unwrap(); - let item_value = if CONFIG.common.meta_store_external { + let item_value = if config::get_config().common.meta_store_external { match db::get(&ev.key).await { Ok(val) => val, Err(e) => { diff --git a/src/service/db/metrics.rs b/src/service/db/metrics.rs index 401901534c..50c26e7f79 100644 --- a/src/service/db/metrics.rs +++ b/src/service/db/metrics.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -73,7 +73,7 @@ pub async fn watch_prom_cluster_leader() -> Result<(), anyhow::Error> { match ev { db::Event::Put(ev) => { let item_key = ev.key.strip_prefix(key).unwrap(); - let item_value: ClusterLeader = if config::CONFIG.common.meta_store_external { + let item_value: ClusterLeader = if config::get_config().common.meta_store_external { match db::get(&ev.key).await { Ok(val) => match json::from_slice(&val) { Ok(val) => val, diff --git a/src/service/db/ofga.rs b/src/service/db/ofga.rs index 59a5491fc0..79f68f0b08 100644 --- a/src/service/db/ofga.rs +++ b/src/service/db/ofga.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -110,7 +110,7 @@ pub async fn watch() -> Result<(), anyhow::Error> { }; match ev { db::Event::Put(ev) => { - let item_value: OFGAModel = if config::CONFIG.common.meta_store_external { + let item_value: OFGAModel = if config::get_config().common.meta_store_external { match db::get(&ev.key).await { Ok(val) => match json::from_slice(&val) { Ok(val) => val, diff --git a/src/service/db/organization.rs b/src/service/db/organization.rs index edc036745f..d40a8ebc7f 100644 --- a/src/service/db/organization.rs +++ b/src/service/db/organization.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -93,7 +93,7 @@ pub async fn watch() -> Result<(), anyhow::Error> { if let db::Event::Put(ev) = ev { let item_key = ev.key; let item_value = ev.value.unwrap(); - let json_val: OrganizationSetting = if config::CONFIG.common.meta_store_external { + let json_val: OrganizationSetting = if config::get_config().common.meta_store_external { match db::get(&item_key).await { Ok(val) => match json::from_slice(&val) { Ok(val) => val, diff --git a/src/service/db/pipelines.rs b/src/service/db/pipelines.rs index 49122a1709..8747de6cfd 100644 --- a/src/service/db/pipelines.rs +++ b/src/service/db/pipelines.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -15,7 +15,7 @@ use std::sync::Arc; -use config::{meta::stream::StreamType, utils::json, CONFIG}; +use config::{meta::stream::StreamType, utils::json}; use crate::{ common::{infra::config::STREAM_PIPELINES, meta::pipelines::PipeLine}, @@ -101,7 +101,7 @@ pub async fn watch() -> Result<(), anyhow::Error> { db::Event::Put(ev) => { let item_key = ev.key.strip_prefix(key).unwrap(); let org_id = &item_key[0..item_key.find('/').unwrap()]; - let item_value: PipeLine = if CONFIG.common.meta_store_external { + let item_value: PipeLine = if config::get_config().common.meta_store_external { match db::get(&ev.key).await { Ok(val) => match json::from_slice(&val) { Ok(val) => val, diff --git a/src/service/db/saved_view.rs b/src/service/db/saved_view.rs index 763521825f..b2d7fa45c5 100644 --- a/src/service/db/saved_view.rs +++ b/src/service/db/saved_view.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/db/schema.rs b/src/service/db/schema.rs index d7a78430b1..eaf059bc24 100644 --- a/src/service/db/schema.rs +++ b/src/service/db/schema.rs @@ -17,7 +17,7 @@ use std::sync::Arc; use arrow_schema::{Field, Schema}; use bytes::Bytes; -use config::{is_local_disk_storage, meta::stream::StreamType, utils::json, CONFIG}; +use config::{get_config, is_local_disk_storage, meta::stream::StreamType, utils::json}; use hashbrown::{HashMap, HashSet}; use infra::{ cache, @@ -331,7 +331,8 @@ pub async fn watch() -> Result<(), anyhow::Error> { SchemaCache::new(latest_schema.clone()), ); drop(w); - if CONFIG.common.schema_cache_compress_enabled { + let cfg = get_config(); + if cfg.common.schema_cache_compress_enabled { let schema_versions = schema_versions .into_iter() .map(|(start_dt, data)| { @@ -436,7 +437,7 @@ pub async fn watch() -> Result<(), anyhow::Error> { if stream_type.eq(&StreamType::EnrichmentTables) && is_local_disk_storage() { let data_dir = format!( "{}files/{org_id}/{stream_type}/{stream_name}", - CONFIG.common.data_wal_dir + get_config().common.data_wal_dir ); let path = std::path::Path::new(&data_dir); if path.exists() { @@ -492,7 +493,7 @@ pub async fn cache() -> Result<(), anyhow::Error> { SchemaCache::new(latest_schema.clone()), ); drop(w); - if CONFIG.common.schema_cache_compress_enabled { + if get_config().common.schema_cache_compress_enabled { let schema_versions = schema_versions .into_iter() .map(|(start_dt, data)| { @@ -555,7 +556,7 @@ pub async fn cache_enrichment_tables() -> Result<(), anyhow::Error> { } // waiting for querier to be ready - let expect_querier_num = CONFIG.limit.starting_expect_querier_num; + let expect_querier_num = get_config().limit.starting_expect_querier_num; loop { let nodes = get_cached_online_querier_nodes().await.unwrap_or_default(); if nodes.len() >= expect_querier_num { diff --git a/src/service/db/session.rs b/src/service/db/session.rs index e9cd9f5e9e..193c80549c 100644 --- a/src/service/db/session.rs +++ b/src/service/db/session.rs @@ -15,7 +15,7 @@ use std::sync::Arc; -use config::{utils::json, CONFIG}; +use config::utils::json; use crate::{ common::infra::config::USER_SESSIONS, @@ -74,7 +74,7 @@ pub async fn watch() -> Result<(), anyhow::Error> { match ev { db::Event::Put(ev) => { let item_key = ev.key.strip_prefix(key).unwrap(); - let item_value = if CONFIG.common.meta_store_external { + let item_value = if config::get_config().common.meta_store_external { match db::get(&ev.key).await { Ok(val) => match json::from_slice(&val) { Ok(val) => val, diff --git a/src/service/db/syslog.rs b/src/service/db/syslog.rs index d83566a41c..6d3374174d 100644 --- a/src/service/db/syslog.rs +++ b/src/service/db/syslog.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -15,7 +15,7 @@ use std::sync::Arc; -use config::{utils::json, CONFIG}; +use config::utils::json; use crate::{ common::{ @@ -83,7 +83,7 @@ pub async fn watch() -> Result<(), anyhow::Error> { }; match ev { db::Event::Put(ev) => { - let item_value: SyslogRoute = if CONFIG.common.meta_store_external { + let item_value: SyslogRoute = if config::get_config().common.meta_store_external { match db::get(&ev.key).await { Ok(val) => match json::from_slice(&val) { Ok(val) => val, diff --git a/src/service/db/user.rs b/src/service/db/user.rs index 6db26fb124..c913d4fa6b 100644 --- a/src/service/db/user.rs +++ b/src/service/db/user.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -16,7 +16,7 @@ use std::sync::Arc; use anyhow::bail; -use config::{utils::json, CONFIG}; +use config::utils::json; use crate::{ common::{ @@ -157,7 +157,7 @@ pub async fn watch() -> Result<(), anyhow::Error> { db::Event::Put(ev) => { let item_key = ev.key.strip_prefix(key).unwrap(); - let item_value: DBUser = if CONFIG.common.meta_store_external { + let item_value: DBUser = if config::get_config().common.meta_store_external { match db::get(&ev.key).await { Ok(val) => match json::from_slice(&val) { Ok(val) => val, diff --git a/src/service/db/version.rs b/src/service/db/version.rs index 3bfb1b2ea7..717469db92 100644 --- a/src/service/db/version.rs +++ b/src/service/db/version.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/enrichment_table/geoip.rs b/src/service/enrichment_table/geoip.rs index 26f59b71b7..fca542f48e 100644 --- a/src/service/enrichment_table/geoip.rs +++ b/src/service/enrichment_table/geoip.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -17,7 +17,7 @@ use std::{collections::BTreeMap, fs, net::IpAddr, sync::Arc, time::SystemTime}; -use config::{CONFIG, MMDB_CITY_FILE_NAME}; +use config::{get_config, MMDB_CITY_FILE_NAME}; use maxminddb::{ geoip2::{City, ConnectionType, Isp}, MaxMindDBError, Reader, @@ -92,7 +92,11 @@ fn default_locale() -> String { impl Default for GeoipConfig { fn default() -> self::GeoipConfig { GeoipConfig { - path: format!("{}{}", &CONFIG.common.mmdb_data_dir, MMDB_CITY_FILE_NAME), + path: format!( + "{}{}", + &get_config().common.mmdb_data_dir, + MMDB_CITY_FILE_NAME + ), locale: default_locale(), } } @@ -101,7 +105,7 @@ impl Default for GeoipConfig { impl GeoipConfig { pub fn new(name: &str) -> self::GeoipConfig { GeoipConfig { - path: format!("{}{}", &CONFIG.common.mmdb_data_dir, name), + path: format!("{}{}", &get_config().common.mmdb_data_dir, name), locale: default_locale(), } } diff --git a/src/service/enrichment_table/mod.rs b/src/service/enrichment_table/mod.rs index f0b21b5178..e2e09ae22d 100644 --- a/src/service/enrichment_table/mod.rs +++ b/src/service/enrichment_table/mod.rs @@ -23,13 +23,12 @@ use actix_web::{ use bytes::Bytes; use chrono::Utc; use config::{ - cluster, + cluster, get_config, meta::{ stream::{PartitionTimeLevel, StreamType}, usage::UsageType, }, utils::{flatten::format_key, json, schema_ext::SchemaExt}, - CONFIG, }; use futures::{StreamExt, TryStreamExt}; use infra::{ @@ -152,7 +151,7 @@ pub async fn save_enrichment_data( json_record.insert(header.into(), json::Value::String(field.into())); } json_record.insert( - CONFIG.common.column_timestamp.clone(), + get_config().common.column_timestamp.clone(), json::Value::Number(timestamp.into()), ); diff --git a/src/service/file_list.rs b/src/service/file_list.rs index 2e72e2d0de..1977080616 100644 --- a/src/service/file_list.rs +++ b/src/service/file_list.rs @@ -17,14 +17,13 @@ use std::io::Write; use config::{ cluster::LOCAL_NODE_UUID, - ider, + get_config, ider, meta::{ cluster::Node, search::ScanStats, stream::{FileKey, FileMeta, PartitionTimeLevel, StreamType}, }, utils::{file::get_file_meta as util_get_file_meta, json}, - CONFIG, }; use futures::future::try_join_all; use infra::{ @@ -32,7 +31,12 @@ use infra::{ file_list, storage, }; use proto::cluster_rpc; -use tonic::{codec::CompressionEncoding, metadata::MetadataValue, transport::Channel, Request}; +use tonic::{ + codec::CompressionEncoding, + metadata::{MetadataKey, MetadataValue}, + transport::Channel, + Request, +}; use tracing_opentelemetry::OpenTelemetrySpanExt; use crate::{ @@ -49,7 +53,8 @@ pub async fn query( time_max: i64, is_local: bool, ) -> Result, anyhow::Error> { - if is_local || CONFIG.common.local_mode { + let cfg = get_config(); + if is_local || cfg.common.local_mode { return query_inner( org_id, stream_name, @@ -72,6 +77,7 @@ pub async fn query( let mut tasks = Vec::with_capacity(3); // get first three nodes to check file list max id for node in nodes.into_iter().take(3) { + let cfg = cfg.clone(); let org_id = org_id.to_string(); let task = tokio::task::spawn(async move { let req = cluster_rpc::EmptyRequest::default(); @@ -87,12 +93,17 @@ pub async fn query( ) }); + let org_header_key: MetadataKey<_> = cfg + .grpc + .org_header_key + .parse() + .map_err(|_| Error::Message("invalid org_header_key".to_string()))?; let token: MetadataValue<_> = cluster::get_internal_grpc_token() .parse() .map_err(|_| Error::Message("invalid token".to_string()))?; let channel = Channel::from_shared(node.grpc_addr.clone()) .unwrap() - .connect_timeout(std::time::Duration::from_secs(CONFIG.grpc.connect_timeout)) + .connect_timeout(std::time::Duration::from_secs(cfg.grpc.connect_timeout)) .connect() .await .map_err(|err| { @@ -110,15 +121,15 @@ pub async fn query( move |mut req: Request<()>| { req.metadata_mut().insert("authorization", token.clone()); req.metadata_mut() - .insert(CONFIG.grpc.org_header_key.as_str(), org_id.clone()); + .insert(org_header_key.clone(), org_id.clone()); Ok(req) }, ); client = client .send_compressed(CompressionEncoding::Gzip) .accept_compressed(CompressionEncoding::Gzip) - .max_decoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024) - .max_encoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024); + .max_decoding_message_size(cfg.grpc.max_message_size * 1024 * 1024) + .max_encoding_message_size(cfg.grpc.max_message_size * 1024 * 1024); let response: cluster_rpc::MaxIdResponse = match client.max_id(request).await { Ok(res) => res.into_inner(), Err(err) => { @@ -194,12 +205,17 @@ pub async fn query( ) }); + let org_header_key: MetadataKey<_> = cfg + .grpc + .org_header_key + .parse() + .map_err(|_| Error::Message("invalid org_header_key".to_string()))?; let token: MetadataValue<_> = cluster::get_internal_grpc_token() .parse() .map_err(|_| Error::Message("invalid token".to_string()))?; let channel = Channel::from_shared(node.grpc_addr.clone()) .unwrap() - .connect_timeout(std::time::Duration::from_secs(CONFIG.grpc.connect_timeout)) + .connect_timeout(std::time::Duration::from_secs(cfg.grpc.connect_timeout)) .connect() .await .map_err(|err| { @@ -218,15 +234,16 @@ pub async fn query( move |mut req: Request<()>| { req.metadata_mut().insert("authorization", token.clone()); req.metadata_mut() - .insert(CONFIG.grpc.org_header_key.as_str(), org_id.clone()); + .insert(org_header_key.clone(), org_id.clone()); Ok(req) }, ); + client = client .send_compressed(CompressionEncoding::Gzip) .accept_compressed(CompressionEncoding::Gzip) - .max_decoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024) - .max_encoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024); + .max_decoding_message_size(cfg.grpc.max_message_size * 1024 * 1024) + .max_encoding_message_size(cfg.grpc.max_message_size * 1024 * 1024); let response: cluster_rpc::FileList = match client.query(request).await { Ok(res) => res.into_inner(), Err(err) => { @@ -312,7 +329,7 @@ pub fn calculate_local_files_size(files: &[String]) -> Result Result<(), anyhow::Error> { - if CONFIG.common.meta_store_external { + if get_config().common.meta_store_external { delete_parquet_file_db_only(key, file_list_only).await } else { delete_parquet_file_s3(key, file_list_only).await diff --git a/src/service/ingestion/grpc.rs b/src/service/ingestion/grpc.rs index 50e57a312a..db0a744aae 100644 --- a/src/service/ingestion/grpc.rs +++ b/src/service/ingestion/grpc.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/ingestion/mod.rs b/src/service/ingestion/mod.rs index 70a2d1cac3..63e0c46d07 100644 --- a/src/service/ingestion/mod.rs +++ b/src/service/ingestion/mod.rs @@ -21,13 +21,13 @@ use std::{ use anyhow::{anyhow, Result}; use chrono::{Duration, TimeZone, Utc}; use config::{ - cluster, + cluster, get_config, meta::{ stream::{PartitionTimeLevel, PartitioningDetails, Routing, StreamPartition, StreamType}, usage::{RequestStats, TriggerData, TriggerDataStatus, TriggerDataType}, }, utils::{flatten, json::*}, - CONFIG, SIZE_IN_MB, + SIZE_IN_MB, }; use vector_enrichment::TableRegistry; use vrl::{ @@ -368,7 +368,7 @@ pub fn apply_stream_functions( value = apply_vrl_fn(runtime, vrl_runtime, &value, org_id, stream_name); } } - flatten::flatten_with_level(value, CONFIG.limit.ingest_flatten_level) + flatten::flatten_with_level(value, get_config().limit.ingest_flatten_level) } pub fn init_functions_runtime() -> Runtime { @@ -413,7 +413,9 @@ pub fn check_ingestion_allowed(org_id: &str, stream_name: Option<&str>) -> Resul if !cluster::is_ingester(&cluster::LOCAL_NODE_ROLE) { return Err(anyhow!("not an ingester")); } - if !db::file_list::BLOCKED_ORGS.is_empty() && db::file_list::BLOCKED_ORGS.contains(&org_id) { + if !db::file_list::BLOCKED_ORGS.is_empty() + && db::file_list::BLOCKED_ORGS.contains(&org_id.to_string()) + { return Err(anyhow!("Quota exceeded for this organization [{}]", org_id)); } @@ -535,6 +537,7 @@ pub async fn get_user_defined_schema( streams: &[StreamParams], user_defined_schema_map: &mut HashMap>, ) { + let cfg = get_config(); for stream in streams { let stream_settings = infra::schema::get_settings(&stream.org_id, &stream.stream_name, stream.stream_type) @@ -543,8 +546,8 @@ pub async fn get_user_defined_schema( if let Some(fields) = stream_settings.defined_schema_fields { if !fields.is_empty() { let mut fields: HashSet<_> = fields.iter().cloned().collect(); - if !fields.contains(&CONFIG.common.column_timestamp) { - fields.insert(CONFIG.common.column_timestamp.to_string()); + if !fields.contains(&cfg.common.column_timestamp) { + fields.insert(cfg.common.column_timestamp.to_string()); } user_defined_schema_map.insert(stream.stream_name.to_string(), fields); } diff --git a/src/service/logs/bulk.rs b/src/service/logs/bulk.rs index 94174fd615..860aaa1fe1 100644 --- a/src/service/logs/bulk.rs +++ b/src/service/logs/bulk.rs @@ -23,14 +23,14 @@ use actix_web::web; use anyhow::{Error, Result}; use chrono::{Duration, Utc}; use config::{ - cluster, + cluster, get_config, meta::{ stream::{PartitioningDetails, Routing, StreamType}, usage::UsageType, }, metrics, utils::{flatten, json, schema_ext::SchemaExt, time::parse_timestamp_micro_from_value}, - BLOCKED_STREAMS, CONFIG, DISTINCT_FIELDS, + BLOCKED_STREAMS, DISTINCT_FIELDS, }; use infra::schema::{unwrap_partition_time_level, SchemaCache}; @@ -69,7 +69,9 @@ pub async fn ingest( return Err(anyhow::anyhow!("not an ingester")); } - if !db::file_list::BLOCKED_ORGS.is_empty() && db::file_list::BLOCKED_ORGS.contains(&org_id) { + if !db::file_list::BLOCKED_ORGS.is_empty() + && db::file_list::BLOCKED_ORGS.contains(&org_id.to_string()) + { return Err(anyhow::anyhow!( "Quota exceeded for this organization [{}]", org_id @@ -86,7 +88,8 @@ pub async fn ingest( items: vec![], }; - let min_ts = (Utc::now() - Duration::try_hours(CONFIG.limit.ingest_allowed_upto).unwrap()) + let cfg = get_config(); + let min_ts = (Utc::now() - Duration::try_hours(cfg.limit.ingest_allowed_upto).unwrap()) .timestamp_micros(); let mut runtime = crate::service::ingestion::init_functions_runtime(); @@ -130,13 +133,13 @@ pub async fn ingest( } (action, stream_name, doc_id) = ret.unwrap(); - if !CONFIG.common.skip_formatting_bulk_stream_name { + if !cfg.common.skip_formatting_bulk_stream_name { stream_name = format_stream_name(&stream_name); } // skip blocked streams let key = format!("{org_id}/{}/{stream_name}", StreamType::Logs); - if BLOCKED_STREAMS.contains(&key.as_str()) { + if BLOCKED_STREAMS.contains(&key) { // print warning only once blocked_stream_warnings.entry(key).or_insert_with(|| { log::warn!("stream [{stream_name}] is blocked from ingestion"); @@ -225,7 +228,7 @@ pub async fn ingest( next_line_is_data = false; // JSON Flattening - let mut value = flatten::flatten_with_level(value, CONFIG.limit.ingest_flatten_level)?; + let mut value = flatten::flatten_with_level(value, cfg.limit.ingest_flatten_level)?; if let Some(routing) = stream_routing_map.get(&stream_name) { if !routing.is_empty() { @@ -305,7 +308,7 @@ pub async fn ingest( } // handle timestamp - let timestamp = match local_val.get(&CONFIG.common.column_timestamp) { + let timestamp = match local_val.get(&cfg.common.column_timestamp) { Some(v) => match parse_timestamp_micro_from_value(v) { Ok(t) => t, Err(_e) => { @@ -340,7 +343,7 @@ pub async fn ingest( continue; } local_val.insert( - CONFIG.common.column_timestamp.clone(), + cfg.common.column_timestamp.clone(), json::Value::Number(timestamp.into()), ); let (partition_keys, partition_time_level) = @@ -375,7 +378,7 @@ pub async fn ingest( // this is for schema inference at stream level , which avoids locks in case schema // changes are frequent within request - if CONFIG.common.infer_schema_per_request { + if cfg.common.infer_schema_per_request { if let Err(e) = add_record( &StreamMeta { org_id: org_id.to_string(), @@ -478,7 +481,7 @@ pub async fn ingest( } // new flow for schema inference at stream level - stream_data.data = if CONFIG.common.infer_schema_per_request { + stream_data.data = if cfg.common.infer_schema_per_request { process_record( &mut stream_data, &StreamParams { @@ -563,6 +566,7 @@ async fn process_record( ) -> Result, Error> { let mut new_stream_buf = HashMap::new(); let mut trigger: TriggerAlertData = Vec::new(); + let cfg = get_config(); for schema_records in stream_data.data.values_mut() { // check schema let mut timestamp = 0; @@ -573,7 +577,7 @@ async fn process_record( .map(|record| { let rec = record.as_ref(); let rec_ts = rec - .get(&CONFIG.common.column_timestamp) + .get(&cfg.common.column_timestamp) .unwrap() .as_i64() .unwrap(); @@ -614,7 +618,7 @@ async fn process_record( match cast_to_schema_v1(&mut local_rec, &schema_latest_map) { Ok(_) => { let timestamp: i64 = local_rec - .get(&CONFIG.common.column_timestamp) + .get(&cfg.common.column_timestamp) .unwrap() .as_i64() .unwrap(); @@ -744,7 +748,7 @@ fn add_record_status( action, BulkResponseItem::new(stream_name.clone(), doc_id, value, stream_name), ); - if !CONFIG.common.bulk_api_response_errors_only { + if !get_config().common.bulk_api_response_errors_only { bulk_res.items.push(item); } } diff --git a/src/service/logs/ingest.rs b/src/service/logs/ingest.rs index 3df9b25d81..3d6568825d 100644 --- a/src/service/logs/ingest.rs +++ b/src/service/logs/ingest.rs @@ -22,10 +22,11 @@ use actix_web::http; use anyhow::Result; use chrono::{Duration, Utc}; use config::{ + get_config, meta::{stream::StreamType, usage::UsageType}, metrics, utils::{flatten, json, time::parse_timestamp_micro_from_value}, - CONFIG, DISTINCT_FIELDS, + DISTINCT_FIELDS, }; use flate2::read::GzDecoder; use infra::schema::SchemaCache; @@ -74,7 +75,8 @@ pub async fn ingest( }); } - let min_ts = (Utc::now() - Duration::try_hours(CONFIG.limit.ingest_allowed_upto).unwrap()) + let cfg = get_config(); + let min_ts = (Utc::now() - Duration::try_hours(cfg.limit.ingest_allowed_upto).unwrap()) .timestamp_micros(); // Start Register Transforms for stream @@ -299,7 +301,8 @@ pub fn apply_functions<'a>( stream_name: &'a str, runtime: &mut Runtime, ) -> Result { - let mut value = flatten::flatten_with_level(item, CONFIG.limit.ingest_flatten_level)?; + let cfg = get_config(); + let mut value = flatten::flatten_with_level(item, cfg.limit.ingest_flatten_level)?; if !local_trans.is_empty() { value = crate::service::ingestion::apply_stream_functions( @@ -323,8 +326,9 @@ pub fn handle_timestamp( local_val: &mut json::Map, min_ts: i64, ) -> Result<(), anyhow::Error> { + let cfg = get_config(); // handle timestamp - let timestamp = match local_val.get(&CONFIG.common.column_timestamp) { + let timestamp = match local_val.get(&cfg.common.column_timestamp) { Some(v) => match parse_timestamp_micro_from_value(v) { Ok(t) => t, Err(_) => return Err(anyhow::Error::msg("Can't parse timestamp")), @@ -336,7 +340,7 @@ pub fn handle_timestamp( return Err(get_upto_discard_error()); } local_val.insert( - CONFIG.common.column_timestamp.clone(), + cfg.common.column_timestamp.clone(), json::Value::Number(timestamp.into()), ); Ok(()) @@ -502,7 +506,7 @@ fn deserialize_aws_record_from_str(data: &str, request_id: &str) -> Result Result, need_trigger: bool, ) -> Result> { + let cfg = get_config(); let mut trigger: TriggerAlertData = Vec::new(); let timestamp: i64 = record_val - .get(&CONFIG.common.column_timestamp) + .get(&cfg.common.column_timestamp) .unwrap() .as_i64() .unwrap(); @@ -324,21 +325,20 @@ async fn add_valid_record( let valid_record = match schema_evolution.types_delta { None => true, Some(delta) => { - let ret_val = if !CONFIG.common.widening_schema_evolution - || !schema_evolution.is_schema_changed - { - cast_to_type(&mut record_val, delta) - } else { - let local_delta = delta - .into_iter() - .filter(|x| x.metadata().contains_key("zo_cast")) - .collect::>(); - if !local_delta.is_empty() { - cast_to_type(&mut record_val, local_delta) + let ret_val = + if !cfg.common.widening_schema_evolution || !schema_evolution.is_schema_changed { + cast_to_type(&mut record_val, delta) } else { - Ok(()) - } - }; + let local_delta = delta + .into_iter() + .filter(|x| x.metadata().contains_key("zo_cast")) + .collect::>(); + if !local_delta.is_empty() { + cast_to_type(&mut record_val, local_delta) + } else { + Ok(()) + } + }; match ret_val { Ok(_) => true, Err(e) => { @@ -407,8 +407,9 @@ async fn add_record( write_buf: &mut HashMap, record_val: Map, ) -> Result<()> { + let cfg = get_config(); let timestamp: i64 = record_val - .get(&CONFIG.common.column_timestamp) + .get(&cfg.common.column_timestamp) .unwrap() .as_i64() .unwrap(); @@ -475,7 +476,7 @@ pub fn refactor_map( if has_elements { new_map.insert( - CONFIG.common.all_fields_name.to_string(), + get_config().common.all_fields_name.to_string(), Value::String(String::from_utf8(non_schema_map).unwrap()), ); } diff --git a/src/service/logs/multi.rs b/src/service/logs/multi.rs index f7473399e8..62e7f1e76e 100644 --- a/src/service/logs/multi.rs +++ b/src/service/logs/multi.rs @@ -25,7 +25,7 @@ use config::{ meta::{stream::StreamType, usage::UsageType}, metrics, utils::{flatten, json, time::parse_timestamp_micro_from_value}, - CONFIG, DISTINCT_FIELDS, + DISTINCT_FIELDS, }; use infra::schema::SchemaCache; @@ -71,6 +71,7 @@ async fn ingest_inner( thread_id: usize, ) -> Result { let start = std::time::Instant::now(); + let cfg = config::get_config(); let mut stream_schema_map: HashMap = HashMap::new(); let mut distinct_values = Vec::with_capacity(16); @@ -80,7 +81,7 @@ async fn ingest_inner( check_ingestion_allowed(org_id, Some(stream_name))?; let mut runtime = crate::service::ingestion::init_functions_runtime(); - let min_ts = (Utc::now() - Duration::try_hours(CONFIG.limit.ingest_allowed_upto).unwrap()) + let min_ts = (Utc::now() - Duration::try_hours(cfg.limit.ingest_allowed_upto).unwrap()) .timestamp_micros(); let mut stream_alerts_map: HashMap> = HashMap::new(); @@ -131,7 +132,7 @@ async fn ingest_inner( } // JSON Flattening - value = flatten::flatten_with_level(value, CONFIG.limit.ingest_flatten_level)?; + value = flatten::flatten_with_level(value, cfg.limit.ingest_flatten_level)?; // Start row based transform if !local_trans.is_empty() { @@ -158,7 +159,7 @@ async fn ingest_inner( }; // handle timestamp - let timestamp = match local_val.get(&CONFIG.common.column_timestamp) { + let timestamp = match local_val.get(&cfg.common.column_timestamp) { Some(v) => match parse_timestamp_micro_from_value(v) { Ok(t) => t, Err(e) => { @@ -176,7 +177,7 @@ async fn ingest_inner( continue; } local_val.insert( - CONFIG.common.column_timestamp.clone(), + cfg.common.column_timestamp.clone(), json::Value::Number(timestamp.into()), ); diff --git a/src/service/logs/otlp_grpc.rs b/src/service/logs/otlp_grpc.rs index cfd83b231c..899091f1ea 100644 --- a/src/service/logs/otlp_grpc.rs +++ b/src/service/logs/otlp_grpc.rs @@ -24,7 +24,7 @@ use config::{ meta::{stream::StreamType, usage::UsageType}, metrics, utils::{flatten, json, time::parse_timestamp_micro_from_value}, - CONFIG, DISTINCT_FIELDS, + DISTINCT_FIELDS, }; use infra::schema::SchemaCache; use opentelemetry::trace::{SpanId, TraceId}; @@ -72,7 +72,9 @@ pub async fn usage_ingest( return Err(anyhow::anyhow!("not an ingester")); } - if !db::file_list::BLOCKED_ORGS.is_empty() && db::file_list::BLOCKED_ORGS.contains(&org_id) { + if !db::file_list::BLOCKED_ORGS.is_empty() + && db::file_list::BLOCKED_ORGS.contains(&org_id.to_string()) + { return Err(anyhow::anyhow!( "Quota exceeded for this organization [{}]", org_id @@ -84,7 +86,8 @@ pub async fn usage_ingest( return Err(anyhow::anyhow!("stream [{stream_name}] is being deleted")); } - let min_ts = (Utc::now() - Duration::try_hours(CONFIG.limit.ingest_allowed_upto).unwrap()) + let cfg = config::get_config(); + let min_ts = (Utc::now() - Duration::try_hours(cfg.limit.ingest_allowed_upto).unwrap()) .timestamp_micros(); let mut stream_alerts_map: HashMap> = HashMap::new(); @@ -117,7 +120,7 @@ pub async fn usage_ingest( let reader: Vec = json::from_slice(&body)?; for item in reader.into_iter() { // JSON Flattening - let mut value = flatten::flatten_with_level(item, CONFIG.limit.ingest_flatten_level)?; + let mut value = flatten::flatten_with_level(item, cfg.limit.ingest_flatten_level)?; // get json object let mut local_val = match value.take() { @@ -129,7 +132,7 @@ pub async fn usage_ingest( }; // handle timestamp - let timestamp = match local_val.get(&CONFIG.common.column_timestamp) { + let timestamp = match local_val.get(&cfg.common.column_timestamp) { Some(v) => match parse_timestamp_micro_from_value(v) { Ok(t) => t, Err(e) => { @@ -147,7 +150,7 @@ pub async fn usage_ingest( continue; } local_val.insert( - CONFIG.common.column_timestamp.clone(), + cfg.common.column_timestamp.clone(), json::Value::Number(timestamp.into()), ); @@ -259,7 +262,9 @@ pub async fn handle_grpc_request( ); } - if !db::file_list::BLOCKED_ORGS.is_empty() && db::file_list::BLOCKED_ORGS.contains(&org_id) { + if !db::file_list::BLOCKED_ORGS.is_empty() + && db::file_list::BLOCKED_ORGS.contains(&org_id.to_string()) + { return Ok(HttpResponse::Forbidden().json(MetaHttpResponse::error( http::StatusCode::FORBIDDEN.into(), format!("Quota exceeded for this organization [{}]", org_id), @@ -342,6 +347,7 @@ pub async fn handle_grpc_request( let mut data_buf: HashMap = HashMap::new(); + let cfg = config::get_config(); for resource_log in &request.resource_logs { for instrumentation_logs in &resource_log.scope_logs { for log_record in &instrumentation_logs.log_records { @@ -374,7 +380,7 @@ pub async fn handle_grpc_request( // check ingestion time let earlest_time = - Utc::now() - Duration::try_hours(CONFIG.limit.ingest_allowed_upto).unwrap(); + Utc::now() - Duration::try_hours(cfg.limit.ingest_allowed_upto).unwrap(); let ts = if log_record.time_unix_nano != 0 { log_record.time_unix_nano / 1000 @@ -388,7 +394,7 @@ pub async fn handle_grpc_request( continue; } - rec[CONFIG.common.column_timestamp.clone()] = ts.into(); + rec[cfg.common.column_timestamp.clone()] = ts.into(); rec["severity"] = log_record.severity_text.to_owned().into(); // rec["name"] = log_record.name.to_owned().into(); rec["body"] = get_val(&log_record.body.as_ref()); @@ -425,7 +431,7 @@ pub async fn handle_grpc_request( }; // flattening - rec = flatten::flatten_with_level(rec, CONFIG.limit.ingest_flatten_level)?; + rec = flatten::flatten_with_level(rec, cfg.limit.ingest_flatten_level)?; if !local_trans.is_empty() { rec = crate::service::ingestion::apply_stream_functions( diff --git a/src/service/logs/otlp_http.rs b/src/service/logs/otlp_http.rs index cb1d55210f..94886d6f97 100644 --- a/src/service/logs/otlp_http.rs +++ b/src/service/logs/otlp_http.rs @@ -23,7 +23,7 @@ use config::{ meta::{stream::StreamType, usage::UsageType}, metrics, utils::{flatten, json}, - CONFIG, DISTINCT_FIELDS, + DISTINCT_FIELDS, }; use infra::schema::SchemaCache; use opentelemetry::trace::{SpanId, TraceId}; @@ -102,7 +102,9 @@ pub async fn logs_json_handler( ); } - if !db::file_list::BLOCKED_ORGS.is_empty() && db::file_list::BLOCKED_ORGS.contains(&org_id) { + if !db::file_list::BLOCKED_ORGS.is_empty() + && db::file_list::BLOCKED_ORGS.contains(&org_id.to_string()) + { return Ok(HttpResponse::Forbidden().json(MetaHttpResponse::error( http::StatusCode::FORBIDDEN.into(), format!("Quota exceeded for this organization [{}]", org_id), @@ -144,7 +146,8 @@ pub async fn logs_json_handler( let mut stream_status = StreamStatus::new(stream_name); let mut trigger: Option = None; - let min_ts = (Utc::now() - Duration::try_hours(CONFIG.limit.ingest_allowed_upto).unwrap()) + let cfg = config::get_config(); + let min_ts = (Utc::now() - Duration::try_hours(cfg.limit.ingest_allowed_upto).unwrap()) .timestamp_micros(); let partition_det = crate::service::ingestion::get_stream_partition_keys( @@ -350,9 +353,8 @@ pub async fn logs_json_handler( stream_status.status.error = get_upto_discard_error().to_string(); continue; } - local_val.insert( - CONFIG.common.column_timestamp.clone(), + cfg.common.column_timestamp.clone(), json::Value::Number(timestamp.into()), ); @@ -361,8 +363,7 @@ pub async fn logs_json_handler( value = json::to_value(local_val)?; // JSON Flattening - value = - flatten::flatten_with_level(value, CONFIG.limit.ingest_flatten_level).unwrap(); + value = flatten::flatten_with_level(value, cfg.limit.ingest_flatten_level).unwrap(); if !local_trans.is_empty() { value = crate::service::ingestion::apply_stream_functions( diff --git a/src/service/logs/syslog.rs b/src/service/logs/syslog.rs index 00154960cd..09bc95d090 100644 --- a/src/service/logs/syslog.rs +++ b/src/service/logs/syslog.rs @@ -23,7 +23,7 @@ use config::{ meta::stream::StreamType, metrics, utils::{flatten, json, time::parse_timestamp_micro_from_value}, - CONFIG, DISTINCT_FIELDS, + DISTINCT_FIELDS, }; use infra::schema::SchemaCache; use syslog_loose::{Message, ProcId, Protocol}; @@ -129,9 +129,10 @@ pub async fn ingest(msg: &str, addr: SocketAddr) -> Result { let mut buf: HashMap = HashMap::new(); + let cfg = config::get_config(); let parsed_msg = syslog_loose::parse_message(msg); let mut value = message_to_value(parsed_msg); - value = flatten::flatten_with_level(value, CONFIG.limit.ingest_flatten_level).unwrap(); + value = flatten::flatten_with_level(value, cfg.limit.ingest_flatten_level).unwrap(); if !local_trans.is_empty() { value = crate::service::ingestion::apply_stream_functions( @@ -160,7 +161,7 @@ pub async fn ingest(msg: &str, addr: SocketAddr) -> Result { }; // handle timestamp - let timestamp = match local_val.get(&CONFIG.common.column_timestamp) { + let timestamp = match local_val.get(&cfg.common.column_timestamp) { Some(v) => match parse_timestamp_micro_from_value(v) { Ok(t) => t, Err(_) => Utc::now().timestamp_micros(), @@ -168,14 +169,14 @@ pub async fn ingest(msg: &str, addr: SocketAddr) -> Result { None => Utc::now().timestamp_micros(), }; // check ingestion time - let earlest_time = Utc::now() - Duration::try_hours(CONFIG.limit.ingest_allowed_upto).unwrap(); + let earlest_time = Utc::now() - Duration::try_hours(cfg.limit.ingest_allowed_upto).unwrap(); if timestamp < earlest_time.timestamp_micros() { stream_status.status.failed += 1; // to old data, just discard stream_status.status.error = get_upto_discard_error().to_string(); } local_val.insert( - CONFIG.common.column_timestamp.clone(), + cfg.common.column_timestamp.clone(), json::Value::Number(timestamp.into()), ); diff --git a/src/service/metadata/distinct_values.rs b/src/service/metadata/distinct_values.rs index 48a188f42f..273dd0128b 100644 --- a/src/service/metadata/distinct_values.rs +++ b/src/service/metadata/distinct_values.rs @@ -23,9 +23,10 @@ use std::{ use arrow_schema::{DataType, Field, Schema}; use config::{ + get_config, meta::stream::StreamType, utils::{json, schema_ext::SchemaExt}, - FxIndexMap, CONFIG, + FxIndexMap, }; use infra::{ errors::{Error, Result}, @@ -152,7 +153,7 @@ impl Metadata for DistinctValues { fn generate_schema(&self) -> Arc { Arc::new(Schema::new(vec![ Field::new( - CONFIG.common.column_timestamp.as_str(), + get_config().common.column_timestamp.as_str(), DataType::Int64, false, ), @@ -222,7 +223,7 @@ impl Metadata for DistinctValues { let data = data.as_object_mut().unwrap(); data.insert("count".to_string(), json::Value::Number(count.into())); data.insert( - CONFIG.common.column_timestamp.clone(), + get_config().common.column_timestamp.clone(), json::Value::Number(timestamp.into()), ); let hour_key = ingestion::get_wal_time_key( @@ -274,7 +275,7 @@ impl Metadata for DistinctValues { async fn run_flush() { let mut interval = time::interval(time::Duration::from_secs( - CONFIG.limit.distinct_values_interval, + get_config().limit.distinct_values_interval, )); interval.tick().await; // trigger the first run loop { diff --git a/src/service/metadata/trace_list_index.rs b/src/service/metadata/trace_list_index.rs index fe7431207b..3a54e28e8f 100644 --- a/src/service/metadata/trace_list_index.rs +++ b/src/service/metadata/trace_list_index.rs @@ -24,9 +24,9 @@ use std::{ use arrow_schema::{DataType, Field, Schema}; use config::{ + get_config, meta::stream::{StreamPartition, StreamSettings, StreamType}, utils::{json, schema_ext::SchemaExt}, - CONFIG, }; use infra::schema::unwrap_partition_time_level; use once_cell::sync::Lazy; @@ -65,7 +65,7 @@ impl Metadata for TraceListIndex { fn generate_schema(&self) -> Arc { Arc::new(Schema::new(vec![ Field::new( - CONFIG.common.column_timestamp.as_str(), + get_config().common.column_timestamp.as_str(), DataType::Int64, false, ), @@ -202,7 +202,7 @@ impl TraceListIndex { mod tests { use std::{collections::HashMap, sync::Arc}; - use config::{meta::stream::StreamType, utils::json, CONFIG}; + use config::{meta::stream::StreamType, utils::json}; use infra::schema::unwrap_partition_time_level; use crate::{ @@ -240,7 +240,7 @@ mod tests { let mut data = json::to_value(item).unwrap(); let data = data.as_object_mut().unwrap(); data.insert( - CONFIG.common.column_timestamp.clone(), + config::get_config().common.column_timestamp.clone(), json::Value::Number(timestamp.into()), ); let hour_key = ingestion::get_wal_time_key( diff --git a/src/service/metrics/json.rs b/src/service/metrics/json.rs index 9c53b2da1b..7ffa1d695c 100644 --- a/src/service/metrics/json.rs +++ b/src/service/metrics/json.rs @@ -25,7 +25,6 @@ use config::{ }, metrics, utils::{flatten, json, schema::infer_json_schema, schema_ext::SchemaExt, time}, - CONFIG, }; use datafusion::arrow::datatypes::Schema; use infra::schema::{unwrap_partition_time_level, SchemaCache}; @@ -54,7 +53,9 @@ pub async fn ingest(org_id: &str, body: web::Bytes, thread_id: usize) -> Result< return Err(anyhow::anyhow!("not an ingester")); } - if !db::file_list::BLOCKED_ORGS.is_empty() && db::file_list::BLOCKED_ORGS.contains(&org_id) { + if !db::file_list::BLOCKED_ORGS.is_empty() + && db::file_list::BLOCKED_ORGS.contains(&org_id.to_string()) + { return Err(anyhow::anyhow!( "Quota exceeded for this organization [{}]", org_id @@ -134,8 +135,9 @@ pub async fn ingest(org_id: &str, body: web::Bytes, thread_id: usize) -> Result< let record = record.as_object_mut().unwrap(); + let cfg = config::get_config(); // check timestamp & value - let timestamp: i64 = match record.get(&CONFIG.common.column_timestamp) { + let timestamp: i64 = match record.get(&cfg.common.column_timestamp) { None => chrono::Utc::now().timestamp_micros(), Some(json::Value::Number(s)) => { time::parse_i64_to_timestamp_micros(s.as_f64().unwrap() as i64) @@ -152,7 +154,7 @@ pub async fn ingest(org_id: &str, body: web::Bytes, thread_id: usize) -> Result< }; // reset time & value record.insert( - CONFIG.common.column_timestamp.clone(), + cfg.common.column_timestamp.clone(), json::Value::Number(timestamp.into()), ); record.insert( @@ -170,7 +172,7 @@ pub async fn ingest(org_id: &str, body: web::Bytes, thread_id: usize) -> Result< if k == NAME_LABEL || k == TYPE_LABEL || k == VALUE_LABEL - || k == &CONFIG.common.column_timestamp + || k == &cfg.common.column_timestamp { continue; } diff --git a/src/service/metrics/mod.rs b/src/service/metrics/mod.rs index 30348525d8..9ce1544318 100644 --- a/src/service/metrics/mod.rs +++ b/src/service/metrics/mod.rs @@ -13,7 +13,6 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -use config::CONFIG; use datafusion::arrow::datatypes::Schema; use once_cell::sync::Lazy; use regex::Regex; @@ -25,7 +24,13 @@ pub mod otlp_grpc; pub mod otlp_http; pub mod prom; -const EXCLUDE_LABELS: [&str; 4] = [VALUE_LABEL, HASH_LABEL, "is_monotonic", "exemplars"]; +const EXCLUDE_LABELS: [&str; 5] = [ + VALUE_LABEL, + HASH_LABEL, + "is_monotonic", + "exemplars", + "_timestamp", +]; static RE_CORRECT_LABEL_NAME: Lazy = Lazy::new(|| Regex::new(r"[^a-zA-Z0-9_]+").unwrap()); @@ -67,8 +72,10 @@ pub fn signature_without_labels( } fn get_exclude_labels() -> Vec<&'static str> { - let mut vec: Vec<&str> = EXCLUDE_LABELS.to_vec(); - vec.push(&CONFIG.common.column_timestamp); + let vec: Vec<&str> = EXCLUDE_LABELS.to_vec(); + // TODO: fixed _timestamp + // let column_timestamp = config::get_config().common.column_timestamp.as_str(); + // vec.push(column_timestamp); vec } diff --git a/src/service/metrics/otlp_grpc.rs b/src/service/metrics/otlp_grpc.rs index edb3ee73ff..9fa2434f0c 100644 --- a/src/service/metrics/otlp_grpc.rs +++ b/src/service/metrics/otlp_grpc.rs @@ -19,14 +19,13 @@ use actix_web::{http, HttpResponse}; use bytes::BytesMut; use chrono::Utc; use config::{ - cluster, + cluster, get_config, meta::{ stream::{PartitioningDetails, StreamType}, usage::UsageType, }, metrics, utils::{flatten, json, schema_ext::SchemaExt}, - CONFIG, }; use hashbrown::HashSet; use infra::schema::{unwrap_partition_time_level, update_setting, SchemaCache}; @@ -72,7 +71,9 @@ pub async fn handle_grpc_request( ); } - if !db::file_list::BLOCKED_ORGS.is_empty() && db::file_list::BLOCKED_ORGS.contains(&org_id) { + if !db::file_list::BLOCKED_ORGS.is_empty() + && db::file_list::BLOCKED_ORGS.contains(&org_id.to_string()) + { return Ok(HttpResponse::Forbidden().json(MetaHttpResponse::error( http::StatusCode::FORBIDDEN.into(), format!("Quota exceeded for this organization [{}]", org_id), @@ -98,6 +99,7 @@ pub async fn handle_grpc_request( let mut stream_trigger_map: HashMap> = HashMap::new(); let mut stream_partitioning_map: HashMap = HashMap::new(); + let cfg = get_config(); for resource_metric in &request.resource_metrics { for scope_metric in &resource_metric.scope_metrics { for metric in &scope_metric.metrics { @@ -214,7 +216,6 @@ pub async fn handle_grpc_request( ); } } - for mut rec in records { // flattening rec = flatten::flatten(rec)?; @@ -289,7 +290,7 @@ pub async fn handle_grpc_request( rec.as_object_mut().unwrap(); let timestamp = val_map - .get(&CONFIG.common.column_timestamp) + .get(&cfg.common.column_timestamp) .unwrap() .as_i64() .unwrap_or(Utc::now().timestamp_micros()); @@ -602,7 +603,7 @@ fn process_data_point(rec: &mut json::Value, data_point: &NumberDataPoint) { rec[format_label_name(attr.key.as_str())] = get_val(&attr.value.as_ref()); } rec[VALUE_LABEL] = get_metric_val(&data_point.value); - rec[&CONFIG.common.column_timestamp] = (data_point.time_unix_nano / 1000).into(); + rec[&get_config().common.column_timestamp] = (data_point.time_unix_nano / 1000).into(); rec["start_time"] = data_point.start_time_unix_nano.to_string().into(); rec["flag"] = if data_point.flags == 1 { DataPointFlags::NoRecordedValueMask.as_str_name() @@ -622,7 +623,7 @@ fn process_hist_data_point( for attr in &data_point.attributes { rec[format_label_name(attr.key.as_str())] = get_val(&attr.value.as_ref()); } - rec[&CONFIG.common.column_timestamp] = (data_point.time_unix_nano / 1000).into(); + rec[&get_config().common.column_timestamp] = (data_point.time_unix_nano / 1000).into(); rec["start_time"] = data_point.start_time_unix_nano.to_string().into(); rec["flag"] = if data_point.flags == 1 { DataPointFlags::NoRecordedValueMask.as_str_name() @@ -671,7 +672,7 @@ fn process_exp_hist_data_point( for attr in &data_point.attributes { rec[format_label_name(attr.key.as_str())] = get_val(&attr.value.as_ref()); } - rec[&CONFIG.common.column_timestamp] = (data_point.time_unix_nano / 1000).into(); + rec[&get_config().common.column_timestamp] = (data_point.time_unix_nano / 1000).into(); rec["start_time"] = data_point.start_time_unix_nano.to_string().into(); rec["flag"] = if data_point.flags == 1 { DataPointFlags::NoRecordedValueMask.as_str_name() @@ -736,7 +737,7 @@ fn process_summary_data_point( for attr in &data_point.attributes { rec[format_label_name(attr.key.as_str())] = get_val(&attr.value.as_ref()); } - rec[&CONFIG.common.column_timestamp] = (data_point.time_unix_nano / 1000).into(); + rec[&get_config().common.column_timestamp] = (data_point.time_unix_nano / 1000).into(); rec["start_time"] = data_point.start_time_unix_nano.to_string().into(); rec["flag"] = if data_point.flags == 1 { DataPointFlags::NoRecordedValueMask.as_str_name() @@ -774,7 +775,8 @@ fn process_exemplars(rec: &mut json::Value, exemplars: &Vec) { exemplar_rec[attr.key.as_str()] = get_val(&attr.value.as_ref()); } exemplar_rec[VALUE_LABEL] = get_exemplar_val(&exemplar.value); - exemplar_rec[&CONFIG.common.column_timestamp] = (exemplar.time_unix_nano / 1000).into(); + exemplar_rec[&get_config().common.column_timestamp] = + (exemplar.time_unix_nano / 1000).into(); match TraceId::from_bytes(exemplar.trace_id.as_slice().try_into().unwrap_or_default()) { TraceId::INVALID => {} diff --git a/src/service/metrics/otlp_http.rs b/src/service/metrics/otlp_http.rs index a73746fbd1..0ff21a80f8 100644 --- a/src/service/metrics/otlp_http.rs +++ b/src/service/metrics/otlp_http.rs @@ -19,14 +19,13 @@ use actix_web::{http, web, HttpResponse}; use bytes::BytesMut; use chrono::Utc; use config::{ - cluster, + cluster, get_config, meta::{ stream::{PartitioningDetails, StreamType}, usage::UsageType, }, metrics, utils::{flatten, json, schema_ext::SchemaExt}, - CONFIG, }; use hashbrown::HashSet; use infra::schema::{unwrap_partition_time_level, update_setting, SchemaCache}; @@ -91,7 +90,9 @@ pub async fn metrics_json_handler( ); } - if !db::file_list::BLOCKED_ORGS.is_empty() && db::file_list::BLOCKED_ORGS.contains(&org_id) { + if !db::file_list::BLOCKED_ORGS.is_empty() + && db::file_list::BLOCKED_ORGS.contains(&org_id.to_string()) + { return Ok(HttpResponse::Forbidden().json(MetaHttpResponse::error( http::StatusCode::FORBIDDEN.into(), format!("Quota exceeded for this organization [{}]", org_id), @@ -145,6 +146,7 @@ pub async fn metrics_json_handler( } }; + let cfg = get_config(); for res_metric in res_metrics.iter() { let mut service_att_map: json::Map = json::Map::new(); if res_metric.get("resource").is_some() { @@ -381,7 +383,7 @@ pub async fn metrics_json_handler( rec.as_object_mut().unwrap(); let timestamp = val_map - .get(&CONFIG.common.column_timestamp) + .get(&cfg.common.column_timestamp) .unwrap() .as_i64() .unwrap_or(Utc::now().timestamp_micros()); @@ -764,7 +766,7 @@ fn process_data_point(rec: &mut json::Value, data_point: &json::Map>() .join("\", \""); if label_names.is_empty() { @@ -578,7 +582,7 @@ pub(crate) async fn get_series( let mut sql_where = Vec::new(); if let Some(selector) = selector { for mat in selector.matchers.matchers.iter() { - if mat.name == CONFIG.common.column_timestamp + if mat.name == cfg.common.column_timestamp || mat.name == VALUE_LABEL || schema.field_with_name(&mat.name).is_err() { @@ -652,6 +656,7 @@ pub(crate) async fn get_labels( Ok(schemas) => schemas, }; let mut label_names = hashbrown::HashSet::new(); + let cfg = get_config(); for schema in stream_schemas { if let Some(ref metric_name) = opt_metric_name { if *metric_name != schema.stream_name { @@ -668,7 +673,7 @@ pub(crate) async fn get_labels( .iter() .map(|f| f.name()) .filter(|&s| { - s != &CONFIG.common.column_timestamp && s != VALUE_LABEL && s != HASH_LABEL + s != &cfg.common.column_timestamp && s != VALUE_LABEL && s != HASH_LABEL }) .cloned(); label_names.extend(field_names); diff --git a/src/service/promql/aggregations/avg.rs b/src/service/promql/aggregations/avg.rs index e45dd4098d..5792f18622 100644 --- a/src/service/promql/aggregations/avg.rs +++ b/src/service/promql/aggregations/avg.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/aggregations/bottomk.rs b/src/service/promql/aggregations/bottomk.rs index eeb5cca820..78721d56fc 100644 --- a/src/service/promql/aggregations/bottomk.rs +++ b/src/service/promql/aggregations/bottomk.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/aggregations/count.rs b/src/service/promql/aggregations/count.rs index 12d892a58f..cd8688f751 100644 --- a/src/service/promql/aggregations/count.rs +++ b/src/service/promql/aggregations/count.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/aggregations/count_values.rs b/src/service/promql/aggregations/count_values.rs index cc62f44819..30950113b3 100644 --- a/src/service/promql/aggregations/count_values.rs +++ b/src/service/promql/aggregations/count_values.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/aggregations/group.rs b/src/service/promql/aggregations/group.rs index 9eae677cc0..e8cce1b5fc 100644 --- a/src/service/promql/aggregations/group.rs +++ b/src/service/promql/aggregations/group.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/aggregations/max.rs b/src/service/promql/aggregations/max.rs index d289a61058..3497cb0cd5 100644 --- a/src/service/promql/aggregations/max.rs +++ b/src/service/promql/aggregations/max.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/aggregations/min.rs b/src/service/promql/aggregations/min.rs index a8b260d0c1..3fa94dd22a 100644 --- a/src/service/promql/aggregations/min.rs +++ b/src/service/promql/aggregations/min.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/aggregations/mod.rs b/src/service/promql/aggregations/mod.rs index 7c1c28558e..1b332b72f8 100644 --- a/src/service/promql/aggregations/mod.rs +++ b/src/service/promql/aggregations/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/aggregations/quantile.rs b/src/service/promql/aggregations/quantile.rs index d11fd93ba7..51101d28e6 100644 --- a/src/service/promql/aggregations/quantile.rs +++ b/src/service/promql/aggregations/quantile.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/aggregations/stddev.rs b/src/service/promql/aggregations/stddev.rs index 2c2b66f2ca..c42c38a2d5 100644 --- a/src/service/promql/aggregations/stddev.rs +++ b/src/service/promql/aggregations/stddev.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/aggregations/stdvar.rs b/src/service/promql/aggregations/stdvar.rs index fe1bacfb78..9303d53de2 100644 --- a/src/service/promql/aggregations/stdvar.rs +++ b/src/service/promql/aggregations/stdvar.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/aggregations/sum.rs b/src/service/promql/aggregations/sum.rs index badd670819..38414caa24 100644 --- a/src/service/promql/aggregations/sum.rs +++ b/src/service/promql/aggregations/sum.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/aggregations/topk.rs b/src/service/promql/aggregations/topk.rs index 7e2552fe46..4612712a2e 100644 --- a/src/service/promql/aggregations/topk.rs +++ b/src/service/promql/aggregations/topk.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/binaries/mod.rs b/src/service/promql/binaries/mod.rs index 415e4f6ee2..0f78cb55fb 100644 --- a/src/service/promql/binaries/mod.rs +++ b/src/service/promql/binaries/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/binaries/scalar_operations.rs b/src/service/promql/binaries/scalar_operations.rs index 7d446cf799..ead44c437b 100644 --- a/src/service/promql/binaries/scalar_operations.rs +++ b/src/service/promql/binaries/scalar_operations.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/binaries/vector_operations.rs b/src/service/promql/binaries/vector_operations.rs index c76ef64f25..1acfc0fa5a 100644 --- a/src/service/promql/binaries/vector_operations.rs +++ b/src/service/promql/binaries/vector_operations.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/common.rs b/src/service/promql/common.rs index e90af6064b..76e187a579 100644 --- a/src/service/promql/common.rs +++ b/src/service/promql/common.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/engine.rs b/src/service/promql/engine.rs index 7bc08a0862..9ea11f8bca 100644 --- a/src/service/promql/engine.rs +++ b/src/service/promql/engine.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -16,7 +16,6 @@ use std::{collections::HashSet, str::FromStr, sync::Arc, time::Duration}; use async_recursion::async_recursion; -use config::CONFIG; use datafusion::{ arrow::{ array::{Float64Array, Int64Array, StringArray}, @@ -916,13 +915,14 @@ async fn selector_load_data_from_datafusion( } }; + let cfg = config::get_config(); let mut df_group = table.clone().filter( - col(&CONFIG.common.column_timestamp) + col(&cfg.common.column_timestamp) .gt(lit(start)) - .and(col(&CONFIG.common.column_timestamp).lt_eq(lit(end))), + .and(col(&cfg.common.column_timestamp).lt_eq(lit(end))), )?; for mat in selector.matchers.matchers.iter() { - if mat.name == CONFIG.common.column_timestamp + if mat.name == cfg.common.column_timestamp || mat.name == VALUE_LABEL || schema.field_with_name(&mat.name).is_err() { @@ -952,7 +952,7 @@ async fn selector_load_data_from_datafusion( } } let batches = df_group - .sort(vec![col(&CONFIG.common.column_timestamp).sort(true, true)])? + .sort(vec![col(&cfg.common.column_timestamp).sort(true, true)])? .collect() .await?; @@ -965,7 +965,7 @@ async fn selector_load_data_from_datafusion( .downcast_ref::() .unwrap(); let time_values = batch - .column_by_name(&CONFIG.common.column_timestamp) + .column_by_name(&cfg.common.column_timestamp) .unwrap() .as_any() .downcast_ref::() @@ -982,7 +982,7 @@ async fn selector_load_data_from_datafusion( let mut labels = Vec::with_capacity(batch.num_columns()); for (k, v) in batch.schema().fields().iter().zip(batch.columns()) { let name = k.name(); - if name == &CONFIG.common.column_timestamp + if name == &cfg.common.column_timestamp || name == HASH_LABEL || name == VALUE_LABEL { diff --git a/src/service/promql/functions/absent.rs b/src/service/promql/functions/absent.rs index b727ffeec4..36282853aa 100644 --- a/src/service/promql/functions/absent.rs +++ b/src/service/promql/functions/absent.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/absent_over_time.rs b/src/service/promql/functions/absent_over_time.rs index 657aa845b5..ba554aac6a 100644 --- a/src/service/promql/functions/absent_over_time.rs +++ b/src/service/promql/functions/absent_over_time.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/avg_over_time.rs b/src/service/promql/functions/avg_over_time.rs index af770251b7..65f8446951 100644 --- a/src/service/promql/functions/avg_over_time.rs +++ b/src/service/promql/functions/avg_over_time.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/changes.rs b/src/service/promql/functions/changes.rs index e33e70717e..fd37e56cf4 100644 --- a/src/service/promql/functions/changes.rs +++ b/src/service/promql/functions/changes.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/clamp.rs b/src/service/promql/functions/clamp.rs index eb568e4b64..8fc82e58f1 100644 --- a/src/service/promql/functions/clamp.rs +++ b/src/service/promql/functions/clamp.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/count_over_time.rs b/src/service/promql/functions/count_over_time.rs index f826fb24a8..8ed032b2d9 100644 --- a/src/service/promql/functions/count_over_time.rs +++ b/src/service/promql/functions/count_over_time.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/delta.rs b/src/service/promql/functions/delta.rs index d2bb5951d2..370acc1235 100644 --- a/src/service/promql/functions/delta.rs +++ b/src/service/promql/functions/delta.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/deriv.rs b/src/service/promql/functions/deriv.rs index 3cc32e3d9e..821ad43fa1 100644 --- a/src/service/promql/functions/deriv.rs +++ b/src/service/promql/functions/deriv.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/histogram.rs b/src/service/promql/functions/histogram.rs index ef7aaa3bff..0079765144 100644 --- a/src/service/promql/functions/histogram.rs +++ b/src/service/promql/functions/histogram.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/holt_winters.rs b/src/service/promql/functions/holt_winters.rs index afccdd3f21..d4d8eee26b 100644 --- a/src/service/promql/functions/holt_winters.rs +++ b/src/service/promql/functions/holt_winters.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/idelta.rs b/src/service/promql/functions/idelta.rs index ba96795da9..50afbd09f7 100644 --- a/src/service/promql/functions/idelta.rs +++ b/src/service/promql/functions/idelta.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/increase.rs b/src/service/promql/functions/increase.rs index c79e71c9ab..0dc1d19d13 100644 --- a/src/service/promql/functions/increase.rs +++ b/src/service/promql/functions/increase.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/irate.rs b/src/service/promql/functions/irate.rs index 33fed0dfdb..be0d0dabe7 100644 --- a/src/service/promql/functions/irate.rs +++ b/src/service/promql/functions/irate.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/label_join.rs b/src/service/promql/functions/label_join.rs index 1fa49842ee..18af036c30 100644 --- a/src/service/promql/functions/label_join.rs +++ b/src/service/promql/functions/label_join.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/label_replace.rs b/src/service/promql/functions/label_replace.rs index c72278fb9d..51b6abde1e 100644 --- a/src/service/promql/functions/label_replace.rs +++ b/src/service/promql/functions/label_replace.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/last_over_time.rs b/src/service/promql/functions/last_over_time.rs index c6ef88193e..04263e0d8f 100644 --- a/src/service/promql/functions/last_over_time.rs +++ b/src/service/promql/functions/last_over_time.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/max_over_time.rs b/src/service/promql/functions/max_over_time.rs index 701b7c8fc9..42c57c1379 100644 --- a/src/service/promql/functions/max_over_time.rs +++ b/src/service/promql/functions/max_over_time.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/min_over_time.rs b/src/service/promql/functions/min_over_time.rs index 40f7c978f2..b9759afde3 100644 --- a/src/service/promql/functions/min_over_time.rs +++ b/src/service/promql/functions/min_over_time.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/mod.rs b/src/service/promql/functions/mod.rs index 4bbb98b4e0..e07e15bb13 100644 --- a/src/service/promql/functions/mod.rs +++ b/src/service/promql/functions/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/predict_linear.rs b/src/service/promql/functions/predict_linear.rs index 19ccbf70cf..b441e00d21 100644 --- a/src/service/promql/functions/predict_linear.rs +++ b/src/service/promql/functions/predict_linear.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/quantile_over_time.rs b/src/service/promql/functions/quantile_over_time.rs index 37fb220bdf..e1bd9f6603 100644 --- a/src/service/promql/functions/quantile_over_time.rs +++ b/src/service/promql/functions/quantile_over_time.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/rate.rs b/src/service/promql/functions/rate.rs index 27b0605c28..929d0e1eaf 100644 --- a/src/service/promql/functions/rate.rs +++ b/src/service/promql/functions/rate.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/resets.rs b/src/service/promql/functions/resets.rs index c87f38c50a..960aae2b4f 100644 --- a/src/service/promql/functions/resets.rs +++ b/src/service/promql/functions/resets.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/stddev_over_time.rs b/src/service/promql/functions/stddev_over_time.rs index c7b69e1689..560956b3f2 100644 --- a/src/service/promql/functions/stddev_over_time.rs +++ b/src/service/promql/functions/stddev_over_time.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/stdvar_over_time.rs b/src/service/promql/functions/stdvar_over_time.rs index 10ea25df93..845fe52285 100644 --- a/src/service/promql/functions/stdvar_over_time.rs +++ b/src/service/promql/functions/stdvar_over_time.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/sum_over_time.rs b/src/service/promql/functions/sum_over_time.rs index 9342868143..a8059e7436 100644 --- a/src/service/promql/functions/sum_over_time.rs +++ b/src/service/promql/functions/sum_over_time.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/functions/vector.rs b/src/service/promql/functions/vector.rs index cd5e958ff0..06dd7974cb 100644 --- a/src/service/promql/functions/vector.rs +++ b/src/service/promql/functions/vector.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/promql/search/grpc/mod.rs b/src/service/promql/search/grpc/mod.rs index f9cba6ef3e..60c38e5389 100644 --- a/src/service/promql/search/grpc/mod.rs +++ b/src/service/promql/search/grpc/mod.rs @@ -19,7 +19,6 @@ use std::{ }; use async_trait::async_trait; -use config::CONFIG; use datafusion::{arrow::datatypes::Schema, error::DataFusionError, prelude::SessionContext}; use infra::{cache::tmpfs, errors::Result}; use promql_parser::parser; @@ -97,7 +96,7 @@ pub async fn search( let timeout = if req.timeout > 0 { req.timeout as u64 } else { - CONFIG.limit.query_timeout + config::get_config().limit.query_timeout }; let mut engine = Query::new( diff --git a/src/service/promql/search/grpc/storage.rs b/src/service/promql/search/grpc/storage.rs index db5d41b0fb..2c2067452a 100644 --- a/src/service/promql/search/grpc/storage.rs +++ b/src/service/promql/search/grpc/storage.rs @@ -21,7 +21,6 @@ use config::{ search::{ScanStats, SearchType, Session as SearchSession, StorageType}, stream::{FileKey, PartitionTimeLevel, StreamPartition, StreamType}, }, - CONFIG, }; use datafusion::{ arrow::datatypes::Schema, @@ -220,14 +219,15 @@ async fn cache_parquet_files( files: &[FileKey], scan_stats: &ScanStats, ) -> Result<(file_data::CacheType, Vec)> { - let cache_type = if CONFIG.memory_cache.enabled - && scan_stats.compressed_size < CONFIG.memory_cache.skip_size as i64 + let cfg = config::get_config(); + let cache_type = if cfg.memory_cache.enabled + && scan_stats.compressed_size < cfg.memory_cache.skip_size as i64 { // if scan_compressed_size < 80% of total memory cache, use memory cache file_data::CacheType::Memory } else if !is_local_disk_storage() - && CONFIG.disk_cache.enabled - && scan_stats.compressed_size < CONFIG.disk_cache.skip_size as i64 + && cfg.disk_cache.enabled + && scan_stats.compressed_size < cfg.disk_cache.skip_size as i64 { // if scan_compressed_size < 80% of total disk cache, use disk cache file_data::CacheType::Disk @@ -237,7 +237,7 @@ async fn cache_parquet_files( }; let mut tasks = Vec::new(); - let semaphore = std::sync::Arc::new(Semaphore::new(CONFIG.limit.query_thread_num)); + let semaphore = std::sync::Arc::new(Semaphore::new(cfg.limit.query_thread_num)); for file in files.iter() { let trace_id = ""; let file_name = file.key.clone(); diff --git a/src/service/promql/search/grpc/wal.rs b/src/service/promql/search/grpc/wal.rs index ca4e4e1fc7..347a9bf4da 100644 --- a/src/service/promql/search/grpc/wal.rs +++ b/src/service/promql/search/grpc/wal.rs @@ -17,11 +17,12 @@ use std::{collections::HashMap, io::Cursor, sync::Arc}; use arrow::{ipc::reader::StreamReader, record_batch::RecordBatch}; use config::{ + get_config, meta::{ search::{ScanStats, SearchType, Session as SearchSession, StorageType}, stream::StreamType, }, - CONFIG, FILE_EXT_PARQUET, + FILE_EXT_PARQUET, }; use datafusion::{ arrow::datatypes::Schema, @@ -33,7 +34,12 @@ use datafusion::{ use futures::future::try_join_all; use infra::cache::tmpfs; use proto::cluster_rpc; -use tonic::{codec::CompressionEncoding, metadata::MetadataValue, transport::Channel, Request}; +use tonic::{ + codec::CompressionEncoding, + metadata::{MetadataKey, MetadataValue}, + transport::Channel, + Request, +}; use tracing::{info_span, Instrument}; use tracing_opentelemetry::OpenTelemetrySpanExt; @@ -228,11 +234,12 @@ async fn get_file_list( std::result::Result, > = tokio::task::spawn( async move { + let cfg = get_config(); let org_id: MetadataValue<_> = org_id .parse() .map_err(|_| DataFusionError::Execution("invalid org_id".to_string()))?; let mut request = tonic::Request::new(req); - // request.set_timeout(Duration::from_secs(CONFIG.grpc.timeout)); + // request.set_timeout(Duration::from_secs(cfg.grpc.timeout)); opentelemetry::global::get_text_map_propagator(|propagator| { propagator.inject_context( @@ -241,12 +248,16 @@ async fn get_file_list( ) }); + let org_header_key: MetadataKey<_> = + cfg.grpc.org_header_key.parse().map_err(|_| { + DataFusionError::Execution("invalid org_header_key".to_string()) + })?; let token: MetadataValue<_> = get_internal_grpc_token() .parse() .map_err(|_| DataFusionError::Execution("invalid token".to_string()))?; let channel = Channel::from_shared(node_addr) .unwrap() - .connect_timeout(std::time::Duration::from_secs(CONFIG.grpc.connect_timeout)) + .connect_timeout(std::time::Duration::from_secs(cfg.grpc.connect_timeout)) .connect() .await .map_err(|_| { @@ -257,15 +268,16 @@ async fn get_file_list( move |mut req: Request<()>| { req.metadata_mut().insert("authorization", token.clone()); req.metadata_mut() - .insert(CONFIG.grpc.org_header_key.as_str(), org_id.clone()); + .insert(org_header_key.clone(), org_id.clone()); Ok(req) }, ); + let cfg = get_config(); client = client .send_compressed(CompressionEncoding::Gzip) .accept_compressed(CompressionEncoding::Gzip) - .max_decoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024) - .max_encoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024); + .max_decoding_message_size(cfg.grpc.max_message_size * 1024 * 1024) + .max_encoding_message_size(cfg.grpc.max_message_size * 1024 * 1024); let response: cluster_rpc::MetricsWalFileResponse = match client .wal_file(request) .await diff --git a/src/service/promql/search/mod.rs b/src/service/promql/search/mod.rs index 06edd15dfb..14c4293988 100644 --- a/src/service/promql/search/mod.rs +++ b/src/service/promql/search/mod.rs @@ -25,13 +25,17 @@ use config::{ stream::StreamType, usage::{RequestStats, UsageType}, }, - CONFIG, }; use futures::future::try_join_all; use hashbrown::HashMap; use infra::errors::{Error, ErrorCodes, Result}; use proto::cluster_rpc; -use tonic::{codec::CompressionEncoding, metadata::MetadataValue, transport::Channel, Request}; +use tonic::{ + codec::CompressionEncoding, + metadata::{MetadataKey, MetadataValue}, + transport::Channel, + Request, +}; use tracing::{info_span, Instrument}; use tracing_opentelemetry::OpenTelemetrySpanExt; @@ -151,12 +155,13 @@ async fn search_in_cluster( let grpc_span = info_span!("promql:search:cluster:grpc_search", org_id = req.org_id); let task = tokio::task::spawn( async move { + let cfg = config::get_config(); let org_id: MetadataValue<_> = req .org_id .parse() .map_err(|_| Error::Message(format!("invalid org_id: {}", req.org_id)))?; let mut request = tonic::Request::new(req); - // request.set_timeout(Duration::from_secs(CONFIG.grpc.timeout)); + // request.set_timeout(Duration::from_secs(cfg.grpc.timeout)); opentelemetry::global::get_text_map_propagator(|propagator| { propagator.inject_context( @@ -165,12 +170,13 @@ async fn search_in_cluster( ) }); + let org_header_key: MetadataKey<_> = cfg.grpc.org_header_key.parse().map_err(|_| Error::Message("invalid org_header_key".to_string()))?; let token: MetadataValue<_> = cluster::get_internal_grpc_token() .parse() .map_err(|_| Error::Message("invalid token".to_string()))?; let channel = Channel::from_shared(node_addr) .unwrap() - .connect_timeout(std::time::Duration::from_secs(CONFIG.grpc.connect_timeout)) + .connect_timeout(std::time::Duration::from_secs(cfg.grpc.connect_timeout)) .connect() .await .map_err(|err| { @@ -181,20 +187,21 @@ async fn search_in_cluster( ); server_internal_error("connect search node error") })?; - let mut client = cluster_rpc::metrics_client::MetricsClient::with_interceptor( - channel, - move |mut req: Request<()>| { + + let mut client = cluster_rpc::metrics_client::MetricsClient::with_interceptor( + channel, + move |mut req: Request<()>| { req.metadata_mut().insert("authorization", token.clone()); req.metadata_mut() - .insert(CONFIG.grpc.org_header_key.as_str(), org_id.clone()); + .insert(org_header_key.clone(), org_id.clone()); Ok(req) }, ); - client = client + client = client .send_compressed(CompressionEncoding::Gzip) .accept_compressed(CompressionEncoding::Gzip) - .max_decoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024) - .max_encoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024); + .max_decoding_message_size(cfg.grpc.max_message_size * 1024 * 1024) + .max_encoding_message_size(cfg.grpc.max_message_size * 1024 * 1024); let response: cluster_rpc::MetricsQueryResponse = match client.query(request).await { Ok(res) => res.into_inner(), diff --git a/src/service/promql/value.rs b/src/service/promql/value.rs index 38f595d12b..7022c1a0e4 100644 --- a/src/service/promql/value.rs +++ b/src/service/promql/value.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/schema.rs b/src/service/schema.rs index c78b44ed0c..2edf2b5852 100644 --- a/src/service/schema.rs +++ b/src/service/schema.rs @@ -17,9 +17,9 @@ use std::{collections::HashMap, sync::Arc}; use anyhow::Result; use config::{ + get_config, meta::stream::StreamType, utils::{json, schema::infer_json_schema_from_map, schema_ext::SchemaExt}, - CONFIG, }; use datafusion::arrow::datatypes::{Field, Schema}; use hashbrown::HashSet; @@ -38,7 +38,7 @@ use crate::{ pub(crate) fn get_upto_discard_error() -> anyhow::Error { anyhow::anyhow!( "Too old data, only last {} hours data can be ingested. Data discarded. You can adjust ingestion max time by setting the environment variable ZO_INGEST_ALLOWED_UPTO=", - CONFIG.limit.ingest_allowed_upto + get_config().limit.ingest_allowed_upto ) } @@ -48,7 +48,7 @@ pub(crate) fn get_request_columns_limit_error( ) -> anyhow::Error { anyhow::anyhow!( "Got {num_fields} columns for stream {stream_name}, only {} columns accept. Data discarded. You can adjust ingestion columns limit by setting the environment variable ZO_COLS_PER_RECORD_LIMIT=", - CONFIG.limit.req_cols_per_record_limit + get_config().limit.req_cols_per_record_limit ) } @@ -64,8 +64,9 @@ pub async fn check_for_schema( let schema = infra::schema::get_cache(org_id, stream_name, stream_type).await?; stream_schema_map.insert(stream_name.to_string(), schema); } + let cfg = get_config(); let schema = stream_schema_map.get(stream_name).unwrap(); - if !schema.schema().fields().is_empty() && CONFIG.common.skip_schema_validation { + if !schema.schema().fields().is_empty() && cfg.common.skip_schema_validation { return Ok(SchemaEvolution { schema_compatible: true, is_schema_changed: false, @@ -86,7 +87,7 @@ pub async fn check_for_schema( }); } - if inferred_schema.fields.len() > CONFIG.limit.req_cols_per_record_limit { + if inferred_schema.fields.len() > cfg.limit.req_cols_per_record_limit { return Err(get_request_columns_limit_error( &format!("{}/{}/{}", org_id, stream_type, stream_name), inferred_schema.fields.len(), @@ -214,7 +215,7 @@ async fn handle_diff_schema( let mut err: Option = None; let mut ret: Option<_> = None; // retry x times for update schema - while retries < CONFIG.limit.meta_transaction_retries { + while retries < get_config().limit.meta_transaction_retries { match db::schema::merge( org_id, stream_name, @@ -311,12 +312,13 @@ pub fn generate_schema_for_defined_schema_fields( return schema.clone(); } + let cfg = get_config(); let mut fields: HashSet<_> = fields.iter().collect(); - if !fields.contains(&CONFIG.common.column_timestamp) { - fields.insert(&CONFIG.common.column_timestamp); + if !fields.contains(&cfg.common.column_timestamp) { + fields.insert(&cfg.common.column_timestamp); } - if !fields.contains(&CONFIG.common.all_fields_name) { - fields.insert(&CONFIG.common.all_fields_name); + if !fields.contains(&cfg.common.all_fields_name) { + fields.insert(&cfg.common.all_fields_name); } let mut new_fields = Vec::with_capacity(fields.len()); for field in fields { @@ -353,7 +355,7 @@ fn get_schema_changes(schema: &SchemaCache, inferred_schema: &Schema) -> (bool, } let existing_field: Arc = schema.schema().fields()[*idx].clone(); if existing_field.data_type() != item_data_type { - if !CONFIG.common.widening_schema_evolution { + if !get_config().common.widening_schema_evolution { field_datatype_delta.push(existing_field.as_ref().to_owned()); } else if infra::schema::is_widening_conversion( existing_field.data_type(), diff --git a/src/service/search/cluster/mod.rs b/src/service/search/cluster/mod.rs index 0921d87449..dde8912a0b 100644 --- a/src/service/search/cluster/mod.rs +++ b/src/service/search/cluster/mod.rs @@ -19,6 +19,7 @@ use ::datafusion::arrow::{datatypes::Schema, ipc, record_batch::RecordBatch}; use async_recursion::async_recursion; use config::{ cluster::{is_ingester, is_querier}, + get_config, meta::{ cluster::{Node, Role}, search::{self, ScanStats}, @@ -27,7 +28,7 @@ use config::{ }, }, utils::json, - CONFIG, DEFAULT_INDEX_TRIM_CHARS, INDEX_MIN_CHAR_LEN, + DEFAULT_INDEX_TRIM_CHARS, INDEX_MIN_CHAR_LEN, }; use hashbrown::{HashMap, HashSet}; use infra::{ @@ -37,7 +38,12 @@ use infra::{ }; use itertools::Itertools; use proto::cluster_rpc; -use tonic::{codec::CompressionEncoding, metadata::MetadataValue, transport::Channel, Request}; +use tonic::{ + codec::CompressionEncoding, + metadata::{MetadataKey, MetadataValue}, + transport::Channel, + Request, +}; use tracing::{info_span, Instrument}; use tracing_opentelemetry::OpenTelemetrySpanExt; @@ -67,6 +73,7 @@ pub async fn search( )> { let start = std::time::Instant::now(); + let cfg = get_config(); // if the request is a super cluster request, then forward it to the super cluster service let is_final_phase = req.stype != cluster_rpc::SearchType::SuperCluster as i32; @@ -120,7 +127,7 @@ pub async fn search( .iter() .flat_map(|t| { let mut tokenized_search_terms = vec![]; - t.split(|c| CONFIG.common.inverted_index_split_chars.contains(c)) + t.split(|c| cfg.common.inverted_index_split_chars.contains(c)) .for_each(|s| { let s = s.trim_matches(|c| DEFAULT_INDEX_TRIM_CHARS.contains(c)); if !s.is_empty() && s.len() >= INDEX_MIN_CHAR_LEN { @@ -278,7 +285,7 @@ pub async fn search( let locker_key = "/search/cluster_queue/".to_string() + work_group_str.as_str(); // get a cluster search queue lock - let locker = if CONFIG.common.local_mode || !CONFIG.common.feature_query_queue_enabled { + let locker = if cfg.common.local_mode || !cfg.common.feature_query_queue_enabled { None } else { dist_lock::lock(&locker_key, 0).await? @@ -318,8 +325,8 @@ pub async fn search( let mut partition_files = Vec::new(); let mut file_num = file_list.len(); let mut partition_strategy = - QueryPartitionStrategy::from(&CONFIG.common.feature_query_partition_strategy); - if CONFIG.memory_cache.cache_latest_files { + QueryPartitionStrategy::from(&cfg.common.feature_query_partition_strategy); + if cfg.memory_cache.cache_latest_files { partition_strategy = QueryPartitionStrategy::FileHash; } let offset = match partition_strategy { @@ -451,12 +458,13 @@ pub async fn search( let task = tokio::task::spawn( async move { + let cfg = config::get_config(); let org_id: MetadataValue<_> = req .org_id .parse() .map_err(|_| Error::Message("invalid org_id".to_string()))?; let mut request = tonic::Request::new(req); - // request.set_timeout(Duration::from_secs(CONFIG.grpc.timeout)); + // request.set_timeout(Duration::from_secs(cfg.grpc.timeout)); opentelemetry::global::get_text_map_propagator(|propagator| { propagator.inject_context( @@ -467,12 +475,17 @@ pub async fn search( log::info!("[trace_id {trace_id}] search->grpc: request node: {}, is_querier: {}, files: {req_files}", &node_addr, is_querier); + let org_header_key: MetadataKey<_> = cfg + .grpc + .org_header_key + .parse() + .map_err(|_| Error::Message("invalid org_header_key".to_string()))?; let token: MetadataValue<_> = infra_cluster::get_internal_grpc_token() .parse() .map_err(|_| Error::Message("invalid token".to_string()))?; let channel = Channel::from_shared(node_addr) .unwrap() - .connect_timeout(std::time::Duration::from_secs(CONFIG.grpc.connect_timeout)) + .connect_timeout(std::time::Duration::from_secs(cfg.grpc.connect_timeout)) .connect() .await .map_err(|err| { @@ -484,15 +497,15 @@ pub async fn search( move |mut req: Request<()>| { req.metadata_mut().insert("authorization", token.clone()); req.metadata_mut() - .insert(CONFIG.grpc.org_header_key.as_str(), org_id.clone()); + .insert(org_header_key.clone(), org_id.clone()); Ok(req) }, ); client = client .send_compressed(CompressionEncoding::Gzip) .accept_compressed(CompressionEncoding::Gzip) - .max_decoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024) - .max_encoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024); + .max_decoding_message_size(cfg.grpc.max_message_size * 1024 * 1024) + .max_encoding_message_size(cfg.grpc.max_message_size * 1024 * 1024); let response; tokio::select! { result = client.search(request) => { @@ -750,7 +763,7 @@ pub(crate) async fn get_file_list( time_level: PartitionTimeLevel, partition_keys: &[StreamPartition], ) -> Vec { - let is_local = CONFIG.common.meta_store_external + let is_local = get_config().common.meta_store_external || infra_cluster::get_cached_online_querier_nodes() .await .unwrap_or_default() @@ -864,27 +877,25 @@ fn handle_metrics_response(sources: Vec) -> Vec { // handle metrics response let mut results_metrics: HashMap = HashMap::with_capacity(16); let mut results_values: HashMap> = HashMap::with_capacity(16); + let cfg = get_config(); for source in sources { let fields = source.as_object().unwrap(); let mut key = Vec::with_capacity(fields.len()); fields.iter().for_each(|(k, v)| { - if *k != CONFIG.common.column_timestamp && k != "value" { + if *k != cfg.common.column_timestamp && k != "value" { key.push(format!("{k}_{v}")); } }); let key = key.join("_"); if !results_metrics.contains_key(&key) { let mut fields = fields.clone(); - fields.remove(&CONFIG.common.column_timestamp); + fields.remove(&cfg.common.column_timestamp); fields.remove("value"); results_metrics.insert(key.clone(), json::Value::Object(fields)); } let entry = results_values.entry(key).or_default(); let value = [ - fields - .get(&CONFIG.common.column_timestamp) - .unwrap() - .to_owned(), + fields.get(&cfg.common.column_timestamp).unwrap().to_owned(), json::Value::String(fields.get("value").unwrap().to_string()), ]; entry.push(value); diff --git a/src/service/search/datafusion/date_format_udf.rs b/src/service/search/datafusion/date_format_udf.rs index 1ffe57ff69..459a108512 100644 --- a/src/service/search/datafusion/date_format_udf.rs +++ b/src/service/search/datafusion/date_format_udf.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/search/datafusion/exec.rs b/src/service/search/datafusion/exec.rs index 6c3cb1860b..f98cb4c39f 100644 --- a/src/service/search/datafusion/exec.rs +++ b/src/service/search/datafusion/exec.rs @@ -17,6 +17,7 @@ use std::{str::FromStr, sync::Arc}; use arrow_schema::Field; use config::{ + get_config, meta::{ search::{SearchType, Session as SearchSession, StorageType}, sql, @@ -26,7 +27,7 @@ use config::{ arrow::record_batches_to_json_rows, flatten, json, parquet::new_parquet_writer, schema::infer_json_schema_from_values, schema_ext::SchemaExt, }, - CONFIG, PARQUET_BATCH_SIZE, + PARQUET_BATCH_SIZE, }; use datafusion::{ arrow::{ @@ -93,12 +94,13 @@ pub async fn sql( return Ok(HashMap::new()); } + let cfg = get_config(); let start = std::time::Instant::now(); let trace_id = session.id.clone(); let select_wildcard = RE_SELECT_WILDCARD.is_match(sql.origin_sql.as_str()); let without_optimizer = select_wildcard - && CONFIG.limit.query_optimization_num_fields > 0 - && schema.fields().len() > CONFIG.limit.query_optimization_num_fields; + && cfg.limit.query_optimization_num_fields > 0 + && schema.fields().len() > cfg.limit.query_optimization_num_fields; let (mut ctx, mut ctx_aggs) = if !file_type.eq(&FileType::ARROW) { let ctx = register_table( session, @@ -184,7 +186,7 @@ pub async fn sql( }; for (name, orig_agg_sql) in sql.aggs.iter() { // Debug SQL - if CONFIG.common.print_key_sql { + if cfg.common.print_key_sql { log::info!("[trace_id {trace_id}] Query agg sql: {}", orig_agg_sql.0); } @@ -261,11 +263,11 @@ async fn exec_query( ) -> Result> { let start = std::time::Instant::now(); let trace_id = session.id.clone(); - + let cfg = get_config(); let select_wildcard = RE_SELECT_WILDCARD.is_match(sql.origin_sql.as_str()); let without_optimizer = select_wildcard - && CONFIG.limit.query_optimization_num_fields > 0 - && schema.fields().len() > CONFIG.limit.query_optimization_num_fields; + && cfg.limit.query_optimization_num_fields > 0 + && schema.fields().len() > cfg.limit.query_optimization_num_fields; let mut fast_mode = false; let (q_ctx, schema) = if sql.fast_mode && session.storage_type != StorageType::Tmpfs { @@ -306,9 +308,9 @@ async fn exec_query( Some(ts_range) => format!( "{} where {} >= {} AND {} < {}", sql_parts[0], - CONFIG.common.column_timestamp, + cfg.common.column_timestamp, ts_range.0, - CONFIG.common.column_timestamp, + cfg.common.column_timestamp, ts_range.1 ), None => sql_parts[0].to_owned(), @@ -325,7 +327,7 @@ async fn exec_query( } // Debug SQL - if CONFIG.common.print_key_sql { + if cfg.common.print_key_sql { log::info!("[trace_id {trace_id}] Query sql: {}", query); } @@ -582,10 +584,11 @@ pub async fn merge( ); } + let cfg = get_config(); let select_wildcard = RE_SELECT_WILDCARD.is_match(sql); let without_optimizer = select_wildcard - && CONFIG.limit.query_optimization_num_fields > 0 - && schema.fields().len() > CONFIG.limit.query_optimization_num_fields; + && cfg.limit.query_optimization_num_fields > 0 + && schema.fields().len() > cfg.limit.query_optimization_num_fields; // rewrite sql let mut query_sql = match merge_rewrite_sql(sql, schema, is_final_phase) { @@ -618,7 +621,7 @@ pub async fn merge( let file_format = ParquetFormat::default(); let listing_options = ListingOptions::new(Arc::new(file_format)) .with_file_extension(FileType::PARQUET.get_ext()) - .with_target_partitions(CONFIG.limit.cpu_num); + .with_target_partitions(cfg.limit.cpu_num); let list_url = format!("tmpfs:///{}/", work_dir.name()); let prefix = match ListingTableUrl::parse(list_url) { Ok(url) => url, @@ -646,7 +649,7 @@ pub async fn merge( register_udf(&mut ctx, org_id).await; // Debug SQL - if CONFIG.common.print_key_sql { + if cfg.common.print_key_sql { log::info!("Merge sql: {query_sql}, is_final_phase: {is_final_phase}"); } @@ -930,11 +933,12 @@ pub async fn convert_parquet_file( rules: HashMap, file_type: FileType, ) -> Result<()> { + let cfg = get_config(); let start = std::time::Instant::now(); let query_sql = format!( "SELECT * FROM tbl ORDER BY {} DESC", - CONFIG.common.column_timestamp + cfg.common.column_timestamp ); let select_wildcard = RE_SELECT_WILDCARD.is_match(query_sql.as_str()); @@ -949,13 +953,13 @@ pub async fn convert_parquet_file( let file_format = ParquetFormat::default(); ListingOptions::new(Arc::new(file_format)) .with_file_extension(FileType::PARQUET.get_ext()) - .with_target_partitions(CONFIG.limit.cpu_num) + .with_target_partitions(cfg.limit.cpu_num) } FileType::JSON => { let file_format = JsonFormat::default(); ListingOptions::new(Arc::new(file_format)) .with_file_extension(FileType::JSON.get_ext()) - .with_target_partitions(CONFIG.limit.cpu_num) + .with_target_partitions(cfg.limit.cpu_num) } _ => { return Err(DataFusionError::Execution(format!( @@ -1045,12 +1049,12 @@ pub async fn merge_parquet_files( schema: Arc, ) -> Result<(Arc, Vec)> { let start = std::time::Instant::now(); - + let cfg = get_config(); // Configure listing options let file_format = ParquetFormat::default(); let listing_options = ListingOptions::new(Arc::new(file_format)) .with_file_extension(FileType::PARQUET.get_ext()) - .with_target_partitions(CONFIG.limit.cpu_num); + .with_target_partitions(cfg.limit.cpu_num); let prefix = ListingTableUrl::parse(format!("tmpfs:///{trace_id}/"))?; let config = ListingTableConfig::new(prefix) .with_listing_options(listing_options) @@ -1062,22 +1066,20 @@ pub async fn merge_parquet_files( // TODO: NOT IN is not efficient, need to optimize it: NOT EXIST format!( "SELECT * FROM tbl WHERE file_name NOT IN (SELECT file_name FROM tbl WHERE deleted is True) ORDER BY {} ASC", - CONFIG.common.column_timestamp + cfg.common.column_timestamp ) - } else if CONFIG.limit.distinct_values_hourly + } else if cfg.limit.distinct_values_hourly && stream_type == StreamType::Metadata && stream_name == "distinct_values" { format!( "SELECT MIN({}) AS {}, SUM(count) as count, field_name, field_value, filter_name, filter_value, stream_name, stream_type FROM tbl GROUP BY field_name, field_value, filter_name, filter_value, stream_name, stream_type ORDER BY {} ASC", - CONFIG.common.column_timestamp, - CONFIG.common.column_timestamp, - CONFIG.common.column_timestamp + cfg.common.column_timestamp, cfg.common.column_timestamp, cfg.common.column_timestamp ) } else { format!( "SELECT * FROM tbl ORDER BY {} ASC", - CONFIG.common.column_timestamp + cfg.common.column_timestamp ) }; @@ -1114,10 +1116,11 @@ pub fn create_session_config(search_type: &SearchType) -> Result config = config.set_bool("datafusion.execution.parquet.pushdown_filters", true); config = config.set_bool("datafusion.execution.parquet.reorder_filters", true); } - if CONFIG.common.bloom_filter_enabled { + let cfg = get_config(); + if cfg.common.bloom_filter_enabled { config = config.set_bool("datafusion.execution.parquet.bloom_filter_on_read", true); } - if CONFIG.common.bloom_filter_disabled_on_search { + if cfg.common.bloom_filter_disabled_on_search { config = config.set_bool("datafusion.execution.parquet.bloom_filter_on_read", false); } Ok(config) @@ -1138,20 +1141,21 @@ pub fn create_runtime_env(_work_group: Option) -> Result { let tmpfs_url = url::Url::parse("tmpfs:///").unwrap(); object_store_registry.register_store(&tmpfs_url, Arc::new(tmpfs)); + let cfg = get_config(); let mut rn_config = RuntimeConfig::new().with_object_store_registry(Arc::new(object_store_registry)); - if CONFIG.limit.datafusion_file_stat_cache_max_entries > 0 { + if cfg.limit.datafusion_file_stat_cache_max_entries > 0 { let cache_config = CacheManagerConfig::default(); let cache_config = cache_config.with_files_statistics_cache(Some( super::storage::file_statistics_cache::GLOBAL_CACHE.clone(), )); rn_config = rn_config.with_cache_manager(cache_config); } - if CONFIG.memory_cache.datafusion_max_size > 0 { + if cfg.memory_cache.datafusion_max_size > 0 { #[cfg(not(feature = "enterprise"))] - let memory_size = CONFIG.memory_cache.datafusion_max_size; + let memory_size = cfg.memory_cache.datafusion_max_size; #[cfg(feature = "enterprise")] - let mut memory_size = CONFIG.memory_cache.datafusion_max_size; + let mut memory_size = cfg.memory_cache.datafusion_max_size; #[cfg(feature = "enterprise")] if let Some(wg) = _work_group { use o2_enterprise::enterprise::search::WorkGroup; @@ -1161,7 +1165,7 @@ pub fn create_runtime_env(_work_group: Option) -> Result { log::debug!("group:{} memory pool size: {}", wg, memory_size); } } - let mem_pool = super::MemoryPoolType::from_str(&CONFIG.memory_cache.datafusion_memory_pool) + let mem_pool = super::MemoryPoolType::from_str(&cfg.memory_cache.datafusion_memory_pool) .map_err(|e| { DataFusionError::Execution(format!("Invalid datafusion memory pool type: {}", e)) })?; @@ -1230,20 +1234,21 @@ pub async fn register_table( without_optimizer, )?; + let cfg = get_config(); // Configure listing options let listing_options = match file_type { FileType::PARQUET => { let file_format = ParquetFormat::default(); ListingOptions::new(Arc::new(file_format)) .with_file_extension(FileType::PARQUET.get_ext()) - .with_target_partitions(CONFIG.limit.cpu_num) + .with_target_partitions(cfg.limit.cpu_num) .with_collect_stat(true) } FileType::JSON => { let file_format = JsonFormat::default(); ListingOptions::new(Arc::new(file_format)) .with_file_extension(FileType::JSON.get_ext()) - .with_target_partitions(CONFIG.limit.cpu_num) + .with_target_partitions(cfg.limit.cpu_num) .with_collect_stat(true) } _ => { @@ -1277,9 +1282,9 @@ pub async fn register_table( }; let mut config = ListingTableConfig::new(prefix).with_listing_options(listing_options); - if CONFIG.common.feature_query_infer_schema - && (CONFIG.limit.query_optimization_num_fields > 0 - && schema.fields().len() > CONFIG.limit.query_optimization_num_fields) + if cfg.common.feature_query_infer_schema + && (cfg.limit.query_optimization_num_fields > 0 + && schema.fields().len() > cfg.limit.query_optimization_num_fields) { config = config.infer_schema(&ctx.state()).await?; } else { diff --git a/src/service/search/datafusion/match_udf.rs b/src/service/search/datafusion/match_udf.rs index 2808d8dac3..c99de06db6 100644 --- a/src/service/search/datafusion/match_udf.rs +++ b/src/service/search/datafusion/match_udf.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/search/datafusion/mod.rs b/src/service/search/datafusion/mod.rs index 01a651caf0..e715ff09f3 100644 --- a/src/service/search/datafusion/mod.rs +++ b/src/service/search/datafusion/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/search/datafusion/regexp_udf.rs b/src/service/search/datafusion/regexp_udf.rs index dc44e30e24..5803dba0a0 100644 --- a/src/service/search/datafusion/regexp_udf.rs +++ b/src/service/search/datafusion/regexp_udf.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/search/datafusion/rewrite.rs b/src/service/search/datafusion/rewrite.rs index c6a0d4c799..b5d5415f98 100644 --- a/src/service/search/datafusion/rewrite.rs +++ b/src/service/search/datafusion/rewrite.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/search/datafusion/storage/file_statistics_cache.rs b/src/service/search/datafusion/storage/file_statistics_cache.rs index 5c9978dd85..19f12722f3 100644 --- a/src/service/search/datafusion/storage/file_statistics_cache.rs +++ b/src/service/search/datafusion/storage/file_statistics_cache.rs @@ -56,7 +56,11 @@ impl FileStatisticsCache { impl Default for FileStatisticsCache { fn default() -> Self { - Self::new(config::CONFIG.limit.datafusion_file_stat_cache_max_entries) + Self::new( + config::get_config() + .limit + .datafusion_file_stat_cache_max_entries, + ) } } diff --git a/src/service/search/datafusion/storage/memory.rs b/src/service/search/datafusion/storage/memory.rs index 715b7c1461..de90779aa5 100644 --- a/src/service/search/datafusion/storage/memory.rs +++ b/src/service/search/datafusion/storage/memory.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/search/datafusion/storage/tmpfs.rs b/src/service/search/datafusion/storage/tmpfs.rs index cef824cfa7..6cbde1ee40 100644 --- a/src/service/search/datafusion/storage/tmpfs.rs +++ b/src/service/search/datafusion/storage/tmpfs.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/search/datafusion/string_to_array_v2_udf.rs b/src/service/search/datafusion/string_to_array_v2_udf.rs index 868ae574ff..34011a93fa 100644 --- a/src/service/search/datafusion/string_to_array_v2_udf.rs +++ b/src/service/search/datafusion/string_to_array_v2_udf.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/search/datafusion/time_range_udf.rs b/src/service/search/datafusion/time_range_udf.rs index 3e724c870a..95668ae49b 100644 --- a/src/service/search/datafusion/time_range_udf.rs +++ b/src/service/search/datafusion/time_range_udf.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/search/grpc/mod.rs b/src/service/search/grpc/mod.rs index 9bb8a03106..bec6091529 100644 --- a/src/service/search/grpc/mod.rs +++ b/src/service/search/grpc/mod.rs @@ -18,12 +18,12 @@ use std::{collections::HashSet, sync::Arc}; use ::datafusion::arrow::{ipc, record_batch::RecordBatch}; use arrow_schema::{DataType, Field, Schema}; use config::{ - cluster, + cluster, get_config, meta::{ search::ScanStats, stream::{FileKey, StreamType}, }, - FxIndexSet, CONFIG, + FxIndexSet, }; use futures::future::try_join_all; use hashbrown::HashMap; @@ -51,7 +51,7 @@ pub async fn search( let timeout = if req.timeout > 0 { req.timeout as u64 } else { - CONFIG.limit.query_timeout + get_config().limit.query_timeout }; // check if we are allowed to search @@ -312,6 +312,7 @@ pub async fn search( } fn check_memory_circuit_breaker(trace_id: &str, scan_stats: &ScanStats) -> Result<(), Error> { + let cfg = get_config(); let scan_size = if scan_stats.compressed_size > 0 { scan_stats.compressed_size } else { @@ -319,10 +320,9 @@ fn check_memory_circuit_breaker(trace_id: &str, scan_stats: &ScanStats) -> Resul }; if let Some(cur_memory) = memory_stats::memory_stats() { // left memory < datafusion * breaker_ratio and scan_size >= left memory - let left_mem = CONFIG.limit.mem_total - cur_memory.physical_mem; + let left_mem = cfg.limit.mem_total - cur_memory.physical_mem; if (left_mem - < (CONFIG.memory_cache.datafusion_max_size - * CONFIG.common.memory_circuit_breaker_ratio + < (cfg.memory_cache.datafusion_max_size * cfg.common.memory_circuit_breaker_ratio / 100)) && (scan_size >= left_mem as i64) { @@ -331,8 +331,7 @@ fn check_memory_circuit_breaker(trace_id: &str, scan_stats: &ScanStats) -> Resul scan_size, cur_memory.physical_mem, left_mem, - CONFIG.memory_cache.datafusion_max_size - * CONFIG.common.memory_circuit_breaker_ratio + cfg.memory_cache.datafusion_max_size * cfg.common.memory_circuit_breaker_ratio / 100 ); log::warn!("[{trace_id}] {}", err); @@ -380,7 +379,7 @@ fn generate_search_schema( } let mut schema = Schema::new(new_fields); - let timestamp = &CONFIG.common.column_timestamp; + let timestamp = &get_config().common.column_timestamp; if schema.field_with_name(timestamp).is_err() { // self add timestamp column if no exist let field = Arc::new(Field::new(timestamp, DataType::Int64, false)); @@ -425,13 +424,14 @@ fn generate_select_start_search_schema( } } } + let cfg = get_config(); let schema = if !defined_schema_fields.is_empty() { let mut fields: HashSet = defined_schema_fields.iter().cloned().collect(); - if !fields.contains(&CONFIG.common.column_timestamp) { - fields.insert(CONFIG.common.column_timestamp.to_string()); + if !fields.contains(&cfg.common.column_timestamp) { + fields.insert(cfg.common.column_timestamp.to_string()); } - if !fields.contains(&CONFIG.common.all_fields_name) { - fields.insert(CONFIG.common.all_fields_name.to_string()); + if !fields.contains(&cfg.common.all_fields_name) { + fields.insert(cfg.common.all_fields_name.to_string()); } let new_fields = fields .iter() diff --git a/src/service/search/grpc/storage.rs b/src/service/search/grpc/storage.rs index 2df9d4b154..2f745473bb 100644 --- a/src/service/search/grpc/storage.rs +++ b/src/service/search/grpc/storage.rs @@ -16,13 +16,12 @@ use std::sync::Arc; use config::{ - is_local_disk_storage, + get_config, is_local_disk_storage, meta::{ search::{ScanStats, SearchType, StorageType}, stream::{FileKey, PartitionTimeLevel, StreamPartition, StreamType}, }, utils::schema_ext::SchemaExt, - CONFIG, }; use datafusion::{arrow::record_batch::RecordBatch, common::FileType}; use futures::future::try_join_all; @@ -120,10 +119,11 @@ pub async fn search( files.len(), ); + let cfg = get_config(); let mut files_group: HashMap> = HashMap::with_capacity(schema_versions.len()); let mut scan_stats = ScanStats::new(); - if !CONFIG.common.widening_schema_evolution || schema_versions.len() == 1 { + if !cfg.common.widening_schema_evolution || schema_versions.len() == 1 { let files = files.to_vec(); scan_stats = match file_list::calculate_files_size(&files).await { Ok(size) => size, @@ -175,7 +175,7 @@ pub async fn search( scan_stats.compressed_size ); - if CONFIG.common.memory_circuit_breaker_enable { + if cfg.common.memory_circuit_breaker_enable { super::check_memory_circuit_breaker(trace_id, &scan_stats)?; } @@ -412,14 +412,15 @@ async fn cache_parquet_files( files: &[FileKey], scan_stats: &ScanStats, ) -> Result<(file_data::CacheType, Vec, CachedFiles), Error> { - let cache_type = if CONFIG.memory_cache.enabled - && scan_stats.compressed_size < CONFIG.memory_cache.skip_size as i64 + let cfg = get_config(); + let cache_type = if cfg.memory_cache.enabled + && scan_stats.compressed_size < cfg.memory_cache.skip_size as i64 { // if scan_compressed_size < 80% of total memory cache, use memory cache file_data::CacheType::Memory } else if !is_local_disk_storage() - && CONFIG.disk_cache.enabled - && scan_stats.compressed_size < CONFIG.disk_cache.skip_size as i64 + && cfg.disk_cache.enabled + && scan_stats.compressed_size < cfg.disk_cache.skip_size as i64 { // if scan_compressed_size < 80% of total disk cache, use disk cache file_data::CacheType::Disk @@ -432,22 +433,23 @@ async fn cache_parquet_files( let mut disk_cached_files = 0; let mut tasks = Vec::new(); - let semaphore = std::sync::Arc::new(Semaphore::new(CONFIG.limit.query_thread_num)); + let semaphore = std::sync::Arc::new(Semaphore::new(cfg.limit.query_thread_num)); for file in files.iter() { let trace_id = trace_id.to_string(); let file_name = file.key.clone(); let permit = semaphore.clone().acquire_owned().await.unwrap(); let task: tokio::task::JoinHandle<(Option, bool, bool)> = tokio::task::spawn( async move { + let cfg = get_config(); let ret = match cache_type { file_data::CacheType::Memory => { let mut disk_exists = false; let mem_exists = file_data::memory::exist(&file_name).await; - if !mem_exists && !CONFIG.memory_cache.skip_disk_check { + if !mem_exists && !cfg.memory_cache.skip_disk_check { // when skip_disk_check = false, need to check disk cache disk_exists = file_data::disk::exist(&file_name).await; } - if !mem_exists && (CONFIG.memory_cache.skip_disk_check || !disk_exists) { + if !mem_exists && (cfg.memory_cache.skip_disk_check || !disk_exists) { ( file_data::memory::download(&trace_id, &file_name) .await diff --git a/src/service/search/grpc/wal.rs b/src/service/search/grpc/wal.rs index ee7997dec4..0b7ab9459f 100644 --- a/src/service/search/grpc/wal.rs +++ b/src/service/search/grpc/wal.rs @@ -17,6 +17,7 @@ use std::{path::Path, sync::Arc}; use arrow::array::{new_null_array, ArrayRef}; use config::{ + get_config, meta::{ search::{ScanStats, SearchType, StorageType}, stream::{FileKey, PartitionTimeLevel, StreamPartition, StreamType}, @@ -25,7 +26,6 @@ use config::{ file::scan_files, parquet::{parse_time_range_from_filename, read_metadata_from_file}, }, - CONFIG, }; use datafusion::{ arrow::{datatypes::Schema, record_batch::RecordBatch}, @@ -93,12 +93,13 @@ pub async fn search_parquet( let mut scan_stats = ScanStats::new(); let mut lock_files = files.iter().map(|f| f.key.clone()).collect::>(); - + let cfg = get_config(); // get file metadata to build file_list let files_num = files.len(); let mut new_files = Vec::with_capacity(files_num); let files_metadata = futures::stream::iter(files) .map(|file| async move { + let cfg = get_config(); let r = WAL_PARQUET_METADATA.read().await; if let Some(meta) = r.get(file.key.as_str()) { let mut file = file; @@ -106,7 +107,7 @@ pub async fn search_parquet( return file; } drop(r); - let source_file = CONFIG.common.data_wal_dir.to_string() + file.key.as_str(); + let source_file = cfg.common.data_wal_dir.to_string() + file.key.as_str(); let meta = read_metadata_from_file(&source_file.into()) .await .unwrap_or_default(); @@ -118,7 +119,7 @@ pub async fn search_parquet( .insert(file.key.clone(), file.meta.clone()); file }) - .buffer_unordered(CONFIG.limit.cpu_num) + .buffer_unordered(cfg.limit.cpu_num) .collect::>() .await; for file in files_metadata { @@ -176,7 +177,7 @@ pub async fn search_parquet( let mut files_group: HashMap> = HashMap::with_capacity(schema_versions.len()); let mut scan_stats = ScanStats::new(); - if !CONFIG.common.widening_schema_evolution || schema_versions.len() == 1 { + if !cfg.common.widening_schema_evolution || schema_versions.len() == 1 { let files = files.to_vec(); scan_stats = match file_list::calculate_files_size(&files).await { Ok(size) => size, @@ -228,7 +229,7 @@ pub async fn search_parquet( scan_stats.compressed_size ); - if CONFIG.common.memory_circuit_breaker_enable { + if cfg.common.memory_circuit_breaker_enable { if let Err(e) = super::check_memory_circuit_breaker(trace_id, &scan_stats) { // release all files wal::release_files(&lock_files).await; @@ -440,7 +441,8 @@ pub async fn search_memtable( scan_stats.original_size ); - if CONFIG.common.memory_circuit_breaker_enable { + let cfg = get_config(); + if cfg.common.memory_circuit_breaker_enable { super::check_memory_circuit_breaker(trace_id, &scan_stats)?; } @@ -683,7 +685,7 @@ async fn get_file_list( stream_type, _partition_time_level, partition_keys, - &CONFIG.common.data_wal_dir, + &get_config().common.data_wal_dir, "parquet", ) .await @@ -704,7 +706,7 @@ async fn get_file_list_arrow( stream_type, _partition_time_level, partition_keys, - &CONFIG.common.data_idx_dir, + &get_config().common.data_idx_dir, "arrow", ) .await diff --git a/src/service/search/mod.rs b/src/service/search/mod.rs index b15fd182fd..6c5ee82f62 100644 --- a/src/service/search/mod.rs +++ b/src/service/search/mod.rs @@ -17,13 +17,12 @@ use std::cmp::max; use chrono::Duration; use config::{ - ider, + get_config, ider, meta::{ search, stream::{FileKey, StreamType}, }, utils::str::find, - CONFIG, }; use infra::{ errors::{Error, ErrorCodes}, @@ -72,8 +71,9 @@ pub async fn search( user_id: Option, req: &search::Request, ) -> Result { + let cfg = get_config(); let trace_id = if trace_id.is_empty() { - if CONFIG.common.tracing_enabled || CONFIG.common.tracing_search_enabled { + if cfg.common.tracing_enabled || cfg.common.tracing_search_enabled { let ctx = tracing::Span::current().context(); ctx.span().span_context().trace_id().to_string() } else { @@ -152,6 +152,7 @@ pub async fn search_partition( stream_type: StreamType, req: &search::SearchPartitionRequest, ) -> Result { + let cfg = get_config(); let query = cluster_rpc::SearchQuery { start_time: req.start_time, end_time: req.end_time, @@ -209,16 +210,16 @@ pub async fn search_partition( compressed_size: compressed_size as usize, partitions: vec![], }; - let mut total_secs = resp.original_size / CONFIG.limit.query_group_base_speed / cpu_cores; - if total_secs * CONFIG.limit.query_group_base_speed * cpu_cores < resp.original_size { + let mut total_secs = resp.original_size / cfg.limit.query_group_base_speed / cpu_cores; + if total_secs * cfg.limit.query_group_base_speed * cpu_cores < resp.original_size { total_secs += 1; } - let mut part_num = max(1, total_secs / CONFIG.limit.query_partition_by_secs); - if part_num * CONFIG.limit.query_partition_by_secs < total_secs { + let mut part_num = max(1, total_secs / cfg.limit.query_partition_by_secs); + if part_num * cfg.limit.query_partition_by_secs < total_secs { part_num += 1; } let mut step = max( - Duration::try_seconds(CONFIG.limit.query_partition_min_secs) + Duration::try_seconds(cfg.limit.query_partition_min_secs) .unwrap() .num_microseconds() .unwrap(), @@ -269,6 +270,7 @@ pub async fn query_status() -> Result { let task = tokio::task::spawn( async move { + let cfg = get_config(); let mut request = tonic::Request::new(proto::cluster_rpc::QueryStatusRequest {}); opentelemetry::global::get_text_map_propagator(|propagator| { @@ -283,7 +285,7 @@ pub async fn query_status() -> Result { .map_err(|_| Error::Message("invalid token".to_string()))?; let channel = Channel::from_shared(node_addr) .unwrap() - .connect_timeout(std::time::Duration::from_secs(CONFIG.grpc.connect_timeout)) + .connect_timeout(std::time::Duration::from_secs(cfg.grpc.connect_timeout)) .connect() .await .map_err(|err| { @@ -298,16 +300,14 @@ pub async fn query_status() -> Result { channel, move |mut req: Request<()>| { req.metadata_mut().insert("authorization", token.clone()); - // req.metadata_mut() - // .insert(CONFIG.grpc.org_header_key.as_str(), org_id.clone()); Ok(req) }, ); client = client .send_compressed(CompressionEncoding::Gzip) .accept_compressed(CompressionEncoding::Gzip) - .max_decoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024) - .max_encoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024); + .max_decoding_message_size(cfg.grpc.max_message_size * 1024 * 1024) + .max_encoding_message_size(cfg.grpc.max_message_size * 1024 * 1024); let response = match client.query_status(request).await { Ok(res) => res.into_inner(), Err(err) => { @@ -416,9 +416,10 @@ pub async fn cancel_query(trace_id: &str) -> Result Result Result| { req.metadata_mut().insert("authorization", token.clone()); - // req.metadata_mut() - // .insert(CONFIG.grpc.org_header_key.as_str(), org_id.clone()); Ok(req) }, ); client = client .send_compressed(CompressionEncoding::Gzip) .accept_compressed(CompressionEncoding::Gzip) - .max_decoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024) - .max_encoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024); + .max_decoding_message_size(cfg.grpc.max_message_size * 1024 * 1024) + .max_encoding_message_size(cfg.grpc.max_message_size * 1024 * 1024); let response = match client.cancel_query(request).await { Ok(res) => res.into_inner(), Err(err) => { diff --git a/src/service/search/sql.rs b/src/service/search/sql.rs index 44631cca64..5359dd60cb 100644 --- a/src/service/search/sql.rs +++ b/src/service/search/sql.rs @@ -20,11 +20,12 @@ use std::{ use chrono::Duration; use config::{ + get_config, meta::{ sql::{Sql as MetaSql, SqlOperator}, stream::{FileKey, StreamPartition, StreamType}, }, - CONFIG, QUICK_MODEL_FIELDS, SQL_FULL_TEXT_SEARCH_FIELDS, + QUICK_MODEL_FIELDS, SQL_FULL_TEXT_SEARCH_FIELDS, }; use datafusion::arrow::datatypes::{DataType, Schema}; use hashbrown::HashSet; @@ -140,13 +141,14 @@ impl Sql { } }; + let cfg = get_config(); // need check some things: // 1. no where // 2. no aggregation // 3. no group by let mut fast_mode = meta.selection.is_none() && meta.group_by.is_empty() - && (meta.order_by.is_empty() || meta.order_by[0].0 == CONFIG.common.column_timestamp) + && (meta.order_by.is_empty() || meta.order_by[0].0 == cfg.common.column_timestamp) && !meta.fields.iter().any(|f| f.contains('(')) && !meta.field_alias.iter().any(|f| f.0.contains('(')) && !origin_sql.to_lowercase().contains("distinct"); @@ -232,10 +234,10 @@ impl Sql { if !sql_mode.eq(&SqlMode::Full) && meta.order_by.is_empty() && !origin_sql.contains('*') { let caps = RE_SELECT_FROM.captures(origin_sql.as_str()).unwrap(); let cap_str = caps.get(1).unwrap().as_str(); - if !cap_str.contains(&CONFIG.common.column_timestamp) { + if !cap_str.contains(&cfg.common.column_timestamp) { origin_sql = origin_sql.replace( cap_str, - &format!("{}, {}", &CONFIG.common.column_timestamp, cap_str), + &format!("{}, {}", &cfg.common.column_timestamp, cap_str), ); } } @@ -278,15 +280,15 @@ impl Sql { let time_range_sql = if time_range.0 > 0 && time_range.1 > 0 { format!( "({} >= {} AND {} < {})", - CONFIG.common.column_timestamp, + cfg.common.column_timestamp, time_range.0, - CONFIG.common.column_timestamp, + cfg.common.column_timestamp, time_range.1 ) } else if time_range.0 > 0 { - format!("{} >= {}", CONFIG.common.column_timestamp, time_range.0) + format!("{} >= {}", cfg.common.column_timestamp, time_range.0) } else if time_range.1 > 0 { - format!("{} < {}", CONFIG.common.column_timestamp, time_range.1) + format!("{} < {}", cfg.common.column_timestamp, time_range.1) } else { "".to_string() }; @@ -340,7 +342,7 @@ impl Sql { if meta.limit == 0 && sql_mode.eq(&SqlMode::Full) { // sql mode context, allow limit 0, used to no hits, but return aggs // sql mode full, disallow without limit, default limit 1000 - meta.limit = CONFIG.limit.query_full_mode_limit; + meta.limit = cfg.limit.query_full_mode_limit; } origin_sql = if meta.order_by.is_empty() && (!sql_mode.eq(&SqlMode::Full) @@ -353,8 +355,8 @@ impl Sql { .contains('('))) { let sort_by = if req_query.sort_by.is_empty() { - meta.order_by = vec![(CONFIG.common.column_timestamp.to_string(), true)]; - format!("{} DESC", CONFIG.common.column_timestamp) + meta.order_by = vec![(cfg.common.column_timestamp.to_string(), true)]; + format!("{} DESC", cfg.common.column_timestamp) } else { if req_query.sort_by.to_uppercase().ends_with(" DESC") { meta.order_by = vec![( @@ -402,11 +404,11 @@ impl Sql { // Hack for quick_mode // replace `select *` to `select f1,f2,f3` if req_query.quick_mode - && schema_fields.len() > CONFIG.limit.quick_mode_num_fields + && schema_fields.len() > cfg.limit.quick_mode_num_fields && RE_ONLY_SELECT.is_match(&origin_sql) { let stream_key = format!("{}/{}/{}", org_id, stream_type, meta.source); - let cached_fields: Option> = if CONFIG.limit.quick_mode_file_list_enabled { + let cached_fields: Option> = if cfg.limit.quick_mode_file_list_enabled { STREAM_SCHEMAS_FIELDS .read() .await @@ -784,7 +786,8 @@ pub(crate) fn generate_quick_mode_fields( cached_fields: Option>, fts_fields: &[String], ) -> Vec { - let strategy = CONFIG.limit.quick_mode_strategy.to_lowercase(); + let cfg = get_config(); + let strategy = cfg.limit.quick_mode_strategy.to_lowercase(); let schema_fields = match cached_fields { Some(v) => v, None => schema @@ -795,11 +798,11 @@ pub(crate) fn generate_quick_mode_fields( }; let mut fields = match strategy.as_str() { "last" => { - let skip = std::cmp::max(0, schema_fields.len() - CONFIG.limit.quick_mode_num_fields); + let skip = std::cmp::max(0, schema_fields.len() - cfg.limit.quick_mode_num_fields); schema_fields.into_iter().skip(skip).collect() } "both" => { - let need_num = std::cmp::min(schema_fields.len(), CONFIG.limit.quick_mode_num_fields); + let need_num = std::cmp::min(schema_fields.len(), cfg.limit.quick_mode_num_fields); let mut inner_fields = schema_fields .iter() .take(need_num / 2) @@ -815,13 +818,13 @@ pub(crate) fn generate_quick_mode_fields( // default is first mode schema_fields .into_iter() - .take(CONFIG.limit.quick_mode_num_fields) + .take(cfg.limit.quick_mode_num_fields) .collect() } }; // check _timestamp - if !fields.contains(&CONFIG.common.column_timestamp) { - fields.push(CONFIG.common.column_timestamp.to_string()); + if !fields.contains(&cfg.common.column_timestamp) { + fields.push(cfg.common.column_timestamp.to_string()); } // check fts fields for field in fts_fields { diff --git a/src/service/stream.rs b/src/service/stream.rs index baaaf37b3f..41f1cb735d 100644 --- a/src/service/stream.rs +++ b/src/service/stream.rs @@ -20,7 +20,7 @@ use config::{ is_local_disk_storage, meta::stream::{StreamSettings, StreamStats, StreamType}, utils::json, - CONFIG, SIZE_IN_MB, SQL_FULL_TEXT_SEARCH_FIELDS, + SIZE_IN_MB, SQL_FULL_TEXT_SEARCH_FIELDS, }; use datafusion::arrow::datatypes::Schema; use infra::{ @@ -354,7 +354,7 @@ pub async fn delete_fields( stream_type: Option, fields: &[String], ) -> Result<(), anyhow::Error> { - if !CONFIG.common.widening_schema_evolution { + if !config::get_config().common.widening_schema_evolution { return Err(anyhow::anyhow!( "widening schema evolution is disabled, can't delete fields" )); diff --git a/src/service/syslogs_route.rs b/src/service/syslogs_route.rs index 15981e0330..74e5d4221a 100644 --- a/src/service/syslogs_route.rs +++ b/src/service/syslogs_route.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/service/traces/mod.rs b/src/service/traces/mod.rs index d0590106b2..eab390218a 100644 --- a/src/service/traces/mod.rs +++ b/src/service/traces/mod.rs @@ -19,14 +19,14 @@ use actix_web::{http, HttpResponse}; use bytes::BytesMut; use chrono::{Duration, Utc}; use config::{ - cluster, + cluster, get_config, meta::{ stream::{PartitionTimeLevel, StreamPartition, StreamType}, usage::UsageType, }, metrics, utils::{flatten, json, schema_ext::SchemaExt}, - CONFIG, DISTINCT_FIELDS, + DISTINCT_FIELDS, }; use infra::schema::{unwrap_partition_time_level, SchemaCache}; use opentelemetry::trace::{SpanId, TraceId}; @@ -84,7 +84,9 @@ pub async fn handle_trace_request( ); } - if !db::file_list::BLOCKED_ORGS.is_empty() && db::file_list::BLOCKED_ORGS.contains(&org_id) { + if !db::file_list::BLOCKED_ORGS.is_empty() + && db::file_list::BLOCKED_ORGS.contains(&org_id.to_string()) + { return Ok(HttpResponse::Forbidden().json(MetaHttpResponse::error( http::StatusCode::FORBIDDEN.into(), format!("Quota exceeded for this organization [{}]", org_id), @@ -119,9 +121,11 @@ pub async fn handle_trace_request( ) .await; + let cfg = get_config(); + let mut partition_keys: Vec = vec![]; let mut partition_time_level = - PartitionTimeLevel::from(CONFIG.limit.traces_file_retention.as_str()); + PartitionTimeLevel::from(cfg.limit.traces_file_retention.as_str()); if stream_schema.has_partition_keys { let partition_det = crate::service::ingestion::get_stream_partition_keys( org_id, @@ -159,7 +163,7 @@ pub async fn handle_trace_request( let mut trigger: Option = None; - let min_ts = (Utc::now() - Duration::try_hours(CONFIG.limit.ingest_allowed_upto).unwrap()) + let min_ts = (Utc::now() - Duration::try_hours(cfg.limit.ingest_allowed_upto).unwrap()) .timestamp_micros(); let mut partial_success = ExportTracePartialSuccess::default(); @@ -288,7 +292,7 @@ pub async fn handle_trace_request( }; record_val.insert( - CONFIG.common.column_timestamp.clone(), + cfg.common.column_timestamp.clone(), json::Value::Number(timestamp.into()), ); diff --git a/src/service/traces/otlp_http.rs b/src/service/traces/otlp_http.rs index cdca053b02..006a8f4273 100644 --- a/src/service/traces/otlp_http.rs +++ b/src/service/traces/otlp_http.rs @@ -18,14 +18,14 @@ use std::{collections::HashMap, io::Error, sync::Arc}; use actix_web::{http, web, HttpResponse}; use chrono::{Duration, Utc}; use config::{ - cluster, + cluster, get_config, meta::{ stream::{PartitionTimeLevel, StreamPartition, StreamType}, usage::UsageType, }, metrics, utils::{flatten, json, schema_ext::SchemaExt}, - CONFIG, DISTINCT_FIELDS, + DISTINCT_FIELDS, }; use infra::schema::{unwrap_partition_time_level, SchemaCache}; use opentelemetry_proto::tonic::collector::trace::v1::ExportTraceServiceRequest; @@ -84,7 +84,9 @@ pub async fn traces_json( ); } - if !db::file_list::BLOCKED_ORGS.is_empty() && db::file_list::BLOCKED_ORGS.contains(&org_id) { + if !db::file_list::BLOCKED_ORGS.is_empty() + && db::file_list::BLOCKED_ORGS.contains(&org_id.to_string()) + { return Ok(HttpResponse::Forbidden().json(MetaHttpResponse::error( http::StatusCode::FORBIDDEN.into(), format!("Quota exceeded for this organization [{}]", org_id), @@ -106,7 +108,8 @@ pub async fn traces_json( let mut stream_alerts_map: HashMap> = HashMap::new(); let mut distinct_values = Vec::with_capacity(16); - let min_ts = (Utc::now() - Duration::try_hours(CONFIG.limit.ingest_allowed_upto).unwrap()) + let cfg = get_config(); + let min_ts = (Utc::now() - Duration::try_hours(cfg.limit.ingest_allowed_upto).unwrap()) .timestamp_micros(); let mut partial_success = ExportTracePartialSuccess::default(); let mut data_buf: HashMap = HashMap::new(); @@ -126,7 +129,7 @@ pub async fn traces_json( let mut partition_keys: Vec = vec![]; let mut partition_time_level = - PartitionTimeLevel::from(CONFIG.limit.traces_file_retention.as_str()); + PartitionTimeLevel::from(cfg.limit.traces_file_retention.as_str()); if stream_schema.has_partition_keys { let partition_det = crate::service::ingestion::get_stream_partition_keys( org_id, @@ -344,7 +347,7 @@ pub async fn traces_json( }; record_val.insert( - CONFIG.common.column_timestamp.clone(), + cfg.common.column_timestamp.clone(), json::Value::Number(timestamp.into()), ); diff --git a/src/service/usage/ingestion_service.rs b/src/service/usage/ingestion_service.rs index c76e2dc6e0..8587945053 100644 --- a/src/service/usage/ingestion_service.rs +++ b/src/service/usage/ingestion_service.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -14,10 +14,14 @@ // along with this program. If not, see . use anyhow::Error; -use config::CONFIG; use proto::cluster_rpc; use rand::{rngs::StdRng, seq::SliceRandom, SeedableRng}; -use tonic::{codec::CompressionEncoding, metadata::MetadataValue, transport::Channel, Request}; +use tonic::{ + codec::CompressionEncoding, + metadata::{MetadataKey, MetadataValue}, + transport::Channel, + Request, +}; use crate::common::infra::cluster; @@ -25,6 +29,7 @@ pub async fn ingest( dest_org_id: &str, req: cluster_rpc::UsageRequest, ) -> Result { + let cfg = config::get_config(); let mut nodes = cluster::get_cached_online_ingester_nodes().await.unwrap(); nodes.sort_by_key(|x| x.id); @@ -47,12 +52,17 @@ pub async fn ingest( let node = node.unwrap(); let node_addr = node.grpc_addr.clone(); + let org_header_key: MetadataKey<_> = cfg + .grpc + .org_header_key + .parse() + .map_err(|_| Error::msg("invalid org_header_key".to_string()))?; let token: MetadataValue<_> = cluster::get_internal_grpc_token() .parse() .map_err(|_| Error::msg("invalid token".to_string()))?; let channel = Channel::from_shared(node_addr) .unwrap() - .connect_timeout(std::time::Duration::from_secs(CONFIG.grpc.connect_timeout)) + .connect_timeout(std::time::Duration::from_secs(cfg.grpc.connect_timeout)) .connect() .await .map_err(|err| { @@ -67,18 +77,16 @@ pub async fn ingest( channel, move |mut req: Request<()>| { req.metadata_mut().insert("authorization", token.clone()); - req.metadata_mut().insert( - CONFIG.grpc.org_header_key.as_str(), - dest_org_id.parse().unwrap(), - ); + req.metadata_mut() + .insert(org_header_key.clone(), dest_org_id.parse().unwrap()); Ok(req) }, ); client = client .send_compressed(CompressionEncoding::Gzip) .accept_compressed(CompressionEncoding::Gzip) - .max_decoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024) - .max_encoding_message_size(CONFIG.grpc.max_message_size * 1024 * 1024); + .max_decoding_message_size(cfg.grpc.max_message_size * 1024 * 1024) + .max_encoding_message_size(cfg.grpc.max_message_size * 1024 * 1024); let res: cluster_rpc::UsageResponse = match client.report_usage(req).await { Ok(res) => res.into_inner(), Err(err) => { diff --git a/src/service/usage/mod.rs b/src/service/usage/mod.rs index bb6d1d6b47..15bb1904b3 100644 --- a/src/service/usage/mod.rs +++ b/src/service/usage/mod.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -17,6 +17,7 @@ use std::sync::Arc; use chrono::{Datelike, Timelike, Utc}; use config::{ + get_config, meta::{ stream::StreamType, usage::{ @@ -26,7 +27,7 @@ use config::{ }, metrics, utils::json, - CONFIG, SIZE_IN_MB, + SIZE_IN_MB, }; use hashbrown::HashMap; #[cfg(feature = "enterprise")] @@ -60,7 +61,7 @@ pub async fn report_request_usage_stats( .inc_by((stats.size * SIZE_IN_MB) as u64); let event: UsageEvent = usage_type.into(); - if !CONFIG.common.usage_enabled { + if !get_config().common.usage_enabled { return; } @@ -135,7 +136,7 @@ pub async fn report_request_usage_stats( pub async fn publish_usage(mut usage: Vec) { let mut usages = USAGE_DATA.write().await; usages.append(&mut usage); - if usages.len() < CONFIG.common.usage_batch_size { + if usages.len() < get_config().common.usage_batch_size { return; } @@ -147,13 +148,14 @@ pub async fn publish_usage(mut usage: Vec) { } pub async fn publish_triggers_usage(trigger: TriggerData) { - if !CONFIG.common.usage_enabled { + let cfg = get_config(); + if !cfg.common.usage_enabled { return; } let mut usages = TRIGGERS_USAGE_DATA.write().await; usages.push(trigger); - if usages.len() < CONFIG.common.usage_batch_size { + if usages.len() < cfg.common.usage_batch_size { return; } @@ -176,7 +178,7 @@ pub async fn flush() { } async fn flush_usage() { - if !CONFIG.common.usage_enabled { + if !get_config().common.usage_enabled { return; } @@ -193,7 +195,7 @@ async fn flush_usage() { } async fn flush_triggers_usage() { - if !CONFIG.common.usage_enabled { + if !get_config().common.usage_enabled { return; } @@ -254,16 +256,16 @@ async fn ingest_usages(curr_usages: Vec) { // Push all the search events report_data.append(&mut search_events); - - if &CONFIG.common.usage_reporting_mode != "local" - && !CONFIG.common.usage_reporting_url.is_empty() - && !CONFIG.common.usage_reporting_creds.is_empty() + let cfg = get_config(); + if &cfg.common.usage_reporting_mode != "local" + && !cfg.common.usage_reporting_url.is_empty() + && !cfg.common.usage_reporting_creds.is_empty() { - let url = url::Url::parse(&CONFIG.common.usage_reporting_url).unwrap(); - let creds = if CONFIG.common.usage_reporting_creds.starts_with("Basic") { - CONFIG.common.usage_reporting_creds.to_string() + let url = url::Url::parse(&cfg.common.usage_reporting_url).unwrap(); + let creds = if cfg.common.usage_reporting_creds.starts_with("Basic") { + cfg.common.usage_reporting_creds.to_string() } else { - format!("Basic {}", &CONFIG.common.usage_reporting_creds) + format!("Basic {}", &cfg.common.usage_reporting_creds) }; if let Err(e) = Client::builder() .build() @@ -276,7 +278,7 @@ async fn ingest_usages(curr_usages: Vec) { .await { log::error!("Error in ingesting usage data to external URL {:?}", e); - if &CONFIG.common.usage_reporting_mode != "both" { + if &cfg.common.usage_reporting_mode != "both" { // on error in ingesting usage data, push back the data let mut usages = USAGE_DATA.write().await; let mut curr_usages = curr_usages.clone(); @@ -286,7 +288,7 @@ async fn ingest_usages(curr_usages: Vec) { } } - if &CONFIG.common.usage_reporting_mode != "remote" { + if &cfg.common.usage_reporting_mode != "remote" { let report_data = report_data .iter_mut() .map(|usage| json::to_value(usage).unwrap()) @@ -296,7 +298,7 @@ async fn ingest_usages(curr_usages: Vec) { stream_name: USAGE_STREAM.to_owned(), data: Some(cluster_rpc::UsageData::from(report_data)), }; - if let Err(e) = ingestion_service::ingest(&CONFIG.common.usage_org, req).await { + if let Err(e) = ingestion_service::ingest(&cfg.common.usage_org, req).await { log::error!("Error in ingesting usage data {:?}", e); // on error in ingesting usage data, push back the data let mut usages = USAGE_DATA.write().await; @@ -318,7 +320,7 @@ async fn ingest_trigger_usages(curr_usages: Vec) { stream_name: TRIGGERS_USAGE_STREAM.to_owned(), data: Some(cluster_rpc::UsageData::from(json_triggers)), }; - if let Err(e) = ingestion_service::ingest(&CONFIG.common.usage_org, req).await { + if let Err(e) = ingestion_service::ingest(&get_config().common.usage_org, req).await { log::error!("Error in ingesting triggers usage data {:?}", e); // on error in ingesting usage data, push back the data let mut usages = TRIGGERS_USAGE_DATA.write().await; @@ -342,5 +344,5 @@ pub async fn flush_audit() { async fn publish_audit( req: cluster_rpc::UsageRequest, ) -> Result { - ingestion_service::ingest(&CONFIG.common.usage_org, req).await + ingestion_service::ingest(&get_config().common.usage_org, req).await } diff --git a/src/service/usage/stats.rs b/src/service/usage/stats.rs index 3f7969c54c..80779eedc5 100644 --- a/src/service/usage/stats.rs +++ b/src/service/usage/stats.rs @@ -17,12 +17,12 @@ use std::{collections::HashMap, sync::Arc}; use config::{ cluster::LOCAL_NODE_UUID, + get_config, meta::{ stream::StreamType, usage::{Stats, UsageEvent, STATS_STREAM, USAGE_STREAM}, }, utils::json, - CONFIG, }; use infra::dist_lock; use once_cell::sync::Lazy; @@ -38,8 +38,9 @@ use crate::{ pub static CLIENT: Lazy> = Lazy::new(|| Arc::new(Client::new())); pub async fn publish_stats() -> Result<(), anyhow::Error> { + let cfg = get_config(); let mut orgs = db::schema::list_organizations_from_cache().await; - orgs.retain(|org: &String| org != &CONFIG.common.usage_org); + orgs.retain(|org: &String| org != &cfg.common.usage_org); for org_id in orgs { // get the working node for the organization @@ -94,9 +95,7 @@ pub async fn publish_stats() -> Result<(), anyhow::Error> { timeout: 0, }; // do search - match SearchService::search("", &CONFIG.common.usage_org, StreamType::Logs, None, &req) - .await - { + match SearchService::search("", &cfg.common.usage_org, StreamType::Logs, None, &req).await { Ok(res) => { if !res.hits.is_empty() { match report_stats(res.hits, &org_id, last_query_ts, current_ts).await { @@ -153,7 +152,15 @@ async fn get_last_stats( clusters: vec![], timeout: 0, }; - match SearchService::search("", &CONFIG.common.usage_org, StreamType::Logs, None, &req).await { + match SearchService::search( + "", + &get_config().common.usage_org, + StreamType::Logs, + None, + &req, + ) + .await + { Ok(res) => Ok(res.hits), Err(err) => match &err { infra::errors::Error::ErrorCode(infra::errors::ErrorCodes::SearchStreamNotFound(_)) => { @@ -217,7 +224,7 @@ async fn report_stats( data: Some(cluster_rpc::UsageData::from(report_data)), }; - match ingestion_service::ingest(&CONFIG.common.usage_org, req).await { + match ingestion_service::ingest(&get_config().common.usage_org, req).await { Ok(_) => Ok(()), Err(err) => Err(err), } diff --git a/src/service/users.rs b/src/service/users.rs index e3c68d98c2..53869f22c3 100644 --- a/src/service/users.rs +++ b/src/service/users.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/wal/benches/write.rs b/src/wal/benches/write.rs index e726cccd1f..9ec5ae4c77 100644 --- a/src/wal/benches/write.rs +++ b/src/wal/benches/write.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/wal/src/errors.rs b/src/wal/src/errors.rs index aa16ae0c9f..140f00b646 100644 --- a/src/wal/src/errors.rs +++ b/src/wal/src/errors.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/wal/src/lib.rs b/src/wal/src/lib.rs index 20a3c202e4..739ce2839d 100644 --- a/src/wal/src/lib.rs +++ b/src/wal/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/wal/src/reader.rs b/src/wal/src/reader.rs index 30f2119c95..9a6e04775d 100644 --- a/src/wal/src/reader.rs +++ b/src/wal/src/reader.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/wal/src/writer.rs b/src/wal/src/writer.rs index db45d4c540..dafd394334 100644 --- a/src/wal/src/writer.rs +++ b/src/wal/src/writer.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/src/wal/tests/wal.rs b/src/wal/tests/wal.rs index a66205538a..5e95be797b 100644 --- a/src/wal/tests/wal.rs +++ b/src/wal/tests/wal.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by diff --git a/tests/integration_test.rs b/tests/integration_test.rs index dbf1ce44dc..e431132e79 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -1,4 +1,4 @@ -// Copyright 2023 Zinc Labs Inc. +// Copyright 2024 Zinc Labs Inc. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by @@ -21,7 +21,7 @@ mod tests { use actix_web::{http::header::ContentType, test, web, App}; use bytes::{Bytes, BytesMut}; use chrono::Utc; - use config::{utils::json, CONFIG}; + use config::{get_config, utils::json}; use openobserve::{ common::meta::dashboards::{v1, Dashboard, Dashboards}, handler::http::router::*, @@ -42,7 +42,9 @@ mod tests { env::set_var("ZO_JSON_LIMIT", "209715200"); env::set_var("ZO_TIME_STAMP_COL", "_timestamp"); - env_logger::init_from_env(env_logger::Env::new().default_filter_or(&CONFIG.log.level)); + env_logger::init_from_env( + env_logger::Env::new().default_filter_or(&get_config().log.level), + ); log::info!("setup Invoked"); }); @@ -180,8 +182,10 @@ mod tests { let thread_id: usize = 0; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .app_data(web::Data::new(thread_id)) .configure(get_service_routes) .configure(get_basic_routes), @@ -203,8 +207,10 @@ mod tests { let thread_id: usize = 0; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .app_data(web::Data::new(thread_id)) .configure(get_service_routes) .configure(get_basic_routes), @@ -226,8 +232,10 @@ mod tests { let thread_id: usize = 0; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .app_data(web::Data::new(thread_id)) .configure(get_service_routes) .configure(get_basic_routes), @@ -247,8 +255,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -268,8 +278,10 @@ mod tests { thread::sleep(one_sec); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -294,8 +306,10 @@ mod tests { let thread_id: usize = 0; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .app_data(web::Data::new(thread_id)) .configure(get_service_routes) .configure(get_basic_routes), @@ -318,8 +332,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -337,8 +353,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -361,8 +379,10 @@ mod tests { }"#; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -384,8 +404,10 @@ mod tests { }"#; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -407,8 +429,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -426,8 +450,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -448,8 +474,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -467,8 +495,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -495,8 +525,10 @@ mod tests { }"#; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -517,8 +549,10 @@ mod tests { let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -541,8 +575,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -560,8 +596,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -579,8 +617,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -599,8 +639,10 @@ mod tests { let body_str = ""; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -623,8 +665,10 @@ mod tests { }"#; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -646,8 +690,10 @@ mod tests { }"#; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -670,8 +716,10 @@ mod tests { }"#; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -695,8 +743,10 @@ mod tests { }"#; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -716,8 +766,10 @@ mod tests { let body_str = r#"{}"#; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -739,8 +791,10 @@ mod tests { }"#; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -759,8 +813,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -779,8 +835,10 @@ mod tests { let body_str = r##"{"title":"b2","dashboardId":"","description":"desc2","role":"","owner":"root@example.com","created":"2023-03-30T07:49:41.744+00:00","panels":[{"id":"Panel_ID7857010","type":"bar","fields":{"stream":"default","stream_type":"logs","x":[{"label":"Timestamp","alias":"x_axis_1","column":"_timestamp","color":null,"aggregationFunction":"histogram"}],"y":[{"label":"Kubernetes Host","alias":"y_axis_1","column":"kubernetes_host","color":"#5960b2","aggregationFunction":"count"}],"filter":[{"type":"condition","values":[],"column":"method","operator":"Is Not Null","value":null}]},"config":{"title":"p5","description":"sample config blah blah blah","show_legends":true},"query":"SELECT histogram(_timestamp) as \"x_axis_1\", count(kubernetes_host) as \"y_axis_1\" FROM \"default\" WHERE method IS NOT NULL GROUP BY \"x_axis_1\" ORDER BY \"x_axis_1\"","customQuery":false}],"layouts":[{"x":0,"y":0,"w":12,"h":13,"i":1,"panelId":"Panel_ID7857010","static":false}]}"##; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -800,8 +858,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -820,8 +880,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -844,8 +906,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -864,8 +928,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -888,8 +954,10 @@ mod tests { let thread_id: usize = 0; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .app_data(web::Data::new(thread_id)) .configure(get_service_routes) .configure(get_basic_routes), @@ -970,8 +1038,10 @@ mod tests { let thread_id: usize = 0; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .app_data(web::Data::new(thread_id)) .configure(get_service_routes) .configure(get_basic_routes), @@ -993,8 +1063,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1014,8 +1086,10 @@ mod tests { let body_str = r#"{"name":"slackTemplate","body":"{\"text\":\"For stream {stream_name} of organization {org_name} alert {alert_name} of type {alert_type} is active app_name {app_name}\"}"}"#; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1034,8 +1108,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1056,8 +1132,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1078,8 +1156,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1106,8 +1186,10 @@ mod tests { }"#; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1126,8 +1208,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1145,8 +1229,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1165,8 +1251,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1206,8 +1294,10 @@ mod tests { }"#; let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1226,8 +1316,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1249,8 +1341,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1272,8 +1366,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1291,8 +1387,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1310,8 +1408,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1329,8 +1429,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_config_routes) .configure(get_service_routes) .configure(get_basic_routes), @@ -1359,8 +1461,10 @@ mod tests { let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), ) @@ -1379,8 +1483,10 @@ mod tests { let auth = setup(); let app = test::init_service( App::new() - .app_data(web::JsonConfig::default().limit(CONFIG.limit.req_json_limit)) - .app_data(web::PayloadConfig::new(CONFIG.limit.req_payload_limit)) + .app_data(web::JsonConfig::default().limit(get_config().limit.req_json_limit)) + .app_data(web::PayloadConfig::new( + get_config().limit.req_payload_limit, + )) .configure(get_service_routes) .configure(get_basic_routes), )