1
0
Fork 0
This commit is contained in:
Adrian Hedqvist 2024-04-23 20:09:11 +02:00
parent 035bc89310
commit 63f474c7af
Signed by: tollyx
SSH key fingerprint: SHA256:NqZilNUilqR38F1LQMrz2E65ZsA621eT3lO+FqHS48Y
8 changed files with 31 additions and 27 deletions

View file

@ -62,10 +62,10 @@ WORKDIR /app
COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/website ./ COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/website ./
COPY ./static ./static COPY ./static ./static
COPY ./templates ./templates COPY ./templates ./templates
COPY ./posts ./posts COPY ./pages ./pages
COPY ./config.toml ./config.toml COPY ./config.toml ./config.toml
EXPOSE 8180 EXPOSE 8080
# Use an unprivileged user. # Use an unprivileged user.
USER website:website USER website:website

View file

@ -2,15 +2,17 @@ name: "tlxite"
services: services:
web: web:
build: . build: .
restart: unless-stopped
ports: ports:
- "8080:8080" - "8080:8080"
depends_on: depends_on:
- otel-collector - otel-collector
environment: environment:
TLX_OTLP_ENABLED: true TLX_OTLP_ENABLED: true
TLX_LOG: debug
otel-collector: otel-collector:
image: otel/opentelemetry-collector:latest image: otel/opentelemetry-collector:latest
restart: always restart: unless-stopped
command: ["--config=/etc/otel-collector-config.yaml", "${OTELCOL_ARGS}"] command: ["--config=/etc/otel-collector-config.yaml", "${OTELCOL_ARGS}"]
volumes: volumes:
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml - ./otel-collector-config.yaml:/etc/otel-collector-config.yaml

View file

@ -4,7 +4,7 @@ bind_address = "0.0.0.0:8080"
logging = "info,website=debug" logging = "info,website=debug"
[otlp] [otlp]
enabled = false enabled = true
endpoint = "http://otel-collector:4317" endpoint = "http://otel-collector:4317"
authorization = "Basic YWRyaWFuQHRvbGx5eC5uZXQ6N3VHVDU1NGpudGdxVE5LMg==" authorization = "Basic YWRyaWFuQHRvbGx5eC5uZXQ6N3VHVDU1NGpudGdxVE5LMg=="
organization = "default" organization = "default"

View file

@ -18,8 +18,10 @@ anyway here's a new todo list:
- [x] docker from-scratch image (it's small!) - [x] docker from-scratch image (it's small!)
- [x] opentelemetry (metrics, traces) - [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?) - [ ] 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) - [ ] 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) - [ ] ~~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)) - [ ] 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!!!) - [ ] other pages (now I've got it set up so I can write any page in markdown!!!)

View file

@ -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() }) .get_or_init(|| async { global::meter("tlxite").u64_counter("page_hit_count").init() })
.await; .await;
counter.add(1, &[KeyValue::new("path", format!("{method} {path}"))]); counter.add(1, &[
KeyValue::new("path", format!("{method} {path}")),
]);
} }
pub fn routes() -> Router<Arc<AppState>> { pub fn routes() -> Router<Arc<AppState>> {

View file

@ -178,6 +178,7 @@ pub async fn feed(
.into_response()) .into_response())
} }
#[instrument]
async fn get_static_file(base_dir: &str, uri: Uri) -> Result<Response, WebsiteError> { async fn get_static_file(base_dir: &str, uri: Uri) -> Result<Response, WebsiteError> {
let req = Request::builder().uri(uri).body(Body::empty()).unwrap(); let req = Request::builder().uri(uri).body(Body::empty()).unwrap();

View file

@ -1,7 +1,7 @@
use syntect::{highlighting::ThemeSet, parsing::SyntaxSet}; use syntect::{highlighting::ThemeSet, parsing::SyntaxSet};
use tracing::{error, instrument}; use tracing::{error, instrument};
#[instrument(skip(content, lang, theme))] #[instrument(skip(content))]
pub fn hilight(content: &str, lang: &str, theme: Option<&str>) -> anyhow::Result<String> { pub fn hilight(content: &str, lang: &str, theme: Option<&str>) -> anyhow::Result<String> {
let ss = SyntaxSet::load_defaults_newlines(); let ss = SyntaxSet::load_defaults_newlines();
let s = ss let s = ss

View file

@ -3,16 +3,13 @@ use std::{borrow::Cow, net::SocketAddr, time::Duration};
use anyhow::{Error, Result}; use anyhow::{Error, Result};
use axum::{ use axum::{
extract::{ConnectInfo, MatchedPath, OriginalUri, Request}, extract::{ConnectInfo, MatchedPath, OriginalUri, Request},
http::{header, uri::PathAndQuery, HeaderMap}, http::{header, HeaderMap},
response::Response, response::Response,
}; };
use opentelemetry::{global, KeyValue}; use opentelemetry::{global, KeyValue};
use opentelemetry_otlp::WithExportConfig; use opentelemetry_otlp::WithExportConfig;
use opentelemetry_sdk::{ use opentelemetry_sdk::{
metrics::reader::{DefaultAggregationSelector, DefaultTemporalitySelector}, metrics::reader::{DefaultAggregationSelector, DefaultTemporalitySelector}, propagation::TraceContextPropagator, trace::{RandomIdGenerator, Sampler}, Resource
propagation::TraceContextPropagator,
trace::{RandomIdGenerator, Sampler},
Resource,
}; };
use tracing::{field::Empty, info_span, Span}; use tracing::{field::Empty, info_span, Span};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
@ -21,6 +18,7 @@ use crate::settings::Settings;
pub fn init(cfg: &Settings) -> Result<(), Error> { pub fn init(cfg: &Settings) -> Result<(), Error> {
let filter = EnvFilter::builder() let filter = EnvFilter::builder()
.with_env_var("TLX_LOG")
.with_default_directive("info".parse()?) .with_default_directive("info".parse()?)
.parse_lossy(&cfg.logging); .parse_lossy(&cfg.logging);
@ -74,7 +72,8 @@ pub fn init(cfg: &Settings) -> Result<(), Error> {
.with(otel_tracer) .with(otel_tracer)
.with(tracing_subscriber::fmt::layer().compact()) .with(tracing_subscriber::fmt::layer().compact())
.init(); .init();
} else { }
else {
tracing_subscriber::registry() tracing_subscriber::registry()
.with(filter) .with(filter)
.with(tracing_subscriber::fmt::layer().compact()) .with(tracing_subscriber::fmt::layer().compact())
@ -90,22 +89,19 @@ pub fn make_span(req: &Request) -> Span {
} else { } else {
req.uri() req.uri()
}; };
let path = uri.path();
let route = req let route = req
.extensions() .extensions()
.get::<MatchedPath>() .get::<MatchedPath>()
.map_or(uri.path(), axum::extract::MatchedPath::as_str); .map_or(path, axum::extract::MatchedPath::as_str);
let method = req.method().as_str(); let method = req.method().as_str();
let scheme = req.uri().scheme().map_or("HTTP", |s| s.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 let user_agent = req
.headers() .headers()
.get(header::USER_AGENT) .get(header::USER_AGENT)
.map_or("", |h| h.to_str().unwrap_or("")); .map_or("", |h| h.to_str().unwrap_or(""));
let name = format!("{method} {route}");
let client_ip = parse_x_forwarded_for(req.headers()) let client_ip = parse_x_forwarded_for(req.headers())
.or_else(|| { .or_else(|| {
@ -116,16 +112,17 @@ pub fn make_span(req: &Request) -> Span {
.unwrap_or_default(); .unwrap_or_default();
info_span!( info_span!(
"request", "http request",
otel.name = %name, otel.name = %format!("{method} {route}"),
otel.kind = &"server", otel.kind = &"server",
http.client_ip = %client_ip, client.address = %client_ip,
http.route = %route, http.route = %route,
http.method = %method, http.request.method = %method,
http.target = %target, url.scheme = %scheme,
http.scheme = %scheme, url.path = %path,
http.user_agent = %user_agent, url.query = %uri.query().unwrap_or_default(),
http.status_code = Empty, user_agent.original = %user_agent,
http.response.status_code = Empty,
otel.status_code = Empty, otel.status_code = Empty,
) )
} }
@ -138,7 +135,7 @@ fn parse_x_forwarded_for(headers: &HeaderMap) -> Option<Cow<'_, str>> {
} }
pub fn on_response(response: &Response, _latency: Duration, span: &Span) { 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() { if response.status().is_server_error() {
span.record( span.record(
"otel.status_code", "otel.status_code",