feat(corp/tvixbolt): implement optional runtime tracing
Uses Tvix's new `TracingObserver` to optionally produce a runtime trace, which the user can toggle via a checkbox. Runtime traces can be quite long, so they're only produced if asked for. Change-Id: Id0f27dc8ef6e9d81a31ecf22c81757b066815320 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6331 Tested-by: BuildkiteCI Reviewed-by: tazjin <tazjin@tvl.su>
This commit is contained in:
		
							parent
							
								
									85e3281f75
								
							
						
					
					
						commit
						01a0d5c822
					
				
					 1 changed files with 28 additions and 6 deletions
				
			
		| 
						 | 
					@ -1,17 +1,21 @@
 | 
				
			||||||
use std::fmt::Write;
 | 
					use std::fmt::Write;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::rc::Rc;
 | 
					use std::rc::Rc;
 | 
				
			||||||
use tvix_eval::observer::DisassemblingObserver;
 | 
					use tvix_eval::observer::TracingObserver;
 | 
				
			||||||
 | 
					use tvix_eval::observer::{DisassemblingObserver, NoOpObserver};
 | 
				
			||||||
 | 
					use web_sys::HtmlInputElement;
 | 
				
			||||||
use web_sys::HtmlTextAreaElement;
 | 
					use web_sys::HtmlTextAreaElement;
 | 
				
			||||||
use yew::prelude::*;
 | 
					use yew::prelude::*;
 | 
				
			||||||
use yew::TargetCast;
 | 
					use yew::TargetCast;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum Msg {
 | 
					enum Msg {
 | 
				
			||||||
    CodeChange(String),
 | 
					    CodeChange(String),
 | 
				
			||||||
 | 
					    ToggleTrace(bool),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Model {
 | 
					struct Model {
 | 
				
			||||||
    code: String,
 | 
					    code: String,
 | 
				
			||||||
 | 
					    trace: bool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn tvixbolt_overview() -> Html {
 | 
					fn tvixbolt_overview() -> Html {
 | 
				
			||||||
| 
						 | 
					@ -65,11 +69,17 @@ impl Component for Model {
 | 
				
			||||||
    fn create(_ctx: &Context<Self>) -> Self {
 | 
					    fn create(_ctx: &Context<Self>) -> Self {
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            code: String::new(),
 | 
					            code: String::new(),
 | 
				
			||||||
 | 
					            trace: false,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
 | 
					    fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
 | 
				
			||||||
        match msg {
 | 
					        match msg {
 | 
				
			||||||
 | 
					            Msg::ToggleTrace(trace) => {
 | 
				
			||||||
 | 
					                self.trace = trace;
 | 
				
			||||||
 | 
					                true
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Msg::CodeChange(new_code) => {
 | 
					            Msg::CodeChange(new_code) => {
 | 
				
			||||||
                self.code = new_code;
 | 
					                self.code = new_code;
 | 
				
			||||||
                true
 | 
					                true
 | 
				
			||||||
| 
						 | 
					@ -102,8 +112,14 @@ impl Component for Model {
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <div class="form-group">
 | 
					                    <div class="form-group">
 | 
				
			||||||
                      <label for="disable-bytecode">{"Disassemble:"}</label>
 | 
					                      <label for="trace-runtime">{"Trace runtime:"}</label>
 | 
				
			||||||
                      <input for="disable-bytecode" type="checkbox" checked=true disabled=true />
 | 
					                      <input
 | 
				
			||||||
 | 
					                       for="trace-runtime" type="checkbox" checked={self.trace}
 | 
				
			||||||
 | 
					                       onchange={link.callback(|e: Event| {
 | 
				
			||||||
 | 
					                           let trace = e.target_unchecked_into::<HtmlInputElement>().checked();
 | 
				
			||||||
 | 
					                           Msg::ToggleTrace(trace)
 | 
				
			||||||
 | 
					                       })}
 | 
				
			||||||
 | 
					                       />
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                  </fieldset>
 | 
					                  </fieldset>
 | 
				
			||||||
                </form>
 | 
					                </form>
 | 
				
			||||||
| 
						 | 
					@ -132,7 +148,7 @@ impl Model {
 | 
				
			||||||
        html! {
 | 
					        html! {
 | 
				
			||||||
            <>
 | 
					            <>
 | 
				
			||||||
              <h2>{"Result:"}</h2>
 | 
					              <h2>{"Result:"}</h2>
 | 
				
			||||||
              {eval(&self.code).display()}
 | 
					              {eval(self.trace, &self.code).display()}
 | 
				
			||||||
            </>
 | 
					            </>
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -146,6 +162,7 @@ struct Output {
 | 
				
			||||||
    runtime_errors: String,
 | 
					    runtime_errors: String,
 | 
				
			||||||
    output: String,
 | 
					    output: String,
 | 
				
			||||||
    bytecode: Vec<u8>,
 | 
					    bytecode: Vec<u8>,
 | 
				
			||||||
 | 
					    trace: Vec<u8>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn maybe_show(title: &str, s: &str) -> Html {
 | 
					fn maybe_show(title: &str, s: &str) -> Html {
 | 
				
			||||||
| 
						 | 
					@ -171,12 +188,13 @@ impl Output {
 | 
				
			||||||
            {maybe_show("Bytecode:", &String::from_utf8_lossy(&self.bytecode))}
 | 
					            {maybe_show("Bytecode:", &String::from_utf8_lossy(&self.bytecode))}
 | 
				
			||||||
            {maybe_show("Runtime errors:", &self.runtime_errors)}
 | 
					            {maybe_show("Runtime errors:", &self.runtime_errors)}
 | 
				
			||||||
            {maybe_show("Output:", &self.output)}
 | 
					            {maybe_show("Output:", &self.output)}
 | 
				
			||||||
 | 
					            {maybe_show("Runtime trace:", &String::from_utf8_lossy(&self.trace))}
 | 
				
			||||||
            </>
 | 
					            </>
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn eval(code: &str) -> Output {
 | 
					fn eval(trace: bool, code: &str) -> Output {
 | 
				
			||||||
    let mut out = Output::default();
 | 
					    let mut out = Output::default();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if code.is_empty() {
 | 
					    if code.is_empty() {
 | 
				
			||||||
| 
						 | 
					@ -241,7 +259,11 @@ fn eval(code: &str) -> Output {
 | 
				
			||||||
        return out;
 | 
					        return out;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let result = tvix_eval::run_lambda(result.lambda);
 | 
					    let result = if trace {
 | 
				
			||||||
 | 
					        tvix_eval::run_lambda(&mut TracingObserver::new(&mut out.trace), result.lambda)
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        tvix_eval::run_lambda(&mut NoOpObserver::default(), result.lambda)
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    match result {
 | 
					    match result {
 | 
				
			||||||
        Ok(value) => writeln!(&mut out.output, "{}", value).unwrap(),
 | 
					        Ok(value) => writeln!(&mut out.output, "{}", value).unwrap(),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue