-
Notifications
You must be signed in to change notification settings - Fork 3
/
usage_collector.cpp
283 lines (248 loc) · 10.3 KB
/
usage_collector.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
#include <chrono>
#include <cstdio>
#include <dirent.h>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include <thread>
#include <unistd.h>
#include <vector>
#include "usage_collector.h"
// 명령어를 실행하고 그 결과를 문자열로 반환하는 함수
int CUsageCollector::RunCommand(const char* pCommand, std::string& strResult) {
char chOutputBuffer[BUFFER_SIZE];
strResult = "";
FILE* pPipe = nullptr;
try {
pPipe = popen(pCommand, "r");
if (!pPipe) return ERROR_CANNOT_OPEN_FILE;
while (fgets(chOutputBuffer, sizeof(chOutputBuffer), pPipe) != nullptr) {
strResult += chOutputBuffer;
}
if (pclose(pPipe) == -1) return ERROR_CANNOT_CLOSE_FILE_SYSTEM;
} catch (const std::exception& e) {
if (pPipe) pclose(pPipe);
return ERROR_UNKNOWN;
}
return SUCCESS_CODE;
}
// 데이터를 파일에 저장하는 함수
int CUsageCollector::SaveDataToFile(const std::string& strData, const std::string& strFileName) {
std::ofstream outputFile;
try {
outputFile.open(strFileName, std::ios::out | std::ios::app);
if (!outputFile) return ERROR_CANNOT_OPEN_FILE;
outputFile << strData;
if (!outputFile.good()) return ERROR_CANNOT_WRITE_FILE;
} catch (const std::exception& e) {
if (outputFile.is_open()) outputFile.close();
return ERROR_UNKNOWN;
}
if (outputFile.is_open()) outputFile.close();
return SUCCESS_CODE;
}
// 시스템의 CPU 사용량을 체크하는 함수
int CUsageCollector::GetCpuUsage(std::string& strResult) {
int nErrorCode = RunCommand("mpstat -P ALL 1 1", strResult);
if (nErrorCode != SUCCESS_CODE) return nErrorCode;
if (!strResult.empty() && strResult.back() == '\n') strResult.pop_back();
return SUCCESS_CODE;
}
// 시스템의 디스크 I/O 사용량을 체크하는 함수
int CUsageCollector::GetDiskUsage(std::string& strResult) {
int nErrorCode = RunCommand("iostat -dx", strResult);
if (nErrorCode != SUCCESS_CODE) return nErrorCode;
if (!strResult.empty() && strResult.back() == '\n') strResult.pop_back();
return SUCCESS_CODE;
}
// 시스템의 네트워크 인터페이스 목록을 가져오는 함수
int CUsageCollector::GetNetworkInterfaces(std::vector<std::string>& strInterfaces) {
std::string strResult;
int nErrorCode = RunCommand("ls /sys/class/net", strResult);
if (nErrorCode != SUCCESS_CODE) return nErrorCode;
std::istringstream ss(strResult);
std::string strLine;
while (std::getline(ss, strLine)) {
if (!strLine.empty()) strInterfaces.push_back(strLine);
}
return SUCCESS_CODE;
}
// 시스템의 네트워크 사용량을 체크하는 함수
int CUsageCollector::GetNetworkUsage(std::string& strResult) {
std::vector<std::string> strInterfaces;
int nErrorCode = GetNetworkInterfaces(strInterfaces);
if (nErrorCode != SUCCESS_CODE) return nErrorCode;
strResult = "\n## Network Usage:\n";
for (const auto& iface : strInterfaces) {
std::string strIfaceResult;
std::string command = "sar -n DEV 1 1 | grep " + iface;
nErrorCode = RunCommand(command.c_str(), strIfaceResult);
if (nErrorCode == SUCCESS_CODE) {
strResult += iface + ":\n" + strIfaceResult + "\n";
}
}
return SUCCESS_CODE;
}
// 시스템의 메모리 사용량을 체크하는 함수
int CUsageCollector::GetMemoryUsage(std::string& strResult) {
int nErrorCode = RunCommand("free -h", strResult);
if (nErrorCode != SUCCESS_CODE) return nErrorCode;
if (!strResult.empty() && strResult.back() == '\n') strResult.pop_back();
return SUCCESS_CODE;
}
// 특정 데이터를 수집하고 이를 포매팅하여 파일에 저장
int CUsageCollector::SaveUsageToFile(const std::string& strFileName, bool bCpu, bool bDisk, bool bNetwork, bool bMemory) {
std::string strCpuUsage, strDiskUsage, strNetworkUsage, strMemoryUsage, strUsageInfo;
try {
if (bCpu) {
int nErrorCode = GetCpuUsage(strCpuUsage);
if (nErrorCode != SUCCESS_CODE) return nErrorCode;
strCpuUsage = "\n## CPU Usage:\n" + strCpuUsage + "\n";
strUsageInfo += strCpuUsage;
}
if (bDisk) {
int nErrorCode = GetDiskUsage(strDiskUsage);
if (nErrorCode != SUCCESS_CODE) return nErrorCode;
strDiskUsage = "\n## Disk Usage:\n" + strDiskUsage;
strUsageInfo += strDiskUsage;
}
if (bNetwork) {
int nErrorCode = GetNetworkUsage(strNetworkUsage);
if (nErrorCode != SUCCESS_CODE) return nErrorCode;
strUsageInfo += strNetworkUsage;
}
if (bMemory) {
int nErrorCode = GetMemoryUsage(strMemoryUsage);
if (nErrorCode != SUCCESS_CODE) return nErrorCode;
strMemoryUsage = "\n## Memory Usage:\n" + strMemoryUsage;
strUsageInfo += strMemoryUsage;
}
strUsageInfo = "\n********************************************************************************* Usage Information *********************************************************************************\n" + strUsageInfo;
int nErrorCode = SaveDataToFile(strUsageInfo, strFileName);
if (nErrorCode != SUCCESS_CODE) return nErrorCode;
return SUCCESS_CODE;
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
return ERROR_UNKNOWN;
}
}
// 메뉴를 표시하는 함수
void CUsageCollector::DisplayMenu() {
std::cout << "====================================================\n";
std::cout << " System Usage Collector \n";
std::cout << "====================================================\n";
std::cout << "1. Collect CPU usage\n";
std::cout << "2. Collect Disk usage\n";
std::cout << "3. Collect Network usage\n";
std::cout << "4. Collect Memory usage\n";
std::cout << "5. Exit\n";
std::cout << "====================================================\n";
std::cout << "Enter numbers of your choices (ex. 1 2 3 4): ";
}
// 사용자의 입력을 받아 선택된 옵션을 설정하는 함수
void CUsageCollector::GetUserChoices(bool& bCollectCpu, bool& bCollectDisk, bool& bCollectNetwork, bool& bCollectMemory) {
std::string strInput;
std::getline(std::cin, strInput);
std::istringstream iss(strInput);
int nChoice;
while (iss >> nChoice) {
switch (nChoice) {
case 1:
bCollectCpu = true;
break;
case 2:
bCollectDisk = true;
break;
case 3:
bCollectNetwork = true;
break;
case 4:
bCollectMemory = true;
break;
default:
std::cerr << "Invalid choice: " << nChoice << std::endl;
break;
}
}
}
// 프로그레스 바를 표시하는 함수
void CUsageCollector::ShowProgress(const std::string& strMessage, int nProgress, int nTotal) {
int nBarWidth = 70;
float progressRatio = static_cast<float>(nProgress) / nTotal;
int nPos = static_cast<int>(nBarWidth * progressRatio);
std::cout << COLOR_GREEN << "[";
for (int nIndex = 0; nIndex < nBarWidth; ++nIndex) {
if (nIndex < nPos) std::cout << "=";
else if (nIndex == nPos) std::cout << ">";
else std::cout << " ";
}
std::cout << "] " << int(progressRatio * 100.0) << " % " << strMessage << COLOR_RESET << "\r";
std::cout.flush();
}
// 사용자의 입력을 받아 수집할 데이터 유형을 선택하고 저장하는 함수
int CUsageCollector::CollectAndSaveUsage() {
std::string strFilename = "usage_data.txt";
bool bCollectCpu = false;
bool bCollectDisk = false;
bool bCollectNetwork = false;
bool bCollectMemory = false;
try {
DisplayMenu();
GetUserChoices(bCollectCpu, bCollectDisk, bCollectNetwork, bCollectMemory);
if (!bCollectCpu && !bCollectDisk && !bCollectNetwork && !bCollectMemory) {
std::cerr << COLOR_GREEN << "\nNo data collection selected. Exiting." << COLOR_RESET << std::endl;
return ERROR_UNKNOWN;
}
int nTotalTasks = 0;
if (bCollectCpu) nTotalTasks++;
if (bCollectDisk) nTotalTasks++;
if (bCollectNetwork) nTotalTasks++;
if (bCollectMemory) nTotalTasks++;
int nCompletedTasks = 0;
std::string strCpuUsage, strDiskUsage, strNetworkUsage, strMemoryUsage, strUsageInfo;
std::cout << "\nCollecting data...\n\n";
if (bCollectCpu) {
ShowProgress("CPU Usage", nCompletedTasks, nTotalTasks);
int result = GetCpuUsage(strCpuUsage);
nCompletedTasks++;
ShowProgress("CPU Usage", nCompletedTasks, nTotalTasks);
if (result != SUCCESS_CODE) return result;
}
if (bCollectDisk) {
ShowProgress("Disk Usage", nCompletedTasks, nTotalTasks);
int result = GetDiskUsage(strDiskUsage);
nCompletedTasks++;
ShowProgress("Disk Usage", nCompletedTasks, nTotalTasks);
if (result != SUCCESS_CODE) return result;
}
if (bCollectNetwork) {
ShowProgress("Network Usage", nCompletedTasks, nTotalTasks);
int result = GetNetworkUsage(strNetworkUsage);
nCompletedTasks++;
ShowProgress("Network Usage", nCompletedTasks, nTotalTasks);
if (result != SUCCESS_CODE) return result;
}
if (bCollectMemory) {
ShowProgress("Memory Usage", nCompletedTasks, nTotalTasks);
int result = GetMemoryUsage(strMemoryUsage);
nCompletedTasks++;
ShowProgress("Memory Usage", nCompletedTasks, nTotalTasks);
if (result != SUCCESS_CODE) return result;
}
std::cout << std::endl;
int result = SaveUsageToFile(strFilename, bCollectCpu, bCollectDisk, bCollectNetwork, bCollectMemory);
if (result != SUCCESS_CODE) {
return result;
}
std::cout << COLOR_GREEN << "Output has been saved to " << strFilename << COLOR_RESET << std::endl;
return SUCCESS_CODE;
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
return ERROR_UNKNOWN;
}
}