plugins/input/process/input_process_cache_other.go (215 lines of code) (raw):

// Copyright 2021 iLogtail Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //go:build !linux // +build !linux package process import ( "context" "strconv" "time" "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/process" "github.com/alibaba/ilogtail/pkg/helper" "github.com/alibaba/ilogtail/pkg/logger" ) type processCacheOther struct { meta *processMeta status *processStatus proc *process.Process createTime int64 commName string isRunning bool // Dynamic infos timesStat *cpu.TimesStat lastTimesStat *cpu.TimesStat } func findAllProcessCache(maxLabelLength int) ([]processCache, error) { processes, err := process.Processes() if err != nil { logger.Errorf(context.Background(), "PROCESS_LIST_ALARM", "error: %v", err) return nil, err } if len(processes) == 0 { return []processCache{}, nil } caches := make([]processCache, 0, len(processes)) for _, proc := range processes { createTime, err := proc.CreateTime() if err != nil { logger.Debugf(context.Background(), "PID:%d error in getting create time", proc.Pid, err) continue } caches = append(caches, &processCacheOther{ meta: newProcessCacheMeta(maxLabelLength), status: newProcessCacheStatus(), proc: proc, createTime: createTime, isRunning: true, }) } return caches, nil } func (pc *processCacheOther) GetProcessStatus() *processStatus { return pc.status } func (pc *processCacheOther) GetPid() int { return int(pc.proc.Pid) } func (pc *processCacheOther) Same(cache processCache) bool { other := cache.(*processCacheOther) return pc.proc.Pid == other.proc.Pid && pc.createTime == other.createTime } func (pc *processCacheOther) GetExe() string { if pc.isRunning && pc.meta.exe == "" { if exe, err := pc.proc.Exe(); err != nil { pc.tryChangeRunningStatus(err) logger.Debug(context.Background(), "get exe error, error", err) } else { pc.meta.exe = exe } } return pc.meta.exe } func (pc *processCacheOther) GetCmdLine() string { if pc.isRunning && pc.meta.cmdline == "" { cmdline, err := pc.proc.Cmdline() if err != nil { pc.tryChangeRunningStatus(err) logger.Debug(context.Background(), "get cmdline error, error", err) return "" } pc.meta.cmdline = cmdline } return pc.meta.cmdline } func (pc *processCacheOther) getCommName() string { if pc.isRunning && pc.commName == "" { name, err := pc.proc.Name() if err != nil { pc.tryChangeRunningStatus(err) logger.Debug(context.Background(), "get cmdline error, error", err) return "" } pc.commName = name } return pc.commName } func (pc *processCacheOther) FetchCoreCount() int64 { return pc.meta.fetchCoreCount } func (pc *processCacheOther) Labels(customLabels *helper.MetricLabels) *helper.MetricLabels { if pc.meta.labels == nil { if name := pc.getCommName(); name != "" { processLabels := customLabels.Clone() processLabels.Append("pid", strconv.Itoa(pc.GetPid())) if pc.meta.maxLabelLength < len(name) { logger.Warningf(context.Background(), "PROCESS_LABEL_TOO_LONG_ALARM", "the stat cmdline label is over %d chars: %s", pc.meta.maxLabelLength, name) processLabels.Append("comm", name[:pc.meta.maxLabelLength]) } else { processLabels.Append("comm", name) } pc.meta.labels = processLabels } } return pc.meta.labels } func (pc *processCacheOther) FetchCore() bool { if !pc.isRunning { return false } times, err := pc.proc.Times() if err != nil { pc.tryChangeRunningStatus(err) logger.Debug(context.Background(), "get cpu time error, error", err) return false } info, err := pc.proc.MemoryInfo() if err != nil { pc.tryChangeRunningStatus(err) logger.Debug(context.Background(), "get Memory error, error", err) return false } pc.meta.lastFetchTime = pc.meta.nowFetchTime pc.meta.nowFetchTime = time.Now() pc.meta.fetchCoreCount++ pc.lastTimesStat = pc.timesStat pc.timesStat = times if pc.meta.fetchCoreCount > 1 { totalTime := pc.meta.nowFetchTime.Sub(pc.meta.lastFetchTime).Seconds() pc.status.CPUPercentage = &cpuPercentage{ TotalPercentage: 100 * (pc.timesStat.System + pc.timesStat.User - pc.lastTimesStat.System - pc.lastTimesStat.User) / totalTime, STimePercentage: 100 * (pc.timesStat.System - pc.lastTimesStat.System) / totalTime, UTimePercentage: 100 * (pc.timesStat.User - pc.lastTimesStat.User) / totalTime, } } pc.status.Memory = &memory{ Rss: info.RSS, Data: info.Data, Vsz: info.VMS, Swap: info.Swap, } return true } func (pc *processCacheOther) FetchFds() bool { if !pc.isRunning { return false } openFiles, err := pc.proc.OpenFiles() if err != nil { pc.tryChangeRunningStatus(err) logger.Debug(context.Background(), "get fds error, error", err) return false } pc.status.FdsNum = len(openFiles) return true } func (pc *processCacheOther) FetchNetIO() bool { if !pc.isRunning { return false } netIoCounters, err := pc.proc.NetIOCounters(false) if err != nil { pc.tryChangeRunningStatus(err) logger.Debug(context.Background(), "get net IO error, error", err) return false } pc.status.NetIO = &netIO{ InBytes: netIoCounters[0].BytesRecv, OutBytes: netIoCounters[0].BytesSent, InPacket: netIoCounters[0].PacketsRecv, OutPacket: netIoCounters[0].PacketsSent, } return true } func (pc *processCacheOther) FetchIO() bool { if !pc.isRunning { return false } ioCounters, err := pc.proc.IOCounters() if err != nil { pc.tryChangeRunningStatus(err) logger.Debug(context.Background(), "get IO error, error", err) return false } pc.status.IO = &io{ ReadeBytes: ioCounters.ReadBytes, WriteBytes: ioCounters.WriteBytes, ReadCount: ioCounters.ReadCount, WriteCount: ioCounters.WriteCount, } return true } func (pc *processCacheOther) FetchThreads() bool { if !pc.isRunning { return false } threads, err := pc.proc.Threads() if err != nil { pc.tryChangeRunningStatus(err) logger.Debug(context.Background(), "get threads error, error", err) return false } pc.status.ThreadsNum = len(threads) return true } func (pc *processCacheOther) tryChangeRunningStatus(err error) { if err == process.ErrorProcessNotRunning { pc.isRunning = false logger.Debugf(context.Background(), "PID_%d process closed", pc.GetPid()) } }