init
This commit is contained in:
commit
aeb2801b56
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
2317
Cargo.lock
generated
Normal file
2317
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
17
Cargo.toml
Normal file
17
Cargo.toml
Normal file
@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "demo"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
opentelemetry = { version = "0.24.0", features = ["metrics", "otel_unstable"] }
|
||||
opentelemetry-prometheus = { version = "0.17.0", features = ["prometheus-encoding"] }
|
||||
# opentelemetry-stdout = { version = "0.26.0", features = ["metrics"] }
|
||||
opentelemetry_sdk = { version = "0.24.0", features = ["metrics", "rt-tokio"] }
|
||||
prometheus = "0.13.4"
|
||||
rocket = "0.5.1"
|
||||
tokio = { version = "1.40.0", features = ["full"] }
|
||||
tracing = "0.1.40"
|
||||
tracing-loki = "0.2.5"
|
||||
tracing-subscriber = "0.3.18"
|
||||
url = "2.5.2"
|
13
README.md
Normal file
13
README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Visable Rocket
|
||||
|
||||
Adding visability to rocket.rs
|
||||
|
||||
In the project you need to specifiy the url that Loki is at.
|
||||
|
||||
Then you need to add this project's url to your prometheus config.
|
||||
```toml
|
||||
scrape_configs:
|
||||
- job_name: rocket
|
||||
static_configs:
|
||||
- targets: ['localhost:8000']
|
||||
```
|
112
src/main.rs
Normal file
112
src/main.rs
Normal file
@ -0,0 +1,112 @@
|
||||
use opentelemetry::{global, metrics::Counter, KeyValue};
|
||||
use prometheus::Registry;
|
||||
use rocket::{fairing::{Fairing, Info, Kind}, get, routes, Request, Response, State};
|
||||
use tracing::error;
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
|
||||
use std::process;
|
||||
use url::Url;
|
||||
|
||||
struct MetricsState {
|
||||
counter: Counter<u64>,
|
||||
}
|
||||
|
||||
#[rocket::main]
|
||||
async fn main() -> Result<(), tracing_loki::Error> {
|
||||
let logs_provider = init_logs_provider("http://127.0.0.1:3100");
|
||||
let (meter_provider, registry) = init_meter_provider();
|
||||
|
||||
// Create a meter from the above MeterProvider.
|
||||
let meter = global::meter("mylibraryname");
|
||||
|
||||
// Create a Counter Instrument.
|
||||
let counter = meter.u64_counter("my_counter").init();
|
||||
|
||||
let _ = rocket::build()
|
||||
.mount("/", routes![metrics, hello_world])
|
||||
.manage(registry)
|
||||
.attach(MetricsState { counter })
|
||||
.launch().await;
|
||||
|
||||
meter_provider.shutdown().unwrap();
|
||||
logs_provider.abort();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
fn hello_world() -> &'static str {
|
||||
"Hello world."
|
||||
}
|
||||
|
||||
// "/metrics" Is where prometheus expects to gather metrics at.
|
||||
// If you change this make sure your prometheus config reflects the change.
|
||||
#[get("/metrics")]
|
||||
fn metrics(state: &State<Registry>) -> String {
|
||||
let mut buffer = String::new();
|
||||
let encoder = prometheus::TextEncoder::new();
|
||||
let metric_families = state.gather();
|
||||
encoder.encode_utf8(&metric_families, &mut buffer).unwrap();
|
||||
buffer
|
||||
}
|
||||
|
||||
fn init_logs_provider(url: &str) -> tokio::task::JoinHandle<()> {
|
||||
// Setup logs
|
||||
let (layer, task) = tracing_loki::builder()
|
||||
/*
|
||||
* Labels are for static things
|
||||
* Fields are for dynamic things
|
||||
*/
|
||||
.label("program", "webserver").expect("Invalid log label name")
|
||||
.extra_field("version", "v1.0").expect("Invalid log field name")
|
||||
.extra_field("pid", format!("{}", process::id())).expect("Invalid log field name")
|
||||
.build_url(Url::parse(url).unwrap()).expect("Invalid log url endpoint");
|
||||
tracing_subscriber::registry()
|
||||
.with(layer)
|
||||
// Stdout if disired:
|
||||
// .with(tracing_subscriber::fmt::Layer::new())
|
||||
.init();
|
||||
tokio::spawn(task)
|
||||
}
|
||||
|
||||
fn init_meter_provider() -> (opentelemetry_sdk::metrics::SdkMeterProvider, Registry) {
|
||||
use opentelemetry_sdk::metrics::SdkMeterProvider;
|
||||
|
||||
let registry = Registry::new();
|
||||
let exporter = opentelemetry_prometheus::exporter()
|
||||
.with_registry(registry.clone())
|
||||
.build().unwrap();
|
||||
let provider = SdkMeterProvider::builder()
|
||||
.with_reader(exporter)
|
||||
// .with_resource(Resource::new([KeyValue::new(
|
||||
// "service.name",
|
||||
// "metrics-basic-example",
|
||||
// )]))
|
||||
.build();
|
||||
global::set_meter_provider(provider.clone());
|
||||
(provider, registry)
|
||||
}
|
||||
|
||||
|
||||
#[rocket::async_trait]
|
||||
impl Fairing for MetricsState {
|
||||
fn info(&self) -> Info {
|
||||
Info {
|
||||
name: "Route metris provider",
|
||||
kind: Kind::Response
|
||||
}
|
||||
}
|
||||
|
||||
async fn on_response<'r>(&self, req: &'r Request<'_>, res: &mut Response<'r>) {
|
||||
let path = req.uri().path().as_str().to_owned();
|
||||
let method = req.method().as_str();
|
||||
let status = res.status().to_string();
|
||||
let query = req.query_fields().map(|f| format!("{}={},", f.name, f.value)).collect::<String>();
|
||||
|
||||
self.counter.add(
|
||||
1, &[
|
||||
KeyValue::new("Path", path),
|
||||
KeyValue::new("Method", method),
|
||||
KeyValue::new("Status", status),
|
||||
KeyValue::new("Query", query),
|
||||
], );
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user