Interactive Flame Graph Visualization in Angular
Flame graphs are powerful tools for visualizing performance bottlenecks in software. This challenge asks you to implement a basic, interactive flame graph component in Angular. The goal is to create a visual representation of call stacks, allowing users to identify the most time-consuming functions in a given application or process.
Problem Description
You are tasked with building an Angular component that renders a flame graph based on provided data. The data will be an array of objects, where each object represents a function call and contains the following properties:
name: (string) The name of the function.totalTime: (number) The total time spent in this function (in milliseconds).childFunctions: (array of objects) An array of child function call objects representing functions called within this function. This array can be empty.
The component should display the functions as rectangles, with the height of each rectangle proportional to its totalTime. The rectangles should be nested to represent the call stack hierarchy. The graph should be interactive, allowing users to click on a function rectangle to expand or collapse its child functions. The graph should also support scrolling to view functions that extend beyond the visible viewport.
Key Requirements:
- Data Input: The component should accept the flame graph data as an input property.
- Visualization: The component should render the flame graph visually, using HTML and CSS. SVG is a recommended technology for rendering the graph.
- Interactivity: Clicking on a function rectangle should toggle the visibility of its child functions.
- Scrolling: The graph should be scrollable if the total height of the functions exceeds the component's height.
- Responsiveness: The graph should adapt to different screen sizes.
Expected Behavior:
- The component should render correctly with valid input data.
- Clicking on a function should expand/collapse its children.
- The graph should be scrollable when necessary.
- The graph should be visually clear and easy to understand.
- The component should handle empty data gracefully (e.g., display a message indicating no data).
Edge Cases to Consider:
- Empty Data: What should happen if the input data is empty?
- Deeply Nested Call Stacks: How will the component handle very deep call stacks?
- Large
totalTimeValues: How will the component handle functions with extremely largetotalTimevalues? Consider scaling or logarithmic representation. - Zero
totalTimeValues: How should functions with zerototalTimebe displayed? - Performance with Large Datasets: Consider the performance implications of rendering a large flame graph. Techniques like virtualization might be necessary.
Examples
Example 1:
Input:
[
{
"name": "A",
"totalTime": 100,
"childFunctions": [
{
"name": "B",
"totalTime": 50,
"childFunctions": []
},
{
"name": "C",
"totalTime": 50,
"childFunctions": []
}
]
}
]
Output: A flame graph with a rectangle representing function "A" with a height proportional to 100. Inside "A", there are two rectangles representing "B" and "C", each with a height proportional to 50. Clicking "A" should toggle the visibility of "B" and "C".
Explanation: The graph visually represents the call stack. "A" is the top-level function, and "B" and "C" are called within "A".
Example 2:
Input:
[
{
"name": "Root",
"totalTime": 200,
"childFunctions": [
{
"name": "Func1",
"totalTime": 100,
"childFunctions": [
{
"name": "SubFunc1",
"totalTime": 50,
"childFunctions": []
}
]
},
{
"name": "Func2",
"totalTime": 100,
"childFunctions": []
}
]
}
]
Output: A flame graph with "Root" at the top, "Func1" and "Func2" as children. "Func1" has "SubFunc1" as a child. Clicking "Root" toggles "Func1" and "Func2". Clicking "Func1" toggles "SubFunc1".
Explanation: Demonstrates a deeper nesting of functions.
Constraints
- Data Format: The input data must conform to the specified object structure.
- Angular Version: Use Angular version 14 or higher.
- Rendering Technology: SVG is recommended for rendering the graph, but other technologies are acceptable if they meet the requirements.
- Performance: The component should render reasonably quickly, even with moderately sized datasets (up to 100 functions). Avoid excessive DOM manipulations.
- Responsiveness: The graph should be responsive and adapt to different screen sizes.
Notes
- Consider using a library like D3.js or Chart.js to simplify the SVG rendering process, but it's not required.
- Focus on the core functionality of rendering the flame graph and handling interactivity. Styling can be added later.
- Think about how to efficiently handle large datasets to avoid performance bottlenecks. Virtualization techniques might be helpful.
- The visual representation of the graph is important, but the functionality (expanding/collapsing, scrolling) is crucial.
- Error handling and input validation are important considerations.