1use base64::prelude::*;
2use scouter_types::StorageType;
3use std::env;
4use tracing::warn;
5
6pub mod auth;
7pub mod database;
8pub mod events;
9pub mod http;
10pub mod llm;
11pub mod polling;
12pub mod storage;
13
14use crate::events::HttpConsumerSettings;
15pub use auth::AuthSettings;
16pub use database::DatabaseSettings;
17pub use events::{KafkaSettings, RabbitMQSettings, RedisSettings};
18pub use http::HTTPConfig;
19pub use llm::LLMSettings;
20pub use polling::PollingSettings;
21pub use storage::ObjectStorageSettings;
22
23fn generate_default_secret() -> String {
24 let mut key = [0u8; 32];
27 for (i, item) in key.iter_mut().enumerate() {
28 *item = (31 - i) as u8;
30 }
31
32 BASE64_STANDARD.encode(key)
33}
34
35#[derive(Debug, Clone)]
36pub struct ScouterServerConfig {
37 pub polling_settings: PollingSettings,
38 pub database_settings: DatabaseSettings,
39 pub kafka_settings: Option<KafkaSettings>,
40 pub rabbitmq_settings: Option<RabbitMQSettings>,
41 pub redis_settings: Option<RedisSettings>,
42 pub http_consumer_settings: HttpConsumerSettings,
43 pub llm_settings: LLMSettings,
44 pub auth_settings: AuthSettings,
45 pub bootstrap_key: String,
46 pub storage_settings: ObjectStorageSettings,
47}
48
49impl ScouterServerConfig {
50 fn get_storage_type(storage_uri: &str) -> StorageType {
51 let storage_uri_lower = storage_uri.to_lowercase();
52 if storage_uri_lower.starts_with("gs://") {
53 StorageType::Google
54 } else if storage_uri_lower.starts_with("s3://") {
55 StorageType::Aws
56 } else if storage_uri_lower.starts_with("az://") {
57 StorageType::Azure
58 } else {
59 StorageType::Local
60 }
61 }
62}
63
64impl Default for ScouterServerConfig {
65 fn default() -> Self {
66 let polling = PollingSettings::default();
67 let database = DatabaseSettings::default();
68 let kafka = if env::var("KAFKA_BROKERS").is_ok() {
69 Some(KafkaSettings::default())
70 } else {
71 None
72 };
73
74 let rabbitmq = if env::var("RABBITMQ_ADDR").is_ok() {
75 Some(RabbitMQSettings::default())
76 } else {
77 None
78 };
79
80 let redis = if std::env::var("REDIS_ADDR").is_ok() {
81 Some(RedisSettings::default())
82 } else {
83 None
84 };
85 let http_consumer_settings = HttpConsumerSettings::default();
86
87 let auth_settings = AuthSettings {
88 jwt_secret: env::var("SCOUTER_ENCRYPT_SECRET").unwrap_or_else(|_| {
89 warn!(
90 "Using default secret for encryption
91 This is not recommended for production use."
92 );
93 generate_default_secret()
94 }),
95 refresh_secret: env::var("SCOUTER_REFRESH_SECRET").unwrap_or_else(|_| {
96 warn!(
97 "Using default secret for refreshing.
98 This is not recommended for production use."
99 );
100
101 generate_default_secret()
102 }),
103 };
104
105 let bootstrap_key =
106 env::var("SCOUTER_BOOTSTRAP_KEY").unwrap_or_else(|_| generate_default_secret());
107
108 let llm_settings = LLMSettings::default();
109
110 Self {
111 polling_settings: polling,
112 database_settings: database,
113 kafka_settings: kafka,
114 rabbitmq_settings: rabbitmq,
115 redis_settings: redis,
116 auth_settings,
117 bootstrap_key,
118 llm_settings,
119 http_consumer_settings,
120 storage_settings: ObjectStorageSettings::default(),
121 }
122 }
123}
124
125impl ScouterServerConfig {
126 pub fn kafka_enabled(&self) -> bool {
127 self.kafka_settings.is_some()
128 }
129
130 pub fn rabbitmq_enabled(&self) -> bool {
131 self.rabbitmq_settings.is_some()
132 }
133
134 pub fn redis_enabled(&self) -> bool {
135 self.redis_settings.is_some()
136 }
137
138 pub fn llm_enabled(&self) -> bool {
139 self.llm_settings.is_configured()
140 }
141}