mirror of
https://github.com/katanemo/plano.git
synced 2026-05-27 14:17:15 +02:00
commit
d741fdc2de
2 changed files with 126 additions and 0 deletions
|
|
@ -1,14 +1,24 @@
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use stats::IncrementingMetric;
|
||||||
|
use stats::Metric;
|
||||||
|
use stats::RecordingMetric;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use proxy_wasm::traits::*;
|
use proxy_wasm::traits::*;
|
||||||
use proxy_wasm::types::*;
|
use proxy_wasm::types::*;
|
||||||
|
|
||||||
|
mod stats;
|
||||||
|
|
||||||
proxy_wasm::main! {{
|
proxy_wasm::main! {{
|
||||||
proxy_wasm::set_log_level(LogLevel::Trace);
|
proxy_wasm::set_log_level(LogLevel::Trace);
|
||||||
proxy_wasm::set_root_context(|_| -> Box<dyn RootContext> {
|
proxy_wasm::set_root_context(|_| -> Box<dyn RootContext> {
|
||||||
Box::new(HttpHeaderRoot {
|
Box::new(HttpHeaderRoot {
|
||||||
header_content: String::new(),
|
header_content: String::new(),
|
||||||
|
metrics: WasmMetrics {
|
||||||
|
counter: stats::Counter::new(String::from("wasm_counter")),
|
||||||
|
gauge: stats::Gauge::new(String::from("wasm_gauge")),
|
||||||
|
histogram: stats::Histogram::new(String::from("wasm_histogram")),
|
||||||
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
|
@ -16,6 +26,7 @@ proxy_wasm::main! {{
|
||||||
struct HttpHeader {
|
struct HttpHeader {
|
||||||
context_id: u32,
|
context_id: u32,
|
||||||
header_content: String,
|
header_content: String,
|
||||||
|
metrics: WasmMetrics,
|
||||||
}
|
}
|
||||||
|
|
||||||
// HttpContext is the trait that allows the Rust code to interact with HTTP objects.
|
// HttpContext is the trait that allows the Rust code to interact with HTTP objects.
|
||||||
|
|
@ -23,6 +34,14 @@ impl HttpContext for HttpHeader {
|
||||||
// Envoy's HTTP model is event driven. The WASM ABI has given implementors events to hook onto
|
// Envoy's HTTP model is event driven. The WASM ABI has given implementors events to hook onto
|
||||||
// the lifecycle of the http request and response.
|
// the lifecycle of the http request and response.
|
||||||
fn on_http_request_headers(&mut self, _num_headers: usize, _end_of_stream: bool) -> Action {
|
fn on_http_request_headers(&mut self, _num_headers: usize, _end_of_stream: bool) -> Action {
|
||||||
|
// Metrics
|
||||||
|
self.metrics.counter.increment(10);
|
||||||
|
info!("counter -> {}", self.metrics.counter.value());
|
||||||
|
self.metrics.gauge.record(20);
|
||||||
|
info!("gauge -> {}", self.metrics.gauge.value());
|
||||||
|
self.metrics.histogram.record(30);
|
||||||
|
info!("histogram -> {}", self.metrics.histogram.value());
|
||||||
|
|
||||||
// Example of reading the HTTP headers on the incoming request
|
// Example of reading the HTTP headers on the incoming request
|
||||||
for (name, value) in &self.get_http_request_headers() {
|
for (name, value) in &self.get_http_request_headers() {
|
||||||
info!("#{} -> {}: {}", self.context_id, name, value);
|
info!("#{} -> {}: {}", self.context_id, name, value);
|
||||||
|
|
@ -86,8 +105,16 @@ impl Context for HttpHeader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct WasmMetrics {
|
||||||
|
counter: stats::Counter,
|
||||||
|
gauge: stats::Gauge,
|
||||||
|
histogram: stats::Histogram,
|
||||||
|
}
|
||||||
|
|
||||||
struct HttpHeaderRoot {
|
struct HttpHeaderRoot {
|
||||||
header_content: String,
|
header_content: String,
|
||||||
|
metrics: WasmMetrics,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context for HttpHeaderRoot {}
|
impl Context for HttpHeaderRoot {}
|
||||||
|
|
@ -105,6 +132,7 @@ impl RootContext for HttpHeaderRoot {
|
||||||
Some(Box::new(HttpHeader {
|
Some(Box::new(HttpHeader {
|
||||||
context_id,
|
context_id,
|
||||||
header_content: self.header_content.clone(),
|
header_content: self.header_content.clone(),
|
||||||
|
metrics: self.metrics,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
98
envoyfilter/src/stats.rs
Normal file
98
envoyfilter/src/stats.rs
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
|
||||||
|
use proxy_wasm::hostcalls;
|
||||||
|
use proxy_wasm::types::*;
|
||||||
|
|
||||||
|
pub trait Metric {
|
||||||
|
fn id(&self) -> u32;
|
||||||
|
|
||||||
|
fn value(&self) -> u64 {
|
||||||
|
match hostcalls::get_metric(self.id()) {
|
||||||
|
Ok(value) => value,
|
||||||
|
Err(Status::NotFound) => panic!("metric not found: {}", self.id()),
|
||||||
|
Err(err) => panic!("unexpected status: {:?}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait IncrementingMetric: Metric {
|
||||||
|
fn increment(&self, offset: i64) {
|
||||||
|
match hostcalls::increment_metric(self.id(), offset) {
|
||||||
|
Ok(_) => return,
|
||||||
|
Err(Status::NotFound) => panic!("metric not found: {}", self.id()),
|
||||||
|
Err(err) => panic!("unexpected status: {:?}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait RecordingMetric: Metric {
|
||||||
|
fn record(&self, value: u64) {
|
||||||
|
match hostcalls::record_metric(self.id(), value) {
|
||||||
|
Ok(_) => return,
|
||||||
|
Err(Status::NotFound) => panic!("metric not found: {}", self.id()),
|
||||||
|
Err(err) => panic!("unexpected status: {:?}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Counter {
|
||||||
|
id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Counter {
|
||||||
|
pub fn new(name: String) -> Counter {
|
||||||
|
let returned_id = hostcalls::define_metric(MetricType::Counter, &name)
|
||||||
|
.expect("failed to define counter '{}', name");
|
||||||
|
Counter { id: returned_id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Metric for Counter {
|
||||||
|
fn id(&self) -> u32 {
|
||||||
|
self.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IncrementingMetric for Counter {}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Gauge {
|
||||||
|
id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Gauge {
|
||||||
|
pub fn new(name: String) -> Gauge {
|
||||||
|
let returned_id = hostcalls::define_metric(MetricType::Gauge, &name)
|
||||||
|
.expect("failed to define gauge '{}', name");
|
||||||
|
Gauge { id: returned_id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Metric for Gauge {
|
||||||
|
fn id(&self) -> u32 {
|
||||||
|
self.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RecordingMetric for Gauge {}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Histogram {
|
||||||
|
id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Histogram {
|
||||||
|
pub fn new(name: String) -> Histogram {
|
||||||
|
let returned_id = hostcalls::define_metric(MetricType::Histogram, &name)
|
||||||
|
.expect("failed to define histogram '{}', name");
|
||||||
|
Histogram { id: returned_id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Metric for Histogram {
|
||||||
|
fn id(&self) -> u32 {
|
||||||
|
self.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RecordingMetric for Histogram {}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue