feat: add telemetry to appflowy collaborate service (#662)

This commit is contained in:
Khor Shu Heng 2024-06-28 13:44:59 +08:00 committed by GitHub
parent 9884d93aa2
commit 7dfb52f80b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 82 additions and 1 deletions

1
Cargo.lock generated
View File

@ -730,6 +730,7 @@ dependencies = [
"tokio-stream",
"tokio-util",
"tracing",
"tracing-subscriber",
"uuid",
"validator",
"workspace-access",

View File

@ -36,6 +36,7 @@ serde_json.workspace = true
serde_repr.workspace = true
sqlx = { workspace = true, default-features = false, features = ["runtime-tokio-rustls", "macros", "postgres", "uuid", "chrono"] }
thiserror = "1.0.56"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
anyhow = "1"
bytes.workspace = true

View File

@ -3,10 +3,12 @@ use std::str::FromStr;
use anyhow::Context;
use secrecy::Secret;
use serde::Deserialize;
use sqlx::postgres::{PgConnectOptions, PgSslMode};
#[derive(Clone, Debug)]
pub struct Config {
pub app_env: Environment,
pub application: ApplicationSetting,
pub websocket: WebsocketSetting,
pub db_settings: DatabaseSetting,
@ -21,6 +23,36 @@ pub struct ApplicationSetting {
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)]
pub struct WebsocketSetting {
pub heartbeat_interval: u8,
@ -60,7 +92,7 @@ impl DatabaseSetting {
}
}
#[derive(serde::Deserialize, Clone, Debug)]
#[derive(Clone, Debug, Deserialize)]
pub struct GoTrueSetting {
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> {
let config = Config {
app_env: get_env_var("APPFLOWY_ENVIRONMENT", "local")
.parse()
.context("fail to get APPFLOWY_ENVIRONMENT")?,
application: ApplicationSetting {
port: get_env_var("APPFLOWY_COLLAB_SERVICE_PORT", "8001").parse()?,
host: get_env_var("APPFLOWY_COLLAB_SERVICE_HOST", "0.0.0.0"),

View File

@ -16,6 +16,7 @@ mod rt_server;
pub mod shared_state;
pub mod snapshot;
mod state;
pub mod telemetry;
mod util;
pub use metrics::*;

View File

@ -1,5 +1,6 @@
use appflowy_collaborate::application::{init_state, Application};
use appflowy_collaborate::config::get_configuration;
use appflowy_collaborate::telemetry::init_subscriber;
#[actix_web::main]
async fn main() -> anyhow::Result<()> {
@ -8,6 +9,7 @@ async fn main() -> anyhow::Result<()> {
let conf =
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 state = init_state(&conf, tx)

View File

@ -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();
},
}
});
}