@@ -393,7 +393,7 @@ func StartOTelCollector(cfg *OTelConfig) error {
393393
394394 interval := cfg .CollectionInterval
395395 if interval == 0 {
396- interval = 15 * time .Second
396+ interval = 30 * time .Second
397397 }
398398
399399 meterProvider = sdkmetric .NewMeterProvider (
@@ -1776,10 +1776,12 @@ func collectProcesses(limit int) ([]ProcessInfo, error) {
17761776 continue
17771777 }
17781778
1779- cpuPercent , _ := p .CPUPercent ()
1779+ // Only use MemoryPercent for filtering (non-blocking)
1780+ // Skip CPUPercent - it blocks for 100ms per process!
17801781 memPercent , _ := p .MemoryPercent ()
17811782
1782- if cpuPercent < 0.1 && memPercent < 0.1 {
1783+ // Filter by memory only (processes with < 0.1% memory are not interesting)
1784+ if memPercent < 0.1 {
17831785 continue
17841786 }
17851787
@@ -1788,82 +1790,32 @@ func collectProcesses(limit int) ([]ProcessInfo, error) {
17881790 Name : name ,
17891791 }
17901792
1791- if ppid , err := p .Ppid (); err == nil {
1792- pi .PPID = int (ppid )
1793- }
1794-
1795- pi .CPUPercent = cpuPercent
17961793 pi .MemoryPercent = float64 (memPercent )
17971794
1795+ // Minimal syscalls: only cmdline and memory info
17981796 if cmdline , err := p .Cmdline (); err == nil {
17991797 pi .Command = truncateString (cmdline , 200 )
18001798 } else {
18011799 pi .Command = name
18021800 }
18031801
1804- if exe , err := p .Exe (); err == nil {
1805- pi .Exe = exe
1806- }
1807-
1808- if uids , err := p .Uids (); err == nil && len (uids ) > 0 {
1809- pi .UID = uids [0 ]
1810- pi .User = fmt .Sprintf ("%d" , uids [0 ])
1811- }
1812-
1813- if gids , err := p .Gids (); err == nil && len (gids ) > 0 {
1814- pi .GID = gids [0 ]
1815- }
1816-
18171802 if memInfo , err := p .MemoryInfo (); err == nil && memInfo != nil {
18181803 pi .MemoryRSS = memInfo .RSS
1819- pi .MemoryVMS = memInfo .VMS
18201804 }
18211805
18221806 if status , err := p .Status (); err == nil && len (status ) > 0 {
18231807 pi .Status = string (status [0 ])
18241808 }
18251809
1826- if threads , err := p .NumThreads (); err == nil {
1827- pi .NumThreads = uint16 (threads )
1828- }
1829-
1830- if fds , err := p .NumFDs (); err == nil {
1831- pi .NumFDs = uint32 (fds )
1832- }
1833-
1834- if ioCounters , err := p .IOCounters (); err == nil && ioCounters != nil {
1835- pi .IOReadBytes = ioCounters .ReadBytes
1836- pi .IOWriteBytes = ioCounters .WriteBytes
1837- }
1838-
1839- if createTime , err := p .CreateTime (); err == nil {
1840- pi .CreateTime = createTime / 1000
1841- }
1842-
1843- if times , err := p .Times (); err == nil && times != nil {
1844- pi .CPUTimeUser = times .User
1845- pi .CPUTimeSystem = times .System
1846- }
1847-
1848- if nice , err := p .Nice (); err == nil {
1849- pi .Nice = int8 (nice )
1850- }
1851-
1852- if terminal , err := p .Terminal (); err == nil {
1853- pi .TTY = terminal
1854- }
1855-
1856- pi .CPUUsage = pi .CPUPercent
18571810 pi .MemoryUsage = pi .MemoryPercent
18581811 pi .MemoryKB = int64 (pi .MemoryRSS / 1024 )
1859- pi .Threads = int (pi .NumThreads )
18601812
18611813 processes = append (processes , pi )
18621814 }
18631815
1864- // Sort by CPU usage
1816+ // Sort by memory usage (since we don't have CPU anymore)
18651817 sort .Slice (processes , func (i , j int ) bool {
1866- return processes [i ].CPUPercent > processes [j ].CPUPercent
1818+ return processes [i ].MemoryPercent > processes [j ].MemoryPercent
18671819 })
18681820
18691821 if len (processes ) > limit {
@@ -1890,8 +1842,9 @@ func collectContainers() ([]ContainerMetrics, error) {
18901842}
18911843
18921844func collectDockerContainers () ([]ContainerMetrics , error ) {
1893- // Check if docker is available
1894- cmd := exec .Command ("docker" , "ps" , "-q" )
1845+ // Single call to docker stats - gets all running containers at once
1846+ // Skip "docker ps" check - if no containers, stats returns empty
1847+ cmd := exec .Command ("docker" , "stats" , "--no-stream" , "--format" , "{{json .}}" )
18951848 output , err := cmd .Output ()
18961849 if err != nil {
18971850 return nil , err
@@ -1901,13 +1854,6 @@ func collectDockerContainers() ([]ContainerMetrics, error) {
19011854 return nil , nil
19021855 }
19031856
1904- // Get container stats
1905- cmd = exec .Command ("docker" , "stats" , "--no-stream" , "--format" , "{{json .}}" )
1906- output , err = cmd .Output ()
1907- if err != nil {
1908- return nil , err
1909- }
1910-
19111857 var containers []ContainerMetrics
19121858
19131859 lines := strings .Split (strings .TrimSpace (string (output )), "\n " )
@@ -1917,14 +1863,11 @@ func collectDockerContainers() ([]ContainerMetrics, error) {
19171863 }
19181864
19191865 var stats struct {
1920- ID string `json:"ID"`
1921- Name string `json:"Name"`
1922- CPUPerc string `json:"CPUPerc"`
1923- MemUsage string `json:"MemUsage"`
1924- MemPerc string `json:"MemPerc"`
1925- NetIO string `json:"NetIO"`
1926- BlockIO string `json:"BlockIO"`
1927- PIDs string `json:"PIDs"`
1866+ ID string `json:"ID"`
1867+ Name string `json:"Name"`
1868+ CPUPerc string `json:"CPUPerc"`
1869+ MemUsage string `json:"MemUsage"`
1870+ MemPerc string `json:"MemPerc"`
19281871 }
19291872
19301873 if err := json .Unmarshal ([]byte (line ), & stats ); err != nil {
@@ -1953,38 +1896,8 @@ func collectDockerContainers() ([]ContainerMetrics, error) {
19531896 containers = append (containers , c )
19541897 }
19551898
1956- // Get more details with docker inspect
1957- for i := range containers {
1958- cmd := exec .Command ("docker" , "inspect" , "--format" , "{{json .}}" , containers [i ].ContainerID )
1959- output , err := cmd .Output ()
1960- if err != nil {
1961- continue
1962- }
1963-
1964- var inspect struct {
1965- Config struct {
1966- Image string `json:"Image"`
1967- Labels map [string ]string `json:"Labels"`
1968- } `json:"Config"`
1969- State struct {
1970- Status string `json:"Status"`
1971- Health * struct { Status string } `json:"Health"`
1972- StartedAt string `json:"StartedAt"`
1973- ExitCode int16 `json:"ExitCode"`
1974- } `json:"State"`
1975- }
1976-
1977- if err := json .Unmarshal (output , & inspect ); err == nil {
1978- containers [i ].ImageName = inspect .Config .Image
1979- containers [i ].Status = inspect .State .Status
1980- if inspect .State .Health != nil {
1981- containers [i ].Health = inspect .State .Health .Status
1982- }
1983- if labels , err := json .Marshal (inspect .Config .Labels ); err == nil {
1984- containers [i ].Labels = string (labels )
1985- }
1986- }
1987- }
1899+ // Skip docker inspect for each container - too expensive (N syscalls)
1900+ // Basic stats from "docker stats" are enough for monitoring
19881901
19891902 return containers , nil
19901903}
0 commit comments