1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "metrics.h"
17 #include <regex>
18 #include "string_help.h"
19
20 namespace SysTuning {
21 namespace TraceStreamer {
22 const uint32_t EXTRA_CHAR = 4;
23 const uint32_t SEND_FINISH = 1;
Metrics()24 Metrics ::Metrics()
25 {
26 metricsFunction_ = {
27 {TRACE_MEM, std::bind(&Metrics::InitMemoryStrategy, this, std::placeholders::_1)},
28 {TRACE_MEM_TOP_TEN, std::bind(&Metrics::InitMemoryStrategy, this, std::placeholders::_1)},
29 {TRACE_MEM_UNAGG, std::bind(&Metrics::InitMemoryUnAggStrategy, this, std::placeholders::_1)},
30 {TRACE_TASK_NAMES, std::bind(&Metrics::InitMemoryTaskNameStrategy, this, std::placeholders::_1)},
31 {TRACE_STATS, std::bind(&Metrics::InitTraceStatsStrategy, this, std::placeholders::_1)},
32 {TRACE_METADATA, std::bind(&Metrics::InitTraceMetaDataStrategy, this, std::placeholders::_1)},
33 {SYS_CALLS, std::bind(&Metrics::InitSysCallStrategy, this, std::placeholders::_1)}};
34 initMetricsMap_ = {
35 {METRICS_TRACE_MEM, TRACE_MEM},
36 {METRICS_TRACE_MEM_TOP_TEN, TRACE_MEM_TOP_TEN},
37 {METRICS_TRACE_MEM_UNAGG, TRACE_MEM_UNAGG},
38 {METRICS_TRACE_TASK_NAMES, TRACE_TASK_NAMES},
39 {METRICS_TRACE_STATS, TRACE_STATS},
40 {METRICS_TRACE_METADATA, TRACE_METADATA},
41 {METRICS_SYS_CALLS, SYS_CALLS},
42 };
43 }
44
ParserJson(const std::string & metrics,std::string & result)45 void Metrics::ParserJson(const std::string& metrics, std::string& result)
46 {
47 result = result.substr(EXTRA_CHAR, result.size());
48 auto it = metricsFunction_.find(metrics);
49 if (it == metricsFunction_.end()) {
50 TS_LOGE("Not support metrics!");
51 return;
52 }
53 it->second(result);
54 }
55
InitMemoryStrategy(const std::string & result)56 void Metrics::InitMemoryStrategy(const std::string& result)
57 {
58 json jMessage = json::parse(result);
59 const uint32_t TYPE_INFO_ITEM_MAX = 0;
60 const uint32_t TYPE_INFO_ITEM_MIN = 1;
61 const uint32_t TYPE_INFO_ITEM_AVG = 2;
62 const uint32_t PROCESS_METRICES_ITEMS_NAME = 4;
63 for (int i = 0; i < jMessage.at("values").size(); i++) {
64 TypeInfoItem typeInfoItem;
65 typeInfoItem.max = jMessage.at("values")[i].at(TYPE_INFO_ITEM_MAX);
66 typeInfoItem.min = jMessage.at("values")[i].at(TYPE_INFO_ITEM_MIN);
67 typeInfoItem.avg = jMessage.at("values")[i].at(TYPE_INFO_ITEM_AVG);
68 ProcessMetricsItems processMetricsItems;
69 processMetricsItems.overallCounters = typeInfoItem;
70 processMetricsItems.processName = jMessage.at("values")[i].at(PROCESS_METRICES_ITEMS_NAME);
71 memStrategy_.emplace_back(std::move(processMetricsItems));
72 }
73 return;
74 }
InitMemoryUnAggStrategy(const std::string & result)75 void Metrics::InitMemoryUnAggStrategy(const std::string& result)
76 {
77 json jMessage = json::parse(result);
78 const uint32_t PROCESS_VALUES_ITEM_NAME = 0;
79 const uint32_t NAMES = 1;
80 const uint32_t VALUES = 2;
81 const uint32_t TIMES = 3;
82 for (int i = 0; i < jMessage.at("values").size(); i++) {
83 ProcessValuesItem processValuesItem;
84 if (jMessage.at("values")[i].at(0).is_null()) {
85 processValuesItem.processName = "";
86 } else {
87 processValuesItem.processName = jMessage.at("values")[i].at(PROCESS_VALUES_ITEM_NAME);
88 }
89 auto names = base::SplitStringToVec(jMessage.at("values")[i].at(NAMES), ",");
90 auto values = base::SplitStringToVec(jMessage.at("values")[i].at(VALUES), ",");
91 auto times = base::SplitStringToVec(jMessage.at("values")[i].at(TIMES), ",");
92 auto oomScoreValue = 0;
93 for (auto index = 0; index < names.size(); index++) {
94 if (names[index] == "oom_score_adj") {
95 oomScoreValue = atoi(values.at(index).c_str());
96 }
97 TypeItem typeItem;
98 typeItem.ts = atoll(times.at(index).c_str());
99 typeItem.oomScore = oomScoreValue;
100 typeItem.value = atoi(values.at(index).c_str());
101 if (names.at(index) == "mem.rss.anon") {
102 processValuesItem.anonRss = typeItem;
103 } else if (names.at(index) == "mem.swap") {
104 processValuesItem.swap = typeItem;
105 } else if (names.at(index) == "mem.rss.file") {
106 processValuesItem.fileRss = typeItem;
107 } else if (names.at(index) == "oom_score_adj") {
108 processValuesItem.anonAndSwap = typeItem;
109 }
110 }
111 memAggStrategy_.emplace_back(processValuesItem);
112 }
113 return;
114 }
InitMemoryTaskNameStrategy(const std::string & result)115 void Metrics::InitMemoryTaskNameStrategy(const std::string& result)
116 {
117 json jMessage = json::parse(result);
118 const uint32_t JMESSAGE_VALUE_SIZE_ONE = 1;
119 const uint32_t JMESSAGE_VALUE_SIZE_TWO = 2;
120 const uint32_t JMESSAGE_VALUE_SIZE_THREE = 3;
121 for (int i = 0; i < jMessage.at("values").size(); i++) {
122 TaskProcessItem taskProcessItem;
123 taskProcessItem.pid = jMessage.at("values")[i].at(JMESSAGE_VALUE_SIZE_ONE);
124 if (jMessage.at("values")[i].at(JMESSAGE_VALUE_SIZE_TWO).is_null()) {
125 taskProcessItem.processName = "";
126 } else {
127 taskProcessItem.processName = jMessage.at("values")[i].at(JMESSAGE_VALUE_SIZE_TWO);
128 }
129 if (!jMessage.at("values")[i].at(JMESSAGE_VALUE_SIZE_THREE).is_null()) {
130 taskProcessItem.threadName =
131 base::SplitStringToVec(jMessage.at("values")[i].at(JMESSAGE_VALUE_SIZE_THREE), ",");
132 }
133 taskNameStrategy_.emplace_back(taskProcessItem);
134 }
135 return;
136 }
InitTraceStatsStrategy(const std::string & result)137 void Metrics::InitTraceStatsStrategy(const std::string& result)
138 {
139 json jMessage = json::parse(result);
140 const uint32_t STAT_ITEM_NAME = 0;
141 const uint32_t STAT_ITEM_COUNT = 2;
142 const uint32_t STAT_ITEM_SOURCE = 3;
143 const uint32_t STAT_ITEM_SEVERITY = 4;
144 for (int i = 0; i < jMessage.at("values").size(); i++) {
145 StatItem statItem;
146 statItem.name = jMessage.at("values")[i].at(STAT_ITEM_NAME);
147 statItem.count = jMessage.at("values")[i].at(STAT_ITEM_COUNT);
148 statItem.source = jMessage.at("values")[i].at(STAT_ITEM_SOURCE);
149 statItem.severity = jMessage.at("values")[i].at(STAT_ITEM_SEVERITY);
150 statStrategy_.emplace_back(statItem);
151 }
152 return;
153 }
InitTraceMetaDataStrategy(const std::string & result)154 void Metrics::InitTraceMetaDataStrategy(const std::string& result)
155 {
156 json jMessage = json::parse(result);
157 const uint32_t TRACE_METADATA_ITEM_NAME = 0;
158 const uint32_t TRACE_METADATA_ITEM_VALUE = 1;
159 for (int i = 0; i < jMessage.at("values").size(); i++) {
160 TraceMetadataItem traceMetadataItem;
161 traceMetadataItem.name = jMessage.at("values")[i].at(TRACE_METADATA_ITEM_NAME);
162 traceMetadataItem.value = jMessage.at("values")[i].at(TRACE_METADATA_ITEM_VALUE);
163 metaDataStrategy_.emplace_back(traceMetadataItem);
164 }
165 return;
166 }
InitSysCallStrategy(const std::string & result)167 void Metrics::InitSysCallStrategy(const std::string& result)
168 {
169 json jMessage = json::parse(result);
170 const uint32_t FUNCTION_ITEM_DUR_MIN = 1;
171 const uint32_t FUNCTION_ITEM_DUR_MAX = 2;
172 const uint32_t FUNCTION_ITEM_DUR_AVG = 3;
173 const uint32_t FUNCTION_ITEM_FUNCTION_NAME = 4;
174 for (int i = 0; i < jMessage.at("values").size(); i++) {
175 FunctionItem functionItem;
176 functionItem.functionName = jMessage.at("values")[i].at(FUNCTION_ITEM_FUNCTION_NAME);
177 functionItem.durMax = jMessage.at("values")[i].at(FUNCTION_ITEM_DUR_MAX);
178 functionItem.durMin = jMessage.at("values")[i].at(FUNCTION_ITEM_DUR_MIN);
179 functionItem.durAvg = jMessage.at("values")[i].at(FUNCTION_ITEM_DUR_AVG);
180 sysCallStrategy_.emplace_back(functionItem);
181 }
182 return;
183 }
PrintMetricsResult(uint32_t metricsIndex,ResultCallBack callback)184 void Metrics::PrintMetricsResult(uint32_t metricsIndex, ResultCallBack callback)
185 {
186 std::string res = "\r\n";
187 std::string metricsName = "";
188 std::string repeateValue = "";
189 switch (metricsIndex) {
190 case METRICS_TRACE_MEM:
191 UpdataRepeateValueByTraceMem(repeateValue, metricsName);
192 break;
193 case METRICS_TRACE_MEM_TOP_TEN:
194 UpdataRepeateValueByTopTen(repeateValue, metricsName);
195 break;
196 case METRICS_TRACE_MEM_UNAGG:
197 UpdataRepeateValueByMemUnagg(repeateValue, metricsName);
198 break;
199 case METRICS_TRACE_TASK_NAMES:
200 UpdataRepeateValueByTaskNames(repeateValue, metricsName);
201 break;
202 case METRICS_TRACE_STATS:
203 UpdataRepeateValueByStats(repeateValue, metricsName);
204 break;
205 case METRICS_TRACE_METADATA:
206 UpdataRepeateValueByMetadata(repeateValue, metricsName);
207 break;
208 case METRICS_SYS_CALLS:
209 UpdataRepeateValueBySysCalls(repeateValue, metricsName);
210 break;
211 default:
212 break;
213 }
214 if (repeateValue != "") {
215 repeateValue.pop_back();
216 }
217 res += metricsName + ": {" + repeateValue + "}";
218 res = JsonFormat(res) + "\r\n";
219 std::regex strRegex(",");
220 auto str = std::regex_replace(res, strRegex, "");
221 #ifndef IS_WASM
222 printf("%s", str.c_str());
223 #else
224 callback(str, SEND_FINISH);
225 #endif
226 return;
227 }
UpdataRepeateValueByTraceMem(std::string & repeateValue,std::string & metricsName)228 void Metrics::UpdataRepeateValueByTraceMem(std::string& repeateValue, std::string& metricsName)
229 {
230 metricsName = TRACE_MEM;
231 for (auto item : memStrategy_) {
232 repeateValue += PROCESS_METRICES + PROCESS_NAME + "\"" + item.processName + "\"," + OVERALL_COUNTERS +
233 ANON_RSS + MIN + std::to_string(item.overallCounters.min) + "," + MAX +
234 std::to_string(item.overallCounters.max) + "," + AVG +
235 std::to_string(item.overallCounters.avg) + "}}},";
236 }
237 }
UpdataRepeateValueByTopTen(std::string & repeateValue,std::string & metricsName)238 void Metrics::UpdataRepeateValueByTopTen(std::string& repeateValue, std::string& metricsName)
239 {
240 metricsName = TRACE_MEM_TOP_TEN;
241 for (auto item : memStrategy_) {
242 repeateValue += PROCESS_METRICES + PROCESS_NAME + "\"" + item.processName + "\"," + OVERALL_COUNTERS +
243 ANON_RSS + MIN + std::to_string(item.overallCounters.min) + "," + MAX +
244 std::to_string(item.overallCounters.max) + "," + AVG +
245 std::to_string(item.overallCounters.avg) + "}}},";
246 }
247 }
UpdataRepeateValueByMemUnagg(std::string & repeateValue,std::string & metricsName)248 void Metrics::UpdataRepeateValueByMemUnagg(std::string& repeateValue, std::string& metricsName)
249 {
250 metricsName = TRACE_MEM_UNAGG;
251 for (auto item : memAggStrategy_) {
252 repeateValue += PROCESS_VALUES + PROCESS_NAME + "\"" + item.processName + "\"," + ANON_RSS + TS +
253 std::to_string(item.anonRss.ts) + "," + OOM_SCORE + std::to_string(item.anonRss.oomScore) +
254 "," + VALUE + std::to_string(item.anonRss.value) + "}," + FILE_RSS + TS +
255 std::to_string(item.fileRss.ts) + "," + OOM_SCORE + std::to_string(item.fileRss.oomScore) +
256 "," + VALUE + std::to_string(item.fileRss.value) + "}," + SWAP + TS +
257 std::to_string(item.swap.ts) + "," + OOM_SCORE + std::to_string(item.swap.oomScore) + "," +
258 VALUE + std::to_string(item.swap.value) + "}},";
259 }
260 }
UpdataRepeateValueByTaskNames(std::string & repeateValue,std::string & metricsName)261 void Metrics::UpdataRepeateValueByTaskNames(std::string& repeateValue, std::string& metricsName)
262 {
263 metricsName = TRACE_TASK_NAMES;
264 for (auto item : taskNameStrategy_) {
265 repeateValue += PROCESS + PID + std::to_string(item.pid) + "," + PROCESS_NAME + "\"" + item.processName + "\",";
266 for (auto threadItem : item.threadName) {
267 repeateValue += THREAD_NAME + "\"" + threadItem + "\",";
268 }
269 repeateValue.pop_back();
270 repeateValue += "},";
271 }
272 }
UpdataRepeateValueByStats(std::string & repeateValue,std::string & metricsName)273 void Metrics::UpdataRepeateValueByStats(std::string& repeateValue, std::string& metricsName)
274 {
275 metricsName = TRACE_STATS;
276 for (auto item : statStrategy_) {
277 repeateValue += STAT + NAME + "\"" + item.name + "\"," + COUNT + std::to_string(item.count) + "," + SOURCE +
278 "\"" + item.source + "\"," + SEVERITY + "\"" + item.severity + "\"" + "},";
279 }
280 }
UpdataRepeateValueByMetadata(std::string & repeateValue,std::string & metricsName)281 void Metrics::UpdataRepeateValueByMetadata(std::string& repeateValue, std::string& metricsName)
282 {
283 metricsName = TRACE_METADATA;
284 for (auto item : metaDataStrategy_) {
285 repeateValue +=
286 TRACE_METADATA + ":{" + NAME + "\"" + item.name + "\"," + VALUE + "\"" + item.value + "\"" + "},";
287 }
288 }
UpdataRepeateValueBySysCalls(std::string & repeateValue,std::string & metricsName)289 void Metrics::UpdataRepeateValueBySysCalls(std::string& repeateValue, std::string& metricsName)
290 {
291 metricsName = SYS_CALLS;
292 for (auto item : sysCallStrategy_) {
293 repeateValue += FUNCTION + FUNCTION_NAME + "\"" + item.functionName + "\"," + DUR_MAX +
294 std::to_string(item.durMax) + "," + DUR_MIN + std::to_string(item.durMin) + "," + DUR_AVG +
295 std::to_string(item.durAvg) + "},";
296 }
297 }
GetLevelSpace(int level)298 std::string Metrics::GetLevelSpace(int level)
299 {
300 std::string levelStr = "";
301 for (int i = 0; i < level; i++) {
302 levelStr += " ";
303 }
304 return levelStr;
305 }
JsonFormat(std::string json)306 std::string Metrics::JsonFormat(std::string json)
307 {
308 std::string result = "";
309 int level = 0;
310 for (std::string::size_type index = 0; index < json.size(); index++) {
311 char value = json[index];
312 if (level > 0 && json[json.size() - 1] == '\n') {
313 result += GetLevelSpace(level);
314 }
315 switch (value) {
316 case '{':
317 case '[':
318 result = result + value + "\n";
319 level++;
320 result += GetLevelSpace(level);
321 break;
322 case ',':
323 result = result + value + "\n";
324 result += GetLevelSpace(level);
325 break;
326 case '}':
327 case ']':
328 result += "\n";
329 level--;
330 result += GetLevelSpace(level);
331 result += value;
332 break;
333 default:
334 result += value;
335 break;
336 }
337 }
338 return result;
339 }
340 } // namespace TraceStreamer
341 } // namespace SysTuning
342