1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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 constexpr uint32_t EXTRA_CHAR = 4;
23 constexpr uint32_t SEND_FINISH = 1;
24 constexpr uint32_t FUNCTION_ITEM_DUR_MIN = 1;
25 constexpr uint32_t FUNCTION_ITEM_DUR_MAX = 2;
26 constexpr uint32_t FUNCTION_ITEM_DUR_AVG = 3;
27 constexpr uint32_t FUNCTION_ITEM_FUNCTION_NAME = 4;
Metrics()28 Metrics ::Metrics()
29 {
30 metricsFunction_ = {
31 {TRACE_MEM, std::bind(&Metrics::InitMemoryStrategy, this, std::placeholders::_1)},
32 {TRACE_MEM_TOP_TEN, std::bind(&Metrics::InitMemoryStrategy, this, std::placeholders::_1)},
33 {TRACE_MEM_UNAGG, std::bind(&Metrics::InitMemoryUnAggStrategy, this, std::placeholders::_1)},
34 {TRACE_TASK_NAMES, std::bind(&Metrics::InitMemoryTaskNameStrategy, this, std::placeholders::_1)},
35 {TRACE_STATS, std::bind(&Metrics::InitTraceStatsStrategy, this, std::placeholders::_1)},
36 {TRACE_METADATA, std::bind(&Metrics::InitTraceMetaDataStrategy, this, std::placeholders::_1)},
37 {SYS_CALLS, std::bind(&Metrics::InitSysCallStrategy, this, std::placeholders::_1)}};
38 initMetricsMap_ = {
39 {METRICS_TRACE_MEM, TRACE_MEM},
40 {METRICS_TRACE_MEM_TOP_TEN, TRACE_MEM_TOP_TEN},
41 {METRICS_TRACE_MEM_UNAGG, TRACE_MEM_UNAGG},
42 {METRICS_TRACE_TASK_NAMES, TRACE_TASK_NAMES},
43 {METRICS_TRACE_STATS, TRACE_STATS},
44 {METRICS_TRACE_METADATA, TRACE_METADATA},
45 {METRICS_SYS_CALLS, SYS_CALLS},
46 };
47 }
48
ParserJson(const std::string & metrics,std::string & result)49 void Metrics::ParserJson(const std::string &metrics, std::string &result)
50 {
51 result = result.substr(EXTRA_CHAR, result.size());
52 auto it = metricsFunction_.find(metrics);
53 if (it == metricsFunction_.end()) {
54 TS_LOGE("Not support metrics!");
55 return;
56 }
57 it->second(result);
58 }
59
InitMemoryStrategy(const std::string & result)60 void Metrics::InitMemoryStrategy(const std::string &result)
61 {
62 json jMessage = json::parse(result);
63 const uint32_t typeInfoItemMax = 0;
64 const uint32_t typeInfoItemMin = 1;
65 const uint32_t typeInfoItemAvg = 2;
66 const uint32_t processMetricesItemsName = 4;
67 for (int i = 0; i < jMessage.at("values").size(); i++) {
68 TypeInfoItem typeInfoItem;
69 typeInfoItem.max = jMessage.at("values")[i].at(typeInfoItemMax);
70 typeInfoItem.min = jMessage.at("values")[i].at(typeInfoItemMin);
71 typeInfoItem.avg = jMessage.at("values")[i].at(typeInfoItemAvg);
72 ProcessMetricsItems processMetricsItems;
73 processMetricsItems.overallCounters = typeInfoItem;
74 processMetricsItems.processName = jMessage.at("values")[i].at(processMetricesItemsName);
75 memStrategy_.emplace_back(std::move(processMetricsItems));
76 }
77 return;
78 }
InitMemoryUnAggStrategy(const std::string & result)79 void Metrics::InitMemoryUnAggStrategy(const std::string &result)
80 {
81 json jMessage = json::parse(result);
82 const uint32_t processValuesItemName = 0;
83 const uint32_t namesIndex = 1;
84 const uint32_t valuesIndex = 2;
85 const uint32_t timesIndex = 3;
86 for (int i = 0; i < jMessage.at("values").size(); i++) {
87 ProcessValuesItem processValuesItem;
88 if (jMessage.at("values")[i].at(0).is_null()) {
89 processValuesItem.processName = "";
90 } else {
91 processValuesItem.processName = jMessage.at("values")[i].at(processValuesItemName);
92 }
93 auto names = base::SplitStringToVec(jMessage.at("values")[i].at(namesIndex), ",");
94 auto values = base::SplitStringToVec(jMessage.at("values")[i].at(valuesIndex), ",");
95 auto times = base::SplitStringToVec(jMessage.at("values")[i].at(timesIndex), ",");
96 auto oomScoreValue = 0;
97 for (auto index = 0; index < names.size(); index++) {
98 if (names[index] == "oom_score_adj") {
99 oomScoreValue = atoi(values.at(index).c_str());
100 }
101 TypeItem typeItem;
102 typeItem.ts = atoll(times.at(index).c_str());
103 typeItem.oomScore = oomScoreValue;
104 typeItem.value = atoi(values.at(index).c_str());
105 if (names.at(index) == "mem.rss.anon") {
106 processValuesItem.anonRss = typeItem;
107 } else if (names.at(index) == "mem.swap") {
108 processValuesItem.swap = typeItem;
109 } else if (names.at(index) == "mem.rss.file") {
110 processValuesItem.fileRss = typeItem;
111 } else if (names.at(index) == "oom_score_adj") {
112 processValuesItem.anonAndSwap = typeItem;
113 }
114 }
115 memAggStrategy_.emplace_back(processValuesItem);
116 }
117 return;
118 }
InitMemoryTaskNameStrategy(const std::string & result)119 void Metrics::InitMemoryTaskNameStrategy(const std::string &result)
120 {
121 json jMessage = json::parse(result);
122 const uint32_t jmessageValueSizeOne = 1;
123 const uint32_t jmessageValueSizeTwo = 2;
124 const uint32_t jmessageValueSizeThree = 3;
125 for (int i = 0; i < jMessage.at("values").size(); i++) {
126 TaskProcessItem taskProcessItem;
127 taskProcessItem.pid = jMessage.at("values")[i].at(jmessageValueSizeOne);
128 if (jMessage.at("values")[i].at(jmessageValueSizeTwo).is_null()) {
129 taskProcessItem.processName = "";
130 } else {
131 taskProcessItem.processName = jMessage.at("values")[i].at(jmessageValueSizeTwo);
132 }
133 if (!jMessage.at("values")[i].at(jmessageValueSizeThree).is_null()) {
134 taskProcessItem.threadName =
135 base::SplitStringToVec(jMessage.at("values")[i].at(jmessageValueSizeThree), ",");
136 }
137 taskNameStrategy_.emplace_back(taskProcessItem);
138 }
139 return;
140 }
InitTraceStatsStrategy(const std::string & result)141 void Metrics::InitTraceStatsStrategy(const std::string &result)
142 {
143 json jMessage = json::parse(result);
144 const uint32_t statItemName = 0;
145 const uint32_t statItemCount = 2;
146 const uint32_t statItemSource = 3;
147 const uint32_t statItemSeverity = 4;
148 for (int i = 0; i < jMessage.at("values").size(); i++) {
149 StatItem statItem;
150 statItem.name = jMessage.at("values")[i].at(statItemName);
151 statItem.count = jMessage.at("values")[i].at(statItemCount);
152 statItem.source = jMessage.at("values")[i].at(statItemSource);
153 statItem.severity = jMessage.at("values")[i].at(statItemSeverity);
154 statStrategy_.emplace_back(statItem);
155 }
156 return;
157 }
InitTraceMetaDataStrategy(const std::string & result)158 void Metrics::InitTraceMetaDataStrategy(const std::string &result)
159 {
160 json jMessage = json::parse(result);
161 const uint32_t traceMetaDataItemName = 0;
162 const uint32_t traceMetaDataItemValue = 1;
163 for (int i = 0; i < jMessage.at("values").size(); i++) {
164 TraceMetadataItem traceMetadataItem;
165 traceMetadataItem.name = jMessage.at("values")[i].at(traceMetaDataItemName);
166 traceMetadataItem.value = jMessage.at("values")[i].at(traceMetaDataItemValue);
167 metaDataStrategy_.emplace_back(traceMetadataItem);
168 }
169 return;
170 }
InitSysCallStrategy(const std::string & result)171 void Metrics::InitSysCallStrategy(const std::string &result)
172 {
173 json jMessage = json::parse(result);
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 if (!jMessage.at("values")[i].at(FUNCTION_ITEM_DUR_MAX).is_null()) {
178 functionItem.durMax = jMessage.at("values")[i].at(FUNCTION_ITEM_DUR_MAX);
179 }
180 if (!jMessage.at("values")[i].at(FUNCTION_ITEM_DUR_MIN).is_null()) {
181 functionItem.durMin = jMessage.at("values")[i].at(FUNCTION_ITEM_DUR_MIN);
182 }
183 if (!jMessage.at("values")[i].at(FUNCTION_ITEM_DUR_AVG).is_null()) {
184 functionItem.durAvg = jMessage.at("values")[i].at(FUNCTION_ITEM_DUR_AVG);
185 }
186 sysCallStrategy_.emplace_back(functionItem);
187 }
188 return;
189 }
PrintMetricsResult(uint32_t metricsIndex,ResultCallBack callback)190 void Metrics::PrintMetricsResult(uint32_t metricsIndex, ResultCallBack callback)
191 {
192 std::string res = "\r\n";
193 std::string metricsName = "";
194 std::string repeateValue = "";
195 switch (metricsIndex) {
196 case METRICS_TRACE_MEM:
197 UpdataRepeateValueByTraceMem(repeateValue, metricsName);
198 break;
199 case METRICS_TRACE_MEM_TOP_TEN:
200 UpdataRepeateValueByTopTen(repeateValue, metricsName);
201 break;
202 case METRICS_TRACE_MEM_UNAGG:
203 UpdataRepeateValueByMemUnagg(repeateValue, metricsName);
204 break;
205 case METRICS_TRACE_TASK_NAMES:
206 UpdataRepeateValueByTaskNames(repeateValue, metricsName);
207 break;
208 case METRICS_TRACE_STATS:
209 UpdataRepeateValueByStats(repeateValue, metricsName);
210 break;
211 case METRICS_TRACE_METADATA:
212 UpdataRepeateValueByMetadata(repeateValue, metricsName);
213 break;
214 case METRICS_SYS_CALLS:
215 UpdataRepeateValueBySysCalls(repeateValue, metricsName);
216 break;
217 default:
218 break;
219 }
220 if (repeateValue != "") {
221 repeateValue.pop_back();
222 }
223 res += metricsName + ": {" + repeateValue + "}";
224 res = JsonFormat(res) + "\r\n";
225 std::regex strRegex(",");
226 auto str = std::regex_replace(res, strRegex, "");
227 #ifndef IS_WASM
228 printf("%s", str.c_str());
229 #else
230 callback(str, SEND_FINISH);
231 #endif
232 return;
233 }
UpdataRepeateValueByTraceMem(std::string & repeateValue,std::string & metricsName)234 void Metrics::UpdataRepeateValueByTraceMem(std::string &repeateValue, std::string &metricsName)
235 {
236 metricsName = TRACE_MEM;
237 for (auto item : memStrategy_) {
238 repeateValue += PROCESS_METRICES + PROCESS_NAME + "\"" + item.processName + "\"," + OVERALL_COUNTERS +
239 ANON_RSS + MIN + std::to_string(item.overallCounters.min) + "," + MAX +
240 std::to_string(item.overallCounters.max) + "," + AVG +
241 std::to_string(item.overallCounters.avg) + "}}},";
242 }
243 }
UpdataRepeateValueByTopTen(std::string & repeateValue,std::string & metricsName)244 void Metrics::UpdataRepeateValueByTopTen(std::string &repeateValue, std::string &metricsName)
245 {
246 metricsName = TRACE_MEM_TOP_TEN;
247 for (auto item : memStrategy_) {
248 repeateValue += PROCESS_METRICES + PROCESS_NAME + "\"" + item.processName + "\"," + OVERALL_COUNTERS +
249 ANON_RSS + MIN + std::to_string(item.overallCounters.min) + "," + MAX +
250 std::to_string(item.overallCounters.max) + "," + AVG +
251 std::to_string(item.overallCounters.avg) + "}}},";
252 }
253 }
UpdataRepeateValueByMemUnagg(std::string & repeateValue,std::string & metricsName)254 void Metrics::UpdataRepeateValueByMemUnagg(std::string &repeateValue, std::string &metricsName)
255 {
256 metricsName = TRACE_MEM_UNAGG;
257 for (auto item : memAggStrategy_) {
258 repeateValue += PROCESS_VALUES + PROCESS_NAME + "\"" + item.processName + "\"," + ANON_RSS + TS +
259 std::to_string(item.anonRss.ts) + "," + OOM_SCORE + std::to_string(item.anonRss.oomScore) +
260 "," + VALUE + std::to_string(item.anonRss.value) + "}," + FILE_RSS + TS +
261 std::to_string(item.fileRss.ts) + "," + OOM_SCORE + std::to_string(item.fileRss.oomScore) +
262 "," + VALUE + std::to_string(item.fileRss.value) + "}," + SWAP + TS +
263 std::to_string(item.swap.ts) + "," + OOM_SCORE + std::to_string(item.swap.oomScore) + "," +
264 VALUE + std::to_string(item.swap.value) + "}},";
265 }
266 }
UpdataRepeateValueByTaskNames(std::string & repeateValue,std::string & metricsName)267 void Metrics::UpdataRepeateValueByTaskNames(std::string &repeateValue, std::string &metricsName)
268 {
269 metricsName = TRACE_TASK_NAMES;
270 for (auto item : taskNameStrategy_) {
271 repeateValue += PROCESS + PID + std::to_string(item.pid) + "," + PROCESS_NAME + "\"" + item.processName + "\",";
272 for (auto threadItem : item.threadName) {
273 repeateValue += THREAD_NAME + "\"" + threadItem + "\",";
274 }
275 repeateValue.pop_back();
276 repeateValue += "},";
277 }
278 }
UpdataRepeateValueByStats(std::string & repeateValue,std::string & metricsName)279 void Metrics::UpdataRepeateValueByStats(std::string &repeateValue, std::string &metricsName)
280 {
281 metricsName = TRACE_STATS;
282 for (auto item : statStrategy_) {
283 repeateValue += STAT + NAME + "\"" + item.name + "\"," + COUNT + std::to_string(item.count) + "," + SOURCE +
284 "\"" + item.source + "\"," + SEVERITY + "\"" + item.severity + "\"" + "},";
285 }
286 }
UpdataRepeateValueByMetadata(std::string & repeateValue,std::string & metricsName)287 void Metrics::UpdataRepeateValueByMetadata(std::string &repeateValue, std::string &metricsName)
288 {
289 metricsName = TRACE_METADATA;
290 for (auto item : metaDataStrategy_) {
291 repeateValue +=
292 TRACE_METADATA + ":{" + NAME + "\"" + item.name + "\"," + VALUE + "\"" + item.value + "\"" + "},";
293 }
294 }
UpdataRepeateValueBySysCalls(std::string & repeateValue,std::string & metricsName)295 void Metrics::UpdataRepeateValueBySysCalls(std::string &repeateValue, std::string &metricsName)
296 {
297 metricsName = SYS_CALLS;
298 for (auto item : sysCallStrategy_) {
299 repeateValue += FUNCTION + FUNCTION_NAME + "\"" + item.functionName + "\"," + DUR_MAX +
300 std::to_string(item.durMax) + "," + DUR_MIN + std::to_string(item.durMin) + "," + DUR_AVG +
301 std::to_string(item.durAvg) + "},";
302 }
303 }
GetLevelSpace(int level)304 std::string Metrics::GetLevelSpace(int level)
305 {
306 std::string levelStr = "";
307 for (int i = 0; i < level; i++) {
308 levelStr += " ";
309 }
310 return levelStr;
311 }
JsonFormat(std::string json)312 std::string Metrics::JsonFormat(std::string json)
313 {
314 std::string result = "";
315 int level = 0;
316 for (std::string::size_type index = 0; index < json.size(); index++) {
317 char value = json[index];
318 if (level > 0 && json[json.size() - 1] == '\n') {
319 result += GetLevelSpace(level);
320 }
321 switch (value) {
322 case '{':
323 case '[':
324 result = result + value + "\n";
325 level++;
326 result += GetLevelSpace(level);
327 break;
328 case ',':
329 result = result + value + "\n";
330 result += GetLevelSpace(level);
331 break;
332 case '}':
333 case ']':
334 result += "\n";
335 level--;
336 result += GetLevelSpace(level);
337 result += value;
338 break;
339 default:
340 result += value;
341 break;
342 }
343 }
344 return result;
345 }
346 } // namespace TraceStreamer
347 } // namespace SysTuning
348