• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 "trace_json_parser.h"
17 
18 #include <cinttypes>
19 #include <unistd.h>
20 #include <cstdio>
21 #include <fstream>
22 #include <fcntl.h>
23 
24 #include "common_define.h"
25 #include "cJSON.h"
26 #include "hilog/log.h"
27 
28 #include "common_utils.h"
29 
30 namespace OHOS {
31 namespace HiviewDFX {
32 namespace Hitrace {
33 #ifdef LOG_DOMAIN
34 #undef LOG_DOMAIN
35 #define LOG_DOMAIN 0xD002D33
36 #endif
37 #ifdef LOG_TAG
38 #undef LOG_TAG
39 #define LOG_TAG "HitraceUtils"
40 #endif
41 namespace {
42 static const char* HTIRACE_UTILS_JSON = "/system/etc/hiview/hitrace_utils.json";
43 static const char* PRODUCT_CONFIG_JSON = "/sys_prod/etc/hiview/hitrace/hitrace_param.json";
44 
45 constexpr int DEFAULT_SNAPSHOT_BUFFER_SIZE_KB = 12 * 1024;
46 constexpr int HM_DEFAULT_SNAPSHOT_BUFFER_SIZE_KB = 144 * 1024;
47 
48 constexpr uint32_t DEFAULT_RECORD_FILE_NUMBER_LIMIT = 15;
49 
50 constexpr uint32_t DEFAULT_SNAPSHOT_FILE_NUMBER_LIMIT = 20;
51 
GetInt64FromJson(cJSON * jsonNode,const std::string & key,int64_t & value)52 bool GetInt64FromJson(cJSON* jsonNode, const std::string& key, int64_t& value)
53 {
54     cJSON* item = cJSON_GetObjectItem(jsonNode, key.c_str());
55     if (item == nullptr) {
56         HILOG_ERROR(LOG_CORE, "GetInt64FromJson: [%{public}s] not found.", key.c_str());
57         return false;
58     }
59     if (!cJSON_IsNumber(item)) {
60         HILOG_ERROR(LOG_CORE, "GetInt64FromJson: [%{public}s] item is illegal.", key.c_str());
61         return false;
62     }
63     value = static_cast<int64_t>(item->valueint);
64     return true;
65 }
66 
GetIntFromJson(cJSON * jsonNode,const std::string & key,int & value)67 bool GetIntFromJson(cJSON* jsonNode, const std::string& key, int& value)
68 {
69     cJSON* item = cJSON_GetObjectItem(jsonNode, key.c_str());
70     if (item == nullptr) {
71         HILOG_ERROR(LOG_CORE, "GetIntFromJson: [%{public}s] not found.", key.c_str());
72         return false;
73     }
74     if (!cJSON_IsNumber(item)) {
75         HILOG_ERROR(LOG_CORE, "GetIntFromJson: [%{public}s] item is illegal.", key.c_str());
76         return false;
77     }
78     value = item->valueint;
79     return true;
80 }
81 
GetStringFromJsonVector(cJSON * jsonNode,const std::string & key,std::vector<std::string> & vec)82 void GetStringFromJsonVector(cJSON *jsonNode, const std::string& key, std::vector<std::string>& vec)
83 {
84     cJSON* node = cJSON_GetObjectItem(jsonNode, key.c_str());
85     if (node != nullptr && cJSON_IsArray(node)) {
86         cJSON *item = nullptr;
87         cJSON_ArrayForEach(item, node) {
88             if (cJSON_IsString(item)) {
89                 vec.push_back(item->valuestring);
90             }
91         }
92     }
93 }
94 
ParseJsonFromFile(const std::string & filePath)95 cJSON* ParseJsonFromFile(const std::string& filePath)
96 {
97     std::ifstream inFile(filePath, std::ios::in);
98     if (!inFile.is_open()) {
99         HILOG_ERROR(LOG_CORE, "ParseJsonFromFile: %{public}s is not existed.", filePath.c_str());
100         return nullptr;
101     }
102     std::string fileContent((std::istreambuf_iterator<char>(inFile)), std::istreambuf_iterator<char>());
103     cJSON* rootNode = cJSON_Parse(fileContent.c_str());
104     if (rootNode == nullptr) {
105         HILOG_ERROR(LOG_CORE, "ParseJsonFromFile: %{public}s is not in JSON format.", filePath.c_str());
106     }
107     inFile.close();
108     return rootNode;
109 }
110 
ParseTagCategory(cJSON * jsonNode,std::map<std::string,TraceTag> & tagInfos)111 bool ParseTagCategory(cJSON* jsonNode, std::map<std::string, TraceTag>& tagInfos)
112 {
113     cJSON* tagCategoryNode = cJSON_GetObjectItem(jsonNode, "tag_category");
114     if (tagCategoryNode == nullptr) {
115         HILOG_ERROR(LOG_CORE, "TraceJsonParser: tag_category json node not found.");
116         return false;
117     }
118     cJSON* tagNode = nullptr;
119     cJSON_ArrayForEach(tagNode, tagCategoryNode) {
120         if (tagNode == nullptr || tagNode->string == nullptr) {
121             continue;
122         }
123         // when base info has been parsed, only try to parse particial trace infos.
124         if (tagInfos.find(tagNode->string) != tagInfos.end()) {
125             GetStringFromJsonVector(tagNode, "enable_path", tagInfos[tagNode->string].enablePath);
126             GetStringFromJsonVector(tagNode, "format_path", tagInfos[tagNode->string].formatPath);
127             continue;
128         }
129         TraceTag tag;
130         cJSON* description = cJSON_GetObjectItem(tagNode, "description");
131         if (description != nullptr && cJSON_IsString(description)) {
132             tag.description = description->valuestring;
133         }
134         cJSON* tagOffset = cJSON_GetObjectItem(tagNode, "tag_offset");
135         if (tagOffset != nullptr && cJSON_IsNumber(tagOffset)) {
136             tag.tag = 1ULL << tagOffset->valueint;
137         }
138         cJSON* type = cJSON_GetObjectItem(tagNode, "type");
139 
140         if (type != nullptr && cJSON_IsNumber(type)) {
141             tag.type = static_cast<TraceType>(type->valueint);
142         }
143         GetStringFromJsonVector(tagNode, "enable_path", tag.enablePath);
144         GetStringFromJsonVector(tagNode, "format_path", tag.formatPath);
145         tagInfos.insert(std::pair<std::string, TraceTag>(tagNode->string, tag));
146     }
147     return true;
148 }
149 
ParseTagGroups(cJSON * jsonNode,std::map<std::string,std::vector<std::string>> & tagGroups)150 bool ParseTagGroups(cJSON* jsonNode, std::map<std::string, std::vector<std::string>>& tagGroups)
151 {
152     cJSON* tagGroupsNode = cJSON_GetObjectItem(jsonNode, "tag_groups");
153     if (tagGroupsNode == nullptr) {
154         HILOG_ERROR(LOG_CORE, "ParseTraceJson: tag_groups json node not found.");
155         return false;
156     }
157     cJSON* tagGroupNode = nullptr;
158     cJSON_ArrayForEach(tagGroupNode, tagGroupsNode) {
159         if (tagGroupNode == nullptr || tagGroupNode->string == nullptr) {
160             continue;
161         }
162         std::string tagGroupName = tagGroupNode->string;
163         std::vector<std::string> tagList;
164         cJSON* tagNameNode = nullptr;
165         cJSON_ArrayForEach(tagNameNode, tagGroupNode) {
166             if (cJSON_IsString(tagNameNode)) {
167                 tagList.push_back(tagNameNode->valuestring);
168             }
169         }
170         tagGroups.insert(std::pair<std::string, std::vector<std::string>>(tagGroupName, tagList));
171     }
172     return true;
173 }
174 }
175 
Instance()176 TraceJsonParser& TraceJsonParser::Instance()
177 {
178     static TraceJsonParser parser(HTIRACE_UTILS_JSON, PRODUCT_CONFIG_JSON);
179     return parser;
180 }
181 
TraceJsonParser(const std::string & hitraceUtilsJson,const std::string & productConfigJson)182 TraceJsonParser::TraceJsonParser(const std::string& hitraceUtilsJson, const std::string& productConfigJson)
183 {
184     InitSnapshotDefaultBufferSize();
185     InitAgeingParam();
186 
187     ParseHitraceUtilsJson(hitraceUtilsJson);
188     ParseProductConfigJson(productConfigJson);
189 
190     PrintParseResult();
191 }
192 
ParseHitraceUtilsJson(const std::string & hitraceUtilsJson)193 void TraceJsonParser::ParseHitraceUtilsJson(const std::string& hitraceUtilsJson)
194 {
195     cJSON* hitraceUtilsJsonRoot = ParseJsonFromFile(hitraceUtilsJson);
196     if (hitraceUtilsJsonRoot == nullptr) {
197         HILOG_ERROR(LOG_CORE, "ParseTraceJson: open %{public}s fail", hitraceUtilsJson.c_str());
198     } else {
199         ParseTagCategory(hitraceUtilsJsonRoot, traceTagInfos_);
200         GetStringFromJsonVector(hitraceUtilsJsonRoot, "base_format_path", baseTraceFormats_);
201         ParseTagGroups(hitraceUtilsJsonRoot, tagGroups_);
202 
203         int value = 0;
204         if (GetIntFromJson(hitraceUtilsJsonRoot, "snapshot_file_aging", value)) {
205             snapShotAgeingParam_.rootEnable = (value != 0);
206         }
207         if (GetIntFromJson(hitraceUtilsJsonRoot, "record_file_aging", value)) {
208             recordAgeingParam_.rootEnable = (value != 0);
209         }
210         if (GetIntFromJson(hitraceUtilsJsonRoot, "snapshot_buffer_kb", value) && value != 0) {
211             snapshotBufSzKb_ = value;
212         }
213     }
214     cJSON_Delete(hitraceUtilsJsonRoot);
215 }
216 
ParseProductConfigJson(const std::string & productConfigJson)217 void TraceJsonParser::ParseProductConfigJson(const std::string& productConfigJson)
218 {
219     cJSON* productConfigJsonRoot = ParseJsonFromFile(productConfigJson);
220     if (productConfigJsonRoot == nullptr) {
221         HILOG_DEBUG(LOG_CORE, "ParseTraceJson: open %{public}s fail", productConfigJson.c_str());
222     } else {
223         GetInt64FromJson(productConfigJsonRoot, "record_file_kb_size", recordAgeingParam_.fileSizeKbLimit);
224         GetInt64FromJson(productConfigJsonRoot, "snapshot_file_kb_size", snapShotAgeingParam_.fileSizeKbLimit);
225         GetIntFromJson(productConfigJsonRoot, "default_buffer_kb_size", snapshotBufSzKb_);
226 
227         int tRootAgeingEnable = -1;
228         if (GetIntFromJson(productConfigJsonRoot, "root_ageing_enable", tRootAgeingEnable)) {
229             bool enable = (tRootAgeingEnable != 0);
230             snapShotAgeingParam_.rootEnable = enable;
231             recordAgeingParam_.rootEnable = enable;
232         }
233     }
234 
235     cJSON_Delete(productConfigJsonRoot);
236 }
237 
GetAgeingParam(TraceDumpType type) const238 const AgeingParam& TraceJsonParser::GetAgeingParam(TraceDumpType type) const
239 {
240     if (type == TraceDumpType::TRACE_RECORDING) {
241         return recordAgeingParam_;
242     }
243     if (type == TraceDumpType::TRACE_SNAPSHOT) {
244         return snapShotAgeingParam_;
245     }
246 
247     static AgeingParam defaultParam;
248     return defaultParam;
249 }
250 
InitSnapshotDefaultBufferSize()251 void TraceJsonParser::InitSnapshotDefaultBufferSize()
252 {
253     snapshotBufSzKb_ = DEFAULT_SNAPSHOT_BUFFER_SIZE_KB;
254 
255     if (IsHmKernel()) {
256         snapshotBufSzKb_ = HM_DEFAULT_SNAPSHOT_BUFFER_SIZE_KB;
257     }
258 
259 #if defined(SNAPSHOT_TRACEBUFFER_SIZE) && (SNAPSHOT_TRACEBUFFER_SIZE != 0)
260     snapshotBufSzKb_ = SNAPSHOT_TRACEBUFFER_SIZE;
261 #endif
262 }
263 
InitAgeingParam()264 void TraceJsonParser::InitAgeingParam()
265 {
266     // record file number limit
267     recordAgeingParam_.fileNumberLimit = DEFAULT_RECORD_FILE_NUMBER_LIMIT;
268 #if defined(RECORD_FILE_LIMIT) && (RECORD_FILE_LIMIT != 0)
269     recordAgeingParam_.fileNumberLimit = RECORD_FILE_LIMIT;
270 #endif
271 
272     // snapshot file number limit
273     snapShotAgeingParam_.fileNumberLimit = DEFAULT_SNAPSHOT_FILE_NUMBER_LIMIT;
274 #if defined(SNAPSHOT_FILE_LIMIT) && (SNAPSHOT_FILE_LIMIT != 0)
275     snapShotAgeingParam_.fileNumberLimit = SNAPSHOT_FILE_LIMIT;
276 #endif
277 }
278 
PrintParseResult()279 void TraceJsonParser::PrintParseResult()
280 {
281     HILOG_INFO(LOG_CORE, "PrintParseResult snap:[%{public}d %{public}" PRId64" %{public}" PRId64 "] "
282         "reco:[%{public}d %{public}" PRId64 " %{public}" PRId64 "] bufsz:[%{public}d]",
283         snapShotAgeingParam_.rootEnable, snapShotAgeingParam_.fileNumberLimit, snapShotAgeingParam_.fileSizeKbLimit,
284         recordAgeingParam_.rootEnable, recordAgeingParam_.fileNumberLimit, recordAgeingParam_.fileSizeKbLimit,
285         snapshotBufSzKb_);
286 }
287 
288 } // namespace HiTrace
289 } // namespace HiviewDFX
290 } // namespace OHOS