• 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 #include <sstream>
24 
25 #include "common_define.h"
26 #include "cJSON.h"
27 #include "hilog/log.h"
28 
29 namespace OHOS {
30 namespace HiviewDFX {
31 namespace Hitrace {
32 #ifdef LOG_DOMAIN
33 #undef LOG_DOMAIN
34 #define LOG_DOMAIN 0xD002D33
35 #endif
36 #ifdef LOG_TAG
37 #undef LOG_TAG
38 #define LOG_TAG "HitraceUtils"
39 #endif
40 namespace {
41 const std::string HTIRACE_TAG_CONFIG_FILE = "/system/etc/hiview/hitrace_utils.json";
42 
ParseEnablePath(cJSON * tagNode,TraceTag & tag)43 void ParseEnablePath(cJSON *tagNode, TraceTag& tag)
44 {
45     cJSON *enablePathNode = cJSON_GetObjectItem(tagNode, "enable_path");
46     if (enablePathNode != nullptr && cJSON_IsArray(enablePathNode)) {
47         cJSON *pathItem = nullptr;
48         cJSON_ArrayForEach(pathItem, enablePathNode) {
49             if (cJSON_IsString(pathItem)) {
50                 tag.enablePath.push_back(pathItem->valuestring);
51             }
52         }
53     }
54 }
55 
ParseFormatPath(cJSON * tagNode,TraceTag & tag)56 void ParseFormatPath(cJSON *tagNode, TraceTag& tag)
57 {
58     cJSON *formatPathNode = cJSON_GetObjectItem(tagNode, "format_path");
59     if (formatPathNode != nullptr && cJSON_IsArray(formatPathNode)) {
60         cJSON *pathItem = nullptr;
61         cJSON_ArrayForEach(pathItem, formatPathNode) {
62             if (cJSON_IsString(pathItem)) {
63                 tag.formatPath.push_back(pathItem->valuestring);
64             }
65         }
66     }
67 }
68 
ParseJsonFromFile(const std::string & filePath)69 cJSON* ParseJsonFromFile(const std::string& filePath)
70 {
71     std::ifstream inFile(filePath, std::ios::in);
72     if (!inFile.is_open()) {
73         HILOG_ERROR(LOG_CORE, "ParseJsonFromFile: %{public}s is not existed.", filePath.c_str());
74         return nullptr;
75     }
76     std::string fileContent((std::istreambuf_iterator<char>(inFile)), std::istreambuf_iterator<char>());
77     cJSON* rootNode = cJSON_Parse(fileContent.c_str());
78     if (rootNode == nullptr) {
79         HILOG_ERROR(LOG_CORE, "ParseJsonFromFile: %{public}s is not in JSON format.", filePath.c_str());
80     }
81     inFile.close();
82     return rootNode;
83 }
84 
ParseTagCategory(cJSON * jsonNode,bool parseEnable,bool parseFmt,std::map<std::string,TraceTag> & tagInfos)85 bool ParseTagCategory(cJSON* jsonNode, bool parseEnable, bool parseFmt, std::map<std::string, TraceTag>& tagInfos)
86 {
87     cJSON* tagCategoryNode = cJSON_GetObjectItem(jsonNode, "tag_category");
88     if (tagCategoryNode == nullptr) {
89         HILOG_ERROR(LOG_CORE, "TraceJsonParser: tag_category json node not found.");
90         return false;
91     }
92     cJSON* tagNode = nullptr;
93     cJSON_ArrayForEach(tagNode, tagCategoryNode) {
94         if (tagNode == nullptr || tagNode->string == nullptr) {
95             continue;
96         }
97         // when base info has been parsed, only try to parse particial trace infos.
98         if (tagInfos.find(tagNode->string) != tagInfos.end()) {
99             if (parseEnable) {
100                 ParseEnablePath(tagNode, tagInfos[tagNode->string]);
101             }
102             if (parseFmt) {
103                 ParseFormatPath(tagNode, tagInfos[tagNode->string]);
104             }
105             continue;
106         }
107         TraceTag tag;
108         cJSON* description = cJSON_GetObjectItem(tagNode, "description");
109         if (description != nullptr && cJSON_IsString(description)) {
110             tag.description = description->valuestring;
111         }
112         cJSON* tagOffset = cJSON_GetObjectItem(tagNode, "tag_offset");
113         if (tagOffset != nullptr && cJSON_IsNumber(tagOffset)) {
114             tag.tag = 1ULL << tagOffset->valueint;
115         }
116         cJSON* type = cJSON_GetObjectItem(tagNode, "type");
117         if (type != nullptr && cJSON_IsNumber(type)) {
118             tag.type = static_cast<TraceType>(type->valueint);
119         }
120         if (parseEnable) {
121             ParseEnablePath(tagNode, tag);
122         }
123         if (parseFmt) {
124             ParseFormatPath(tagNode, tag);
125         }
126         tagInfos.insert(std::pair<std::string, TraceTag>(tagNode->string, tag));
127     }
128     return true;
129 }
130 
ParseBaseFormatPath(cJSON * jsonNode,std::vector<std::string> & baseTraceFormats)131 bool ParseBaseFormatPath(cJSON* jsonNode, std::vector<std::string>& baseTraceFormats)
132 {
133     cJSON* baseTraceFormatsNode = cJSON_GetObjectItem(jsonNode, "base_format_path");
134     if (baseTraceFormatsNode == nullptr) {
135         HILOG_ERROR(LOG_CORE, "ParseTraceJson: base_format_path json node not found.");
136         return false;
137     }
138     if (cJSON_IsArray(baseTraceFormatsNode)) {
139         cJSON *formatItem = nullptr;
140         cJSON_ArrayForEach(formatItem, baseTraceFormatsNode) {
141             if (cJSON_IsString(formatItem)) {
142                 baseTraceFormats.push_back(formatItem->valuestring);
143             }
144         }
145     }
146     return true;
147 }
148 
ParseTagGroups(cJSON * jsonNode,std::map<std::string,std::vector<std::string>> & tagGroups)149 bool ParseTagGroups(cJSON* jsonNode, std::map<std::string, std::vector<std::string>>& tagGroups)
150 {
151     cJSON* tagGroupsNode = cJSON_GetObjectItem(jsonNode, "tag_groups");
152     if (tagGroupsNode == nullptr) {
153         HILOG_ERROR(LOG_CORE, "ParseTraceJson: tag_groups json node not found.");
154         return false;
155     }
156     cJSON* tagGroupNode = nullptr;
157     cJSON_ArrayForEach(tagGroupNode, tagGroupsNode) {
158         if (tagGroupNode == nullptr || tagGroupNode->string == nullptr) {
159             continue;
160         }
161         std::string tagGroupName = tagGroupNode->string;
162         std::vector<std::string> tagList;
163         cJSON* tagNameNode = nullptr;
164         cJSON_ArrayForEach(tagNameNode, tagGroupNode) {
165             if (cJSON_IsString(tagNameNode)) {
166                 tagList.push_back(tagNameNode->valuestring);
167             }
168         }
169         tagGroups.insert(std::pair<std::string, std::vector<std::string>>(tagGroupName, tagList));
170     }
171     return true;
172 }
173 
ParseTraceBufSz(cJSON * jsonNode,int & bufSz)174 bool ParseTraceBufSz(cJSON* jsonNode, int& bufSz)
175 {
176     cJSON* bufSzNode = cJSON_GetObjectItem(jsonNode, "snapshot_buffer_kb");
177     if (bufSzNode == nullptr) {
178         HILOG_ERROR(LOG_CORE, "ParseTraceJson: snapshot_buffer_kb json node not found.");
179         return false;
180     }
181     if (!cJSON_IsNumber(bufSzNode)) {
182         HILOG_ERROR(LOG_CORE, "ParseTraceJson: snapshot_buffer_kb item is illegal.");
183         return false;
184     }
185     bufSz = bufSzNode->valueint;
186     return true;
187 }
188 
ParseTraceFileAge(cJSON * jsonNode,const std::string & jsonLabel,bool & agingSwitcher)189 bool ParseTraceFileAge(cJSON* jsonNode, const std::string& jsonLabel, bool& agingSwitcher)
190 {
191     cJSON* agingNode = cJSON_GetObjectItem(jsonNode, jsonLabel.c_str());
192     if (agingNode == nullptr) {
193         HILOG_ERROR(LOG_CORE, "ParseTraceJson: %{public}s json node not found.", jsonLabel.c_str());
194         return false;
195     }
196     if (!cJSON_IsNumber(agingNode)) {
197         HILOG_ERROR(LOG_CORE, "ParseTraceJson:  %{public}s item is illegal.", jsonLabel.c_str());
198         return false;
199     }
200     agingSwitcher = agingNode->valueint == 0 ? false : true;
201     return true;
202 }
203 
UpdateParseItem(const uint8_t parseItem)204 uint8_t UpdateParseItem(const uint8_t parseItem)
205 {
206     uint8_t retParseItem = parseItem;
207     if ((parseItem & TRACE_TAG_ENABLE_INFO) > 0 || (parseItem & TRACE_TAG_FORMAT_INFO) > 0 ||
208         (parseItem & TRACE_TAG_GROUP_INFO) > 0) {
209         retParseItem |= TRACE_TAG_BASE_INFO;
210     }
211     return retParseItem;
212 }
213 }
214 
ParseTraceJson(const uint8_t policy)215 bool TraceJsonParser::ParseTraceJson(const uint8_t policy)
216 {
217     if ((policy & parserState_) == policy) {
218         HILOG_INFO(LOG_CORE, "ParseTraceJson: Parser policy(%{public}d) already done.", policy);
219         return true;
220     }
221 
222     uint8_t needParseItem = UpdateParseItem(policy);
223     needParseItem &= (~parserState_);
224 
225     cJSON* rootNode = ParseJsonFromFile(HTIRACE_TAG_CONFIG_FILE);
226     if (rootNode == nullptr) {
227         return false;
228     }
229 
230     if ((needParseItem & TRACE_SNAPSHOT_BUFSZ) > 0 && ParseTraceBufSz(rootNode, snapshotBufSzKb_)) {
231         parserState_ |= TRACE_SNAPSHOT_BUFSZ;
232     }
233     if ((needParseItem & TRACE_SNAPSHOT_FILE_AGE) > 0 &&
234         ParseTraceFileAge(rootNode, "snapshot_file_aging", snapshotFileAge_)) {
235         parserState_ |= TRACE_SNAPSHOT_FILE_AGE;
236     }
237 
238     bool needParseTagEnableInfo = (needParseItem & TRACE_TAG_ENABLE_INFO) > 0;
239     bool needParseTagFmtInfo = (needParseItem & TRACE_TAG_FORMAT_INFO) > 0;
240     if ((needParseItem & TRACE_TAG_BASE_INFO) > 0 || needParseTagEnableInfo || needParseTagFmtInfo) {
241         if (ParseTagCategory(rootNode, needParseTagEnableInfo, needParseTagFmtInfo, traceTagInfos_)) {
242             parserState_ |= TRACE_TAG_BASE_INFO;
243             if (needParseTagEnableInfo) {
244                 parserState_ |= TRACE_TAG_ENABLE_INFO;
245             }
246         }
247     }
248 
249     if (needParseTagFmtInfo && ParseBaseFormatPath(rootNode, baseTraceFormats_)) {
250         parserState_ |= TRACE_TAG_FORMAT_INFO;
251     }
252 
253     if ((needParseItem & TRACE_TAG_GROUP_INFO) > 0 && ParseTagGroups(rootNode, tagGroups_)) {
254         parserState_ |= TRACE_TAG_GROUP_INFO;
255     }
256 
257     cJSON_Delete(rootNode);
258     HILOG_INFO(LOG_CORE, "ParseTraceJson: parse done, input policy(%{public}u), parser state(%{public}u)",
259         policy, parserState_);
260     return (policy & parserState_) == policy;
261 }
262 } // namespace HiTrace
263 } // namespace HiviewDFX
264 } // namespace OHOS