Remove opentelemetry (#4741)

* Remove opentelemetry

* remove unused deps, use backtrace

* always print db migration messages regardless of log level (fixes #4725)

* fix ci

* Remove useless root span builder

---------

Co-authored-by: SleeplessOne1917 <28871516+SleeplessOne1917@users.noreply.github.com>
This commit is contained in:
Nutomic 2024-09-10 19:36:03 +02:00 committed by GitHub
parent ef49a0eb8d
commit c90ee3094d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 489 additions and 1095 deletions

View file

@ -157,7 +157,7 @@ steps:
CARGO_HOME: .cargo_home CARGO_HOME: .cargo_home
commands: commands:
- rustup component add clippy - rustup component add clippy
- cargo clippy --workspace --tests --all-targets --features console -- -D warnings - cargo clippy --workspace --tests --all-targets -- -D warnings
when: *slow_check_paths when: *slow_check_paths
cargo_build: cargo_build:

1344
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -37,15 +37,6 @@ debug = 0
[features] [features]
embed-pictrs = ["pict-rs"] embed-pictrs = ["pict-rs"]
# This feature requires building with `tokio_unstable` flag, see documentation:
# https://docs.rs/tokio/latest/tokio/#unstable-features
console = [
"console-subscriber",
"opentelemetry",
"opentelemetry-otlp",
"tracing-opentelemetry",
"reqwest-tracing/opentelemetry_0_16",
]
json-log = ["tracing-subscriber/json"] json-log = ["tracing-subscriber/json"]
default = [] default = []
@ -117,9 +108,7 @@ actix-web = { version = "4.8.0", default-features = false, features = [
"cookies", "cookies",
] } ] }
tracing = "0.1.40" tracing = "0.1.40"
tracing-actix-web = { version = "0.7.11", default-features = false } tracing-actix-web = { version = "0.7.10", default-features = false }
tracing-error = "0.2.0"
tracing-log = "0.2.0"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
url = { version = "2.5.2", features = ["serde"] } url = { version = "2.5.2", features = ["serde"] }
reqwest = { version = "0.11.27", default-features = false, features = [ reqwest = { version = "0.11.27", default-features = false, features = [
@ -154,8 +143,6 @@ itertools = "0.13.0"
futures = "0.3.30" futures = "0.3.30"
http = "0.2.12" http = "0.2.12"
rosetta-i18n = "0.1.3" rosetta-i18n = "0.1.3"
opentelemetry = { version = "0.19.0", features = ["rt-tokio"] }
tracing-opentelemetry = { version = "0.19.0" }
ts-rs = { version = "7.1.1", features = [ ts-rs = { version = "7.1.1", features = [
"serde-compat", "serde-compat",
"chrono-impl", "chrono-impl",
@ -188,8 +175,6 @@ diesel-async = { workspace = true }
actix-web = { workspace = true } actix-web = { workspace = true }
tracing = { workspace = true } tracing = { workspace = true }
tracing-actix-web = { workspace = true } tracing-actix-web = { workspace = true }
tracing-error = { workspace = true }
tracing-log = { workspace = true }
tracing-subscriber = { workspace = true } tracing-subscriber = { workspace = true }
url = { workspace = true } url = { workspace = true }
reqwest = { workspace = true } reqwest = { workspace = true }
@ -197,10 +182,6 @@ reqwest-middleware = { workspace = true }
reqwest-tracing = { workspace = true } reqwest-tracing = { workspace = true }
clokwerk = { workspace = true } clokwerk = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
tracing-opentelemetry = { workspace = true, optional = true }
opentelemetry = { workspace = true, optional = true }
console-subscriber = { version = "0.4.0", optional = true }
opentelemetry-otlp = { version = "0.12.0", optional = true }
pict-rs = { version = "0.5.16", optional = true } pict-rs = { version = "0.5.16", optional = true }
rustls = { workspace = true } rustls = { workspace = true }
tokio.workspace = true tokio.workspace = true

View file

@ -2,7 +2,6 @@ use anyhow::Context;
use diesel::{connection::SimpleConnection, Connection, PgConnection}; use diesel::{connection::SimpleConnection, Connection, PgConnection};
use diesel_migrations::{EmbeddedMigrations, MigrationHarness}; use diesel_migrations::{EmbeddedMigrations, MigrationHarness};
use lemmy_utils::error::LemmyError; use lemmy_utils::error::LemmyError;
use tracing::info;
const MIGRATIONS: EmbeddedMigrations = embed_migrations!(); const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
@ -34,7 +33,7 @@ pub fn run(db_url: &str) -> Result<(), LemmyError> {
// transaction as `REPLACEABLE_SCHEMA`. This code will be becone less hacky when the conditional // transaction as `REPLACEABLE_SCHEMA`. This code will be becone less hacky when the conditional
// setup of things in `REPLACEABLE_SCHEMA` is done without using the number of pending // setup of things in `REPLACEABLE_SCHEMA` is done without using the number of pending
// migrations. // migrations.
info!("Running Database migrations (This may take a long time)..."); println!("Running Database migrations (This may take a long time)...");
let migrations = conn let migrations = conn
.pending_migrations(MIGRATIONS) .pending_migrations(MIGRATIONS)
.map_err(|e| anyhow::anyhow!("Couldn't determine pending migrations: {e}"))?; .map_err(|e| anyhow::anyhow!("Couldn't determine pending migrations: {e}"))?;
@ -60,7 +59,7 @@ pub fn run(db_url: &str) -> Result<(), LemmyError> {
Ok(()) Ok(())
})?; })?;
info!("Database migrations complete."); println!("Database migrations complete.");
Ok(()) Ok(())
} }

View file

@ -32,7 +32,6 @@ full = [
"dep:actix-web", "dep:actix-web",
"dep:serde_json", "dep:serde_json",
"dep:anyhow", "dep:anyhow",
"dep:tracing-error",
"dep:http", "dep:http",
"dep:deser-hjson", "dep:deser-hjson",
"dep:regex", "dep:regex",
@ -53,7 +52,6 @@ full = [
[dependencies] [dependencies]
regex = { workspace = true, optional = true } regex = { workspace = true, optional = true }
tracing = { workspace = true, optional = true } tracing = { workspace = true, optional = true }
tracing-error = { workspace = true, optional = true }
itertools = { workspace = true, optional = true } itertools = { workspace = true, optional = true }
serde = { workspace = true } serde = { workspace = true }
serde_json = { workspace = true, optional = true } serde_json = { workspace = true, optional = true }

View file

@ -1,6 +1,6 @@
use cfg_if::cfg_if; use cfg_if::cfg_if;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt::Debug; use std::{backtrace::Backtrace, fmt::Debug};
use strum::{Display, EnumIter}; use strum::{Display, EnumIter};
#[derive(Display, Debug, Serialize, Deserialize, Clone, PartialEq, Eq, EnumIter, Hash)] #[derive(Display, Debug, Serialize, Deserialize, Clone, PartialEq, Eq, EnumIter, Hash)]
@ -186,14 +186,13 @@ pub enum LemmyErrorType {
cfg_if! { cfg_if! {
if #[cfg(feature = "full")] { if #[cfg(feature = "full")] {
use tracing_error::SpanTrace;
use std::fmt; use std::fmt;
pub type LemmyResult<T> = Result<T, LemmyError>; pub type LemmyResult<T> = Result<T, LemmyError>;
pub struct LemmyError { pub struct LemmyError {
pub error_type: LemmyErrorType, pub error_type: LemmyErrorType,
pub inner: anyhow::Error, pub inner: anyhow::Error,
pub context: SpanTrace, pub context: Backtrace,
} }
/// Maximum number of items in an array passed as API parameter. See [[LemmyErrorType::TooManyItems]] /// Maximum number of items in an array passed as API parameter. See [[LemmyErrorType::TooManyItems]]
@ -208,7 +207,7 @@ cfg_if! {
LemmyError { LemmyError {
error_type: LemmyErrorType::Unknown(format!("{}", &cause)), error_type: LemmyErrorType::Unknown(format!("{}", &cause)),
inner: cause, inner: cause,
context: SpanTrace::capture(), context: Backtrace::capture(),
} }
} }
} }
@ -253,7 +252,7 @@ cfg_if! {
LemmyError { LemmyError {
error_type, error_type,
inner, inner,
context: SpanTrace::capture(), context: Backtrace::capture(),
} }
} }
} }
@ -267,7 +266,7 @@ cfg_if! {
self.map_err(|error| LemmyError { self.map_err(|error| LemmyError {
error_type, error_type,
inner: error.into(), inner: error.into(),
context: SpanTrace::capture(), context: Backtrace::capture(),
}) })
} }
} }

View file

@ -1,17 +1,10 @@
pub mod api_routes_http; pub mod api_routes_http;
pub mod code_migrations; pub mod code_migrations;
pub mod prometheus_metrics; pub mod prometheus_metrics;
pub mod root_span_builder;
pub mod scheduled_tasks; pub mod scheduled_tasks;
pub mod session_middleware; pub mod session_middleware;
#[cfg(feature = "console")]
pub mod telemetry;
use crate::{ use crate::{code_migrations::run_advanced_migrations, session_middleware::SessionMiddleware};
code_migrations::run_advanced_migrations,
root_span_builder::QuieterRootSpanBuilder,
session_middleware::SessionMiddleware,
};
use activitypub_federation::config::{FederationConfig, FederationMiddleware}; use activitypub_federation::config::{FederationConfig, FederationMiddleware};
use actix_cors::Cors; use actix_cors::Cors;
use actix_web::{ use actix_web::{
@ -55,14 +48,9 @@ use prometheus_metrics::serve_prometheus;
use reqwest_middleware::ClientBuilder; use reqwest_middleware::ClientBuilder;
use reqwest_tracing::TracingMiddleware; use reqwest_tracing::TracingMiddleware;
use serde_json::json; use serde_json::json;
use std::{env, ops::Deref, time::Duration}; use std::{ops::Deref, time::Duration};
use tokio::signal::unix::SignalKind; use tokio::signal::unix::SignalKind;
use tracing::subscriber::set_global_default; use tracing_actix_web::{DefaultRootSpanBuilder, TracingLogger};
use tracing_actix_web::TracingLogger;
use tracing_error::ErrorLayer;
use tracing_log::LogTracer;
use tracing_subscriber::{filter::Targets, layer::SubscriberExt, Layer, Registry};
use url::Url;
/// Timeout for HTTP requests while sending activities. A longer timeout provides better /// Timeout for HTTP requests while sending activities. A longer timeout provides better
/// compatibility with other ActivityPub software that might allocate more time for synchronous /// compatibility with other ActivityPub software that might allocate more time for synchronous
@ -119,7 +107,7 @@ pub struct CmdArgs {
/// Placing the main function in lib.rs allows other crates to import it and embed Lemmy /// Placing the main function in lib.rs allows other crates to import it and embed Lemmy
pub async fn start_lemmy_server(args: CmdArgs) -> LemmyResult<()> { pub async fn start_lemmy_server(args: CmdArgs) -> LemmyResult<()> {
// Print version number to log // Print version number to log
println!("Lemmy v{VERSION}"); println!("Starting Lemmy v{VERSION}");
// return error 503 while running db migrations and startup tasks // return error 503 while running db migrations and startup tasks
let mut startup_server_handle = None; let mut startup_server_handle = None;
@ -318,7 +306,7 @@ fn create_http_server(
)) ))
.wrap(middleware::Compress::default()) .wrap(middleware::Compress::default())
.wrap(cors_config) .wrap(cors_config)
.wrap(TracingLogger::<QuieterRootSpanBuilder>::new()) .wrap(TracingLogger::<DefaultRootSpanBuilder>::new())
.wrap(ErrorHandlers::new().default_handler(jsonify_plain_text_errors)) .wrap(ErrorHandlers::new().default_handler(jsonify_plain_text_errors))
.app_data(Data::new(context.clone())) .app_data(Data::new(context.clone()))
.app_data(Data::new(rate_limit_cell.clone())) .app_data(Data::new(rate_limit_cell.clone()))
@ -373,38 +361,3 @@ fn cors_config(settings: &Settings) -> Cors {
.max_age(3600), .max_age(3600),
} }
} }
pub fn init_logging(opentelemetry_url: &Option<Url>) -> LemmyResult<()> {
LogTracer::init()?;
let log_description = env::var("RUST_LOG").unwrap_or_else(|_| "info".into());
let targets = log_description
.trim()
.trim_matches('"')
.parse::<Targets>()?;
let format_layer = {
#[cfg(feature = "json-log")]
let layer = tracing_subscriber::fmt::layer().with_ansi(false).json();
#[cfg(not(feature = "json-log"))]
let layer = tracing_subscriber::fmt::layer().with_ansi(false);
layer.with_filter(targets.clone())
};
let subscriber = Registry::default()
.with(format_layer)
.with(ErrorLayer::default());
if let Some(_url) = opentelemetry_url {
#[cfg(feature = "console")]
telemetry::init_tracing(_url.as_ref(), subscriber, targets)?;
#[cfg(not(feature = "console"))]
tracing::error!("Feature `console` must be enabled for opentelemetry tracing");
} else {
set_global_default(subscriber)?;
}
Ok(())
}

View file

@ -1,12 +1,18 @@
use clap::Parser; use clap::Parser;
use lemmy_server::{init_logging, start_lemmy_server, CmdArgs}; use lemmy_server::{start_lemmy_server, CmdArgs};
use lemmy_utils::{error::LemmyResult, settings::SETTINGS}; use lemmy_utils::error::LemmyResult;
use tracing::level_filters::LevelFilter;
use tracing_subscriber::EnvFilter;
pub extern crate rustls; pub extern crate rustls;
#[tokio::main] #[tokio::main]
pub async fn main() -> LemmyResult<()> { pub async fn main() -> LemmyResult<()> {
init_logging(&SETTINGS.opentelemetry_url)?; let filter = EnvFilter::builder()
.with_default_directive(LevelFilter::INFO.into())
.from_env_lossy();
tracing_subscriber::fmt().with_env_filter(filter).init();
let args = CmdArgs::parse(); let args = CmdArgs::parse();
rustls::crypto::ring::default_provider() rustls::crypto::ring::default_provider()

View file

@ -1,83 +0,0 @@
use actix_web::{http::StatusCode, ResponseError};
use tracing::Span;
use tracing_actix_web::RootSpanBuilder;
// Code in this module adapted from DefaultRootSpanBuilder
// https://github.com/LukeMathWalker/tracing-actix-web/blob/main/src/root_span_builder.rs
// and root_span!
// https://github.com/LukeMathWalker/tracing-actix-web/blob/main/src/root_span_macro.rs
pub struct QuieterRootSpanBuilder;
impl RootSpanBuilder for QuieterRootSpanBuilder {
fn on_request_start(request: &actix_web::dev::ServiceRequest) -> Span {
let request_id = tracing_actix_web::root_span_macro::private::get_request_id(request);
tracing::info_span!(
"HTTP request",
http.method = %request.method(),
http.scheme = request.connection_info().scheme(),
http.host = %request.connection_info().host(),
http.target = %request.uri().path(),
http.status_code = tracing::field::Empty,
otel.kind = "server",
otel.status_code = tracing::field::Empty,
trace_id = tracing::field::Empty,
request_id = %request_id,
exception.message = tracing::field::Empty,
// Not proper OpenTelemetry, but their terminology is fairly exception-centric
exception.details = tracing::field::Empty,
)
}
fn on_request_end<B>(
span: tracing::Span,
outcome: &Result<actix_web::dev::ServiceResponse<B>, actix_web::Error>,
) {
match &outcome {
Ok(response) => {
if let Some(error) = response.response().error() {
// use the status code already constructed for the outgoing HTTP response
handle_error(span, response.status(), error.as_response_error());
} else {
let code: i32 = response.response().status().as_u16().into();
span.record("http.status_code", code);
span.record("otel.status_code", "OK");
}
}
Err(error) => {
let response_error = error.as_response_error();
handle_error(span, response_error.status_code(), response_error);
}
};
}
}
fn handle_error(span: Span, status_code: StatusCode, response_error: &dyn ResponseError) {
let code: i32 = status_code.as_u16().into();
span.record("http.status_code", code);
if status_code.is_client_error() {
span.record("otel.status_code", "OK");
} else {
span.record("otel.status_code", "ERROR");
}
// pre-formatting errors is a workaround for https://github.com/tokio-rs/tracing/issues/1565
let display_error = format!("{response_error}");
tracing::info_span!(
parent: None,
"Error encountered while processing the incoming HTTP request"
)
.in_scope(|| {
if status_code.is_client_error() {
tracing::warn!("{}", display_error);
} else {
tracing::error!("{}", display_error);
}
});
span.record("exception.message", tracing::field::display(display_error));
}

View file

@ -1,47 +0,0 @@
use console_subscriber::ConsoleLayer;
use lemmy_utils::error::LemmyResult;
use opentelemetry::{
sdk::{propagation::TraceContextPropagator, Resource},
KeyValue,
};
use opentelemetry_otlp::WithExportConfig;
use tracing::{subscriber::set_global_default, Subscriber};
use tracing_subscriber::{filter::Targets, layer::SubscriberExt, registry::LookupSpan, Layer};
pub fn init_tracing<S>(opentelemetry_url: &str, subscriber: S, targets: Targets) -> LemmyResult<()>
where
S: Subscriber + for<'a> LookupSpan<'a> + Send + Sync + 'static,
{
opentelemetry::global::set_text_map_propagator(TraceContextPropagator::new());
let console_layer = ConsoleLayer::builder()
.with_default_env()
.server_addr(([0, 0, 0, 0], 6669))
.event_buffer_capacity(1024 * 1024)
.spawn();
let subscriber = subscriber.with(console_layer);
let tracer = opentelemetry_otlp::new_pipeline()
.tracing()
.with_trace_config(
opentelemetry::sdk::trace::config()
.with_resource(Resource::new(vec![KeyValue::new("service.name", "lemmy")])),
)
.with_exporter(
opentelemetry_otlp::new_exporter()
.tonic()
.with_endpoint(opentelemetry_url),
)
.install_batch(opentelemetry::runtime::Tokio)?;
let otel_layer = tracing_opentelemetry::layer()
.with_tracer(tracer)
.with_filter(targets);
let subscriber = subscriber.with(otel_layer);
set_global_default(subscriber)?;
Ok(())
}