Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 65 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
use regex::Regex;
use serde_json::Value;
use std::cell::RefCell;
use std::fmt::Write as FmtWrite;
use std::fs::{self, File};
use std::io::{self, BufRead};
use std::path::{Path, PathBuf};
Expand All @@ -23,6 +24,7 @@ use crate::types::*;
pub mod parsers;
mod templates;
mod types;
pub mod vllm;

pub use types::{
ArtifactFlags, CollectiveSchedule, CollectivesParityReport, Diagnostics, DivergenceFlags,
Expand Down Expand Up @@ -121,6 +123,7 @@ fn add_file_output(
output: &mut ParseOutput,
compile_directory: &mut Vec<OutputFile>,
output_count: &mut i32,
vllm_state: &vllm::VllmState,
) {
let is_stack_traces = is_stack_traces_file(&filename);
let maybe_content = if is_stack_traces {
Expand All @@ -130,6 +133,7 @@ fn add_file_output(
};
output.push((filename.clone(), content));
let filename_str = filename.to_string_lossy().to_string();

let suffix = if filename_str.contains("cache_miss") {
"❌".to_string()
} else if filename_str.contains("cache_hit") {
Expand All @@ -139,6 +143,10 @@ fn add_file_output(
} else {
"".to_string()
};

// Track artifact for vLLM summary
vllm_state.add_artifact(&filename, suffix.clone());

let readable_url = if let Some(c) = maybe_content {
Some(add_stack_traces_html(&filename, &c, output, output_count))
} else {
Expand Down Expand Up @@ -214,6 +222,7 @@ fn run_parser<'t>(
compile_directory: &mut Vec<OutputFile>,
multi: &MultiProgress,
stats: &mut Stats,
vllm_state: &vllm::VllmState,
) -> ParserResult {
let mut payload_filename = ParserResult::NoPayload;
if let Some(md) = parser.get_metadata(&e) {
Expand All @@ -224,10 +233,24 @@ fn run_parser<'t>(
match parser_result {
ParserOutput::File(raw_filename, out) => {
let filename = add_unique_suffix(raw_filename, *output_count);
add_file_output(filename, out, output, compile_directory, output_count);
add_file_output(
filename,
out,
output,
compile_directory,
output_count,
vllm_state,
);
}
ParserOutput::GlobalFile(filename, out) => {
add_file_output(filename, out, output, compile_directory, output_count);
add_file_output(
filename,
out,
output,
compile_directory,
output_count,
vllm_state,
);
}
ParserOutput::PayloadFile(raw_filename) => {
let filename = add_unique_suffix(raw_filename, *output_count);
Expand All @@ -240,6 +263,7 @@ fn run_parser<'t>(
output,
compile_directory,
output_count,
vllm_state,
);
}
ParserOutput::PayloadReformatFile(raw_filename, formatter) => {
Expand All @@ -255,6 +279,7 @@ fn run_parser<'t>(
output,
compile_directory,
output_count,
vllm_state,
);
}
Err(err) => {
Expand Down Expand Up @@ -340,6 +365,7 @@ fn handle_guard(
tt: &TinyTemplate,
sym_expr_info_index: &RefCell<SymExprInfoIndex>,
export_failures: &mut Vec<ExportFailure>,
vllm_state: &vllm::VllmState,
) {
let sym_expr_info_index_borrowed = sym_expr_info_index.borrow();
let parser: Box<dyn StructuredLogParser> =
Expand All @@ -357,6 +383,7 @@ fn handle_guard(
compile_directory,
multi,
stats,
vllm_state,
);

let filename = format!(
Expand Down Expand Up @@ -473,6 +500,16 @@ pub fn parse_path(path: &PathBuf, config: &ParseConfig) -> anyhow::Result<ParseO

let mut tt: TinyTemplate = TinyTemplate::new();
tt.add_formatter("format_unescaped", tinytemplate::format_unescaped);
tt.add_formatter("format_float", |value, output| {
if let serde_json::Value::Number(n) = value {
if let Some(f) = n.as_f64() {
write!(output, "{:.3}", f)?;
return Ok(());
}
}
write!(output, "{}", value)?;
Ok(())
});
if config.export {
tt.add_template("index.html", TEMPLATE_EXPORT_INDEX)?;
tt.add_template(
Expand All @@ -494,6 +531,7 @@ pub fn parse_path(path: &PathBuf, config: &ParseConfig) -> anyhow::Result<ParseO
)?;
}
tt.add_template("provenance_tracking.html", TEMPLATE_PROVENANCE_TRACKING)?;
tt.add_template("vllm_summary.html", vllm::templates::VLLM_SUMMARY_TEMPLATE)?;

let mut unknown_fields: FxHashSet<String> = FxHashSet::default();

Expand All @@ -520,7 +558,10 @@ pub fn parse_path(path: &PathBuf, config: &ParseConfig) -> anyhow::Result<ParseO
.peekable();

let default_parsers = default_parsers(&tt, config);
let vllm_state = vllm::VllmState::new();
let vllm_parsers = vllm::vllm_parsers_with_state(vllm_state.clone());
let mut all_parsers: Vec<&Box<dyn StructuredLogParser>> = default_parsers.iter().collect();
all_parsers.extend(vllm_parsers.iter());
let mut chromium_events: Vec<serde_json::Value> = Vec::new();
all_parsers.extend(config.custom_parsers.iter());

Expand Down Expand Up @@ -757,6 +798,7 @@ pub fn parse_path(path: &PathBuf, config: &ParseConfig) -> anyhow::Result<ParseO
compile_directory,
&multi,
&mut stats,
&vllm_state,
);
// Take the last PayloadFilename entry as per the requirement
if matches!(result, ParserResult::PayloadFilename(_)) {
Expand Down Expand Up @@ -790,6 +832,7 @@ pub fn parse_path(path: &PathBuf, config: &ParseConfig) -> anyhow::Result<ParseO
compile_directory,
&multi,
&mut stats,
&vllm_state,
);
// Take the last PayloadFilename entry as per the requirement
if matches!(result, ParserResult::PayloadFilename(_)) {
Expand All @@ -801,6 +844,7 @@ pub fn parse_path(path: &PathBuf, config: &ParseConfig) -> anyhow::Result<ParseO
"compilation_metrics_{}.html",
(output_count - 1).to_string(),
);

let id = e.compile_id.clone().map_or("(unknown) ".to_string(), |c| {
format!(
"<a href='{}/{}'>{cid}</a> ",
Expand Down Expand Up @@ -875,6 +919,7 @@ pub fn parse_path(path: &PathBuf, config: &ParseConfig) -> anyhow::Result<ParseO
&tt,
&sym_expr_info_index,
&mut export_failures,
&vllm_state,
);
}

Expand Down Expand Up @@ -904,6 +949,7 @@ pub fn parse_path(path: &PathBuf, config: &ParseConfig) -> anyhow::Result<ParseO
&tt,
&sym_expr_info_index,
&mut export_failures,
&vllm_state,
);
}

Expand Down Expand Up @@ -1101,6 +1147,8 @@ pub fn parse_path(path: &PathBuf, config: &ParseConfig) -> anyhow::Result<ParseO
PathBuf::from("compile_directory.json"),
serde_json::to_string_pretty(&directory_to_json(&directory))?,
));

// Generate traditional tlparse index
let index_context = IndexContext {
css: CSS,
javascript: JAVASCRIPT,
Expand All @@ -1122,10 +1170,21 @@ pub fn parse_path(path: &PathBuf, config: &ParseConfig) -> anyhow::Result<ParseO
has_inductor_provenance: config.inductor_provenance,
directory_names: directory_names.clone(),
};
output.push((
PathBuf::from("index.html"),
tt.render("index.html", &index_context)?,
));
let tlparse_index_html = tt.render("index.html", &index_context)?;

if vllm_state.has_artifacts() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this override the normal html, can we add a more detailed description of when would vllm_state.has_artifacts() = True? e.g. it's true when there exist at least a file that starts with vllm

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated the comment!

// If vLLM artifacts are present, use vLLM summary as index.html and
// save traditional tlparse index as tlparse_index.html for reference.
// `has_vllm_artifacts` gets set to true when the vLLM parsers are
// triggered. This happens when we see the following events:
// `vllm_subgraph_*`, `vllm_compilation_config`,
// `vllm_piecewise_split_graph`.
let vllm_html = vllm::generate_vllm_summary(&vllm_state, &tt, &config.custom_header_html)?;
output.push((PathBuf::from("index.html"), vllm_html));
output.push((PathBuf::from("tlparse_index.html"), tlparse_index_html));
} else {
output.push((PathBuf::from("index.html"), tlparse_index_html));
}

output.push((PathBuf::from("raw.log"), fs::read_to_string(path)?));

Expand Down
8 changes: 7 additions & 1 deletion src/parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ pub trait StructuredLogParser {
}

// Helper function to build file path with compile ID directory
fn build_file_path(filename: &str, lineno: usize, compile_id: &Option<CompileId>) -> PathBuf {
pub fn build_file_path(filename: &str, lineno: usize, compile_id: &Option<CompileId>) -> PathBuf {
let compile_id_dir: PathBuf = compile_id
.as_ref()
.map_or(format!("unknown_{lineno}"), |cid| cid.as_directory_name())
Expand Down Expand Up @@ -151,6 +151,12 @@ impl StructuredLogParser for GraphDumpParser {
"graph_dump" // ToDO: more specific?
}
fn get_metadata<'e>(&self, e: &'e Envelope) -> Option<Metadata<'e>> {
if let Some(graph_dump) = &e.graph_dump {
if graph_dump.name.starts_with("vllm_") {
// Skip vLLM-specific graph dumps (handled by parsers under src/vllm)
return None;
}
}
e.graph_dump.as_ref().map(|m| Metadata::GraphDump(m))
}
fn parse<'e>(
Expand Down
11 changes: 11 additions & 0 deletions src/vllm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! vLLM-specific parsing and visualization for tlparse.
//!
//! This module provides parsers and templates for vLLM's structured logs,
//! including piecewise compilation, subgraph tracking, and cudagraph captures.

pub mod parsers;
pub mod templates;
pub mod types;

pub use parsers::{generate_vllm_summary, vllm_parsers_with_state, VllmState};
pub use types::VllmSummaryContext;
Loading
Loading