146 lines
3.8 KiB
Rust
146 lines
3.8 KiB
Rust
#[macro_use]
|
|
extern crate log;
|
|
extern crate chrono;
|
|
#[cfg(feature = "profile")]
|
|
extern crate cpuprofiler;
|
|
extern crate rand;
|
|
extern crate rtiow;
|
|
extern crate stderrlog;
|
|
extern crate structopt;
|
|
#[macro_use]
|
|
#[cfg(feature = "prom")]
|
|
extern crate lazy_static;
|
|
#[macro_use]
|
|
#[cfg(feature = "prom")]
|
|
extern crate prometheus;
|
|
|
|
use std::fs;
|
|
|
|
use chrono::DateTime;
|
|
use chrono::Utc;
|
|
#[cfg(feature = "profile")]
|
|
use cpuprofiler::PROFILER;
|
|
#[cfg(feature = "prom")]
|
|
use prometheus::Encoder;
|
|
use structopt::StructOpt;
|
|
|
|
use rtiow::renderer::opt_hash;
|
|
use rtiow::renderer::render;
|
|
use rtiow::renderer::Opt;
|
|
|
|
#[cfg(feature = "prom")]
|
|
lazy_static! {
|
|
static ref RUNTIME_COUNTER: prometheus::Gauge =
|
|
register_gauge!("render_time_seconds", "Wall clock time for render").unwrap();
|
|
}
|
|
|
|
#[cfg(not(feature = "prom"))]
|
|
fn push_metrics(_push_gateway_addr: &str, _instance: String, start_time: &DateTime<Utc>) {
|
|
let runtime = (Utc::now() - *start_time).to_std().unwrap();
|
|
info!(
|
|
"Render time {}.{} seconds",
|
|
runtime.as_secs(),
|
|
runtime.subsec_millis()
|
|
);
|
|
}
|
|
|
|
#[cfg(feature = "prom")]
|
|
fn push_metrics(push_gateway_addr: &str, instance: String, start_time: &DateTime<Utc>) {
|
|
let runtime = (Utc::now() - *start_time).to_std().unwrap();
|
|
info!(
|
|
"Render time {}.{} seconds",
|
|
runtime.as_secs(),
|
|
runtime.subsec_millis()
|
|
);
|
|
|
|
RUNTIME_COUNTER.set(runtime.as_secs() as f64 + f64::from(runtime.subsec_nanos()) * 1e-9);
|
|
|
|
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");
|
|
return;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
#[cfg(not(feature = "profile"))]
|
|
struct MockTimer;
|
|
|
|
#[cfg(not(feature = "profile"))]
|
|
impl MockTimer {
|
|
fn start<T: Into<Vec<u8>>>(&self, _: T) -> Result<(), ()> {
|
|
Ok(())
|
|
}
|
|
fn stop(&self) -> Result<(), ()> {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[cfg(not(feature = "profile"))]
|
|
struct MockProfiler;
|
|
|
|
#[cfg(not(feature = "profile"))]
|
|
impl MockProfiler {
|
|
fn lock(&self) -> Option<MockTimer> {
|
|
Some(MockTimer {})
|
|
}
|
|
}
|
|
|
|
#[cfg(not(feature = "profile"))]
|
|
static PROFILER: MockProfiler = MockProfiler {};
|
|
|
|
fn main() -> Result<(), std::io::Error> {
|
|
stderrlog::new()
|
|
.verbosity(3)
|
|
.timestamp(stderrlog::Timestamp::Millisecond)
|
|
.init()
|
|
.unwrap();
|
|
let start_time: DateTime<Utc> = Utc::now();
|
|
let opt = Opt::from_args();
|
|
let scene = opt.model.scene(&opt);
|
|
fs::create_dir_all(&opt.output)?;
|
|
if opt.pprof.is_some() && !cfg!(feature = "profile") {
|
|
panic!("profiling disabled at compile time, but -pprof specified");
|
|
}
|
|
if let Some(ref pprof_path) = opt.pprof {
|
|
PROFILER
|
|
.lock()
|
|
.unwrap()
|
|
.start(pprof_path.to_str().unwrap().as_bytes())
|
|
.unwrap();
|
|
}
|
|
let res = render(scene, &opt.output);
|
|
if let Some(pprof_path) = &opt.pprof {
|
|
info!("Saving pprof to {}", pprof_path.to_string_lossy());
|
|
PROFILER.lock().unwrap().stop().unwrap();
|
|
}
|
|
push_metrics(&opt.push_gateway, opt_hash(&opt), &start_time);
|
|
|
|
res
|
|
}
|