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.