Basic prometheus support, with push_gateway integration.

This commit is contained in:
Bill Thiede 2019-02-25 20:41:53 -08:00
parent 3256feab1b
commit cdbaa928c2
5 changed files with 1501 additions and 588 deletions

1942
rtiow/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,27 +1,37 @@
[package]
name = "rtiow"
version = "0.1.0"
authors = ["Bill Thiede <rust@xinu.tv>"]
edition = "2018"
name = "rtiow"
version = "0.1.0"
[[bench]]
harness = false
name = "spheres"
[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"
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_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]
debug = true

View File

@ -1,27 +1,75 @@
#[macro_use]
extern crate log;
extern crate chrono;
extern crate cpuprofiler;
extern crate rand;
extern crate rtiow;
extern crate stderrlog;
extern crate structopt;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate prometheus;
use std::fs;
use std::time::Instant;
use chrono::DateTime;
use chrono::Utc;
use cpuprofiler::PROFILER;
use prometheus::Encoder;
use structopt::StructOpt;
use rtiow::renderer::opt_hash;
use rtiow::renderer::render;
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> {
stderrlog::new()
.verbosity(3)
.timestamp(stderrlog::Timestamp::Millisecond)
.init()
.unwrap();
let start = Instant::now();
let start_time: DateTime<Utc> = Utc::now();
let start_instant = Instant::now();
let opt = Opt::from_args();
let scene = opt.model.scene(&opt);
fs::create_dir_all(&opt.output)?;
@ -33,16 +81,20 @@ fn main() -> Result<(), std::io::Error> {
.unwrap();
}
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());
PROFILER.lock().unwrap().stop().unwrap();
}
let runtime = start.elapsed();
let runtime = start_instant.elapsed();
info!(
"Render time {}.{} seconds",
runtime.as_secs(),
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
}

View File

@ -31,3 +31,7 @@ extern crate rayon;
extern crate structopt;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate prometheus;

View File

@ -22,6 +22,11 @@ use crate::scenes;
use crate::texture::EnvMap;
use crate::vec3::Vec3;
lazy_static! {
static ref RAY_COUNTER: prometheus::CounterVec =
register_counter_vec!("rays", "Number of rays fired", &["level"]).unwrap();
}
#[derive(Debug)]
pub enum Model {
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)]
#[structopt(name = "tracer", about = "An experimental ray tracer.")]
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
#[structopt(short = "w", long = "width", default_value = "1024")]
pub width: usize,
@ -109,6 +138,19 @@ pub struct Opt {
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 world: Box<Hit>,
pub camera: Camera,
@ -129,6 +171,7 @@ fn color(
global_illumination: bool,
env_map: &Option<EnvMap>,
) -> Vec3 {
RAY_COUNTER.with_label_values(&[&depth.to_string()]).inc();
if let Some(rec) = world.hit(r, 0.001, std::f32::MAX) {
let (u, v) = rec.uv;
let emitted = rec.material.emitted(u, v, rec.p);