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 20namespace SysTuning { 21namespace TraceStreamer { 22constexpr uint32_t EXTRA_CHAR = 4; 23constexpr uint32_t SEND_FINISH = 1; 24constexpr uint32_t FUNCTION_ITEM_DUR_MIN = 1; 25constexpr uint32_t FUNCTION_ITEM_DUR_MAX = 2; 26constexpr uint32_t FUNCTION_ITEM_DUR_AVG = 3; 27constexpr uint32_t FUNCTION_ITEM_FUNCTION_NAME = 4; 28Metrics ::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 49void 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 60void 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} 79void 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} 119void 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} 141void 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} 158void 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} 171void 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} 190void 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} 234void 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} 244void 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} 254void 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} 267void 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} 279void 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} 287void 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} 295void 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} 304std::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} 312std::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