refactor: config log
This commit is contained in:
parent
7b706b54ce
commit
690ea42d85
|
|
@ -68,11 +68,11 @@ jobs:
|
||||||
- name: Migrate database
|
- name: Migrate database
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install libpq-dev -y
|
sudo apt-get install libpq-dev -y
|
||||||
SKIP_DOCKER=true POSTGRES_PORT=5433 ./scripts/init_database.sh
|
SKIP_DOCKER=true POSTGRES_PORT=5433 ./build/init_database.sh
|
||||||
|
|
||||||
- name: Check sqlx-data.json is up-to-date
|
- name: Check sqlx-data.json is up-to-date
|
||||||
run: |
|
run: |
|
||||||
cargo sqlx prepare --check -- --bin http_server
|
cargo sqlx prepare --check -- --bin appflowy_server
|
||||||
|
|
||||||
- name: Run cargo test
|
- name: Run cargo test
|
||||||
run: cargo test
|
run: cargo test
|
||||||
|
|
@ -140,7 +140,7 @@ jobs:
|
||||||
- name: Migrate database
|
- name: Migrate database
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install libpq-dev -y
|
sudo apt-get install libpq-dev -y
|
||||||
SKIP_DOCKER=true POSTGRES_PORT=5433 ./scripts/init_database.sh
|
SKIP_DOCKER=true POSTGRES_PORT=5433 ./build/init_database.sh
|
||||||
|
|
||||||
- run: rustup component add clippy
|
- run: rustup component add clippy
|
||||||
- run: cargo clippy -- -D warnings
|
- run: cargo clippy -- -D warnings
|
||||||
|
|
|
||||||
|
|
@ -401,9 +401,9 @@ dependencies = [
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-appender",
|
"tracing-actix-web",
|
||||||
"tracing-bunyan-formatter",
|
"tracing-bunyan-formatter",
|
||||||
"tracing-futures",
|
"tracing-log",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -2137,7 +2137,7 @@ dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"url",
|
"url",
|
||||||
"uuid",
|
"uuid 0.8.2",
|
||||||
"whoami",
|
"whoami",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -2388,14 +2388,15 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-appender"
|
name = "tracing-actix-web"
|
||||||
version = "0.2.2"
|
version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e"
|
checksum = "4082e4d81173e0b7ad3cfb71e9eaef0dd0cbb7b139fdb56394f488a3b0760b23"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-channel",
|
"actix-web",
|
||||||
"time 0.3.20",
|
"pin-project",
|
||||||
"tracing-subscriber",
|
"tracing",
|
||||||
|
"uuid 1.3.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2437,16 +2438,6 @@ dependencies = [
|
||||||
"valuable",
|
"valuable",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tracing-futures"
|
|
||||||
version = "0.2.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
|
|
||||||
dependencies = [
|
|
||||||
"pin-project",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-log"
|
name = "tracing-log"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
|
@ -2567,6 +2558,15 @@ version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "valuable"
|
name = "valuable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,10 @@ derive_more = {version = "0.99"}
|
||||||
|
|
||||||
# tracing
|
# tracing
|
||||||
tracing = { version = "0.1.37" }
|
tracing = { version = "0.1.37" }
|
||||||
tracing-futures = "0.2.5"
|
|
||||||
tracing-subscriber = { version = "0.3.16", features = ["registry", "env-filter", "ansi", "json"] }
|
tracing-subscriber = { version = "0.3.16", features = ["registry", "env-filter", "ansi", "json"] }
|
||||||
tracing-bunyan-formatter = "0.3.6"
|
tracing-bunyan-formatter = "0.3.6"
|
||||||
tracing-appender = "0.2.2"
|
tracing-actix-web = "0.7"
|
||||||
|
tracing-log = "0.1.1"
|
||||||
|
|
||||||
ormx = { version = "0.10.0", features = ["postgres"]}
|
ormx = { version = "0.10.0", features = ["postgres"]}
|
||||||
[dependencies.sqlx]
|
[dependencies.sqlx]
|
||||||
|
|
@ -56,7 +56,7 @@ features = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "http_server"
|
name = "appflowy_server"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
12
Dockerfile
12
Dockerfile
|
|
@ -2,11 +2,11 @@ FROM rust:1.56.1 as builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
WORKDIR /app/services/http_server
|
WORKDIR /app/services/appflowy_server
|
||||||
ENV SQLX_OFFLINE true
|
ENV SQLX_OFFLINE true
|
||||||
RUN RUSTFLAGS="-C opt-level=2" cargo build --release --bin http_server
|
RUN RUSTFLAGS="-C opt-level=2" cargo build --release --bin appflowy_server
|
||||||
# Size optimization
|
# Size optimization
|
||||||
#RUN strip ./target/release/http_server
|
#RUN strip ./target/release/appflowy_server
|
||||||
|
|
||||||
FROM debian:bullseye-slim AS runtime
|
FROM debian:bullseye-slim AS runtime
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
@ -17,7 +17,7 @@ RUN apt-get update -y \
|
||||||
&& apt-get clean -y \
|
&& apt-get clean -y \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
COPY --from=builder /app/services/target/release/http_server /usr/local/bin/http_server
|
COPY --from=builder /app/services/target/release/appflowy_server /usr/local/bin/appflowy_server
|
||||||
COPY --from=builder /app/services/http_server/configuration configuration
|
COPY --from=builder /app/services/appflowy_server/configuration configuration
|
||||||
ENV APP_ENVIRONMENT production
|
ENV APP_ENVIRONMENT production
|
||||||
CMD ["http_server"]
|
CMD ["appflowy_server"]
|
||||||
|
|
|
||||||
4
Makefile
4
Makefile
|
|
@ -1,4 +1,4 @@
|
||||||
ROOT = "./scripts"
|
ROOT = "./build"
|
||||||
SEMVER_VERSION=$(shell grep version Cargo.toml | awk -F"\"" '{print $$2}' | head -n 1)
|
SEMVER_VERSION=$(shell grep version Cargo.toml | awk -F"\"" '{print $$2}' | head -n 1)
|
||||||
|
|
||||||
.PHONY: init_database docker_image local_server docker_test
|
.PHONY: init_database docker_image local_server docker_test
|
||||||
|
|
@ -8,7 +8,7 @@ init_database:
|
||||||
|
|
||||||
docker_image:
|
docker_image:
|
||||||
source $(ROOT)/docker_env.sh && docker-compose up -d postgres_db
|
source $(ROOT)/docker_env.sh && docker-compose up -d postgres_db
|
||||||
source $(ROOT)/docker_env.sh && docker-compose up -d http_server
|
source $(ROOT)/docker_env.sh && docker-compose up -d appflowy_server
|
||||||
|
|
||||||
local_server:
|
local_server:
|
||||||
cargo run
|
cargo run
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,15 @@ services:
|
||||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||||
ports:
|
ports:
|
||||||
- "5434:5432"
|
- "5434:5432"
|
||||||
http_server:
|
appflowy_server:
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
environment:
|
environment:
|
||||||
- APP_ENVIRONMENT=production
|
- APP_ENVIRONMENT=production
|
||||||
- DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db/${POSTGRES_DB}"
|
- DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db/${POSTGRES_DB}"
|
||||||
build:
|
build:
|
||||||
context: ../../
|
context: ../../
|
||||||
dockerfile: ./services/http_server/Dockerfile
|
dockerfile: ./services/appflowy_server/Dockerfile
|
||||||
image: http_server:${BACKEND_VERSION}
|
image: appflowy_server:${BACKEND_VERSION}
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres_db
|
- postgres_db
|
||||||
ports:
|
ports:
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,11 @@ use actix_web::{dev::Server, middleware, web, web::Data, App, HttpServer};
|
||||||
use sqlx::{postgres::PgPoolOptions, PgPool};
|
use sqlx::{postgres::PgPoolOptions, PgPool};
|
||||||
use std::net::TcpListener;
|
use std::net::TcpListener;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use tracing_actix_web::TracingLogger;
|
||||||
|
|
||||||
use crate::api::{token_scope, user_scope};
|
use crate::api::{token_scope, user_scope};
|
||||||
|
|
||||||
use crate::config::config::{Config, DatabaseSettings};
|
use crate::config::config::{Config, DatabaseSetting};
|
||||||
use crate::config::env::{domain, secret};
|
use crate::config::env::{domain, secret};
|
||||||
use crate::middleware::cors::default_cors;
|
use crate::middleware::cors::default_cors;
|
||||||
use crate::state::State;
|
use crate::state::State;
|
||||||
|
|
@ -46,6 +47,7 @@ pub fn run(listener: TcpListener, state: State) -> Result<Server, std::io::Error
|
||||||
.wrap(middleware::Logger::default())
|
.wrap(middleware::Logger::default())
|
||||||
.wrap(IdentityMiddleware::default())
|
.wrap(IdentityMiddleware::default())
|
||||||
.wrap(default_cors())
|
.wrap(default_cors())
|
||||||
|
.wrap(TracingLogger::default())
|
||||||
.app_data(web::JsonConfig::default().limit(4096))
|
.app_data(web::JsonConfig::default().limit(4096))
|
||||||
.service(user_scope())
|
.service(user_scope())
|
||||||
.service(token_scope())
|
.service(token_scope())
|
||||||
|
|
@ -72,7 +74,7 @@ pub async fn init_state(configuration: &Config) -> State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_connection_pool(setting: &DatabaseSettings) -> Result<PgPool, sqlx::Error> {
|
pub async fn get_connection_pool(setting: &DatabaseSetting) -> Result<PgPool, sqlx::Error> {
|
||||||
PgPoolOptions::new()
|
PgPoolOptions::new()
|
||||||
.connect_timeout(std::time::Duration::from_secs(5))
|
.connect_timeout(std::time::Duration::from_secs(5))
|
||||||
.connect_with(setting.with_db())
|
.connect_with(setting.with_db())
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
use tracing_subscriber::layer::SubscriberExt;
|
|
||||||
use tracing_subscriber::util::SubscriberInitExt;
|
|
||||||
use tracing_subscriber::EnvFilter;
|
|
||||||
|
|
||||||
pub fn init_log() {
|
|
||||||
if std::env::var_os("RUST_LOG").is_none() {
|
|
||||||
std::env::set_var("RUST_LOG", "debug");
|
|
||||||
}
|
|
||||||
let subscriber = tracing_subscriber::fmt()
|
|
||||||
.with_target(true)
|
|
||||||
.with_max_level(tracing::Level::TRACE)
|
|
||||||
.with_writer(std::io::stderr)
|
|
||||||
.with_thread_ids(true)
|
|
||||||
.compact()
|
|
||||||
.finish()
|
|
||||||
.with(EnvFilter::from_default_env());
|
|
||||||
|
|
||||||
// let formatting_layer = BunyanFormattingLayer::new(self.name, std::io::stdout);
|
|
||||||
// set_global_default(subscriber.with(JsonStorageLayer).with(formatting_layer)).map_err(|e| format!("{:?}", e))?;
|
|
||||||
|
|
||||||
subscriber.try_init().unwrap()
|
|
||||||
}
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
pub mod log;
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use std::convert::{TryFrom, TryInto};
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Clone, Debug)]
|
#[derive(serde::Deserialize, Clone, Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub database: DatabaseSettings,
|
pub database: DatabaseSetting,
|
||||||
pub application: ApplicationSettings,
|
pub application: ApplicationSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@ pub struct ApplicationSettings {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Clone, Debug)]
|
#[derive(serde::Deserialize, Clone, Debug)]
|
||||||
pub struct DatabaseSettings {
|
pub struct DatabaseSetting {
|
||||||
pub username: String,
|
pub username: String,
|
||||||
pub password: String,
|
pub password: String,
|
||||||
#[serde(deserialize_with = "deserialize_number_from_string")]
|
#[serde(deserialize_with = "deserialize_number_from_string")]
|
||||||
|
|
@ -35,7 +35,7 @@ pub struct DatabaseSettings {
|
||||||
pub require_ssl: bool,
|
pub require_ssl: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DatabaseSettings {
|
impl DatabaseSetting {
|
||||||
pub fn without_db(&self) -> PgConnectOptions {
|
pub fn without_db(&self) -> PgConnectOptions {
|
||||||
let ssl_mode = if self.require_ssl {
|
let ssl_mode = if self.require_ssl {
|
||||||
PgSslMode::Require
|
PgSslMode::Require
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,4 @@ pub mod component;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod middleware;
|
pub mod middleware;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
|
pub mod telemetry;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
use appflowy_server::application::{init_state, Application};
|
use appflowy_server::application::{init_state, Application};
|
||||||
use appflowy_server::component::log::init_log;
|
|
||||||
use appflowy_server::config::config::get_configuration;
|
use appflowy_server::config::config::get_configuration;
|
||||||
|
use appflowy_server::telemetry::{get_subscriber, init_subscriber};
|
||||||
|
|
||||||
#[actix_web::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
init_log();
|
let subscriber = get_subscriber("appflowy_server".into(), "info".into(), std::io::stdout);
|
||||||
|
init_subscriber(subscriber);
|
||||||
|
|
||||||
let configuration = get_configuration().expect("Failed to read configuration.");
|
let configuration = get_configuration().expect("Failed to read configuration.");
|
||||||
let state = init_state(&configuration).await;
|
let state = init_state(&configuration).await;
|
||||||
let application = Application::build(configuration, state).await?;
|
let application = Application::build(configuration, state).await?;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
use actix_web::rt::task::JoinHandle;
|
||||||
|
use tracing::subscriber::set_global_default;
|
||||||
|
use tracing::Subscriber;
|
||||||
|
use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer};
|
||||||
|
use tracing_log::LogTracer;
|
||||||
|
use tracing_subscriber::fmt::MakeWriter;
|
||||||
|
use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry};
|
||||||
|
|
||||||
|
/// Compose multiple layers into a `tracing`'s subscriber.
|
||||||
|
pub fn get_subscriber<Sink>(
|
||||||
|
name: String,
|
||||||
|
env_filter: String,
|
||||||
|
sink: Sink,
|
||||||
|
) -> impl Subscriber + Sync + Send
|
||||||
|
where
|
||||||
|
Sink: for<'a> MakeWriter<'a> + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
let env_filter =
|
||||||
|
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(env_filter));
|
||||||
|
let formatting_layer = BunyanFormattingLayer::new(name, sink);
|
||||||
|
Registry::default()
|
||||||
|
.with(env_filter)
|
||||||
|
.with(JsonStorageLayer)
|
||||||
|
.with(formatting_layer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register a subscriber as global default to process span data.
|
||||||
|
///
|
||||||
|
/// It should only be called once!
|
||||||
|
pub fn init_subscriber(subscriber: impl Subscriber + Sync + Send) {
|
||||||
|
LogTracer::init().expect("Failed to set logger");
|
||||||
|
set_global_default(subscriber).expect("Failed to set subscriber");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn_blocking_with_tracing<F, R>(f: F) -> JoinHandle<R>
|
||||||
|
where
|
||||||
|
F: FnOnce() -> R + Send + 'static,
|
||||||
|
R: Send + 'static,
|
||||||
|
{
|
||||||
|
let current_span = tracing::Span::current();
|
||||||
|
actix_web::rt::task::spawn_blocking(move || current_span.in_scope(f))
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
mod test_server;
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
use appflowy_server::application::{init_state, Application};
|
||||||
|
use appflowy_server::config::config::{get_configuration, DatabaseSetting};
|
||||||
|
use appflowy_server::state::State;
|
||||||
|
use sqlx::types::Uuid;
|
||||||
|
use sqlx::{Connection, Executor, PgConnection, PgPool};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct TestServer {
|
||||||
|
pub state: State,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn spawn_server() -> TestServer {
|
||||||
|
let database_name = Uuid::new_v4().to_string();
|
||||||
|
let configuration = {
|
||||||
|
let mut c = get_configuration().expect("Failed to read configuration.");
|
||||||
|
c.database.database_name = database_name.clone();
|
||||||
|
// Use a random OS port
|
||||||
|
c.application.port = 0;
|
||||||
|
c
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = configure_database(&configuration.database).await;
|
||||||
|
let state = init_state(&configuration).await;
|
||||||
|
let application = Application::build(configuration.clone(), state.clone())
|
||||||
|
.await
|
||||||
|
.expect("Failed to build application.");
|
||||||
|
|
||||||
|
let _ = tokio::spawn(async {
|
||||||
|
let _ = application.run_until_stopped();
|
||||||
|
});
|
||||||
|
|
||||||
|
TestServer { state }
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn configure_database(config: &DatabaseSetting) -> PgPool {
|
||||||
|
// Create database
|
||||||
|
let mut connection = PgConnection::connect_with(&config.without_db())
|
||||||
|
.await
|
||||||
|
.expect("Failed to connect to Postgres");
|
||||||
|
connection
|
||||||
|
.execute(&*format!(r#"CREATE DATABASE "{}";"#, config.database_name))
|
||||||
|
.await
|
||||||
|
.expect("Failed to create database.");
|
||||||
|
|
||||||
|
// Migrate database
|
||||||
|
let connection_pool = PgPool::connect_with(config.with_db())
|
||||||
|
.await
|
||||||
|
.expect("Failed to connect to Postgres.");
|
||||||
|
|
||||||
|
sqlx::migrate!("./migrations")
|
||||||
|
.run(&connection_pool)
|
||||||
|
.await
|
||||||
|
.expect("Failed to migrate the database");
|
||||||
|
|
||||||
|
connection_pool
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue