pred
This commit is contained in:
parent
3a6d29b4cb
commit
7928ec9588
5 changed files with 177 additions and 0 deletions
32
Cargo.toml
Normal file
32
Cargo.toml
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
[package]
|
||||||
|
name = "pred"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
axum = { version = "0.6.20", features = ["macros", "headers"] }
|
||||||
|
reqwest = "0.11"
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
select = "0.5"
|
||||||
|
dotenvy = "~0"
|
||||||
|
cfg-if = "~1"
|
||||||
|
|
||||||
|
# -- Tracing
|
||||||
|
tracing-subscriber = { version = "0.3.16", features = ["env-filter", "json", "std"], optional = true }
|
||||||
|
tracing = { version = "~0", features = ["log", "log-always"] }
|
||||||
|
opentelemetry = {version ="0.20.0", features = ["rt-tokio"], optional = true }
|
||||||
|
opentelemetry-otlp = { version = "0.13.0", optional = true }
|
||||||
|
tracing-opentelemetry = { version = "0.21.0", optional = true }
|
||||||
|
tracing-log = { version = "~0", optional = true, features = ["env_logger"] }
|
||||||
|
tracing-bunyan-formatter = { version = "0.3.9", optional = true }
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
thiserror = "~1"
|
||||||
|
log = "~0"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["tracing", "bunyan"]
|
||||||
|
tracing = ["tracing-log", "tracing-subscriber", "tracing-opentelemetry", "opentelemetry", "opentelemetry-otlp"]
|
||||||
|
bunyan = ["tracing-bunyan-formatter"]
|
||||||
29
src/error.rs
Normal file
29
src/error.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
use opentelemetry::trace::TraceError;
|
||||||
|
|
||||||
|
pub type Result<T> = core::result::Result<T, Error>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
TraceErr(String),
|
||||||
|
SetGlobalDefaultErr(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<tracing::subscriber::SetGlobalDefaultError> for Error {
|
||||||
|
fn from(_: tracing::subscriber::SetGlobalDefaultError) -> Self {
|
||||||
|
Error::SetGlobalDefaultErr("Set global err".to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TraceError> for Error {
|
||||||
|
fn from(_: TraceError) -> Self {
|
||||||
|
Error::TraceErr("Trace err".to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl core::fmt::Display for Error {
|
||||||
|
fn fmt(
|
||||||
|
&self,
|
||||||
|
fmt: &mut core::fmt::Formatter,
|
||||||
|
) -> core::result::Result<(), core::fmt::Error> {
|
||||||
|
write!(fmt, "{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
47
src/main.rs
Normal file
47
src/main.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
|
||||||
|
// use crate::observability;
|
||||||
|
|
||||||
|
mod observability;
|
||||||
|
mod error;
|
||||||
|
use axum::{response::Html, routing::get, Router};
|
||||||
|
use tracing::debug;
|
||||||
|
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> error::Result<()> {
|
||||||
|
|
||||||
|
// Set up a tracing subscriber with JSON formatting
|
||||||
|
tracing_log::LogTracer::builder()
|
||||||
|
.ignore_crate("sqlx")
|
||||||
|
.with_max_level(log::LevelFilter::Info)
|
||||||
|
.init()
|
||||||
|
.expect("could not initialize log tracer");
|
||||||
|
|
||||||
|
match observability::configure_observability().await {
|
||||||
|
Ok(_) => {
|
||||||
|
tracing::debug!("tracing configured");
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
tracing::error!("error configuring tracing: {}", err);
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// build our application with a route
|
||||||
|
let app = Router::new().route("/", get(handler));
|
||||||
|
|
||||||
|
// run it
|
||||||
|
debug!("listening on 0.0.0.0:3000");
|
||||||
|
|
||||||
|
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
|
||||||
|
.serve(app.into_make_service())
|
||||||
|
.await
|
||||||
|
.expect("server failed");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
async fn handler() -> Html<&'static str> {
|
||||||
|
Html("<h1>Hello, World!</h1>")
|
||||||
|
}
|
||||||
1
src/mod.rs
Normal file
1
src/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod observability;
|
||||||
68
src/observability.rs
Executable file
68
src/observability.rs
Executable file
|
|
@ -0,0 +1,68 @@
|
||||||
|
use opentelemetry_otlp::WithExportConfig;
|
||||||
|
use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer};
|
||||||
|
use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt;
|
||||||
|
use crate::error::Result;
|
||||||
|
use tracing::debug;
|
||||||
|
|
||||||
|
const OTEL_EXPORTER_OTLP_ENDPOINT_ENV_VAR: &str = "OTEL_EXPORTER_OTLP_ENDPOINT";
|
||||||
|
const OTEL_EXPORTER_OTLP_ENDPOINT_DEFAULT: &str = "http://localhost:4317";
|
||||||
|
|
||||||
|
const OBSERVABILITY_SERVICE_NAME_ENV_VAR: &str = "OBSERVABILITY_SERVICE_NAME";
|
||||||
|
const OBSERVABILITY_SERVICE_NAME_DEFAULT: &str = "pred";
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
pub async fn configure_observability() -> Result<()> {
|
||||||
|
debug!("{:<12} - configure_observability", "fn");
|
||||||
|
|
||||||
|
let otel_exporter_endpoint =
|
||||||
|
dotenvy::var(OTEL_EXPORTER_OTLP_ENDPOINT_ENV_VAR).unwrap_or_else(|_| {
|
||||||
|
tracing::warn!(
|
||||||
|
"{} Env var not set, using default",
|
||||||
|
OTEL_EXPORTER_OTLP_ENDPOINT_DEFAULT
|
||||||
|
);
|
||||||
|
OTEL_EXPORTER_OTLP_ENDPOINT_DEFAULT.to_string()
|
||||||
|
});
|
||||||
|
|
||||||
|
let observability_service_name = dotenvy::var(OBSERVABILITY_SERVICE_NAME_ENV_VAR)
|
||||||
|
.unwrap_or_else(|_| OBSERVABILITY_SERVICE_NAME_DEFAULT.to_string());
|
||||||
|
|
||||||
|
let tracer = opentelemetry_otlp::new_pipeline()
|
||||||
|
.tracing()
|
||||||
|
.with_exporter(
|
||||||
|
opentelemetry_otlp::new_exporter()
|
||||||
|
.tonic()
|
||||||
|
.with_endpoint(otel_exporter_endpoint),
|
||||||
|
)
|
||||||
|
.with_trace_config(opentelemetry::sdk::trace::config().with_resource(
|
||||||
|
opentelemetry::sdk::Resource::new(vec![opentelemetry::KeyValue::new(
|
||||||
|
"service.name",
|
||||||
|
observability_service_name.clone(),
|
||||||
|
)]),
|
||||||
|
))
|
||||||
|
.install_batch(opentelemetry::runtime::Tokio)?;
|
||||||
|
|
||||||
|
// Create a tracing layer with the configured tracer
|
||||||
|
let telemetry_layer = tracing_opentelemetry::layer().with_tracer(tracer);
|
||||||
|
|
||||||
|
let filter = tracing_subscriber::EnvFilter::from_default_env();
|
||||||
|
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(feature="bunyan")] {
|
||||||
|
// Create a new formatting layer to print bunyan formatted logs to stdout, pipe into bunyan to view
|
||||||
|
let formatting_layer = BunyanFormattingLayer::new(observability_service_name, std::io::stdout);
|
||||||
|
let subscriber = tracing_subscriber::Registry::default()
|
||||||
|
.with(filter)
|
||||||
|
.with(telemetry_layer)
|
||||||
|
.with(JsonStorageLayer)
|
||||||
|
.with(formatting_layer);
|
||||||
|
} else {
|
||||||
|
let subscriber = tracing_subscriber::Registry::default()
|
||||||
|
.with_filter(filter)
|
||||||
|
.with_writer(std::io::stdout)
|
||||||
|
.with(telemetry_layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(tracing::subscriber::set_global_default(subscriber)?)
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue