diff --git a/Dockerfile b/Dockerfile index 3061f94..2b494ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -62,10 +62,10 @@ WORKDIR /app COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/website ./ COPY ./static ./static COPY ./templates ./templates -COPY ./posts ./posts +COPY ./pages ./pages COPY ./config.toml ./config.toml -EXPOSE 8180 +EXPOSE 8080 # Use an unprivileged user. USER website:website diff --git a/compose.yaml b/compose.yaml index 4381ea8..0843626 100644 --- a/compose.yaml +++ b/compose.yaml @@ -2,15 +2,17 @@ name: "tlxite" services: web: build: . + restart: unless-stopped ports: - "8080:8080" depends_on: - otel-collector environment: TLX_OTLP_ENABLED: true + TLX_LOG: debug otel-collector: image: otel/opentelemetry-collector:latest - restart: always + restart: unless-stopped command: ["--config=/etc/otel-collector-config.yaml", "${OTELCOL_ARGS}"] volumes: - ./otel-collector-config.yaml:/etc/otel-collector-config.yaml diff --git a/config.toml b/config.toml index db52b75..f655277 100644 --- a/config.toml +++ b/config.toml @@ -4,7 +4,7 @@ bind_address = "0.0.0.0:8080" logging = "info,website=debug" [otlp] -enabled = false +enabled = true endpoint = "http://otel-collector:4317" authorization = "Basic YWRyaWFuQHRvbGx5eC5uZXQ6N3VHVDU1NGpudGdxVE5LMg==" organization = "default" diff --git a/pages/index.md b/pages/index.md index 85485fe..18be4a4 100644 --- a/pages/index.md +++ b/pages/index.md @@ -18,8 +18,10 @@ anyway here's a new todo list: - [x] docker from-scratch image (it's small!) - [x] opentelemetry (metrics, traces) - [ ] opentelemetry logs? (don't know if I'm gonna need it? can probably just make the collector grab them from the docker logs?) -- [ ] sections (currently the posts page is hardcoded, should be able to turn any page-subfolder into its own section) +- [ ] sections (currently the posts page is hardcoded, should be able to turn any page-subfolder into its own section) __👈 NEXT__ - [ ] file-watching (rebuild pages when they're changed, not only on startup) + - [ ] live-reload (I guess it's done by some js and a websocket that sends a message to the browser to reload?) +- [ ] custom - [ ] ~~sass/less compilation~~ (don't think I need it, will skip for now) - [ ] fancy css (but nothing too fancy, I like it [Simple And Clean](https://youtu.be/0nKizH5TV_g?t=42)) - [ ] other pages (now I've got it set up so I can write any page in markdown!!!) diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 7e0cb12..b3dcd54 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -26,7 +26,9 @@ async fn record_hit(method: String, path: String) { .get_or_init(|| async { global::meter("tlxite").u64_counter("page_hit_count").init() }) .await; - counter.add(1, &[KeyValue::new("path", format!("{method} {path}"))]); + counter.add(1, &[ + KeyValue::new("path", format!("{method} {path}")), + ]); } pub fn routes() -> Router> { diff --git a/src/handlers/pages.rs b/src/handlers/pages.rs index 6551fe9..f377366 100644 --- a/src/handlers/pages.rs +++ b/src/handlers/pages.rs @@ -178,6 +178,7 @@ pub async fn feed( .into_response()) } +#[instrument] async fn get_static_file(base_dir: &str, uri: Uri) -> Result { let req = Request::builder().uri(uri).body(Body::empty()).unwrap(); diff --git a/src/hilighting.rs b/src/hilighting.rs index e4bcb9b..80d5b5a 100644 --- a/src/hilighting.rs +++ b/src/hilighting.rs @@ -1,7 +1,7 @@ use syntect::{highlighting::ThemeSet, parsing::SyntaxSet}; use tracing::{error, instrument}; -#[instrument(skip(content, lang, theme))] +#[instrument(skip(content))] pub fn hilight(content: &str, lang: &str, theme: Option<&str>) -> anyhow::Result { let ss = SyntaxSet::load_defaults_newlines(); let s = ss diff --git a/src/observability.rs b/src/observability.rs index c97b6bf..2e20f11 100644 --- a/src/observability.rs +++ b/src/observability.rs @@ -3,16 +3,13 @@ use std::{borrow::Cow, net::SocketAddr, time::Duration}; use anyhow::{Error, Result}; use axum::{ extract::{ConnectInfo, MatchedPath, OriginalUri, Request}, - http::{header, uri::PathAndQuery, HeaderMap}, + http::{header, HeaderMap}, response::Response, }; use opentelemetry::{global, KeyValue}; use opentelemetry_otlp::WithExportConfig; use opentelemetry_sdk::{ - metrics::reader::{DefaultAggregationSelector, DefaultTemporalitySelector}, - propagation::TraceContextPropagator, - trace::{RandomIdGenerator, Sampler}, - Resource, + metrics::reader::{DefaultAggregationSelector, DefaultTemporalitySelector}, propagation::TraceContextPropagator, trace::{RandomIdGenerator, Sampler}, Resource }; use tracing::{field::Empty, info_span, Span}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; @@ -21,6 +18,7 @@ use crate::settings::Settings; pub fn init(cfg: &Settings) -> Result<(), Error> { let filter = EnvFilter::builder() + .with_env_var("TLX_LOG") .with_default_directive("info".parse()?) .parse_lossy(&cfg.logging); @@ -74,7 +72,8 @@ pub fn init(cfg: &Settings) -> Result<(), Error> { .with(otel_tracer) .with(tracing_subscriber::fmt::layer().compact()) .init(); - } else { + } + else { tracing_subscriber::registry() .with(filter) .with(tracing_subscriber::fmt::layer().compact()) @@ -90,22 +89,19 @@ pub fn make_span(req: &Request) -> Span { } else { req.uri() }; + let path = uri.path(); let route = req .extensions() .get::() - .map_or(uri.path(), axum::extract::MatchedPath::as_str); + .map_or(path, axum::extract::MatchedPath::as_str); let method = req.method().as_str(); let scheme = req.uri().scheme().map_or("HTTP", |s| s.as_str()); - let target = uri - .path_and_query() - .map_or(uri.path(), PathAndQuery::as_str); let user_agent = req .headers() .get(header::USER_AGENT) .map_or("", |h| h.to_str().unwrap_or("")); - let name = format!("{method} {route}"); let client_ip = parse_x_forwarded_for(req.headers()) .or_else(|| { @@ -116,16 +112,17 @@ pub fn make_span(req: &Request) -> Span { .unwrap_or_default(); info_span!( - "request", - otel.name = %name, + "http request", + otel.name = %format!("{method} {route}"), otel.kind = &"server", - http.client_ip = %client_ip, + client.address = %client_ip, http.route = %route, - http.method = %method, - http.target = %target, - http.scheme = %scheme, - http.user_agent = %user_agent, - http.status_code = Empty, + http.request.method = %method, + url.scheme = %scheme, + url.path = %path, + url.query = %uri.query().unwrap_or_default(), + user_agent.original = %user_agent, + http.response.status_code = Empty, otel.status_code = Empty, ) } @@ -138,7 +135,7 @@ fn parse_x_forwarded_for(headers: &HeaderMap) -> Option> { } pub fn on_response(response: &Response, _latency: Duration, span: &Span) { - span.record("http.status_code", response.status().as_str()); + span.record("http.response.status_code", response.status().as_str()); if response.status().is_server_error() { span.record( "otel.status_code",