Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add system metric counter in windows #628

Merged
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
248 changes: 244 additions & 4 deletions include/cinatra/ylt/metric/system_metric.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
#if defined(__GNUC__)
#include <sys/resource.h>
#include <sys/time.h>
#endif

#if defined(WIN32)
#include <psapi.h>
#include <tlhelp32.h>
#include <windows.h>

// Link with Psapi.lib
#pragma comment(lib, "Psapi.lib")
#endif

#include <chrono>
#include <cstdint>
Expand Down Expand Up @@ -73,6 +83,175 @@ inline int read_command_output_through_popen(std::ostream& os,
}
#endif

#if defined(WIN32)
typedef struct timeval {
long tv_sec;
long tv_usec;
} timeval;

inline int gettimeofday(struct timeval* tp, struct timezone* tzp) {
// Note: some broken versions only have 8 trailing zero's, the correct epoch
// has 9 trailing zero's This magic number is the number of 100 nanosecond
// intervals since January 1, 1601 (UTC) until 00:00:00 January 1, 1970
static const uint64_t epoch = ((uint64_t)116444736000000000ULL);

SYSTEMTIME system_time;
FILETIME file_time;
uint64_t time;

GetSystemTime(&system_time);
SystemTimeToFileTime(&system_time, &file_time);
time = ((uint64_t)file_time.dwLowDateTime);
time += ((uint64_t)file_time.dwHighDateTime) << 32;

tp->tv_sec = (long)((time - epoch) / 10000000L);
tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
return 0;
}

#define RUSAGE_SELF 0
#define RUSAGE_CHILDREN (-1)

struct rusage {
struct timeval ru_utime; /* user time used */
struct timeval ru_stime; /* system time used */
};

inline int getrusage(int who, struct rusage* rusage) {
FILETIME starttime;
FILETIME exittime;
FILETIME kerneltime;
FILETIME usertime;
ULARGE_INTEGER li;

if (who != RUSAGE_SELF) {
/* Only RUSAGE_SELF is supported in this implementation for now */
errno = EINVAL;
return -1;
}

if (rusage == (struct rusage*)NULL) {
errno = EFAULT;
return -1;
}
memset(rusage, 0, sizeof(struct rusage));
if (GetProcessTimes(GetCurrentProcess(), &starttime, &exittime, &kerneltime,
&usertime) == 0) {
return -1;
}

/* Convert FILETIMEs (0.1 us) to struct timeval */
memcpy(&li, &kerneltime, sizeof(FILETIME));
li.QuadPart /= 10L; /* Convert to microseconds */
rusage->ru_stime.tv_sec = li.QuadPart / 1000000L;
rusage->ru_stime.tv_usec = li.QuadPart % 1000000L;

memcpy(&li, &usertime, sizeof(FILETIME));
li.QuadPart /= 10L; /* Convert to microseconds */
rusage->ru_utime.tv_sec = li.QuadPart / 1000000L;
rusage->ru_utime.tv_usec = li.QuadPart % 1000000L;

return 0;
}

inline SIZE_T get_shared_memory_size(HANDLE h_process) {
MEMORY_BASIC_INFORMATION mbi;
SIZE_T base_address = 0;
SIZE_T shared_memory_size = 0;

while (VirtualQueryEx(h_process, (LPCVOID)base_address, &mbi, sizeof(mbi))) {
if (mbi.State == MEM_COMMIT) {
if (mbi.Type == MEM_MAPPED || mbi.Type == MEM_IMAGE) {
shared_memory_size += mbi.RegionSize;
}
}
base_address = (SIZE_T)mbi.BaseAddress + mbi.RegionSize;
}

return shared_memory_size;
}

inline DWORD getppid() {
HANDLE h_snapshot;
PROCESSENTRY32 pe32;
DWORD ppid = 0, pid = GetCurrentProcessId();

h_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
try {
if (h_snapshot == INVALID_HANDLE_VALUE)
return ppid;

ZeroMemory(&pe32, sizeof(pe32));
pe32.dwSize = sizeof(pe32);
if (!Process32First(h_snapshot, &pe32))
return ppid;

do {
if (pe32.th32ProcessID == pid) {
ppid = pe32.th32ParentProcessID;
break;
}
} while (Process32Next(h_snapshot, &pe32));

} catch (...) {
if (h_snapshot != INVALID_HANDLE_VALUE)
CloseHandle(h_snapshot);
}

if (h_snapshot != INVALID_HANDLE_VALUE)
CloseHandle(h_snapshot);

return ppid;
}

inline DWORD get_thread_number(DWORD processId) {
DWORD thread_count = 0;
HANDLE snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);

if (snapshot_handle == INVALID_HANDLE_VALUE) {
std::cerr << "Failed to create snapshot. Error code: " << GetLastError()
<< std::endl;
return 0;
}

THREADENTRY32 threadEntry;
threadEntry.dwSize = sizeof(THREADENTRY32);

if (Thread32First(snapshot_handle, &threadEntry)) {
do {
if (threadEntry.th32OwnerProcessID == processId) {
++thread_count;
}
} while (Thread32Next(snapshot_handle, &threadEntry));
}
else {
std::cerr << "Failed to retrieve thread information. Error code: "
<< GetLastError() << std::endl;
}

CloseHandle(snapshot_handle);
return thread_count;
}

inline DWORD get_process_group(HANDLE process_handle) {
DWORD_PTR process_affinity_mask;
DWORD_PTR system_affinity_mask;

if (GetProcessAffinityMask(process_handle, &process_affinity_mask,
&system_affinity_mask)) {
// Output the processor group information
// Process Affinity Mask
DWORD grop_id = process_affinity_mask;
return grop_id;
}
else {
std::cerr << "Failed to get process affinity mask. Error code: "
<< GetLastError() << std::endl;
return 0;
}
}
#endif

inline int64_t last_time_us = 0;
inline int64_t last_sys_time_us = 0;
inline int64_t last_user_time_us = 0;
Expand Down Expand Up @@ -145,7 +324,9 @@ inline void stat_memory() {
long virtual_size = 0;
long resident = 0;
long share = 0;
#if defined(__GNUC__)
static long page_size = sysconf(_SC_PAGE_SIZE);
#endif

#if defined(__APPLE__)
static pid_t pid = getpid();
Expand All @@ -169,9 +350,33 @@ inline void stat_memory() {
file >> virtual_size >> resident >> share;
#endif

#if defined(WIN32)
DWORD current_process = GetCurrentProcessId();
// open process
HANDLE h_process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, current_process);
if (h_process == NULL) {
virtual_size = 0;
resident = 0;
share = 0;
}
PROCESS_MEMORY_COUNTERS pmc;
if (GetProcessMemoryInfo(h_process, &pmc, sizeof(pmc))) {
virtual_size = pmc.PagefileUsage;
resident = pmc.WorkingSetSize;
}
share = get_shared_memory_size(h_process);

CloseHandle(h_process);

process_memory_virtual->update(virtual_size);
process_memory_resident->update(resident);
process_memory_shared->update(share);
#else
process_memory_virtual->update(virtual_size * page_size);
process_memory_resident->update(resident * page_size);
process_memory_shared->update(share * page_size);
#endif
}

struct ProcIO {
Expand Down Expand Up @@ -199,8 +404,7 @@ inline void stat_io() {
"ylt_process_io_write_second");

ProcIO s{};
#if defined(__APPLE__)
#else
#if defined(__GUNC__)
auto stream_file =
std::shared_ptr<FILE>(fopen("/proc/self/io", "r"), [](FILE *ptr) {
fclose(ptr);
Expand All @@ -217,6 +421,33 @@ inline void stat_io() {
}
#endif

#if defined(__APPLE__)
#endif
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这两行是多余的吧。

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这两行是之前加的我就保留了,后面可能可以添加mac系统相关功能

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已经删除这个宏


#if defined(WIN32)
DWORD current_process_id = GetCurrentProcessId();
// open process
HANDLE h_process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, current_process_id);
if (h_process == NULL) {
s.rchar = 0;
s.wchar = 0;
s.syscr = 0;
s.syscw = 0;
}
else {
IO_COUNTERS io_counters = {0};
if (GetProcessIoCounters(h_process, &io_counters)) {
s.rchar = io_counters.ReadOperationCount;
s.wchar = io_counters.WriteOperationCount;
s.syscr = io_counters.ReadOperationCount;
s.syscw = io_counters.WriteOperationCount;
}
}

CloseHandle(h_process);
#endif

process_io_read_bytes_second->update(s.rchar);
process_io_write_bytes_second->update(s.wchar);
process_io_read_second->update(s.syscr);
Expand Down Expand Up @@ -344,6 +575,16 @@ inline void process_status() {
&stat.flags, &stat.priority, &stat.nice) != 8) {
return;
}
#elif defined(WIN32)
stat.pid = GetCurrentProcessId();
stat.ppid = getppid();

HANDLE h_process =
OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, stat.pid);
stat.priority = GetPriorityClass(h_process);
stat.num_threads = get_thread_number(stat.pid);
stat.pgrp = get_process_group(h_process);
CloseHandle(h_process);
#endif
process_uptime->inc();
process_priority->update(stat.priority);
Expand Down Expand Up @@ -455,5 +696,4 @@ inline bool start_system_metric() {

return true;
}
} // namespace ylt::metric
#endif
} // namespace ylt::metric
Loading