use std::sync::atomic::{AtomicU64, Ordering};
use serde::{Deserialize, Serialize};
pub static PHP_EMBED_METRICS: PhpEmbedMetrics = PhpEmbedMetrics::new();
pub struct PhpEmbedMetrics {
pub requests_in_flight: AtomicU64,
pub requests_total: AtomicU64,
pub bailouts_total: AtomicU64,
pub request_bytes_total: AtomicU64,
pub response_bytes_total: AtomicU64,
pub threads_spawned_total: AtomicU64,
pub threads_active: AtomicU64,
pub engine_errors_total: AtomicU64,
}
impl PhpEmbedMetrics {
pub const fn new() -> Self {
Self {
requests_in_flight: AtomicU64::new(0),
requests_total: AtomicU64::new(0),
bailouts_total: AtomicU64::new(0),
request_bytes_total: AtomicU64::new(0),
response_bytes_total: AtomicU64::new(0),
threads_spawned_total: AtomicU64::new(0),
threads_active: AtomicU64::new(0),
engine_errors_total: AtomicU64::new(0),
}
}
#[inline]
pub fn request_start(&self) {
self.requests_in_flight.fetch_add(1, Ordering::Relaxed);
self.requests_total.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn request_end(&self) {
self.requests_in_flight.fetch_sub(1, Ordering::Relaxed);
}
#[inline]
pub fn bailout(&self) {
self.bailouts_total.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn add_request_bytes(
&self,
n: u64,
) {
self.request_bytes_total.fetch_add(n, Ordering::Relaxed);
}
#[inline]
pub fn add_response_bytes(
&self,
n: u64,
) {
self.response_bytes_total.fetch_add(n, Ordering::Relaxed);
}
#[inline]
pub fn thread_spawned(&self) {
self.threads_spawned_total.fetch_add(1, Ordering::Relaxed);
self.threads_active.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn thread_exited(&self) {
self.threads_active.fetch_sub(1, Ordering::Relaxed);
}
#[inline]
pub fn engine_error(&self) {
self.engine_errors_total.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn requests_in_flight(&self) -> u64 {
self.requests_in_flight.load(Ordering::Relaxed)
}
#[inline]
pub fn requests_total(&self) -> u64 {
self.requests_total.load(Ordering::Relaxed)
}
#[inline]
pub fn bailouts_total(&self) -> u64 {
self.bailouts_total.load(Ordering::Relaxed)
}
#[inline]
pub fn request_bytes_total(&self) -> u64 {
self.request_bytes_total.load(Ordering::Relaxed)
}
#[inline]
pub fn response_bytes_total(&self) -> u64 {
self.response_bytes_total.load(Ordering::Relaxed)
}
#[inline]
pub fn threads_spawned_total(&self) -> u64 {
self.threads_spawned_total.load(Ordering::Relaxed)
}
#[inline]
pub fn threads_active(&self) -> u64 {
self.threads_active.load(Ordering::Relaxed)
}
#[inline]
pub fn engine_errors_total(&self) -> u64 {
self.engine_errors_total.load(Ordering::Relaxed)
}
pub fn snapshot(&self) -> PhpEmbedMetricsSnapshot {
PhpEmbedMetricsSnapshot {
requests_in_flight: self.requests_in_flight(),
requests_total: self.requests_total(),
bailouts_total: self.bailouts_total(),
request_bytes_total: self.request_bytes_total(),
response_bytes_total: self.response_bytes_total(),
threads_spawned_total: self.threads_spawned_total(),
threads_active: self.threads_active(),
engine_errors_total: self.engine_errors_total(),
}
}
pub fn write_prometheus(
&self,
output: &mut String,
) {
self.snapshot().write_prometheus(output);
}
}
impl Default for PhpEmbedMetrics {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct PhpEmbedMetricsSnapshot {
pub requests_in_flight: u64,
pub requests_total: u64,
pub bailouts_total: u64,
pub request_bytes_total: u64,
pub response_bytes_total: u64,
pub threads_spawned_total: u64,
pub threads_active: u64,
pub engine_errors_total: u64,
}
impl PhpEmbedMetricsSnapshot {
pub fn capture() -> Self {
PHP_EMBED_METRICS.snapshot()
}
pub fn merge(
&mut self,
other: &Self,
) {
self.requests_in_flight += other.requests_in_flight;
self.requests_total += other.requests_total;
self.bailouts_total += other.bailouts_total;
self.request_bytes_total += other.request_bytes_total;
self.response_bytes_total += other.response_bytes_total;
self.threads_spawned_total += other.threads_spawned_total;
self.threads_active += other.threads_active;
self.engine_errors_total += other.engine_errors_total;
}
pub fn write_prometheus(
&self,
output: &mut String,
) {
use std::fmt::Write as _;
let _ = writeln!(
output,
"# HELP claviron_ephp_requests_inflight Currently-running E-PHP requests"
);
let _ =
writeln!(output, "# TYPE claviron_ephp_requests_inflight gauge");
let _ = writeln!(
output,
"claviron_ephp_requests_inflight {}",
self.requests_in_flight
);
let _ = writeln!(
output,
"# HELP claviron_ephp_requests_total Total E-PHP requests served"
);
let _ = writeln!(output, "# TYPE claviron_ephp_requests_total counter");
let _ = writeln!(
output,
"claviron_ephp_requests_total {}",
self.requests_total
);
let _ = writeln!(
output,
"# HELP claviron_ephp_bailouts_total Zend bailouts during E-PHP execution"
);
let _ = writeln!(output, "# TYPE claviron_ephp_bailouts_total counter");
let _ = writeln!(
output,
"claviron_ephp_bailouts_total {}",
self.bailouts_total
);
let _ = writeln!(
output,
"# HELP claviron_ephp_request_bytes_total Total request body bytes fed to E-PHP"
);
let _ = writeln!(
output,
"# TYPE claviron_ephp_request_bytes_total counter"
);
let _ = writeln!(
output,
"claviron_ephp_request_bytes_total {}",
self.request_bytes_total
);
let _ = writeln!(
output,
"# HELP claviron_ephp_response_bytes_total Total response body bytes emitted by E-PHP"
);
let _ = writeln!(
output,
"# TYPE claviron_ephp_response_bytes_total counter"
);
let _ = writeln!(
output,
"claviron_ephp_response_bytes_total {}",
self.response_bytes_total
);
let _ = writeln!(
output,
"# HELP claviron_ephp_threads_spawned_total Total E-PHP SAPI threads spawned (lifetime)"
);
let _ = writeln!(
output,
"# TYPE claviron_ephp_threads_spawned_total counter"
);
let _ = writeln!(
output,
"claviron_ephp_threads_spawned_total {}",
self.threads_spawned_total
);
let _ = writeln!(
output,
"# HELP claviron_ephp_threads_active Currently-alive E-PHP SAPI threads"
);
let _ = writeln!(output, "# TYPE claviron_ephp_threads_active gauge");
let _ = writeln!(
output,
"claviron_ephp_threads_active {}",
self.threads_active
);
let _ = writeln!(
output,
"# HELP claviron_ephp_engine_errors_total E-PHP engine errors blocking request service"
);
let _ = writeln!(
output,
"# TYPE claviron_ephp_engine_errors_total counter"
);
let _ = writeln!(
output,
"claviron_ephp_engine_errors_total {}",
self.engine_errors_total
);
}
}