1#![feature(assert_matches, let_chains)]
16
17use async_trait::async_trait;
18use common_telemetry::{error, info};
19use stat::{get_cpu_limit, get_memory_limit};
20
21use crate::error::Result;
22
23pub mod cli;
24pub mod datanode;
25pub mod error;
26pub mod flownode;
27pub mod frontend;
28pub mod metasrv;
29pub mod options;
30pub mod standalone;
31
32lazy_static::lazy_static! {
33 static ref APP_VERSION: prometheus::IntGaugeVec =
34 prometheus::register_int_gauge_vec!("greptime_app_version", "app version", &["version", "short_version", "app"]).unwrap();
35
36 static ref CPU_LIMIT: prometheus::IntGaugeVec =
37 prometheus::register_int_gauge_vec!("greptime_cpu_limit_in_millicores", "cpu limit in millicores", &["app"]).unwrap();
38
39 static ref MEMORY_LIMIT: prometheus::IntGaugeVec =
40 prometheus::register_int_gauge_vec!("greptime_memory_limit_in_bytes", "memory limit in bytes", &["app"]).unwrap();
41}
42
43#[cfg(unix)]
45async fn start_wait_for_close_signal() -> std::io::Result<()> {
46 use tokio::signal::unix::{signal, SignalKind};
47 let mut sigint = signal(SignalKind::interrupt())?;
48 let mut sigterm = signal(SignalKind::terminate())?;
49
50 tokio::select! {
51 _ = sigint.recv() => {
52 info!("Received SIGINT, shutting down");
53 }
54 _ = sigterm.recv() => {
55 info!("Received SIGTERM, shutting down");
56 }
57 }
58
59 Ok(())
60}
61
62#[cfg(not(unix))]
64async fn start_wait_for_close_signal() -> std::io::Result<()> {
65 tokio::signal::ctrl_c().await
66}
67
68#[async_trait]
69pub trait App: Send {
70 fn name(&self) -> &str;
71
72 async fn pre_start(&mut self) -> Result<()> {
74 Ok(())
75 }
76
77 async fn start(&mut self) -> Result<()>;
78
79 fn wait_signal(&self) -> bool {
81 true
82 }
83
84 async fn stop(&mut self) -> Result<()>;
85
86 async fn run(&mut self) -> Result<()> {
87 info!("Starting app: {}", self.name());
88
89 self.pre_start().await?;
90
91 self.start().await?;
92
93 if self.wait_signal() {
94 if let Err(e) = start_wait_for_close_signal().await {
95 error!(e; "Failed to listen for close signal");
96 }
100 }
101
102 self.stop().await?;
103 info!("Goodbye!");
104 Ok(())
105 }
106}
107
108pub fn log_versions(version: &str, short_version: &str, app: &str) {
113 APP_VERSION
115 .with_label_values(&[env!("CARGO_PKG_VERSION"), short_version, app])
116 .inc();
117
118 info!("GreptimeDB version: {}", version);
120
121 log_env_flags();
122}
123
124pub fn create_resource_limit_metrics(app: &str) {
125 if let Some(cpu_limit) = get_cpu_limit() {
126 info!(
127 "GreptimeDB start with cpu limit in millicores: {}",
128 cpu_limit
129 );
130 CPU_LIMIT.with_label_values(&[app]).set(cpu_limit);
131 }
132
133 if let Some(memory_limit) = get_memory_limit() {
134 info!(
135 "GreptimeDB start with memory limit in bytes: {}",
136 memory_limit
137 );
138 MEMORY_LIMIT.with_label_values(&[app]).set(memory_limit);
139 }
140}
141
142fn log_env_flags() {
143 info!("command line arguments");
144 for argument in std::env::args() {
145 info!("argument: {}", argument);
146 }
147}