@@ -8,29 +8,94 @@ use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use axum::Router;
|
||||
use axum::extract::State;
|
||||
use axum::http::StatusCode;
|
||||
use axum::response::{Html, IntoResponse, Response};
|
||||
use forage_core::session::{FileSessionStore, SessionStore};
|
||||
use forage_db::PgSessionStore;
|
||||
use minijinja::context;
|
||||
use tower_http::services::ServeDir;
|
||||
use tower_http::trace::TraceLayer;
|
||||
use opentelemetry::trace::TracerProvider as _;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
|
||||
use crate::forest_client::GrpcForestClient;
|
||||
use crate::state::AppState;
|
||||
use crate::templates::TemplateEngine;
|
||||
|
||||
fn init_telemetry() {
|
||||
let env_filter =
|
||||
EnvFilter::try_from_default_env().unwrap_or_else(|_| "info,h2=warn,tonic=info".into());
|
||||
let fmt_layer = tracing_subscriber::fmt::layer();
|
||||
|
||||
if std::env::var("OTEL_EXPORTER_OTLP_ENDPOINT").is_ok() {
|
||||
// OTLP exporter configured — send spans + logs to collector
|
||||
let tracer = opentelemetry_otlp::SpanExporter::builder()
|
||||
.with_tonic()
|
||||
.build()
|
||||
.expect("failed to create OTLP span exporter");
|
||||
|
||||
let tracer_provider = opentelemetry_sdk::trace::SdkTracerProvider::builder()
|
||||
.with_batch_exporter(tracer)
|
||||
.with_resource(
|
||||
opentelemetry_sdk::Resource::builder()
|
||||
.with_service_name(
|
||||
std::env::var("OTEL_SERVICE_NAME")
|
||||
.unwrap_or_else(|_| "forage-server".into()),
|
||||
)
|
||||
.build(),
|
||||
)
|
||||
.build();
|
||||
|
||||
let otel_layer = tracing_opentelemetry::layer()
|
||||
.with_tracer(tracer_provider.tracer("forage-server"));
|
||||
|
||||
tracing_subscriber::registry()
|
||||
.with(env_filter)
|
||||
.with(fmt_layer)
|
||||
.with(otel_layer)
|
||||
.init();
|
||||
|
||||
tracing::info!("OpenTelemetry enabled — exporting to OTLP endpoint");
|
||||
} else {
|
||||
tracing_subscriber::registry()
|
||||
.with(env_filter)
|
||||
.with(fmt_layer)
|
||||
.init();
|
||||
}
|
||||
}
|
||||
|
||||
async fn fallback_404(State(state): State<AppState>) -> Response {
|
||||
let html = state.templates.render(
|
||||
"pages/error.html.jinja",
|
||||
context! {
|
||||
title => "Not Found - Forage",
|
||||
description => "The page you're looking for doesn't exist.",
|
||||
status => 404u16,
|
||||
heading => "Page not found",
|
||||
message => "The page you're looking for doesn't exist.",
|
||||
},
|
||||
);
|
||||
match html {
|
||||
Ok(body) => (StatusCode::NOT_FOUND, Html(body)).into_response(),
|
||||
Err(_) => StatusCode::NOT_FOUND.into_response(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_router(state: AppState) -> Router {
|
||||
Router::new()
|
||||
.merge(routes::router())
|
||||
.nest_service("/static", ServeDir::new("static"))
|
||||
.fallback(fallback_404)
|
||||
.layer(TraceLayer::new_for_http())
|
||||
.with_state(state)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()))
|
||||
.init();
|
||||
init_telemetry();
|
||||
|
||||
let forest_endpoint =
|
||||
std::env::var("FOREST_SERVER_URL").unwrap_or_else(|_| "http://localhost:4040".into());
|
||||
@@ -81,7 +146,8 @@ async fn main() -> anyhow::Result<()> {
|
||||
};
|
||||
|
||||
let forest_client = Arc::new(forest_client);
|
||||
let state = AppState::new(template_engine, forest_client.clone(), forest_client, sessions);
|
||||
let state = AppState::new(template_engine, forest_client.clone(), forest_client.clone(), sessions)
|
||||
.with_grpc_client(forest_client);
|
||||
let app = build_router(state);
|
||||
|
||||
let port: u16 = std::env::var("PORT")
|
||||
|
||||
Reference in New Issue
Block a user