Documentation
¶
Overview ¶
Package pstree provides functionality for building and displaying process trees.
This file contains the core tree building and display logic, including: - Process tree construction and hierarchy management - Process marking and filtering - Tree visualization with various display options - Support for different graphical styles (ASCII, UTF-8, etc.)
NOTE: This file has been identified as being too large and complex. Functions like BuildTree, MarkProcesses, and PrintTree could benefit from being broken down into smaller, more focused functions.
Package pstree provides functionality for building and displaying process trees.
This file contains the core data structures and type definitions used throughout the package. It defines the Process, DisplayOptions, ProcessTree, and TreeChars types that form the foundation of the process tree visualization system.
Package pstree provides functionality for building and displaying process trees.
This file contains an alternative implementation of the process tree using a map-based hierarchical structure, which is more intuitive and easier to maintain than the array-based approach. It's designed to work alongside the existing implementation while providing a path for gradual refactoring.
Index ¶
- Variables
- func ReplaceWithOptimizedBuildTree()
- type DisplayOptions
- type Process
- type ProcessGroup
- type ProcessMap
- func (processMap *ProcessMap) BuildTree(processes []Process)
- func (processMap *ProcessMap) FindAllChildren(pid int32, childPIDs *[]int32)
- func (processMap *ProcessMap) FindAllParents(pid int32, parentPIDs *[]int32)
- func (processMap *ProcessMap) FindPrintable()
- func (processMap *ProcessMap) FindProcess(targetPID int32) *ProcessNode
- func (processMap *ProcessMap) HasVisibleSiblings(node *ProcessNode) bool
- func (processMap *ProcessMap) IsLastChild(node *ProcessNode) bool
- func (processMap *ProcessMap) IsLastSibling(node *ProcessNode) bool
- func (processMap *ProcessMap) PrintTree()
- func (processMap *ProcessMap) ShowPrintable()
- type ProcessNode
- type ProcessTree
- func (processTree *ProcessTree) BuildTree()
- func (processTree *ProcessTree) DropUnmarked()
- func (processTree *ProcessTree) FormatCompactOutput(command string, count int, groupPIDs []int32) string
- func (processTree *ProcessTree) GetProcessCount(pidIndex int) (int, []int32, bool)
- func (processTree *ProcessTree) InitCompactMode() error
- func (processTree *ProcessTree) MarkCurrentAndAncestors(currentPid int32)
- func (processTree *ProcessTree) MarkProcesses()
- func (processTree *ProcessTree) MarkUIDTransitions()
- func (processTree *ProcessTree) OptimizedBuildTree()
- func (processTree *ProcessTree) PIDsToString(pids []int32) []string
- func (processTree *ProcessTree) PrintThreads(pidIndex int, head string)
- func (processTree *ProcessTree) PrintTree(pidIndex int, head string)
- func (processTree *ProcessTree) ShouldSkipProcess(pidIndex int) bool
- func (processTree *ProcessTree) ShowPrintable()
- type Thread
- type TreeChars
Constants ¶
This section is empty.
Variables ¶
var AnsiEscape = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`)
var TreeStyles = map[string]TreeChars{ "ascii": { Bar: "|", BarC: "|", BarL: "\\", EG: "", Init: "", NPGL: "-", P: "-+", PGL: "=", S2: "--", SG: "", }, "pc850": { Bar: string([]byte{0xB3}), BarC: string([]byte{0xC3}), BarL: string([]byte{0xB4}), EG: string([]byte{}), Init: string([]byte{}), NPGL: string([]byte{0xDA}), P: string([]byte{0xDA, 0xC2}), PGL: "¤", S2: string([]byte{0xDA, 0xDA}), SG: string([]byte{}), }, "vt100": { Bar: "\x0Ex\x0F", BarC: "\x0Et\x0F", BarL: "\x0Em\x0F", EG: "\x0F", Init: "\033(B\033)0", NPGL: "\x0Eq\x0F", P: "\x0Eqw\x0F", PGL: "◆", S2: "\x0Eqq\x0F", SG: "\x0E", }, "utf8": { Bar: "\342\224\202", BarC: "\342\224\234", BarL: "\342\224\224", EG: "", Init: "", NPGL: "\342\224\200", P: "\342\224\200\342\224\254", PGL: "●", S2: "\342\224\200\342\224\200", SG: "", }, }
TreeStyles defines different graphical styles for tree visualization. Each style uses a different set of characters for drawing the tree structure, allowing users to choose the style that works best with their terminal.
Functions ¶
func ReplaceWithOptimizedBuildTree ¶
func ReplaceWithOptimizedBuildTree()
ReplaceWithOptimizedBuildTree is a placeholder function that could be used to monkey patch the original BuildTree with the optimized version if needed.
This function is currently not implemented and serves as a marker for potential future implementation of runtime method replacement.
Types ¶
type DisplayOptions ¶
type DisplayOptions struct { // Attribute to color by ("age", "cpu", or "mem") ColorAttr string // Number of colors to use in rainbow mode ColorCount int // Whether to colorize the output with predefined colors ColorizeOutput bool // The system color scheme to use ColorScheme string // Whether the terminal supports color output ColorSupport bool // Whether to compact identical processes in the tree CompactMode bool // String to search for in process names Contains string // Whether to exclude processes owned by root ExcludeRoot bool // Whether to hide threads in the output HideThreads bool // Whether to use IBM850 graphics characters for tree lines IBM850Graphics bool // Total installed system memory in bytes InstalledMemory uint64 // Maximum depth of the tree to display (0 for unlimited) MaxDepth int // Sort the results by a number of fields OrderBy string // Whether to use rainbow colors for output RainbowOutput bool // Root process PID RootPID int32 // Width of the terminal screen in characters ScreenWidth int // Whether to show command line arguments ShowArguments bool // Whether to show CPU usage percentage ShowCpuPercent bool // Whether to show the process group ShowGroup bool // Whether to show memory usage ShowMemoryUsage bool // Whether to show thread count ShowNumThreads bool // Whether to show process owner ShowOwner bool // Whether to highlight process group leaders ShowPGLs bool // Whether to show process group IDs ShowPGIDs bool // Whether to show process IDs ShowPIDs bool // Whether to show parent process IDs ShowPPIDs bool // Whether to show process age ShowProcessAge bool // Whether to show UID transitions ShowUIDTransitions bool // Whether to show username transitions ShowUserTransitions bool // Whether to use UTF-8 graphics characters for tree lines UTF8Graphics bool // List of usernames to filter by Usernames []string // Whether to use VT100 graphics characters for tree lines VT100Graphics bool // Whether to display wide output (not truncated to screen width) WideDisplay bool }
DisplayOptions controls how the process tree is displayed, including formatting, coloring, and which information is shown for each process.
type Process ¶
type Process struct { // Process age in seconds since creation Age int64 // Command line arguments Args []string // Index of the first child process in the process tree Child int // Pointer to a slice of child processes Children *[]Process // Command name (executable name) Command string // Network connections associated with this process Connections []net.ConnectionStat // CPU usage percentage CPUPercent float64 // CPU time statistics CPUTimes *cpu.TimesStat // Process creation time as Unix timestamp CreateTime int64 // Environment variables Environment []string // Group IDs associated with this process GIDs []uint32 // The group name associated with the process Group string // A map of group ID < group name Groups map[uint32]string // Indicates if this process has a different UID from its parent HasUIDTransition bool // Indicates if this process is the current process or an ancestor IsCurrentOrAncestor bool // Memory usage information MemoryInfo *process.MemoryInfoStat // Memory usage as percentage of total system memory MemoryPercent float32 // Number of file descriptors NumFDs int32 // Number of threads NumThreads int32 // Open files OpenFiles []process.OpenFilesStat // Index of the parent process in the process tree Parent int // Pointer to the parent process ParentProcess *Process // UID of the parent process ParentUID uint32 // Username of the parent process ParentUsername string // Process group ID PGID int32 // Process ID PID int32 // Parent process ID PPID int32 // Whether or not we plan to display this process Print bool // Index of the next sibling process in the process tree Sister int // Process status information Status []string // A map of threads for the process Threads []Thread // Thread ID (if this is a thread) TID int32 // User IDs associated with this process UIDs []uint32 // Username of the process owner Username string }
Process represents a system process with all its attributes and relationships. It combines information gathered from both gopsutil and direct ps command calls to provide comprehensive details about the process.
type ProcessGroup ¶
type ProcessGroup struct { Count int // Number of identical processes FirstIndex int // Index of the first process in the group FullPath string // Full path of the command Indices []int // Indices of all processes in the group Owner string // Owner of the process group }
ProcessGroup represents a group of identical processes
type ProcessMap ¶
type ProcessMap struct { DisplayOptions DisplayOptions Logger *slog.Logger Nodes map[int32]*ProcessNode TreeChars TreeChars ColorScheme color.ColorScheme Colorizer color.Colorizer }
func NewProcessMap ¶
func NewProcessMap(logger *slog.Logger, processes []Process, displayOptions DisplayOptions) *ProcessMap
NewProcessMap creates a new process tree map from a slice of processes.
This function initializes a ProcessMap structure, configures the tree characters based on display options, builds the process tree hierarchy, and marks UID transitions between processes.
Parameters:
- logger: Logger instance for debug and informational messages
- processes: Slice of Process objects containing the process information
- displayOptions: Configuration options controlling how the tree will be displayed
Returns:
- A pointer to the newly created ProcessMap
func (*ProcessMap) BuildTree ¶
func (processMap *ProcessMap) BuildTree(processes []Process)
BuildTree constructs the hierarchical relationships between processes in the tree.
This method creates nodes for all processes, establishes parent-child relationships, identifies root nodes, and calculates the depth of each node in the tree.
Parameters:
- processes: Slice of Process objects to build the tree from
func (*ProcessMap) FindAllChildren ¶
func (processMap *ProcessMap) FindAllChildren(pid int32, childPIDs *[]int32)
FindAllChildren identifies all child processes of a given PID and adds them to the childPIDs slice. This function recursively traverses down the process tree to find all descendants.
Parameters:
- pid: The process ID to find children for
- childPIDs: Pointer to a slice that will be populated with child PIDs
func (*ProcessMap) FindAllParents ¶
func (processMap *ProcessMap) FindAllParents(pid int32, parentPIDs *[]int32)
FindAllParents identifies all parent processes of a given PID and adds them to the parentPIDs slice. This function recursively traverses up the process tree to find all ancestors.
Parameters:
- pid: The process ID to find parents for
- parentPIDs: Pointer to a slice that will be populated with parent PIDs
func (*ProcessMap) FindPrintable ¶
func (processMap *ProcessMap) FindPrintable()
FindPrintable marks processes that should be displayed based on filtering criteria. It applies various filters such as process name pattern matching, username filtering, root process exclusion, and PID filtering to determine which processes should be displayed.
func (*ProcessMap) FindProcess ¶
func (processMap *ProcessMap) FindProcess(targetPID int32) *ProcessNode
FindProcess locates a process node with the specified PID in the tree.
Parameters:
- targetPID: The PID of the process to find
Returns:
- A pointer to the ProcessNode if found, nil otherwise
func (*ProcessMap) HasVisibleSiblings ¶
func (processMap *ProcessMap) HasVisibleSiblings(node *ProcessNode) bool
HasVisibleSiblings determines if a process has visible siblings This is useful for drawing the correct branch characters in the tree
func (*ProcessMap) IsLastChild ¶
func (processMap *ProcessMap) IsLastChild(node *ProcessNode) bool
IsLastChild determines if a node is the last child of its parent This is useful for drawing the correct branch characters in the tree
func (*ProcessMap) IsLastSibling ¶
func (processMap *ProcessMap) IsLastSibling(node *ProcessNode) bool
IsLastSibling determines if a node is the last sibling among its parent's children
func (*ProcessMap) PrintTree ¶
func (processMap *ProcessMap) PrintTree()
PrintTree prints the process tree with indentation based on depth Each line shows the PID and process name, indented according to its depth in the tree
func (*ProcessMap) ShowPrintable ¶
func (processMap *ProcessMap) ShowPrintable()
type ProcessNode ¶
type ProcessNode struct { Children map[int32]*ProcessNode // Child processes mapped by PID Depth int // Depth in the tree (0 for root nodes) Print bool Process Process // The process data }
ProcessNode represents a node in the hierarchical process tree map
type ProcessTree ¶
type ProcessTree struct { // Logger for debug and informational messages Logger *slog.Logger // Current depth in the tree during traversal AtDepth int // Display options controlling how the tree is rendered DisplayOptions DisplayOptions // Array of process nodes in the tree Nodes []Process // Map from PID to index in the Nodes array for quick lookups PidToIndexMap map[int32]int // Map from index in the Nodes array to PID IndexToPidMap map[int]int32 // PID of the root process for the tree RootPID int32 // Tree characters for drawing the tree TreeChars TreeChars // Enable debugging DebugLevel int // Colorizer for applying colors to text Colorizer color.Colorizer // Color scheme for applying colors to text ColorScheme color.ColorScheme // Process groups for compact mode ProcessGroups map[int32]map[string]map[string]ProcessGroup // Map to track processes that should be skipped during printing SkipProcesses map[int]bool }
ProcessTree handles the construction and display of the process tree. It maintains the tree structure and provides methods for building, manipulating, and displaying the process hierarchy.
func NewProcessTree ¶
func NewProcessTree(debugLevel int, logger *slog.Logger, processes []Process, displayOptions DisplayOptions) (processTree *ProcessTree)
NewProcessTree creates a new process tree from a slice of processes.
This function initializes a ProcessTree structure, populates it with ProcessNode objects created from the provided processes, and builds the hierarchical relationships between them. The resulting tree can be used for traversal, filtering, and visualization of the process hierarchy.
Parameters:
- logger: Logger instance for debug and informational messages
- processes: Slice of Process objects containing the process information
- displayOptions: Configuration options controlling how the tree will be displayed
Returns:
- A pointer to the newly created ProcessTree
func (*ProcessTree) BuildTree ¶
func (processTree *ProcessTree) BuildTree()
BuildTree constructs the hierarchical relationships between processes in the tree.
This method establishes the parent-child relationships between processes by connecting each process to its parent based on the PPID (Parent Process ID). It creates a tree structure where each node can have one parent and multiple children, with siblings linked in a list. The resulting tree structure enables efficient traversal for operations like marking, filtering, and visualization.
The method handles cases where a parent process might not exist in the tree (e.g., if the parent was not included in the original process list or if it's the process itself).
Refactoring opportunity: This function could be broken down into smaller functions: - initializeNodes: Initialize all nodes with default values - buildParentChildRelationships: Establish the parent-child connections
func (*ProcessTree) DropUnmarked ¶
func (processTree *ProcessTree) DropUnmarked()
DropUnmarked removes processes that are not marked for display from the process tree. It modifies the process tree structure to maintain proper parent-child relationships while excluding processes that should not be displayed.
Refactoring opportunity: This function could be split into: - dropUnmarkedChildren: Remove unmarked children from each node - dropUnmarkedSiblings: Remove unmarked siblings from each node
func (*ProcessTree) FormatCompactOutput ¶
func (processTree *ProcessTree) FormatCompactOutput(command string, count int, groupPIDs []int32) string
FormatCompactOutput formats the command with count for compact mode.
This function creates a formatted string representation of a process group in the style of Linux pstree. For regular processes, the format is "N*[command]", and for threads, the format is "N*[{command}]", where N is the count.
Parameters:
- command: The command name to format
- count: Number of identical processes/threads
- isThread: Whether this is a thread group
- hideThreads: Whether threads should be hidden
Returns:
- Formatted string for display, or empty string if threads should be hidden
func (*ProcessTree) GetProcessCount ¶
func (processTree *ProcessTree) GetProcessCount(pidIndex int) (int, []int32, bool)
GetProcessCount returns the count of identical processes for the given process.
For processes that are the first in their group, this returns the total number of identical processes in that group. For processes that are not the first in their group, or are not part of a group, this returns 1.
Parameters:
- processes: Slice of Process structs
- processIndex: Index of the process to get the count for
Returns:
- count: Number of identical processes in the group
- isThread: Whether the process group represents threads
func (*ProcessTree) InitCompactMode ¶
func (processTree *ProcessTree) InitCompactMode() error
InitCompactMode initializes the compact mode by identifying identical processes.
This function analyzes the provided processes slice and groups processes that have identical commands and arguments under the same parent. It populates the processTree.ProcessGroups map with information about these groups and marks processes that should be skipped during printing (all except the first process in each group).
If any process in a potential group has threads and thread display is enabled (HideThreads is false), that group of processes will not be compacted.
This function should be called before printing the tree when compact mode is enabled.
Returns:
- error: nil if successful, or an error if initialization fails
func (*ProcessTree) MarkCurrentAndAncestors ¶
func (processTree *ProcessTree) MarkCurrentAndAncestors(currentPid int32)
MarkCurrentAndAncestors marks the current process and all its ancestors. This function identifies the current process by its PID and marks it and all its ancestors with IsCurrentOrAncestor=true for highlighting in the display.
Parameters:
- currentPid: The PID of the current process to highlight
func (*ProcessTree) MarkProcesses ¶
func (processTree *ProcessTree) MarkProcesses()
MarkProcesses marks processes that should be displayed based on filtering criteria. It applies various filters such as process name pattern matching, username filtering, root process exclusion, and PID filtering to determine which processes should be displayed.
Refactoring opportunity: This function could be broken down into smaller functions: - applyUsernameFilter: Mark processes matching username criteria - applyRootPIDFilter: Mark processes based on root PID - applyCommandFilter: Mark processes matching command pattern - applyRootExclusionFilter: Apply root user exclusion filter
func (*ProcessTree) MarkUIDTransitions ¶
func (processTree *ProcessTree) MarkUIDTransitions()
MarkUIDTransitions identifies and marks processes where the user ID changes from the parent process. This function compares the UIDs of each process with its parent and sets HasUIDTransition=true when a transition is detected. It also stores the parent UID for display purposes.
Parameters:
- logger: Logger instance for debug information
- processes: Pointer to a slice of Process structs
func (*ProcessTree) OptimizedBuildTree ¶
func (processTree *ProcessTree) OptimizedBuildTree()
OptimizedBuildTree is an optimized version of BuildTree that uses the PidToIndexMap to avoid linear searches through the process list.
This function initializes all nodes with default values (-1) for Child, Parent, and Sister fields, then builds the tree structure using O(1) lookups via PidToIndexMap. It establishes parent-child relationships between processes and maintains sibling relationships for processes with the same parent.
The optimization comes from using direct index lookups instead of iterating through the process list to find parent processes, significantly improving performance for large process trees.
func (*ProcessTree) PIDsToString ¶
func (processTree *ProcessTree) PIDsToString(pids []int32) []string
PIDsToString converts a slice of process IDs to a slice of their string representations.
This function is used in compact mode when displaying process groups with PIDs. Each PID is converted to a string representation that can be joined together for display in the process tree.
Parameters:
- pids: Slice of int32 process IDs to convert
Returns:
- []string: Slice of string representations of the PIDs
func (*ProcessTree) PrintThreads ¶
func (processTree *ProcessTree) PrintThreads(pidIndex int, head string)
PrintThreads displays the threads of a process in a tree-like structure. It formats each thread with its thread ID and PGID. This only works on Linux because macOS does not provide thread IDs.
Parameters:
- pidIndex: Index of the parent process whose threads to display
- head: The accumulated prefix string from parent levels
func (*ProcessTree) PrintTree ¶
func (processTree *ProcessTree) PrintTree(pidIndex int, head string)
PrintTree recursively prints a process tree with customizable formatting options.
This function displays a process and all its children in a tree-like structure, with various display options such as process age, CPU usage, memory usage, etc. The tree is formatted using different graphical styles based on the display options.
Parameters:
- pidIndex: Index of the current process to print
- head: String representing the indentation and tree structure for the current line
Refactoring opportunity: This function could be split into: - printCurrentNode: Print just the current node - printChildNodes: Handle the recursive printing of child nodes
func (*ProcessTree) ShouldSkipProcess ¶
func (processTree *ProcessTree) ShouldSkipProcess(pidIndex int) bool
ShouldSkipProcess returns true if the process should be skipped during printing.
In compact mode, only the first process of each identical group is displayed, with a count indicator. This function checks if a process has been marked to be skipped during the initialization phase.
Parameters:
- pidIndex: Index of the process to check
Returns:
- true if the process should be skipped, false otherwise
func (*ProcessTree) ShowPrintable ¶
func (processTree *ProcessTree) ShowPrintable()
ShowPrintable logs all processes that are marked for display.
This method is primarily used for debugging purposes. It iterates through all nodes in the process tree and logs detailed information about each process that has been marked for display (Print=true). The output includes all fields of the Process struct.
The method uses pretty-printing to format the output in a readable way.
type TreeChars ¶
type TreeChars struct { // Bar represents the vertical bar character (│) used for drawing process tree lines Bar string // BarC represents the T-junction character (├) used where a process branches off BarC string // BarL represents the L-junction character (└) used for the last child process in a branch BarL string // EG represents the End Graphics character sequence for terminating graphic mode EG string // Init represents the initialization sequence for the terminal Init string // NPGL represents the character sequence to initialize the graphic set for non-process group leaders NPGL string // P represents the horizontal line character (─) used for connecting processes P string // PGL represents the character sequence used to highlight process group leaders PGL string // S2 represents the secondary process horizontal line character (─) for alternative styling S2 string // SG represents the Start Graphics character sequence for entering graphic mode SG string }
TreeChars defines the characters used for drawing the tree. Different character sets are available for different terminal types and preferences.