Basic prometheus support, with push_gateway integration.
This commit is contained in:
parent
3256feab1b
commit
cdbaa928c2
1942
rtiow/Cargo.lock
generated
1942
rtiow/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,27 +1,37 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rtiow"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Bill Thiede <rust@xinu.tv>"]
|
authors = ["Bill Thiede <rust@xinu.tv>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
name = "rtiow"
|
||||||
|
version = "0.1.0"
|
||||||
|
[[bench]]
|
||||||
|
harness = false
|
||||||
|
name = "spheres"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rand = "0.5.5"
|
|
||||||
image = "0.19.0"
|
|
||||||
crossbeam-channel = "0.2.4"
|
|
||||||
num_cpus = "1.8.0"
|
|
||||||
rayon = "1.0.2"
|
|
||||||
structopt = "0.2.10"
|
|
||||||
stderrlog = "0.4.1"
|
|
||||||
log = "0.4.5"
|
|
||||||
cpuprofiler = "0.0.3"
|
|
||||||
lazy_static = "1.1.0"
|
|
||||||
askama = "0.7.1"
|
|
||||||
actix-web = "0.7.8"
|
actix-web = "0.7.8"
|
||||||
|
askama = "0.7.1"
|
||||||
|
chrono = "*"
|
||||||
|
cpuprofiler = "0.0.3"
|
||||||
|
crossbeam-channel = "0.2.4"
|
||||||
|
getopts = "*"
|
||||||
|
image = "0.19.0"
|
||||||
|
lazy_static = "1.1.0"
|
||||||
|
log = "0.4.5"
|
||||||
|
num_cpus = "1.8.0"
|
||||||
|
rand = "0.5.5"
|
||||||
|
rayon = "1.0.2"
|
||||||
serde = "1.0.79"
|
serde = "1.0.79"
|
||||||
serde_derive = "1.0.79"
|
serde_derive = "1.0.79"
|
||||||
|
stderrlog = "0.4.1"
|
||||||
|
structopt = "0.2.10"
|
||||||
|
|
||||||
# For better profiling support.
|
[dependencies.prometheus]
|
||||||
|
features = ["process", "push"]
|
||||||
|
version = "0.5.0"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
criterion = "0.2"
|
||||||
|
|
||||||
|
[profile]
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = true
|
debug = true
|
||||||
|
|
||||||
|
|||||||
@ -1,27 +1,75 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
extern crate chrono;
|
||||||
extern crate cpuprofiler;
|
extern crate cpuprofiler;
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
extern crate rtiow;
|
extern crate rtiow;
|
||||||
extern crate stderrlog;
|
extern crate stderrlog;
|
||||||
extern crate structopt;
|
extern crate structopt;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate lazy_static;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate prometheus;
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use chrono::DateTime;
|
||||||
|
use chrono::Utc;
|
||||||
use cpuprofiler::PROFILER;
|
use cpuprofiler::PROFILER;
|
||||||
|
use prometheus::Encoder;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
use rtiow::renderer::opt_hash;
|
||||||
use rtiow::renderer::render;
|
use rtiow::renderer::render;
|
||||||
use rtiow::renderer::Opt;
|
use rtiow::renderer::Opt;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref RUNTIME_COUNTER: prometheus::Gauge =
|
||||||
|
register_gauge!("render_time_seconds", "Wall clock time for render").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_metrics(push_gateway_addr: &str, instance: String, start_time: &DateTime<Utc>) {
|
||||||
|
let metric_families = prometheus::gather();
|
||||||
|
let encoder = prometheus::TextEncoder::new();
|
||||||
|
let stdout = std::io::stdout();
|
||||||
|
println!("Prometheus metrics:");
|
||||||
|
encoder
|
||||||
|
.encode(&metric_families, &mut stdout.lock())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if push_gateway_addr.is_empty() {
|
||||||
|
info!("Logging stats to push gateway disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(err) = prometheus::push_metrics(
|
||||||
|
"tracer",
|
||||||
|
labels! {
|
||||||
|
"instance".to_owned() => instance,
|
||||||
|
"start_time".to_owned() => start_time.to_rfc3339(),
|
||||||
|
"timestamp".to_owned() => start_time.timestamp().to_string(),
|
||||||
|
},
|
||||||
|
push_gateway_addr,
|
||||||
|
metric_families,
|
||||||
|
None,
|
||||||
|
// TODO(wathiede): auth?
|
||||||
|
// Some(prometheus::BasicAuthentication {
|
||||||
|
// username: "user".to_owned(),
|
||||||
|
// password: "pass".to_owned(),
|
||||||
|
// }),
|
||||||
|
) {
|
||||||
|
error!("Failed to push to prometheus gateway: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), std::io::Error> {
|
fn main() -> Result<(), std::io::Error> {
|
||||||
stderrlog::new()
|
stderrlog::new()
|
||||||
.verbosity(3)
|
.verbosity(3)
|
||||||
.timestamp(stderrlog::Timestamp::Millisecond)
|
.timestamp(stderrlog::Timestamp::Millisecond)
|
||||||
.init()
|
.init()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let start = Instant::now();
|
let start_time: DateTime<Utc> = Utc::now();
|
||||||
|
let start_instant = Instant::now();
|
||||||
let opt = Opt::from_args();
|
let opt = Opt::from_args();
|
||||||
let scene = opt.model.scene(&opt);
|
let scene = opt.model.scene(&opt);
|
||||||
fs::create_dir_all(&opt.output)?;
|
fs::create_dir_all(&opt.output)?;
|
||||||
@ -33,16 +81,20 @@ fn main() -> Result<(), std::io::Error> {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
let res = render(scene, &opt.output);
|
let res = render(scene, &opt.output);
|
||||||
if let Some(pprof_path) = opt.pprof {
|
if let Some(pprof_path) = &opt.pprof {
|
||||||
info!("Saving pprof to {}", pprof_path.to_string_lossy());
|
info!("Saving pprof to {}", pprof_path.to_string_lossy());
|
||||||
PROFILER.lock().unwrap().stop().unwrap();
|
PROFILER.lock().unwrap().stop().unwrap();
|
||||||
}
|
}
|
||||||
let runtime = start.elapsed();
|
let runtime = start_instant.elapsed();
|
||||||
info!(
|
info!(
|
||||||
"Render time {}.{} seconds",
|
"Render time {}.{} seconds",
|
||||||
runtime.as_secs(),
|
runtime.as_secs(),
|
||||||
runtime.subsec_millis()
|
runtime.subsec_millis()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
RUNTIME_COUNTER.set(runtime.as_secs() as f64 + runtime.subsec_nanos() as f64 * 1e-9);
|
||||||
|
|
||||||
|
push_metrics(&opt.push_gateway, opt_hash(&opt), &start_time);
|
||||||
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,3 +31,7 @@ extern crate rayon;
|
|||||||
extern crate structopt;
|
extern crate structopt;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate lazy_static;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate prometheus;
|
||||||
|
|||||||
@ -22,6 +22,11 @@ use crate::scenes;
|
|||||||
use crate::texture::EnvMap;
|
use crate::texture::EnvMap;
|
||||||
use crate::vec3::Vec3;
|
use crate::vec3::Vec3;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref RAY_COUNTER: prometheus::CounterVec =
|
||||||
|
register_counter_vec!("rays", "Number of rays fired", &["level"]).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Model {
|
pub enum Model {
|
||||||
Bench,
|
Bench,
|
||||||
@ -81,9 +86,33 @@ impl str::FromStr for Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::string::ToString for Model {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Model::Bench => "bench".to_string(),
|
||||||
|
Model::Book => "book".to_string(),
|
||||||
|
Model::Tutorial => "tutorial".to_string(),
|
||||||
|
Model::BVH => "bvh".to_string(),
|
||||||
|
Model::Test => "test".to_string(),
|
||||||
|
Model::CornellBox => "cornell_box".to_string(),
|
||||||
|
Model::CornellSmoke => "cornell_smoke".to_string(),
|
||||||
|
Model::PerlinDebug => "perlin_debug".to_string(),
|
||||||
|
Model::Final => "final".to_string(),
|
||||||
|
Model::Mandelbrot => "mandelbrot".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, StructOpt)]
|
||||||
#[structopt(name = "tracer", about = "An experimental ray tracer.")]
|
#[structopt(name = "tracer", about = "An experimental ray tracer.")]
|
||||||
pub struct Opt {
|
pub struct Opt {
|
||||||
|
/// Prometheus push gateway address, use "" to disable
|
||||||
|
#[structopt(
|
||||||
|
short = "a",
|
||||||
|
long = "pushgateway",
|
||||||
|
default_value = "pushgateway.z.xinu.tv:80"
|
||||||
|
)]
|
||||||
|
pub push_gateway: String,
|
||||||
/// Image width
|
/// Image width
|
||||||
#[structopt(short = "w", long = "width", default_value = "1024")]
|
#[structopt(short = "w", long = "width", default_value = "1024")]
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
@ -109,6 +138,19 @@ pub struct Opt {
|
|||||||
pub output: PathBuf,
|
pub output: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn opt_hash(opt: &Opt) -> String {
|
||||||
|
format!(
|
||||||
|
"w:{}-h:{}-s:{}-pprof:{}-model:{}-use_accel:{}-{}",
|
||||||
|
opt.width,
|
||||||
|
opt.height,
|
||||||
|
opt.subsamples,
|
||||||
|
opt.pprof.is_some(),
|
||||||
|
opt.model.to_string(),
|
||||||
|
opt.use_accel,
|
||||||
|
opt.output.display().to_string().replace("/", "_")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
pub world: Box<Hit>,
|
pub world: Box<Hit>,
|
||||||
pub camera: Camera,
|
pub camera: Camera,
|
||||||
@ -129,6 +171,7 @@ fn color(
|
|||||||
global_illumination: bool,
|
global_illumination: bool,
|
||||||
env_map: &Option<EnvMap>,
|
env_map: &Option<EnvMap>,
|
||||||
) -> Vec3 {
|
) -> Vec3 {
|
||||||
|
RAY_COUNTER.with_label_values(&[&depth.to_string()]).inc();
|
||||||
if let Some(rec) = world.hit(r, 0.001, std::f32::MAX) {
|
if let Some(rec) = world.hit(r, 0.001, std::f32::MAX) {
|
||||||
let (u, v) = rec.uv;
|
let (u, v) = rec.uv;
|
||||||
let emitted = rec.material.emitted(u, v, rec.p);
|
let emitted = rec.material.emitted(u, v, rec.p);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user