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