mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-04 04:17:44 +00:00
c5df1f92c2
* improve code for notify * improve code for logger and fix typo (#272) * Add GNU to build.yml (#275) * fix unzip error * fix url change error fix url change error * Simplify user experience and integrate console and endpoint Simplify user experience and integrate console and endpoint * Add gnu to build.yml * upgrade version * feat: add `cargo clippy --fix --allow-dirty` to pre-commit command (#282) Resolves #277 - Add --fix flag to automatically fix clippy warnings - Add --allow-dirty flag to run on dirty Git trees - Improves code quality in pre-commit workflow * fix: the issue where preview fails when the path length exceeds 255 characters (#280) * fix * fix: improve Windows build support and CI/CD workflow (#283) - Fix Windows zip command issue by using PowerShell Compress-Archive - Add Windows support for OSS upload with ossutil - Replace Chinese comments with English in build.yml - Fix bash syntax error in package_zip function - Improve code formatting and consistency - Update various configuration files for better cross-platform support Resolves Windows build failures in GitHub Actions. * fix: update link in README.md leading to a 404 error (#285) * add rustfs.spec for rustfs (#103) add support on loongarch64 * improve cargo.lock * build(deps): bump the dependencies group with 5 updates (#289) Bumps the dependencies group with 5 updates: | Package | From | To | | --- | --- | --- | | [hyper-util](https://github.com/hyperium/hyper-util) | `0.1.15` | `0.1.16` | | [rand](https://github.com/rust-random/rand) | `0.9.1` | `0.9.2` | | [serde_json](https://github.com/serde-rs/json) | `1.0.140` | `1.0.141` | | [strum](https://github.com/Peternator7/strum) | `0.27.1` | `0.27.2` | | [sysinfo](https://github.com/GuillaumeGomez/sysinfo) | `0.36.0` | `0.36.1` | Updates `hyper-util` from 0.1.15 to 0.1.16 - [Release notes](https://github.com/hyperium/hyper-util/releases) - [Changelog](https://github.com/hyperium/hyper-util/blob/master/CHANGELOG.md) - [Commits](https://github.com/hyperium/hyper-util/compare/v0.1.15...v0.1.16) Updates `rand` from 0.9.1 to 0.9.2 - [Release notes](https://github.com/rust-random/rand/releases) - [Changelog](https://github.com/rust-random/rand/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-random/rand/compare/rand_core-0.9.1...rand_core-0.9.2) Updates `serde_json` from 1.0.140 to 1.0.141 - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.140...v1.0.141) Updates `strum` from 0.27.1 to 0.27.2 - [Release notes](https://github.com/Peternator7/strum/releases) - [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md) - [Commits](https://github.com/Peternator7/strum/compare/v0.27.1...v0.27.2) Updates `sysinfo` from 0.36.0 to 0.36.1 - [Changelog](https://github.com/GuillaumeGomez/sysinfo/blob/master/CHANGELOG.md) - [Commits](https://github.com/GuillaumeGomez/sysinfo/compare/v0.36.0...v0.36.1) --- updated-dependencies: - dependency-name: hyper-util dependency-version: 0.1.16 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dependencies - dependency-name: rand dependency-version: 0.9.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dependencies - dependency-name: serde_json dependency-version: 1.0.141 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dependencies - dependency-name: strum dependency-version: 0.27.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dependencies - dependency-name: sysinfo dependency-version: 0.36.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * improve code for logger * improve * upgrade * refactor: 优化构建工作流,统一 latest 文件处理和简化制品上传 (#293) * Refactor: DatabaseManagerSystem as global Signed-off-by: junxiang Mu <1948535941@qq.com> * fix: fmt Signed-off-by: junxiang Mu <1948535941@qq.com> * Test: add e2e_test for s3select Signed-off-by: junxiang Mu <1948535941@qq.com> * Test: add test script for e2e Signed-off-by: junxiang Mu <1948535941@qq.com> * improve code for registry and intergation * improve code for registry `create_targets_from_config` * fix * Feature up/ilm (#305) * fix * fix * fix * fix delete-marker expiration. add api_restore. * fix * time retry object upload * lock file * make fmt * fix * restore object * fix * fix * serde-rs-xml -> quick-xml * fix * checksum * fix * fix * fix * fix * fix * fix * fix * transfer lang to english * upgrade clap version from 4.5.41 to 4.5.42 * refactor: replace `lazy_static` with `LazyLock` * add router * fix: modify comment * improve code * fix typos * fix * fix: modify name and fmt * improve code for registry * fix test --------- Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: junxiang Mu <1948535941@qq.com> Co-authored-by: loverustfs <155562731+loverustfs@users.noreply.github.com> Co-authored-by: 安正超 <anzhengchao@gmail.com> Co-authored-by: shiro.lee <69624924+shiroleeee@users.noreply.github.com> Co-authored-by: Marco Orlandin <mipnamic@mipnamic.net> Co-authored-by: zhangwenlong <zhangwenlong@loongson.cn> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: junxiang Mu <1948535941@qq.com> Co-authored-by: likewu <likewu@126.com>
352 lines
13 KiB
Rust
352 lines
13 KiB
Rust
// Copyright 2024 RustFS Team
|
||
//
|
||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
// you may not use this file except in compliance with the License.
|
||
// You may obtain a copy of the License at
|
||
//
|
||
// http://www.apache.org/licenses/LICENSE-2.0
|
||
//
|
||
// Unless required by applicable law or agreed to in writing, software
|
||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
// See the License for the specific language governing permissions and
|
||
// limitations under the License.
|
||
|
||
use rustfs_config::observability::{
|
||
DEFAULT_AUDIT_LOGGER_QUEUE_CAPACITY, DEFAULT_SINKS_FILE_BUFFER_SIZE, DEFAULT_SINKS_FILE_FLUSH_INTERVAL_MS,
|
||
DEFAULT_SINKS_FILE_FLUSH_THRESHOLD, DEFAULT_SINKS_KAFKA_BATCH_SIZE, DEFAULT_SINKS_KAFKA_BATCH_TIMEOUT_MS,
|
||
DEFAULT_SINKS_KAFKA_BROKERS, DEFAULT_SINKS_KAFKA_TOPIC, DEFAULT_SINKS_WEBHOOK_AUTH_TOKEN, DEFAULT_SINKS_WEBHOOK_ENDPOINT,
|
||
DEFAULT_SINKS_WEBHOOK_MAX_RETRIES, DEFAULT_SINKS_WEBHOOK_RETRY_DELAY_MS, ENV_AUDIT_LOGGER_QUEUE_CAPACITY, ENV_OBS_ENDPOINT,
|
||
ENV_OBS_ENVIRONMENT, ENV_OBS_LOCAL_LOGGING_ENABLED, ENV_OBS_LOG_FILENAME, ENV_OBS_LOG_KEEP_FILES,
|
||
ENV_OBS_LOG_ROTATION_SIZE_MB, ENV_OBS_LOG_ROTATION_TIME, ENV_OBS_LOGGER_LEVEL, ENV_OBS_METER_INTERVAL, ENV_OBS_SAMPLE_RATIO,
|
||
ENV_OBS_SERVICE_NAME, ENV_OBS_SERVICE_VERSION, ENV_SINKS_FILE_BUFFER_SIZE, ENV_SINKS_FILE_FLUSH_INTERVAL_MS,
|
||
ENV_SINKS_FILE_FLUSH_THRESHOLD, ENV_SINKS_FILE_PATH, ENV_SINKS_KAFKA_BATCH_SIZE, ENV_SINKS_KAFKA_BATCH_TIMEOUT_MS,
|
||
ENV_SINKS_KAFKA_BROKERS, ENV_SINKS_KAFKA_TOPIC, ENV_SINKS_WEBHOOK_AUTH_TOKEN, ENV_SINKS_WEBHOOK_ENDPOINT,
|
||
ENV_SINKS_WEBHOOK_MAX_RETRIES, ENV_SINKS_WEBHOOK_RETRY_DELAY_MS,
|
||
};
|
||
use rustfs_config::observability::{ENV_OBS_LOG_DIRECTORY, ENV_OBS_USE_STDOUT};
|
||
use rustfs_config::{
|
||
APP_NAME, DEFAULT_LOG_KEEP_FILES, DEFAULT_LOG_LEVEL, DEFAULT_LOG_ROTATION_SIZE_MB, DEFAULT_LOG_ROTATION_TIME,
|
||
DEFAULT_OBS_LOG_FILENAME, ENVIRONMENT, METER_INTERVAL, SAMPLE_RATIO, SERVICE_VERSION, USE_STDOUT,
|
||
};
|
||
use rustfs_utils::dirs::get_log_directory_to_string;
|
||
use serde::{Deserialize, Serialize};
|
||
use std::env;
|
||
|
||
/// OpenTelemetry Configuration
|
||
/// Add service name, service version, environment
|
||
/// Add interval time for metric collection
|
||
/// Add sample ratio for trace sampling
|
||
/// Add endpoint for metric collection
|
||
/// Add use_stdout for output to stdout
|
||
/// Add logger level for log level
|
||
/// Add local_logging_enabled for local logging enabled
|
||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||
pub struct OtelConfig {
|
||
pub endpoint: String, // Endpoint for metric collection
|
||
pub use_stdout: Option<bool>, // Output to stdout
|
||
pub sample_ratio: Option<f64>, // Trace sampling ratio
|
||
pub meter_interval: Option<u64>, // Metric collection interval
|
||
pub service_name: Option<String>, // Service name
|
||
pub service_version: Option<String>, // Service version
|
||
pub environment: Option<String>, // Environment
|
||
pub logger_level: Option<String>, // Logger level
|
||
pub local_logging_enabled: Option<bool>, // Local logging enabled
|
||
// Added flexi_logger related configurations
|
||
pub log_directory: Option<String>, // LOG FILE DIRECTORY
|
||
pub log_filename: Option<String>, // The name of the log file
|
||
pub log_rotation_size_mb: Option<u64>, // Log file size cut threshold (MB)
|
||
pub log_rotation_time: Option<String>, // Logs are cut by time (Hour, Day,Minute, Second)
|
||
pub log_keep_files: Option<u16>, // Number of log files to be retained
|
||
}
|
||
|
||
impl OtelConfig {
|
||
/// Helper function: Extract observable configuration from environment variables
|
||
pub fn extract_otel_config_from_env(endpoint: Option<String>) -> OtelConfig {
|
||
let endpoint = if let Some(endpoint) = endpoint {
|
||
if endpoint.is_empty() {
|
||
env::var(ENV_OBS_ENDPOINT).unwrap_or_else(|_| "".to_string())
|
||
} else {
|
||
endpoint
|
||
}
|
||
} else {
|
||
env::var(ENV_OBS_ENDPOINT).unwrap_or_else(|_| "".to_string())
|
||
};
|
||
let mut use_stdout = env::var(ENV_OBS_USE_STDOUT)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(USE_STDOUT));
|
||
if endpoint.is_empty() {
|
||
use_stdout = Some(true);
|
||
}
|
||
|
||
OtelConfig {
|
||
endpoint,
|
||
use_stdout,
|
||
sample_ratio: env::var(ENV_OBS_SAMPLE_RATIO)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(SAMPLE_RATIO)),
|
||
meter_interval: env::var(ENV_OBS_METER_INTERVAL)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(METER_INTERVAL)),
|
||
service_name: env::var(ENV_OBS_SERVICE_NAME)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(APP_NAME.to_string())),
|
||
service_version: env::var(ENV_OBS_SERVICE_VERSION)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(SERVICE_VERSION.to_string())),
|
||
environment: env::var(ENV_OBS_ENVIRONMENT)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(ENVIRONMENT.to_string())),
|
||
logger_level: env::var(ENV_OBS_LOGGER_LEVEL)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(DEFAULT_LOG_LEVEL.to_string())),
|
||
local_logging_enabled: env::var(ENV_OBS_LOCAL_LOGGING_ENABLED)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(false)),
|
||
log_directory: Some(get_log_directory_to_string(ENV_OBS_LOG_DIRECTORY)),
|
||
log_filename: env::var(ENV_OBS_LOG_FILENAME)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(DEFAULT_OBS_LOG_FILENAME.to_string())),
|
||
log_rotation_size_mb: env::var(ENV_OBS_LOG_ROTATION_SIZE_MB)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(DEFAULT_LOG_ROTATION_SIZE_MB)), // Default to 100 MB
|
||
log_rotation_time: env::var(ENV_OBS_LOG_ROTATION_TIME)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(DEFAULT_LOG_ROTATION_TIME.to_string())), // Default to "Day"
|
||
log_keep_files: env::var(ENV_OBS_LOG_KEEP_FILES)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(DEFAULT_LOG_KEEP_FILES)), // Default to keeping 30 log files
|
||
}
|
||
}
|
||
|
||
/// Create a new instance of OtelConfig with default values
|
||
///
|
||
/// # Returns
|
||
/// A new instance of OtelConfig
|
||
pub fn new() -> Self {
|
||
Self::extract_otel_config_from_env(None)
|
||
}
|
||
}
|
||
|
||
impl Default for OtelConfig {
|
||
fn default() -> Self {
|
||
Self::new()
|
||
}
|
||
}
|
||
|
||
/// Kafka Sink Configuration - Add batch parameters
|
||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||
pub struct KafkaSinkConfig {
|
||
pub brokers: String,
|
||
pub topic: String,
|
||
pub batch_size: Option<usize>, // Batch size, default 100
|
||
pub batch_timeout_ms: Option<u64>, // Batch timeout time, default 1000ms
|
||
}
|
||
|
||
impl KafkaSinkConfig {
|
||
pub fn new() -> Self {
|
||
Self::default()
|
||
}
|
||
}
|
||
|
||
impl Default for KafkaSinkConfig {
|
||
fn default() -> Self {
|
||
Self {
|
||
brokers: env::var(ENV_SINKS_KAFKA_BROKERS)
|
||
.ok()
|
||
.filter(|s| !s.trim().is_empty())
|
||
.unwrap_or_else(|| DEFAULT_SINKS_KAFKA_BROKERS.to_string()),
|
||
topic: env::var(ENV_SINKS_KAFKA_TOPIC)
|
||
.ok()
|
||
.filter(|s| !s.trim().is_empty())
|
||
.unwrap_or_else(|| DEFAULT_SINKS_KAFKA_TOPIC.to_string()),
|
||
batch_size: env::var(ENV_SINKS_KAFKA_BATCH_SIZE)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(DEFAULT_SINKS_KAFKA_BATCH_SIZE)),
|
||
batch_timeout_ms: env::var(ENV_SINKS_KAFKA_BATCH_TIMEOUT_MS)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(DEFAULT_SINKS_KAFKA_BATCH_TIMEOUT_MS)),
|
||
}
|
||
}
|
||
}
|
||
|
||
/// Webhook Sink Configuration - Add Retry Parameters
|
||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||
pub struct WebhookSinkConfig {
|
||
pub endpoint: String,
|
||
pub auth_token: String,
|
||
pub max_retries: Option<usize>, // Maximum number of retry times, default 3
|
||
pub retry_delay_ms: Option<u64>, // Retry the delay cardinality, default 100ms
|
||
}
|
||
|
||
impl WebhookSinkConfig {
|
||
pub fn new() -> Self {
|
||
Self::default()
|
||
}
|
||
}
|
||
|
||
impl Default for WebhookSinkConfig {
|
||
fn default() -> Self {
|
||
Self {
|
||
endpoint: env::var(ENV_SINKS_WEBHOOK_ENDPOINT)
|
||
.ok()
|
||
.filter(|s| !s.trim().is_empty())
|
||
.unwrap_or_else(|| DEFAULT_SINKS_WEBHOOK_ENDPOINT.to_string()),
|
||
auth_token: env::var(ENV_SINKS_WEBHOOK_AUTH_TOKEN)
|
||
.ok()
|
||
.filter(|s| !s.trim().is_empty())
|
||
.unwrap_or_else(|| DEFAULT_SINKS_WEBHOOK_AUTH_TOKEN.to_string()),
|
||
max_retries: env::var(ENV_SINKS_WEBHOOK_MAX_RETRIES)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(DEFAULT_SINKS_WEBHOOK_MAX_RETRIES)),
|
||
retry_delay_ms: env::var(ENV_SINKS_WEBHOOK_RETRY_DELAY_MS)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(DEFAULT_SINKS_WEBHOOK_RETRY_DELAY_MS)),
|
||
}
|
||
}
|
||
}
|
||
|
||
/// File Sink Configuration - Add buffering parameters
|
||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||
pub struct FileSinkConfig {
|
||
pub path: String,
|
||
pub buffer_size: Option<usize>, // Write buffer size, default 8192
|
||
pub flush_interval_ms: Option<u64>, // Refresh interval time, default 1000ms
|
||
pub flush_threshold: Option<usize>, // Refresh threshold, default 100 logs
|
||
}
|
||
|
||
impl FileSinkConfig {
|
||
pub fn new() -> Self {
|
||
Self::default()
|
||
}
|
||
}
|
||
|
||
impl Default for FileSinkConfig {
|
||
fn default() -> Self {
|
||
Self {
|
||
path: get_log_directory_to_string(ENV_SINKS_FILE_PATH),
|
||
buffer_size: env::var(ENV_SINKS_FILE_BUFFER_SIZE)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(DEFAULT_SINKS_FILE_BUFFER_SIZE)),
|
||
flush_interval_ms: env::var(ENV_SINKS_FILE_FLUSH_INTERVAL_MS)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(DEFAULT_SINKS_FILE_FLUSH_INTERVAL_MS)),
|
||
flush_threshold: env::var(ENV_SINKS_FILE_FLUSH_THRESHOLD)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(DEFAULT_SINKS_FILE_FLUSH_THRESHOLD)),
|
||
}
|
||
}
|
||
}
|
||
|
||
/// Sink configuration collection
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
#[serde(tag = "type")]
|
||
pub enum SinkConfig {
|
||
File(FileSinkConfig),
|
||
Kafka(KafkaSinkConfig),
|
||
Webhook(WebhookSinkConfig),
|
||
}
|
||
|
||
impl SinkConfig {
|
||
pub fn new() -> Self {
|
||
Self::File(FileSinkConfig::new())
|
||
}
|
||
}
|
||
|
||
impl Default for SinkConfig {
|
||
fn default() -> Self {
|
||
Self::new()
|
||
}
|
||
}
|
||
|
||
///Logger Configuration
|
||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||
pub struct LoggerConfig {
|
||
pub queue_capacity: Option<usize>,
|
||
}
|
||
|
||
impl LoggerConfig {
|
||
pub fn new() -> Self {
|
||
Self {
|
||
queue_capacity: env::var(ENV_AUDIT_LOGGER_QUEUE_CAPACITY)
|
||
.ok()
|
||
.and_then(|v| v.parse().ok())
|
||
.or(Some(DEFAULT_AUDIT_LOGGER_QUEUE_CAPACITY)),
|
||
}
|
||
}
|
||
}
|
||
|
||
impl Default for LoggerConfig {
|
||
fn default() -> Self {
|
||
Self::new()
|
||
}
|
||
}
|
||
|
||
/// Overall application configuration
|
||
/// Add observability, sinks, and logger configuration
|
||
///
|
||
/// Observability: OpenTelemetry configuration
|
||
/// Sinks: Kafka, Webhook, File sink configuration
|
||
/// Logger: Logger configuration
|
||
///
|
||
/// # Example
|
||
/// ```
|
||
/// use rustfs_obs::AppConfig;
|
||
///
|
||
/// let config = AppConfig::new_with_endpoint(None);
|
||
/// ```
|
||
#[derive(Debug, Deserialize, Clone)]
|
||
pub struct AppConfig {
|
||
pub observability: OtelConfig,
|
||
pub sinks: Vec<SinkConfig>,
|
||
pub logger: Option<LoggerConfig>,
|
||
}
|
||
|
||
impl AppConfig {
|
||
/// Create a new instance of AppConfig with default values
|
||
///
|
||
/// # Returns
|
||
/// A new instance of AppConfig
|
||
pub fn new() -> Self {
|
||
Self {
|
||
observability: OtelConfig::default(),
|
||
sinks: vec![SinkConfig::default()],
|
||
logger: Some(LoggerConfig::default()),
|
||
}
|
||
}
|
||
|
||
pub fn new_with_endpoint(endpoint: Option<String>) -> Self {
|
||
Self {
|
||
observability: OtelConfig::extract_otel_config_from_env(endpoint),
|
||
sinks: vec![SinkConfig::new()],
|
||
logger: Some(LoggerConfig::new()),
|
||
}
|
||
}
|
||
}
|
||
|
||
// implement default for AppConfig
|
||
impl Default for AppConfig {
|
||
fn default() -> Self {
|
||
Self::new()
|
||
}
|
||
}
|