tree

package
v0.8.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 9, 2025 License: GPL-3.0 Imports: 17 Imported by: 0

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

Constants

This section is empty.

Variables

View Source
var AnsiEscape = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`)
View Source
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 Thread

type Thread struct {
	// Command line arguments
	Args []string
	// Process group ID
	PGID int32
	// PID
	PID int32
	// Parent PID
	PPID int32
	// Thread ID
	TID int32
	// Command name (executable name)
	Command string
	// CPU Times
	CPUTimes *cpu.TimesStat
}

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL