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