Skip to content

Add inductor provenance tracking higlighter #93

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 14, 2025
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
4 changes: 4 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ pub struct Cli {
/// For export specific logs
#[arg(short, long)]
export: bool,
/// For inductor provenance tracking highlighter
#[arg(short, long)]
inductor_provenance: bool,
}

fn main() -> anyhow::Result<()> {
Expand Down Expand Up @@ -93,6 +96,7 @@ fn main() -> anyhow::Result<()> {
verbose: cli.verbose,
plain_text: cli.plain_text,
export: cli.export,
Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, similar question for @angelayi , why did we end up needing this again? Shouldn't we be able to tell just from the structured log input whether there are export related logs?

inductor_provenance: cli.inductor_provenance,
};

let output = parse_path(&path, config)?;
Expand Down
63 changes: 63 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub struct ParseConfig {
pub verbose: bool,
pub plain_text: bool,
pub export: bool,
pub inductor_provenance: bool,
}

impl Default for ParseConfig {
Expand All @@ -41,6 +42,7 @@ impl Default for ParseConfig {
verbose: false,
plain_text: false,
export: false,
inductor_provenance: false,
}
}
}
Expand Down Expand Up @@ -248,6 +250,7 @@ pub fn parse_path(path: &PathBuf, config: ParseConfig) -> anyhow::Result<ParseOu
TEMPLATE_AOT_AUTOGRAD_BACKWARD_COMPILATION_METRICS,
)?;
}
tt.add_template("provenance_tracking.html", TEMPLATE_PROVENANCE_TRACKING)?;

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

Expand Down Expand Up @@ -668,6 +671,14 @@ pub fn parse_path(path: &PathBuf, config: ParseConfig) -> anyhow::Result<ParseOu

let has_unknown_compile_id = directory.contains_key(&None);

let directory_names: Vec<String> = directory
.iter()
.map(|(x, _)| {
x.as_ref()
.map_or("(unknown)".to_string(), |e| e.as_directory_name())
})
.collect();

let index_context = IndexContext {
css: CSS,
javascript: JAVASCRIPT,
Expand All @@ -686,6 +697,8 @@ pub fn parse_path(path: &PathBuf, config: ParseConfig) -> anyhow::Result<ParseOu
num_breaks: breaks.failures.len(),
has_chromium_events: !chromium_events.is_empty(),
qps: TEMPLATE_QUERY_PARAM_SCRIPT,
has_inductor_provenance: config.inductor_provenance,
directory_names: directory_names.clone(),
};
output.push((
PathBuf::from("index.html"),
Expand Down Expand Up @@ -713,5 +726,55 @@ pub fn parse_path(path: &PathBuf, config: ParseConfig) -> anyhow::Result<ParseOu
return Err(anyhow!("Some log entries did not have compile id"));
}

if config.inductor_provenance {
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of having this be a config to pass to tlparse, can we have it so this logic turns on if there's at least one inductor_provenance_tracking_node_mappings? If we already turned it on in our structured logging, there's no reason to also have to flip a config on tlparse side

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jamesjwu I added it because it's a new feature and I don't want to break the normal tlparse flow accidentally. I'm thinking we can remove this flag after it has been running smoothly for a while.

// Helper function to get file content for a specific directory name
fn get_file_content(
output: &[(PathBuf, String)],
filename_pattern: &str,
directory_name: &str,
) -> String {
output
.iter()
.find(|(path, _)| {
path.to_string_lossy()
.contains(&format!("{}/{}", directory_name, filename_pattern))
})
.map(|(_, content)| content.clone())
.unwrap_or_default()
}

// Generate HTML for each directory name
for directory_name in &directory_names {
let pre_grad_graph_content =
get_file_content(&output, "inductor_pre_grad_graph", directory_name);
let post_grad_graph_content =
get_file_content(&output, "inductor_post_grad_graph", directory_name);
let output_code_content =
get_file_content(&output, "inductor_output_code", directory_name);
let aot_code_content = get_file_content(&output, "inductor_aot_code", directory_name);
let node_mappings_content = get_file_content(
&output,
"inductor_provenance_tracking_node_mappings",
directory_name,
);

output.push((
PathBuf::from(format!("provenance_tracking_{}.html", directory_name)),
tt.render(
"provenance_tracking.html",
&ProvenanceContext {
css: PROVENANCE_CSS,
js: PROVENANCE_JS,
pre_grad_graph_content,
post_grad_graph_content,
output_code_content,
aot_code_content,
node_mappings_content,
},
)?,
));
}
}

Ok(output)
}
152 changes: 152 additions & 0 deletions src/provenance.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
body {
display: flex;
flex-direction: column;
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
height: 100vh;
overflow: hidden;
}

.url-inputs {
display: flex;
padding: 10px;
background-color: #f0f0f0;
}

.url-input {
flex: 1;
margin-right: 10px;
display: flex;
align-items: center;
gap: 10px;
}

.url-input input {
width: 100%;
padding: 5px;
}

.editor-container {
display: flex;
flex: 1;
overflow: hidden;
}

.editor {
height: 100%;
overflow-y: auto;
border: 1px solid #ddd;
padding: 10px;
box-sizing: border-box;
flex: 1;
font-family: monospace;
}

.line {
padding: 2px 5px;
cursor: pointer;
white-space: nowrap;
transition: background-color 0.2s ease;
}

.highlight {
background-color: yellow;
transition: background-color 0.2s ease;
}

.mapped-line {
font-weight: bold;
}

.line-number {
color: #888;
display: inline-block;
width: 30px;
text-align: right;
margin-right: 10px;
}

.divider {
width: 10px;
background-color: #ccc;
cursor: col-resize;
}

.line-content {
white-space: pre;
display: inline;
}

.json-popup {
display: none;
position: fixed;
background: white;
border: 1px solid #ccc;
padding: 10px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
max-width: 400px;
max-height: 300px;
overflow: auto;
z-index: 1000;
white-space: pre-wrap;
font-family: monospace;
font-size: 12px;
}

.json-popup .close-button {
position: sticky;
float: right;
top: 0;
right: 0;
cursor: pointer;
font-size: 20px;
background: white;
padding: 0 5px;
margin-left: 10px;
}

#jsonContent {
margin-top: 10px;
}

.toggle-container {
margin-left: 20px;
display: inline-flex;
align-items: center;
cursor: pointer;
min-width: 200px;
white-space: nowrap;
}

.toggle-container input[type="checkbox"] {
margin-right: 5px;
}

.file-input {
display: none;
}

.url-input {
flex: 1;
margin-right: 10px;
display: flex;
align-items: center;
gap: 10px;
}

.file-label {
background-color: #f0f0f0;
padding: 5px 10px;
border: 1px solid #ddd;
border-radius: 4px;
cursor: pointer;
}

.file-label:hover {
background-color: #e0e0e0;
}

.has-match {
font-weight: bold;
}
35 changes: 35 additions & 0 deletions src/provenance.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Inductor Provenance Tracking Highlighter</title>
<style>
{css | format_unescaped}
</style>
</head>

<body>
<div class="editor-container">
<div id="preGradGraph" class="editor">
<pre>{pre_grad_graph_content}</pre>
</div>
<div id="divider" class="divider"></div>
<div id="postGradGraph" class="editor">
<pre>{post_grad_graph_content}</pre>
</div>
<div id="divider" class="divider"></div>
<div id="generatedCode" class="editor">
<pre>{output_code_content | format_unescaped}{aot_code_content}</pre>
</div>
</div>

<script>
// Make node mappings available to JavaScript
const nodeMappings = {node_mappings_content | format_unescaped};
{js | format_unescaped}
</script>
</body>

</html>
Loading
Loading