1use serde::{Deserialize, Serialize};
6use toml;
7
8use crate::{
9 Error,
10 buffer::BufferConfig,
11 input::InputConfig,
12 output::OutputConfig,
13 processor::ProcessorConfig,
14 stream::StreamConfig,
15};
16
17#[derive(Debug, Clone, Copy)]
19pub enum ConfigFormat {
20 YAML,
22 JSON,
24 TOML,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct LoggingConfig {
31 pub level: String,
33 pub file_output: Option<bool>,
35 pub file_path: Option<String>,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct EngineConfig {
42 pub streams: Vec<StreamConfig>,
44 pub http: Option<HttpServerConfig>,
46 pub metrics: Option<MetricsConfig>,
48 pub logging: Option<LoggingConfig>,
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct HttpServerConfig {
55 pub address: String,
57 pub cors_enabled: bool,
59 pub health_enabled: bool,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct MetricsConfig {
66 pub enabled: bool,
68 pub type_name: String,
70 pub prefix: Option<String>,
72 pub tags: Option<std::collections::HashMap<String, String>>,
74}
75
76impl EngineConfig {
77 pub fn from_file(path: &str) -> Result<Self, Error> {
79 let content = std::fs::read_to_string(path)
80 .map_err(|e| Error::Config(format!("无法读取配置文件: {}", e)))?;
81
82 if let Some(format) = get_format_from_path(path) {
84 match format {
85 ConfigFormat::YAML => {
86 return serde_yaml::from_str(&content)
87 .map_err(|e| Error::Config(format!("YAML解析错误: {}", e)));
88 },
89 ConfigFormat::JSON => {
90 return serde_json::from_str(&content)
91 .map_err(|e| Error::Config(format!("JSON解析错误: {}", e)));
92 },
93 ConfigFormat::TOML => {
94 return toml::from_str(&content)
95 .map_err(|e| Error::Config(format!("TOML解析错误: {}", e)));
96 },
97 }
98 }
99
100 Self::from_string(&content)
102 }
103
104 pub fn from_string(content: &str) -> Result<Self, Error> {
106 if let Ok(config) = serde_yaml::from_str(content) {
108 return Ok(config);
109 }
110
111 if let Ok(config) = toml::from_str(content) {
113 return Ok(config);
114 }
115
116 if let Ok(config) = serde_json::from_str(content) {
118 return Ok(config);
119 }
120
121 Err(Error::Config(format!("无法解析配置文件,支持的格式为:YAML、TOML、JSON")))
123 }
124
125 pub fn save_to_file(&self, path: &str) -> Result<(), Error> {
127 let content = toml::to_string_pretty(self)
128 .map_err(|e| Error::Config(format!("无法序列化配置: {}", e)))?;
129
130 std::fs::write(path, content)
131 .map_err(|e| Error::Config(format!("无法写入配置文件: {}", e)))
132 }
133}
134
135pub fn default_config() -> EngineConfig {
137 EngineConfig {
138 streams: vec![],
139 http: Some(HttpServerConfig {
140 address: "0.0.0.0:8000".to_string(),
141 cors_enabled: false,
142 health_enabled: true,
143 }),
144 metrics: Some(MetricsConfig {
145 enabled: true,
146 type_name: "prometheus".to_string(),
147 prefix: Some("benthos".to_string()),
148 tags: None,
149 }),
150 logging: Some(LoggingConfig {
151 level: "info".to_string(),
152 file_output: None,
153 file_path: None,
154 }),
155 }
156}
157
158fn get_format_from_path(path: &str) -> Option<ConfigFormat> {
160 let path = path.to_lowercase();
161 if path.ends_with(".yaml") || path.ends_with(".yml") {
162 Some(ConfigFormat::YAML)
163 } else if path.ends_with(".json") {
164 Some(ConfigFormat::JSON)
165 } else if path.ends_with(".toml") {
166 Some(ConfigFormat::TOML)
167 } else {
168 None
169 }
170}