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, polling::GenAIPollerSettings};
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 genai_polling_settings: GenAIPollerSettings,
40 pub database_settings: DatabaseSettings,
41 pub kafka_settings: Option<KafkaSettings>,
42 pub rabbitmq_settings: Option<RabbitMQSettings>,
43 pub redis_settings: Option<RedisSettings>,
44 pub http_consumer_settings: HttpConsumerSettings,
45 pub genai_settings: GenAISettings,
46 pub auth_settings: AuthSettings,
47 pub bootstrap_key: String,
48 pub storage_settings: ObjectStorageSettings,
49}
50
51impl ScouterServerConfig {
52 fn get_storage_type(storage_uri: &str) -> StorageType {
53 let storage_uri_lower = storage_uri.to_lowercase();
54 if storage_uri_lower.starts_with("gs://") {
55 StorageType::Google
56 } else if storage_uri_lower.starts_with("s3://") {
57 StorageType::Aws
58 } else if storage_uri_lower.starts_with("az://") {
59 StorageType::Azure
60 } else {
61 StorageType::Local
62 }
63 }
64}
65
66impl ScouterServerConfig {
67 pub async fn new() -> Self {
68 let polling = PollingSettings::default();
69 let genai_polling = GenAIPollerSettings::default();
70 let database = DatabaseSettings::default();
71 let kafka = if env::var("KAFKA_BROKERS").is_ok() {
72 Some(KafkaSettings::default())
73 } else {
74 None
75 };
76
77 let rabbitmq = if env::var("RABBITMQ_ADDR").is_ok() {
78 Some(RabbitMQSettings::default())
79 } else {
80 None
81 };
82
83 let redis = if std::env::var("REDIS_ADDR").is_ok() {
84 Some(RedisSettings::default())
85 } else {
86 None
87 };
88 let http_consumer_settings = HttpConsumerSettings::default();
89
90 let auth_settings = AuthSettings {
91 jwt_secret: env::var("SCOUTER_ENCRYPT_SECRET").unwrap_or_else(|_| {
92 warn!(
93 "Using default secret for encryption
94 This is not recommended for production use."
95 );
96 generate_default_secret()
97 }),
98 refresh_secret: env::var("SCOUTER_REFRESH_SECRET").unwrap_or_else(|_| {
99 warn!(
100 "Using default secret for refreshing.
101 This is not recommended for production use."
102 );
103
104 generate_default_secret()
105 }),
106 };
107
108 let bootstrap_key =
109 env::var("SCOUTER_BOOTSTRAP_KEY").unwrap_or_else(|_| generate_default_secret());
110
111 let genai_settings = GenAISettings::new().await;
112
113 Self {
114 polling_settings: polling,
115 genai_polling_settings: genai_polling,
116 database_settings: database,
117 kafka_settings: kafka,
118 rabbitmq_settings: rabbitmq,
119 redis_settings: redis,
120 auth_settings,
121 bootstrap_key,
122 genai_settings,
123 http_consumer_settings,
124 storage_settings: ObjectStorageSettings::default(),
125 }
126 }
127}
128
129impl ScouterServerConfig {
130 pub fn kafka_enabled(&self) -> bool {
131 self.kafka_settings.is_some()
132 }
133
134 pub fn rabbitmq_enabled(&self) -> bool {
135 self.rabbitmq_settings.is_some()
136 }
137
138 pub fn redis_enabled(&self) -> bool {
139 self.redis_settings.is_some()
140 }
141
142 pub fn genai_enabled(&self) -> bool {
143 self.genai_settings.is_configured()
144 }
145}