• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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