2023-09-30 23:50:04 +00:00
|
|
|
mod http;
|
2023-01-19 17:18:41 +00:00
|
|
|
|
2023-01-19 14:25:52 +00:00
|
|
|
use std::future::Future;
|
2023-09-22 15:24:36 +00:00
|
|
|
use std::path::Path;
|
2023-01-19 14:25:52 +00:00
|
|
|
|
2023-09-22 15:24:36 +00:00
|
|
|
use clap::Parser;
|
2023-01-19 14:25:52 +00:00
|
|
|
use figment::providers::Format;
|
|
|
|
use figment::{providers::Toml, Figment};
|
2024-04-26 10:16:23 +00:00
|
|
|
use opentelemetry::KeyValue;
|
|
|
|
use opentelemetry_otlp::WithExportConfig;
|
|
|
|
use opentelemetry_sdk::trace::{BatchConfig, RandomIdGenerator, Sampler};
|
|
|
|
use opentelemetry_sdk::{runtime, Resource};
|
|
|
|
use opentelemetry_semantic_conventions::resource::SERVICE_NAME;
|
|
|
|
use opentelemetry_semantic_conventions::SCHEMA_URL;
|
2023-02-09 18:19:03 +00:00
|
|
|
use prometheus::Registry as MetricsRegistry;
|
2023-01-19 14:25:52 +00:00
|
|
|
use serde::Deserialize;
|
2024-04-26 10:16:23 +00:00
|
|
|
use tracing_opentelemetry::OpenTelemetryLayer;
|
|
|
|
use tracing_subscriber::fmt::Subscriber;
|
|
|
|
use tracing_subscriber::prelude::*;
|
2023-01-19 14:25:52 +00:00
|
|
|
|
2023-09-30 23:34:35 +00:00
|
|
|
use lavina_core::prelude::*;
|
2023-09-30 23:12:11 +00:00
|
|
|
use lavina_core::repo::Storage;
|
2024-04-21 17:45:50 +00:00
|
|
|
use lavina_core::LavinaCore;
|
2023-01-19 14:25:52 +00:00
|
|
|
|
|
|
|
#[derive(Deserialize, Debug)]
|
2023-02-09 18:19:03 +00:00
|
|
|
struct ServerConfig {
|
2023-09-30 23:50:04 +00:00
|
|
|
telemetry: http::ServerConfig,
|
2023-09-30 23:34:35 +00:00
|
|
|
irc: projection_irc::ServerConfig,
|
2023-09-30 23:47:18 +00:00
|
|
|
xmpp: projection_xmpp::ServerConfig,
|
2023-09-30 23:12:11 +00:00
|
|
|
storage: lavina_core::repo::StorageConfig,
|
2024-04-26 10:16:23 +00:00
|
|
|
tracing: Option<TracingConfig>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
|
|
struct TracingConfig {
|
|
|
|
endpoint: String,
|
|
|
|
service_name: String,
|
2023-01-19 14:25:52 +00:00
|
|
|
}
|
|
|
|
|
2023-09-22 15:24:36 +00:00
|
|
|
#[derive(Parser)]
|
|
|
|
struct CliArgs {
|
|
|
|
#[arg(long)]
|
2023-09-30 23:50:04 +00:00
|
|
|
config: Box<Path>,
|
2023-09-22 15:24:36 +00:00
|
|
|
}
|
|
|
|
|
2023-01-19 14:25:52 +00:00
|
|
|
fn load_config() -> Result<ServerConfig> {
|
2023-09-22 15:24:36 +00:00
|
|
|
let args = CliArgs::parse();
|
|
|
|
let raw_config = Figment::from(Toml::file(args.config));
|
2023-01-19 14:25:52 +00:00
|
|
|
let config: ServerConfig = raw_config.extract()?;
|
|
|
|
Ok(config)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
async fn main() -> Result<()> {
|
|
|
|
let sleep = ctrl_c()?;
|
|
|
|
let config = load_config()?;
|
2024-04-26 10:16:23 +00:00
|
|
|
set_up_logging(&config.tracing)?;
|
2023-01-27 20:43:20 +00:00
|
|
|
|
2023-02-09 18:19:03 +00:00
|
|
|
tracing::info!("Booting up");
|
|
|
|
tracing::info!("Loaded config: {config:?}");
|
2023-02-10 17:09:29 +00:00
|
|
|
let ServerConfig {
|
|
|
|
telemetry: telemetry_config,
|
|
|
|
irc: irc_config,
|
2023-02-17 21:27:58 +00:00
|
|
|
xmpp: xmpp_config,
|
2023-07-07 13:09:24 +00:00
|
|
|
storage: storage_config,
|
2024-04-26 10:16:23 +00:00
|
|
|
tracing: _,
|
2023-02-10 17:09:29 +00:00
|
|
|
} = config;
|
2024-04-21 17:45:50 +00:00
|
|
|
let metrics = MetricsRegistry::new();
|
2023-07-07 13:09:24 +00:00
|
|
|
let storage = Storage::open(storage_config).await?;
|
2024-04-21 17:45:50 +00:00
|
|
|
let core = LavinaCore::new(metrics.clone(), storage.clone()).await?;
|
|
|
|
let telemetry_terminator = http::launch(telemetry_config, metrics.clone(), core.clone(), storage.clone()).await?;
|
2024-05-03 22:37:49 +00:00
|
|
|
let irc = projection_irc::launch(irc_config, core.clone(), metrics.clone()).await?;
|
|
|
|
let xmpp = projection_xmpp::launch(xmpp_config, core.clone(), metrics.clone()).await?;
|
2023-01-19 14:25:52 +00:00
|
|
|
tracing::info!("Started");
|
|
|
|
|
2023-02-09 18:19:03 +00:00
|
|
|
sleep.await;
|
2023-01-19 14:25:52 +00:00
|
|
|
|
|
|
|
tracing::info!("Begin shutdown");
|
2023-02-17 21:27:58 +00:00
|
|
|
xmpp.terminate().await?;
|
2023-02-07 15:21:00 +00:00
|
|
|
irc.terminate().await?;
|
2023-02-09 18:19:03 +00:00
|
|
|
telemetry_terminator.terminate().await?;
|
2024-04-21 17:45:50 +00:00
|
|
|
core.shutdown().await?;
|
2023-01-19 14:25:52 +00:00
|
|
|
tracing::info!("Shutdown complete");
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-07-30 16:59:33 +00:00
|
|
|
#[cfg(windows)]
|
|
|
|
fn ctrl_c() -> Result<impl Future<Output = ()>> {
|
|
|
|
use tokio::signal::windows::*;
|
|
|
|
let chan = ctrl_c()?;
|
|
|
|
async fn recv(mut chan: CtrlC) {
|
|
|
|
let _ = chan.recv().await;
|
|
|
|
}
|
|
|
|
Ok(recv(chan))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(unix)]
|
2023-01-19 14:25:52 +00:00
|
|
|
fn ctrl_c() -> Result<impl Future<Output = ()>> {
|
|
|
|
use tokio::signal::unix::*;
|
|
|
|
let chan = signal(SignalKind::interrupt())?;
|
|
|
|
async fn recv(mut chan: Signal) {
|
|
|
|
let _ = chan.recv().await;
|
|
|
|
}
|
|
|
|
Ok(recv(chan))
|
|
|
|
}
|
|
|
|
|
2024-04-26 10:16:23 +00:00
|
|
|
fn set_up_logging(tracing_config: &Option<TracingConfig>) -> Result<()> {
|
|
|
|
let subscriber = tracing_subscriber::registry().with(tracing_subscriber::fmt::layer());
|
|
|
|
|
|
|
|
let targets = {
|
|
|
|
use std::{env, str::FromStr};
|
2024-04-28 15:19:31 +00:00
|
|
|
use tracing_subscriber::filter::Targets;
|
2024-04-26 10:16:23 +00:00
|
|
|
match env::var("RUST_LOG") {
|
|
|
|
Ok(var) => Targets::from_str(&var)
|
|
|
|
.map_err(|e| {
|
|
|
|
eprintln!("Ignoring `RUST_LOG={:?}`: {}", var, e);
|
|
|
|
})
|
|
|
|
.unwrap_or_default(),
|
|
|
|
Err(env::VarError::NotPresent) => Targets::new().with_default(Subscriber::DEFAULT_MAX_LEVEL),
|
|
|
|
Err(e) => {
|
|
|
|
eprintln!("Ignoring `RUST_LOG`: {}", e);
|
|
|
|
Targets::new().with_default(Subscriber::DEFAULT_MAX_LEVEL)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if let Some(config) = tracing_config {
|
|
|
|
let trace_config = opentelemetry_sdk::trace::Config::default()
|
|
|
|
.with_sampler(Sampler::ParentBased(Box::new(Sampler::TraceIdRatioBased(1.0))))
|
|
|
|
.with_id_generator(RandomIdGenerator::default())
|
|
|
|
.with_resource(Resource::from_schema_url(
|
|
|
|
[KeyValue::new(SERVICE_NAME, config.service_name.to_string())],
|
|
|
|
SCHEMA_URL,
|
|
|
|
));
|
|
|
|
let trace_exporter = opentelemetry_otlp::new_exporter().tonic().with_endpoint(&config.endpoint);
|
|
|
|
let tracer = opentelemetry_otlp::new_pipeline()
|
|
|
|
.tracing()
|
|
|
|
.with_trace_config(trace_config)
|
|
|
|
.with_batch_config(BatchConfig::default())
|
|
|
|
.with_exporter(trace_exporter)
|
|
|
|
.install_batch(runtime::Tokio)?;
|
|
|
|
let subscriber = subscriber.with(OpenTelemetryLayer::new(tracer));
|
|
|
|
targets.with_subscriber(subscriber).try_init()?;
|
|
|
|
} else {
|
|
|
|
targets.with_subscriber(subscriber).try_init()?;
|
|
|
|
}
|
2023-01-19 14:25:52 +00:00
|
|
|
Ok(())
|
|
|
|
}
|