feat: add telemetry to appflowy collaborate service (#662)
This commit is contained in:
parent
9884d93aa2
commit
7dfb52f80b
|
|
@ -730,6 +730,7 @@ dependencies = [
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
"uuid",
|
"uuid",
|
||||||
"validator",
|
"validator",
|
||||||
"workspace-access",
|
"workspace-access",
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ serde_json.workspace = true
|
||||||
serde_repr.workspace = true
|
serde_repr.workspace = true
|
||||||
sqlx = { workspace = true, default-features = false, features = ["runtime-tokio-rustls", "macros", "postgres", "uuid", "chrono"] }
|
sqlx = { workspace = true, default-features = false, features = ["runtime-tokio-rustls", "macros", "postgres", "uuid", "chrono"] }
|
||||||
thiserror = "1.0.56"
|
thiserror = "1.0.56"
|
||||||
|
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
bytes.workspace = true
|
bytes.workspace = true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,12 @@ use std::str::FromStr;
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use secrecy::Secret;
|
use secrecy::Secret;
|
||||||
|
use serde::Deserialize;
|
||||||
use sqlx::postgres::{PgConnectOptions, PgSslMode};
|
use sqlx::postgres::{PgConnectOptions, PgSslMode};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
pub app_env: Environment,
|
||||||
pub application: ApplicationSetting,
|
pub application: ApplicationSetting,
|
||||||
pub websocket: WebsocketSetting,
|
pub websocket: WebsocketSetting,
|
||||||
pub db_settings: DatabaseSetting,
|
pub db_settings: DatabaseSetting,
|
||||||
|
|
@ -21,6 +23,36 @@ pub struct ApplicationSetting {
|
||||||
pub host: String,
|
pub host: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
|
pub enum Environment {
|
||||||
|
Local,
|
||||||
|
Production,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Environment {
|
||||||
|
pub fn as_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Environment::Local => "local",
|
||||||
|
Environment::Production => "production",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Environment {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s.to_lowercase().as_str() {
|
||||||
|
"local" => Ok(Self::Local),
|
||||||
|
"production" => Ok(Self::Production),
|
||||||
|
other => anyhow::bail!(
|
||||||
|
"{} is not a supported environment. Use either `local` or `production`.",
|
||||||
|
other
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct WebsocketSetting {
|
pub struct WebsocketSetting {
|
||||||
pub heartbeat_interval: u8,
|
pub heartbeat_interval: u8,
|
||||||
|
|
@ -60,7 +92,7 @@ impl DatabaseSetting {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Clone, Debug)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
pub struct GoTrueSetting {
|
pub struct GoTrueSetting {
|
||||||
pub jwt_secret: Secret<String>,
|
pub jwt_secret: Secret<String>,
|
||||||
}
|
}
|
||||||
|
|
@ -85,6 +117,9 @@ pub fn get_env_var(key: &str, default: &str) -> String {
|
||||||
|
|
||||||
pub fn get_configuration() -> Result<Config, anyhow::Error> {
|
pub fn get_configuration() -> Result<Config, anyhow::Error> {
|
||||||
let config = Config {
|
let config = Config {
|
||||||
|
app_env: get_env_var("APPFLOWY_ENVIRONMENT", "local")
|
||||||
|
.parse()
|
||||||
|
.context("fail to get APPFLOWY_ENVIRONMENT")?,
|
||||||
application: ApplicationSetting {
|
application: ApplicationSetting {
|
||||||
port: get_env_var("APPFLOWY_COLLAB_SERVICE_PORT", "8001").parse()?,
|
port: get_env_var("APPFLOWY_COLLAB_SERVICE_PORT", "8001").parse()?,
|
||||||
host: get_env_var("APPFLOWY_COLLAB_SERVICE_HOST", "0.0.0.0"),
|
host: get_env_var("APPFLOWY_COLLAB_SERVICE_HOST", "0.0.0.0"),
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ mod rt_server;
|
||||||
pub mod shared_state;
|
pub mod shared_state;
|
||||||
pub mod snapshot;
|
pub mod snapshot;
|
||||||
mod state;
|
mod state;
|
||||||
|
pub mod telemetry;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
pub use metrics::*;
|
pub use metrics::*;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use appflowy_collaborate::application::{init_state, Application};
|
use appflowy_collaborate::application::{init_state, Application};
|
||||||
use appflowy_collaborate::config::get_configuration;
|
use appflowy_collaborate::config::get_configuration;
|
||||||
|
use appflowy_collaborate::telemetry::init_subscriber;
|
||||||
|
|
||||||
#[actix_web::main]
|
#[actix_web::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
|
|
@ -8,6 +9,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
let conf =
|
let conf =
|
||||||
get_configuration().map_err(|e| anyhow::anyhow!("Failed to read configuration: {}", e))?;
|
get_configuration().map_err(|e| anyhow::anyhow!("Failed to read configuration: {}", e))?;
|
||||||
|
init_subscriber(&conf.app_env);
|
||||||
|
|
||||||
let (tx, rx) = tokio::sync::mpsc::channel(1000);
|
let (tx, rx) = tokio::sync::mpsc::channel(1000);
|
||||||
let state = init_state(&conf, tx)
|
let state = init_state(&conf, tx)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
use crate::config::Environment;
|
||||||
|
use std::sync::Once;
|
||||||
|
use tracing::subscriber::set_global_default;
|
||||||
|
use tracing_subscriber::layer::SubscriberExt;
|
||||||
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
|
pub fn init_subscriber(app_env: &Environment) {
|
||||||
|
static START: Once = Once::new();
|
||||||
|
START.call_once(|| {
|
||||||
|
let level = std::env::var("RUST_LOG").unwrap_or("info".to_string());
|
||||||
|
let mut filters = vec![];
|
||||||
|
filters.push(format!("appflowy_collaborate={}", level));
|
||||||
|
filters.push(format!("collab={}", level));
|
||||||
|
filters.push(format!("collab_plugins={}", level));
|
||||||
|
filters.push(format!("database={}", level));
|
||||||
|
let env_filter = EnvFilter::new(filters.join(","));
|
||||||
|
|
||||||
|
let builder = tracing_subscriber::fmt()
|
||||||
|
.with_target(true)
|
||||||
|
.with_max_level(tracing::Level::TRACE)
|
||||||
|
.with_thread_ids(false)
|
||||||
|
.with_file(false);
|
||||||
|
|
||||||
|
match app_env {
|
||||||
|
Environment::Local => {
|
||||||
|
let subscriber = builder
|
||||||
|
.with_ansi(true)
|
||||||
|
.with_target(false)
|
||||||
|
.with_file(false)
|
||||||
|
.pretty()
|
||||||
|
.finish()
|
||||||
|
.with(env_filter);
|
||||||
|
set_global_default(subscriber).unwrap();
|
||||||
|
},
|
||||||
|
Environment::Production => {
|
||||||
|
let subscriber = builder.json().finish().with(env_filter);
|
||||||
|
set_global_default(subscriber).unwrap();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue