106f6ba60Sopenharmony_ci/* 206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. 306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License. 506f6ba60Sopenharmony_ci * You may obtain a copy of the License at 606f6ba60Sopenharmony_ci * 706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 806f6ba60Sopenharmony_ci * 906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and 1306f6ba60Sopenharmony_ci * limitations under the License. 1406f6ba60Sopenharmony_ci */ 1506f6ba60Sopenharmony_ci#include "process_data_plugin.h" 1606f6ba60Sopenharmony_ci 1706f6ba60Sopenharmony_ci#include <fcntl.h> 1806f6ba60Sopenharmony_ci#include <fstream> 1906f6ba60Sopenharmony_ci#include <iostream> 2006f6ba60Sopenharmony_ci#include <sstream> 2106f6ba60Sopenharmony_ci 2206f6ba60Sopenharmony_ci#include "buffer_splitter.h" 2306f6ba60Sopenharmony_ci#include "process_plugin_result.pbencoder.h" 2406f6ba60Sopenharmony_ci#include "securec.h" 2506f6ba60Sopenharmony_ci 2606f6ba60Sopenharmony_cinamespace { 2706f6ba60Sopenharmony_ciusing namespace OHOS::Developtools::Profiler; 2806f6ba60Sopenharmony_ciconstexpr size_t READ_BUFFER_SIZE = 1024 * 16; 2906f6ba60Sopenharmony_ciconstexpr int DEC_BASE = 10; 3006f6ba60Sopenharmony_ciconstexpr int STAT_COUNT = 13; 3106f6ba60Sopenharmony_ciconstexpr int CPU_USER_HZ_L = 100; 3206f6ba60Sopenharmony_ciconstexpr int CPU_USER_HZ_H = 1000; 3306f6ba60Sopenharmony_ciconstexpr int CPU_HZ_H = 10; 3406f6ba60Sopenharmony_ciconst int PERCENT = 100; 3506f6ba60Sopenharmony_ci} // namespace 3606f6ba60Sopenharmony_ci 3706f6ba60Sopenharmony_ciProcessDataPlugin::ProcessDataPlugin() : err_(-1) 3806f6ba60Sopenharmony_ci{ 3906f6ba60Sopenharmony_ci SetPath("/proc/"); 4006f6ba60Sopenharmony_ci buffer_ = std::make_unique<uint8_t[]>(READ_BUFFER_SIZE); 4106f6ba60Sopenharmony_ci} 4206f6ba60Sopenharmony_ci 4306f6ba60Sopenharmony_ciProcessDataPlugin::~ProcessDataPlugin() 4406f6ba60Sopenharmony_ci{ 4506f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "%s:~ProcessDataPlugin!", __func__); 4606f6ba60Sopenharmony_ci 4706f6ba60Sopenharmony_ci buffer_ = nullptr; 4806f6ba60Sopenharmony_ci 4906f6ba60Sopenharmony_ci return; 5006f6ba60Sopenharmony_ci} 5106f6ba60Sopenharmony_ci 5206f6ba60Sopenharmony_ciint ProcessDataPlugin::Start(const uint8_t* configData, uint32_t configSize) 5306f6ba60Sopenharmony_ci{ 5406f6ba60Sopenharmony_ci CHECK_NOTNULL(buffer_, RET_FAIL, "%s:buffer_ == null", __func__); 5506f6ba60Sopenharmony_ci 5606f6ba60Sopenharmony_ci CHECK_TRUE(protoConfig_.ParseFromArray(configData, configSize) > 0, RET_FAIL, 5706f6ba60Sopenharmony_ci "%s:parseFromArray failed!", __func__); 5806f6ba60Sopenharmony_ci 5906f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "%s:start success!", __func__); 6006f6ba60Sopenharmony_ci return RET_SUCC; 6106f6ba60Sopenharmony_ci} 6206f6ba60Sopenharmony_ci 6306f6ba60Sopenharmony_ciint ProcessDataPlugin::ReportOptimize(RandomWriteCtx* randomWrite) 6406f6ba60Sopenharmony_ci{ 6506f6ba60Sopenharmony_ci ProtoEncoder::ProcessData dataProto(randomWrite); 6606f6ba60Sopenharmony_ci if (protoConfig_.report_process_tree()) { 6706f6ba60Sopenharmony_ci WriteProcesseList(dataProto); 6806f6ba60Sopenharmony_ci } 6906f6ba60Sopenharmony_ci 7006f6ba60Sopenharmony_ci int msgSize = dataProto.Finish(); 7106f6ba60Sopenharmony_ci return msgSize; 7206f6ba60Sopenharmony_ci} 7306f6ba60Sopenharmony_ci 7406f6ba60Sopenharmony_ciint ProcessDataPlugin::Report(uint8_t* data, uint32_t dataSize) 7506f6ba60Sopenharmony_ci{ 7606f6ba60Sopenharmony_ci ProcessData dataProto; 7706f6ba60Sopenharmony_ci uint32_t length; 7806f6ba60Sopenharmony_ci 7906f6ba60Sopenharmony_ci if (protoConfig_.report_process_tree()) { 8006f6ba60Sopenharmony_ci WriteProcesseList(dataProto); 8106f6ba60Sopenharmony_ci } 8206f6ba60Sopenharmony_ci 8306f6ba60Sopenharmony_ci length = dataProto.ByteSizeLong(); 8406f6ba60Sopenharmony_ci if (length > dataSize) { 8506f6ba60Sopenharmony_ci return -length; 8606f6ba60Sopenharmony_ci } 8706f6ba60Sopenharmony_ci if (dataProto.SerializeToArray(data, length) > 0) { 8806f6ba60Sopenharmony_ci return length; 8906f6ba60Sopenharmony_ci } 9006f6ba60Sopenharmony_ci return 0; 9106f6ba60Sopenharmony_ci} 9206f6ba60Sopenharmony_ci 9306f6ba60Sopenharmony_ciint ProcessDataPlugin::Stop() 9406f6ba60Sopenharmony_ci{ 9506f6ba60Sopenharmony_ci pids_.clear(); 9606f6ba60Sopenharmony_ci cpuTime_.clear(); 9706f6ba60Sopenharmony_ci bootTime_.clear(); 9806f6ba60Sopenharmony_ci 9906f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "%s:stop success!", __func__); 10006f6ba60Sopenharmony_ci return 0; 10106f6ba60Sopenharmony_ci} 10206f6ba60Sopenharmony_ci 10306f6ba60Sopenharmony_ciDIR* ProcessDataPlugin::OpenDestDir(const char* dirPath) 10406f6ba60Sopenharmony_ci{ 10506f6ba60Sopenharmony_ci DIR* destDir = nullptr; 10606f6ba60Sopenharmony_ci 10706f6ba60Sopenharmony_ci destDir = opendir(dirPath); 10806f6ba60Sopenharmony_ci if (destDir == nullptr) { 10906f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "%s:failed to opendir(%s), errno=%d", __func__, dirPath, errno); 11006f6ba60Sopenharmony_ci } 11106f6ba60Sopenharmony_ci 11206f6ba60Sopenharmony_ci return destDir; 11306f6ba60Sopenharmony_ci} 11406f6ba60Sopenharmony_ci 11506f6ba60Sopenharmony_ciint32_t ProcessDataPlugin::GetValidPid(DIR* dirp) 11606f6ba60Sopenharmony_ci{ 11706f6ba60Sopenharmony_ci if (!dirp) { 11806f6ba60Sopenharmony_ci return 0; 11906f6ba60Sopenharmony_ci } 12006f6ba60Sopenharmony_ci while (struct dirent* dirEnt = readdir(dirp)) { 12106f6ba60Sopenharmony_ci if (dirEnt->d_type != DT_DIR) { 12206f6ba60Sopenharmony_ci continue; 12306f6ba60Sopenharmony_ci } 12406f6ba60Sopenharmony_ci 12506f6ba60Sopenharmony_ci int32_t pid = atoi(dirEnt->d_name); 12606f6ba60Sopenharmony_ci if (pid) { 12706f6ba60Sopenharmony_ci return pid; 12806f6ba60Sopenharmony_ci } 12906f6ba60Sopenharmony_ci } 13006f6ba60Sopenharmony_ci return 0; 13106f6ba60Sopenharmony_ci} 13206f6ba60Sopenharmony_ci 13306f6ba60Sopenharmony_ciint32_t ProcessDataPlugin::ReadProcPidFile(int32_t pid, const char* pFileName) 13406f6ba60Sopenharmony_ci{ 13506f6ba60Sopenharmony_ci char fileName[PATH_MAX + 1] = {0}; 13606f6ba60Sopenharmony_ci char realPath[PATH_MAX + 1] = {0}; 13706f6ba60Sopenharmony_ci int fd = -1; 13806f6ba60Sopenharmony_ci ssize_t bytesRead = 0; 13906f6ba60Sopenharmony_ci 14006f6ba60Sopenharmony_ci if (snprintf_s(fileName, sizeof(fileName), sizeof(fileName) - 1, "%s%d/%s", path_.c_str(), pid, pFileName) < 0) { 14106f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "%s:snprintf_s error", __func__); 14206f6ba60Sopenharmony_ci } 14306f6ba60Sopenharmony_ci if (realpath(fileName, realPath) == nullptr) { 14406f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "%s:realpath failed, errno=%d", __func__, errno); 14506f6ba60Sopenharmony_ci return RET_FAIL; 14606f6ba60Sopenharmony_ci } 14706f6ba60Sopenharmony_ci fd = open(realPath, O_RDONLY | O_CLOEXEC); 14806f6ba60Sopenharmony_ci if (fd == -1) { 14906f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "%s:failed to open(%s), errno=%d", __func__, fileName, errno); 15006f6ba60Sopenharmony_ci err_ = errno; 15106f6ba60Sopenharmony_ci return RET_FAIL; 15206f6ba60Sopenharmony_ci } 15306f6ba60Sopenharmony_ci if (buffer_.get() == nullptr) { 15406f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "%s:empty address, buffer_ is NULL", __func__); 15506f6ba60Sopenharmony_ci err_ = RET_NULL_ADDR; 15606f6ba60Sopenharmony_ci close(fd); 15706f6ba60Sopenharmony_ci return RET_FAIL; 15806f6ba60Sopenharmony_ci } 15906f6ba60Sopenharmony_ci bytesRead = read(fd, buffer_.get(), READ_BUFFER_SIZE - 1); 16006f6ba60Sopenharmony_ci if (bytesRead < 0) { 16106f6ba60Sopenharmony_ci close(fd); 16206f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "%s:failed to read(%s), errno=%d", __func__, fileName, errno); 16306f6ba60Sopenharmony_ci err_ = errno; 16406f6ba60Sopenharmony_ci return RET_FAIL; 16506f6ba60Sopenharmony_ci } 16606f6ba60Sopenharmony_ci buffer_.get()[bytesRead] = '\0'; 16706f6ba60Sopenharmony_ci close(fd); 16806f6ba60Sopenharmony_ci 16906f6ba60Sopenharmony_ci return bytesRead; 17006f6ba60Sopenharmony_ci} 17106f6ba60Sopenharmony_ci 17206f6ba60Sopenharmony_cibool ProcessDataPlugin::BufnCmp(const char* src, int srcLen, const char* key, int keyLen) 17306f6ba60Sopenharmony_ci{ 17406f6ba60Sopenharmony_ci if (!src || !key || (srcLen < keyLen)) { 17506f6ba60Sopenharmony_ci return false; 17606f6ba60Sopenharmony_ci } 17706f6ba60Sopenharmony_ci for (int i = 0; i < keyLen; i++) { 17806f6ba60Sopenharmony_ci if (*src++ != *key++) { 17906f6ba60Sopenharmony_ci return false; 18006f6ba60Sopenharmony_ci } 18106f6ba60Sopenharmony_ci } 18206f6ba60Sopenharmony_ci return true; 18306f6ba60Sopenharmony_ci} 18406f6ba60Sopenharmony_ci 18506f6ba60Sopenharmony_cibool ProcessDataPlugin::addPidBySort(int32_t pid) 18606f6ba60Sopenharmony_ci{ 18706f6ba60Sopenharmony_ci auto pidsEnd = pids_.end(); 18806f6ba60Sopenharmony_ci auto it = std::lower_bound(pids_.begin(), pidsEnd, pid); 18906f6ba60Sopenharmony_ci if (it != pidsEnd && *it == pid) { 19006f6ba60Sopenharmony_ci return false; 19106f6ba60Sopenharmony_ci } 19206f6ba60Sopenharmony_ci it = pids_.insert(it, std::move(pid)); 19306f6ba60Sopenharmony_ci return true; 19406f6ba60Sopenharmony_ci} 19506f6ba60Sopenharmony_ci 19606f6ba60Sopenharmony_citemplate <typename T> 19706f6ba60Sopenharmony_civoid ProcessDataPlugin::WriteProcess(T& processinfo, const char* pFile, uint32_t fileLen, int32_t pid) 19806f6ba60Sopenharmony_ci{ 19906f6ba60Sopenharmony_ci BufferSplitter totalbuffer(const_cast<const char*>(pFile), fileLen + 1); 20006f6ba60Sopenharmony_ci 20106f6ba60Sopenharmony_ci do { 20206f6ba60Sopenharmony_ci totalbuffer.NextWord(':'); 20306f6ba60Sopenharmony_ci if (!totalbuffer.CurWord()) { 20406f6ba60Sopenharmony_ci return; 20506f6ba60Sopenharmony_ci } 20606f6ba60Sopenharmony_ci 20706f6ba60Sopenharmony_ci if (BufnCmp(totalbuffer.CurWord(), totalbuffer.CurWordSize(), "Name", strlen("Name"))) { 20806f6ba60Sopenharmony_ci totalbuffer.NextWord('\n'); 20906f6ba60Sopenharmony_ci if (!totalbuffer.CurWord()) { 21006f6ba60Sopenharmony_ci return; 21106f6ba60Sopenharmony_ci } 21206f6ba60Sopenharmony_ci processinfo.set_name(totalbuffer.CurWord(), totalbuffer.CurWordSize()); 21306f6ba60Sopenharmony_ci } else if (BufnCmp(totalbuffer.CurWord(), totalbuffer.CurWordSize(), "Pid", strlen("Pid"))) { 21406f6ba60Sopenharmony_ci totalbuffer.NextWord('\n'); 21506f6ba60Sopenharmony_ci if (!totalbuffer.CurWord()) { 21606f6ba60Sopenharmony_ci return; 21706f6ba60Sopenharmony_ci } 21806f6ba60Sopenharmony_ci char* end = nullptr; 21906f6ba60Sopenharmony_ci int32_t value = static_cast<int32_t>(strtoul(totalbuffer.CurWord(), &end, DEC_BASE)); 22006f6ba60Sopenharmony_ci if (value < 0) { 22106f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "%s:strtoull value failed", __func__); 22206f6ba60Sopenharmony_ci } 22306f6ba60Sopenharmony_ci processinfo.set_pid(value); 22406f6ba60Sopenharmony_ci } else if (BufnCmp(totalbuffer.CurWord(), totalbuffer.CurWordSize(), "PPid", strlen("PPid"))) { 22506f6ba60Sopenharmony_ci totalbuffer.NextWord('\n'); 22606f6ba60Sopenharmony_ci if (!totalbuffer.CurWord()) { 22706f6ba60Sopenharmony_ci return; 22806f6ba60Sopenharmony_ci } 22906f6ba60Sopenharmony_ci char* end = nullptr; 23006f6ba60Sopenharmony_ci int32_t value = static_cast<int32_t>(strtoul(totalbuffer.CurWord(), &end, DEC_BASE)); 23106f6ba60Sopenharmony_ci if (value < 0) { 23206f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "%s:strtoull value failed", __func__); 23306f6ba60Sopenharmony_ci } 23406f6ba60Sopenharmony_ci processinfo.set_ppid(value); 23506f6ba60Sopenharmony_ci } else if (BufnCmp(totalbuffer.CurWord(), totalbuffer.CurWordSize(), "Uid", strlen("Uid"))) { 23606f6ba60Sopenharmony_ci totalbuffer.NextWord('\n'); 23706f6ba60Sopenharmony_ci if (!totalbuffer.CurWord()) { 23806f6ba60Sopenharmony_ci return; 23906f6ba60Sopenharmony_ci } 24006f6ba60Sopenharmony_ci std::string curWord = std::string(totalbuffer.CurWord(), totalbuffer.CurWordSize()); 24106f6ba60Sopenharmony_ci curWord = curWord.substr(0, curWord.find(" ")); 24206f6ba60Sopenharmony_ci char* end = nullptr; 24306f6ba60Sopenharmony_ci int32_t value = static_cast<int32_t>(strtoul(curWord.c_str(), &end, DEC_BASE)); 24406f6ba60Sopenharmony_ci if (value < 0) { 24506f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "%s:strtoull value failed", __func__); 24606f6ba60Sopenharmony_ci } 24706f6ba60Sopenharmony_ci processinfo.set_uid(value); 24806f6ba60Sopenharmony_ci break; 24906f6ba60Sopenharmony_ci } else { 25006f6ba60Sopenharmony_ci totalbuffer.NextWord('\n'); 25106f6ba60Sopenharmony_ci if (!totalbuffer.CurWord()) { 25206f6ba60Sopenharmony_ci continue; 25306f6ba60Sopenharmony_ci } 25406f6ba60Sopenharmony_ci } 25506f6ba60Sopenharmony_ci } while (totalbuffer.NextLine()); 25606f6ba60Sopenharmony_ci // update process name 25706f6ba60Sopenharmony_ci int32_t ret = ReadProcPidFile(pid, "cmdline"); 25806f6ba60Sopenharmony_ci if (ret > 0) { 25906f6ba60Sopenharmony_ci processinfo.set_name(reinterpret_cast<char*>(buffer_.get()), strlen(reinterpret_cast<char*>(buffer_.get()))); 26006f6ba60Sopenharmony_ci } 26106f6ba60Sopenharmony_ci} 26206f6ba60Sopenharmony_ci 26306f6ba60Sopenharmony_citemplate <typename T> void ProcessDataPlugin::WriteProcessInfo(T& processData, int32_t pid) 26406f6ba60Sopenharmony_ci{ 26506f6ba60Sopenharmony_ci int32_t ret = ReadProcPidFile(pid, "status"); 26606f6ba60Sopenharmony_ci if (ret == RET_FAIL) { 26706f6ba60Sopenharmony_ci return; 26806f6ba60Sopenharmony_ci } 26906f6ba60Sopenharmony_ci if ((buffer_.get() == nullptr) || (ret == 0)) { 27006f6ba60Sopenharmony_ci return; 27106f6ba60Sopenharmony_ci } 27206f6ba60Sopenharmony_ci auto* processinfo = processData.add_processesinfo(); 27306f6ba60Sopenharmony_ci WriteProcess(*processinfo, reinterpret_cast<char*>(buffer_.get()), ret, pid); 27406f6ba60Sopenharmony_ci if (protoConfig_.report_cpu()) { 27506f6ba60Sopenharmony_ci auto* cpuInfo = processinfo->mutable_cpuinfo(); 27606f6ba60Sopenharmony_ci std::vector<uint64_t> cpuUsageVec; 27706f6ba60Sopenharmony_ci std::vector<uint64_t> bootTime; 27806f6ba60Sopenharmony_ci WriteCpuUsageData(pid, *cpuInfo); 27906f6ba60Sopenharmony_ci WriteThreadData(pid, *cpuInfo); 28006f6ba60Sopenharmony_ci } 28106f6ba60Sopenharmony_ci if (protoConfig_.report_diskio()) { 28206f6ba60Sopenharmony_ci WriteDiskioData(pid, *processinfo); 28306f6ba60Sopenharmony_ci } 28406f6ba60Sopenharmony_ci if (protoConfig_.report_pss()) { 28506f6ba60Sopenharmony_ci WritePssData(pid, *processinfo); 28606f6ba60Sopenharmony_ci } 28706f6ba60Sopenharmony_ci} 28806f6ba60Sopenharmony_ci 28906f6ba60Sopenharmony_citemplate <typename T> bool ProcessDataPlugin::WriteProcesseList(T& processData) 29006f6ba60Sopenharmony_ci{ 29106f6ba60Sopenharmony_ci DIR* procDir = nullptr; 29206f6ba60Sopenharmony_ci 29306f6ba60Sopenharmony_ci procDir = OpenDestDir(path_.c_str()); 29406f6ba60Sopenharmony_ci if (procDir == nullptr) { 29506f6ba60Sopenharmony_ci return false; 29606f6ba60Sopenharmony_ci } 29706f6ba60Sopenharmony_ci 29806f6ba60Sopenharmony_ci pids_.clear(); 29906f6ba60Sopenharmony_ci while (int32_t pid = GetValidPid(procDir)) { 30006f6ba60Sopenharmony_ci if (pid <= 0) { 30106f6ba60Sopenharmony_ci closedir(procDir); 30206f6ba60Sopenharmony_ci PROFILER_LOG_WARN(LOG_CORE, "%s: get pid[%d] failed", __func__, pid); 30306f6ba60Sopenharmony_ci return false; 30406f6ba60Sopenharmony_ci } 30506f6ba60Sopenharmony_ci addPidBySort(pid); 30606f6ba60Sopenharmony_ci } 30706f6ba60Sopenharmony_ci 30806f6ba60Sopenharmony_ci for (unsigned int i = 0; i < pids_.size(); i++) { 30906f6ba60Sopenharmony_ci WriteProcessInfo(processData, pids_[i]); 31006f6ba60Sopenharmony_ci } 31106f6ba60Sopenharmony_ci 31206f6ba60Sopenharmony_ci closedir(procDir); 31306f6ba60Sopenharmony_ci return true; 31406f6ba60Sopenharmony_ci} 31506f6ba60Sopenharmony_ci 31606f6ba60Sopenharmony_citemplate <typename T> bool ProcessDataPlugin::WriteThreadData(int pid, T& cpuInfo) 31706f6ba60Sopenharmony_ci{ 31806f6ba60Sopenharmony_ci DIR* procDir = nullptr; 31906f6ba60Sopenharmony_ci std::string path = path_ + std::to_string(pid) + "/task"; 32006f6ba60Sopenharmony_ci procDir = OpenDestDir(path.c_str()); 32106f6ba60Sopenharmony_ci if (procDir == nullptr) { 32206f6ba60Sopenharmony_ci return false; 32306f6ba60Sopenharmony_ci } 32406f6ba60Sopenharmony_ci 32506f6ba60Sopenharmony_ci uint32_t i = 0; 32606f6ba60Sopenharmony_ci while (int32_t tid = GetValidPid(procDir)) { 32706f6ba60Sopenharmony_ci if (tid <= 0) { 32806f6ba60Sopenharmony_ci closedir(procDir); 32906f6ba60Sopenharmony_ci PROFILER_LOG_WARN(LOG_CORE, "%s: get pid[%d] failed", __func__, tid); 33006f6ba60Sopenharmony_ci return false; 33106f6ba60Sopenharmony_ci } 33206f6ba60Sopenharmony_ci i++; 33306f6ba60Sopenharmony_ci } 33406f6ba60Sopenharmony_ci cpuInfo.set_thread_sum(i); 33506f6ba60Sopenharmony_ci closedir(procDir); 33606f6ba60Sopenharmony_ci return true; 33706f6ba60Sopenharmony_ci} 33806f6ba60Sopenharmony_ci 33906f6ba60Sopenharmony_ciint64_t ProcessDataPlugin::GetUserHz() 34006f6ba60Sopenharmony_ci{ 34106f6ba60Sopenharmony_ci int64_t hz = -1; 34206f6ba60Sopenharmony_ci int64_t user_hz = sysconf(_SC_CLK_TCK); 34306f6ba60Sopenharmony_ci switch (user_hz) { 34406f6ba60Sopenharmony_ci case CPU_USER_HZ_L: 34506f6ba60Sopenharmony_ci hz = CPU_HZ_H; 34606f6ba60Sopenharmony_ci break; 34706f6ba60Sopenharmony_ci case CPU_USER_HZ_H: 34806f6ba60Sopenharmony_ci hz = 1; 34906f6ba60Sopenharmony_ci break; 35006f6ba60Sopenharmony_ci default: 35106f6ba60Sopenharmony_ci break; 35206f6ba60Sopenharmony_ci } 35306f6ba60Sopenharmony_ci return hz; 35406f6ba60Sopenharmony_ci} 35506f6ba60Sopenharmony_ci 35606f6ba60Sopenharmony_citemplate <typename T> bool ProcessDataPlugin::WriteCpuUsageData(int pid, T& cpuInfo) 35706f6ba60Sopenharmony_ci{ 35806f6ba60Sopenharmony_ci uint64_t prevCpuTime = 0; 35906f6ba60Sopenharmony_ci uint64_t cpuTime = 0; 36006f6ba60Sopenharmony_ci uint64_t prevBootTime = 0; 36106f6ba60Sopenharmony_ci uint64_t bootTime = 0; 36206f6ba60Sopenharmony_ci double usage = 0.0; 36306f6ba60Sopenharmony_ci ReadCpuUsage(pid, cpuTime); 36406f6ba60Sopenharmony_ci ReadBootTime(pid, bootTime); 36506f6ba60Sopenharmony_ci if (cpuTime_.find(pid) != cpuTime_.end()) { 36606f6ba60Sopenharmony_ci prevCpuTime = cpuTime_[pid]; 36706f6ba60Sopenharmony_ci } 36806f6ba60Sopenharmony_ci if (bootTime_.find(pid) != bootTime_.end()) { 36906f6ba60Sopenharmony_ci prevBootTime = bootTime_[pid]; 37006f6ba60Sopenharmony_ci } 37106f6ba60Sopenharmony_ci if (bootTime - prevBootTime == 0 || bootTime == 0) { 37206f6ba60Sopenharmony_ci return false; 37306f6ba60Sopenharmony_ci } 37406f6ba60Sopenharmony_ci if (cpuTime < prevCpuTime) { 37506f6ba60Sopenharmony_ci return false; 37606f6ba60Sopenharmony_ci } 37706f6ba60Sopenharmony_ci if (prevCpuTime == 0) { 37806f6ba60Sopenharmony_ci usage = static_cast<double>(cpuTime) / (bootTime); 37906f6ba60Sopenharmony_ci } else { 38006f6ba60Sopenharmony_ci usage = static_cast<double>(cpuTime - prevCpuTime) / (bootTime - prevBootTime); 38106f6ba60Sopenharmony_ci } 38206f6ba60Sopenharmony_ci 38306f6ba60Sopenharmony_ci if (usage > 0) { 38406f6ba60Sopenharmony_ci cpuInfo.set_cpu_usage(usage * PERCENT); 38506f6ba60Sopenharmony_ci } 38606f6ba60Sopenharmony_ci cpuInfo.set_cpu_time_ms(cpuTime); 38706f6ba60Sopenharmony_ci cpuTime_[pid] = cpuTime; 38806f6ba60Sopenharmony_ci bootTime_[pid] = bootTime; 38906f6ba60Sopenharmony_ci return true; 39006f6ba60Sopenharmony_ci} 39106f6ba60Sopenharmony_ci 39206f6ba60Sopenharmony_cibool ProcessDataPlugin::ReadBootTime(int pid, uint64_t& bootTime) 39306f6ba60Sopenharmony_ci{ 39406f6ba60Sopenharmony_ci std::string path = path_ + "stat"; 39506f6ba60Sopenharmony_ci std::ifstream input(path, std::ios::in); 39606f6ba60Sopenharmony_ci CHECK_TRUE(!input.fail(), false, "%s open %s failed, errno = %d", __func__, path.c_str(), errno); 39706f6ba60Sopenharmony_ci do { 39806f6ba60Sopenharmony_ci if (!input.good()) { 39906f6ba60Sopenharmony_ci return false; 40006f6ba60Sopenharmony_ci } 40106f6ba60Sopenharmony_ci std::string line; 40206f6ba60Sopenharmony_ci getline(input, line); 40306f6ba60Sopenharmony_ci 40406f6ba60Sopenharmony_ci auto pos = line.find("cpu "); 40506f6ba60Sopenharmony_ci if (pos != std::string::npos) { 40606f6ba60Sopenharmony_ci line += '\n'; 40706f6ba60Sopenharmony_ci GetBootData(line, bootTime); 40806f6ba60Sopenharmony_ci } 40906f6ba60Sopenharmony_ci } while (0); 41006f6ba60Sopenharmony_ci input.close(); 41106f6ba60Sopenharmony_ci 41206f6ba60Sopenharmony_ci return true; 41306f6ba60Sopenharmony_ci} 41406f6ba60Sopenharmony_ci 41506f6ba60Sopenharmony_ciuint32_t ProcessDataPlugin::GetBootData(const std::string& line, uint64_t& bootTime) 41606f6ba60Sopenharmony_ci{ 41706f6ba60Sopenharmony_ci uint64_t num; 41806f6ba60Sopenharmony_ci uint32_t count = 0; 41906f6ba60Sopenharmony_ci char* end = nullptr; 42006f6ba60Sopenharmony_ci char* pTmp = const_cast<char*>(line.c_str()); 42106f6ba60Sopenharmony_ci constexpr uint32_t cntVec = 8; 42206f6ba60Sopenharmony_ci 42306f6ba60Sopenharmony_ci std::vector<uint64_t> bootTimeVec; 42406f6ba60Sopenharmony_ci bootTime = 0; 42506f6ba60Sopenharmony_ci while (pTmp != nullptr && *pTmp != '\n') { 42606f6ba60Sopenharmony_ci CHECK_TRUE(FindFirstNum(&pTmp), count, "%s: FindFirstNum failed", __func__); 42706f6ba60Sopenharmony_ci num = strtoull(pTmp, &end, DEC_BASE); 42806f6ba60Sopenharmony_ci CHECK_TRUE(num >= 0, count, "%s:strtoull failed", __func__); 42906f6ba60Sopenharmony_ci bootTimeVec.push_back(num); 43006f6ba60Sopenharmony_ci bootTime += num; 43106f6ba60Sopenharmony_ci pTmp = end; 43206f6ba60Sopenharmony_ci if (++count >= cntVec) { 43306f6ba60Sopenharmony_ci break; 43406f6ba60Sopenharmony_ci } 43506f6ba60Sopenharmony_ci } 43606f6ba60Sopenharmony_ci bootTime = bootTime * (uint64_t)GetUserHz(); 43706f6ba60Sopenharmony_ci return count; 43806f6ba60Sopenharmony_ci} 43906f6ba60Sopenharmony_ci 44006f6ba60Sopenharmony_cibool ProcessDataPlugin::ReadCpuUsage(int pid, uint64_t& cpuTime) 44106f6ba60Sopenharmony_ci{ 44206f6ba60Sopenharmony_ci std::string path = path_ + std::to_string(pid) + "/stat"; 44306f6ba60Sopenharmony_ci std::ifstream input(path, std::ios::in); 44406f6ba60Sopenharmony_ci CHECK_TRUE(!input.fail(), false, "%s open %s failed, errno = %d", __func__, path.c_str(), errno); 44506f6ba60Sopenharmony_ci do { 44606f6ba60Sopenharmony_ci if (!input.good()) { 44706f6ba60Sopenharmony_ci return false; 44806f6ba60Sopenharmony_ci } 44906f6ba60Sopenharmony_ci std::string line; 45006f6ba60Sopenharmony_ci getline(input, line); 45106f6ba60Sopenharmony_ci line += '\n'; 45206f6ba60Sopenharmony_ci GetCpuUsageData(line, cpuTime); 45306f6ba60Sopenharmony_ci } while (0); 45406f6ba60Sopenharmony_ci input.close(); 45506f6ba60Sopenharmony_ci 45606f6ba60Sopenharmony_ci return true; 45706f6ba60Sopenharmony_ci} 45806f6ba60Sopenharmony_ci 45906f6ba60Sopenharmony_ciuint32_t ProcessDataPlugin::GetCpuUsageData(const std::string& line, uint64_t& cpuTime) 46006f6ba60Sopenharmony_ci{ 46106f6ba60Sopenharmony_ci uint64_t num; 46206f6ba60Sopenharmony_ci uint32_t count = 0; 46306f6ba60Sopenharmony_ci char* end = nullptr; 46406f6ba60Sopenharmony_ci char* pTmp = const_cast<char*>(line.c_str()); 46506f6ba60Sopenharmony_ci int i = 0; 46606f6ba60Sopenharmony_ci constexpr uint32_t cntVec = 4; 46706f6ba60Sopenharmony_ci 46806f6ba60Sopenharmony_ci while (FindFirstSpace(&pTmp)) { 46906f6ba60Sopenharmony_ci pTmp++; 47006f6ba60Sopenharmony_ci if (++i >= STAT_COUNT) { 47106f6ba60Sopenharmony_ci break; 47206f6ba60Sopenharmony_ci } 47306f6ba60Sopenharmony_ci } 47406f6ba60Sopenharmony_ci std::vector<uint64_t> cpuUsageVec; 47506f6ba60Sopenharmony_ci cpuTime = 0; 47606f6ba60Sopenharmony_ci while (pTmp != nullptr && *pTmp != '\n') { 47706f6ba60Sopenharmony_ci CHECK_TRUE(FindFirstNum(&pTmp), count, "%s: FindFirstNum failed", __func__); 47806f6ba60Sopenharmony_ci num = strtoull(pTmp, &end, DEC_BASE); 47906f6ba60Sopenharmony_ci cpuUsageVec.push_back(num); 48006f6ba60Sopenharmony_ci cpuTime += num; 48106f6ba60Sopenharmony_ci pTmp = end; 48206f6ba60Sopenharmony_ci if (++count >= cntVec) { 48306f6ba60Sopenharmony_ci break; 48406f6ba60Sopenharmony_ci } 48506f6ba60Sopenharmony_ci } 48606f6ba60Sopenharmony_ci cpuTime = cpuTime * (uint64_t)GetUserHz(); 48706f6ba60Sopenharmony_ci return count; 48806f6ba60Sopenharmony_ci} 48906f6ba60Sopenharmony_ci 49006f6ba60Sopenharmony_citemplate <typename T> bool ProcessDataPlugin::WriteDiskioData(int pid, T& processinfo) 49106f6ba60Sopenharmony_ci{ 49206f6ba60Sopenharmony_ci std::string path = path_ + std::to_string(pid) + "/io"; 49306f6ba60Sopenharmony_ci std::ifstream input(path, std::ios::in); 49406f6ba60Sopenharmony_ci if (input.fail()) { 49506f6ba60Sopenharmony_ci return false; 49606f6ba60Sopenharmony_ci } 49706f6ba60Sopenharmony_ci 49806f6ba60Sopenharmony_ci auto* diskInfo = processinfo.mutable_diskinfo(); 49906f6ba60Sopenharmony_ci do { 50006f6ba60Sopenharmony_ci if (!input.good()) { 50106f6ba60Sopenharmony_ci return false; 50206f6ba60Sopenharmony_ci } 50306f6ba60Sopenharmony_ci std::string line; 50406f6ba60Sopenharmony_ci getline(input, line); 50506f6ba60Sopenharmony_ci line += '\n'; 50606f6ba60Sopenharmony_ci GetDiskioData(line, *diskInfo); 50706f6ba60Sopenharmony_ci } while (!input.eof()); 50806f6ba60Sopenharmony_ci input.close(); 50906f6ba60Sopenharmony_ci 51006f6ba60Sopenharmony_ci return true; 51106f6ba60Sopenharmony_ci} 51206f6ba60Sopenharmony_ci 51306f6ba60Sopenharmony_citemplate <typename T> bool ProcessDataPlugin::GetDiskioData(std::string& line, T& diskioInfo) 51406f6ba60Sopenharmony_ci{ 51506f6ba60Sopenharmony_ci char* pTmp = const_cast<char*>(line.c_str()); 51606f6ba60Sopenharmony_ci CHECK_NOTNULL(pTmp, false, "param invalid!"); 51706f6ba60Sopenharmony_ci 51806f6ba60Sopenharmony_ci uint64_t num; 51906f6ba60Sopenharmony_ci if (!std::strncmp(pTmp, "rchar:", strlen("rchar:"))) { 52006f6ba60Sopenharmony_ci CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: get rchar failed", __func__); 52106f6ba60Sopenharmony_ci diskioInfo.set_rchar(num); 52206f6ba60Sopenharmony_ci } else if (!std::strncmp(pTmp, "wchar:", strlen("wchar:"))) { 52306f6ba60Sopenharmony_ci CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: get wchar failed", __func__); 52406f6ba60Sopenharmony_ci diskioInfo.set_wchar(num); 52506f6ba60Sopenharmony_ci } else if (!std::strncmp(pTmp, "syscr:", strlen("syscr:"))) { 52606f6ba60Sopenharmony_ci CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: get syscr failed", __func__); 52706f6ba60Sopenharmony_ci diskioInfo.set_syscr(num); 52806f6ba60Sopenharmony_ci } else if (!std::strncmp(pTmp, "syscw:", strlen("syscw:"))) { 52906f6ba60Sopenharmony_ci CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: get syscw failed", __func__); 53006f6ba60Sopenharmony_ci diskioInfo.set_syscw(num); 53106f6ba60Sopenharmony_ci } else if (!std::strncmp(pTmp, "read_bytes:", strlen("read_bytes:"))) { 53206f6ba60Sopenharmony_ci CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: get read_bytes failed", __func__); 53306f6ba60Sopenharmony_ci diskioInfo.set_rbytes(num); 53406f6ba60Sopenharmony_ci } else if (!std::strncmp(pTmp, "write_bytes:", strlen("write_bytes:"))) { 53506f6ba60Sopenharmony_ci CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: get write_bytes failed", __func__); 53606f6ba60Sopenharmony_ci diskioInfo.set_wbytes(num); 53706f6ba60Sopenharmony_ci } else if (!std::strncmp(pTmp, "cancelled_write_bytes:", strlen("cancelled_write_bytes:"))) { 53806f6ba60Sopenharmony_ci CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: get cancelled_write_bytes failed", __func__); 53906f6ba60Sopenharmony_ci diskioInfo.set_cancelled_wbytes(num); 54006f6ba60Sopenharmony_ci } 54106f6ba60Sopenharmony_ci 54206f6ba60Sopenharmony_ci return true; 54306f6ba60Sopenharmony_ci} 54406f6ba60Sopenharmony_ci 54506f6ba60Sopenharmony_cibool ProcessDataPlugin::FindFirstSpace(char** p) 54606f6ba60Sopenharmony_ci{ 54706f6ba60Sopenharmony_ci CHECK_NOTNULL(*p, false, "ProcessDataPlugin:%s", __func__); 54806f6ba60Sopenharmony_ci while (**p != ' ') { 54906f6ba60Sopenharmony_ci if (**p == '\0' || **p == '\n') { 55006f6ba60Sopenharmony_ci return false; 55106f6ba60Sopenharmony_ci } 55206f6ba60Sopenharmony_ci (*p)++; 55306f6ba60Sopenharmony_ci } 55406f6ba60Sopenharmony_ci return true; 55506f6ba60Sopenharmony_ci} 55606f6ba60Sopenharmony_ci 55706f6ba60Sopenharmony_cibool ProcessDataPlugin::FindFirstNum(char** p) 55806f6ba60Sopenharmony_ci{ 55906f6ba60Sopenharmony_ci CHECK_NOTNULL(*p, false, "ProcessDataPlugin:%s", __func__); 56006f6ba60Sopenharmony_ci while (**p > '9' || **p < '0') { 56106f6ba60Sopenharmony_ci if (**p == '\0' || **p == '\n') { 56206f6ba60Sopenharmony_ci return false; 56306f6ba60Sopenharmony_ci } 56406f6ba60Sopenharmony_ci (*p)++; 56506f6ba60Sopenharmony_ci } 56606f6ba60Sopenharmony_ci return true; 56706f6ba60Sopenharmony_ci} 56806f6ba60Sopenharmony_ci 56906f6ba60Sopenharmony_cibool ProcessDataPlugin::GetValidValue(char* p, uint64_t& num) 57006f6ba60Sopenharmony_ci{ 57106f6ba60Sopenharmony_ci char* end = nullptr; 57206f6ba60Sopenharmony_ci CHECK_TRUE(FindFirstNum(&p), false, "%s: FindFirstNum failed", __func__); 57306f6ba60Sopenharmony_ci num = strtoull(p, &end, DEC_BASE); 57406f6ba60Sopenharmony_ci CHECK_TRUE(num >= 0, false, "%s:strtoull failed", __func__); 57506f6ba60Sopenharmony_ci return true; 57606f6ba60Sopenharmony_ci} 57706f6ba60Sopenharmony_ci 57806f6ba60Sopenharmony_ci// read /proc/pid/smaps_rollup 57906f6ba60Sopenharmony_citemplate <typename T> bool ProcessDataPlugin::WritePssData(int pid, T& processInfo) 58006f6ba60Sopenharmony_ci{ 58106f6ba60Sopenharmony_ci std::string path = path_ + std::to_string(pid) + "/smaps_rollup"; 58206f6ba60Sopenharmony_ci std::ifstream input(path, std::ios::in); 58306f6ba60Sopenharmony_ci 58406f6ba60Sopenharmony_ci // Not capturing ENOENT (file does not exist) errors, it is common for node smaps_rollup files to be unreadable. 58506f6ba60Sopenharmony_ci CHECK_TRUE(!input.fail(), false, "%s open %s failed, errno = %d", __func__, path.c_str(), errno); 58606f6ba60Sopenharmony_ci 58706f6ba60Sopenharmony_ci auto* pssInfo = processInfo.mutable_pssinfo(); 58806f6ba60Sopenharmony_ci do { 58906f6ba60Sopenharmony_ci if (!input.good()) { 59006f6ba60Sopenharmony_ci return false; 59106f6ba60Sopenharmony_ci } 59206f6ba60Sopenharmony_ci std::string line; 59306f6ba60Sopenharmony_ci getline(input, line); 59406f6ba60Sopenharmony_ci line += '\n'; 59506f6ba60Sopenharmony_ci std::string::size_type pos = 0u; 59606f6ba60Sopenharmony_ci if (line.find("Pss:", pos) != std::string::npos) { 59706f6ba60Sopenharmony_ci char* pTmp = const_cast<char*>(line.c_str()); 59806f6ba60Sopenharmony_ci uint64_t num; 59906f6ba60Sopenharmony_ci CHECK_TRUE(GetValidValue(pTmp, num), false, "%s: FindFirstNum failed", __func__); 60006f6ba60Sopenharmony_ci pssInfo->set_pss_info(num); 60106f6ba60Sopenharmony_ci return true; 60206f6ba60Sopenharmony_ci } 60306f6ba60Sopenharmony_ci } while (!input.eof()); 60406f6ba60Sopenharmony_ci input.close(); 60506f6ba60Sopenharmony_ci 60606f6ba60Sopenharmony_ci return false; 60706f6ba60Sopenharmony_ci} 608