1 /*
2 * Copyright (c) 2021-2022 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 "base/log/dump_log.h"
17
18 #include <fstream>
19 #include "core/common/ace_application_info.h"
20
21 namespace OHOS::Ace {
22
23 DumpLog::DumpLog() = default;
24 DumpLog::~DumpLog() = default;
25
Print(int32_t depth, const std::string& className, int32_t childSize)26 void DumpLog::Print(int32_t depth, const std::string& className, int32_t childSize)
27 {
28 if (!ostream_ || !ostream_->good()) {
29 return;
30 }
31 std::string space = " ";
32 for (int32_t i = 0; i < depth; ++i) {
33 ostream_->write(space.c_str(), space.length());
34 }
35 ostream_->write(space.c_str(), space.length());
36 std::string data = "|-> ";
37 data.append(className);
38 data.append(" childSize:" + std::to_string(childSize));
39 data.append("\n");
40 ostream_->write(data.c_str(), data.length());
41 for (auto& desc : description_) {
42 for (int32_t i = 0; i < depth; ++i) {
43 ostream_->write(space.c_str(), space.length());
44 }
45 std::string data = "";
46 if (childSize == 0) {
47 data = " ";
48 } else {
49 data = " | ";
50 }
51 data.append(desc);
52 ostream_->write(data.c_str(), data.length());
53 }
54 ostream_->flush();
55 description_.clear();
56 description_.shrink_to_fit();
57 }
58
Print(const std::string& content)59 void DumpLog::Print(const std::string& content)
60 {
61 Print(0, content);
62 }
63
Print(int32_t depth, const std::string& content)64 void DumpLog::Print(int32_t depth, const std::string& content)
65 {
66 std::string space = " ";
67 for (int32_t i = 0; i < depth; ++i) {
68 ostream_->write(space.c_str(), space.length());
69 }
70 std::string data = content + separator_;
71 ostream_->write(data.c_str(), data.length());
72 }
73
Reset()74 void DumpLog::Reset()
75 {
76 ostream_.reset();
77 }
78
ShowDumpHelp(std::vector<std::string>& info)79 void DumpLog::ShowDumpHelp(std::vector<std::string>& info)
80 {
81 info.emplace_back(" -element |show element tree");
82 info.emplace_back(" -render |show render tree");
83 info.emplace_back(" -inspector |show inspector tree");
84 info.emplace_back(" -frontend |show path and components count of current page");
85 info.emplace_back(" -navigation |show navigation path stack");
86 }
87
Append(int32_t depth, const std::string& className, int32_t childSize)88 void DumpLog::Append(int32_t depth, const std::string& className, int32_t childSize)
89 {
90 for (int32_t i = 0; i < depth; ++i) {
91 result_.append(" ");
92 }
93 result_.append("|-> ");
94 result_.append(className);
95 result_.append(" childSize:" + std::to_string(childSize));
96 result_.append("\n");
97 for (auto& desc : description_) {
98 for (int32_t i = 0; i < depth; ++i) {
99 result_.append(" ");
100 }
101 if (childSize == 0) {
102 result_.append(" ");
103 } else {
104 result_.append(" | ");
105 }
106 result_.append(desc);
107 }
108 description_.clear();
109 description_.shrink_to_fit();
110 }
111
OutPutBySize()112 bool DumpLog::OutPutBySize()
113 {
114 if (!ostream_->good()) {
115 result_.clear();
116 return false;
117 }
118 // if current result size > max size, dump will output as file
119 if (result_.size() + 1 > DumpLog::MAX_DUMP_LENGTH) {
120 auto dumpFilePath = AceApplicationInfo::GetInstance().GetDataFileDirPath() + "/arkui.dump";
121 std::unique_ptr<std::ostream> ostream = std::make_unique<std::ofstream>(dumpFilePath);
122 if (!ostream) {
123 result_.clear();
124 result_.append("Dump output failed,please try again");
125 ostream_->write(result_.c_str(), result_.length());
126 result_.clear();
127 }
128 CHECK_NULL_RETURN(ostream, false);
129 DumpLog::GetInstance().SetDumpFile(std::move(ostream));
130 }
131 ostream_->write(result_.c_str(), result_.length());
132 result_.clear();
133 ostream_->flush();
134 return true;
135 }
136
OutPutDefault()137 void DumpLog::OutPutDefault()
138 {
139 if (!ostream_ || !ostream_->good()) {
140 result_.clear();
141 return;
142 }
143 ostream_->write(result_.c_str(), result_.length());
144 result_.clear();
145 ostream_->flush();
146 }
147
PrintJson(const std::string& content)148 void DumpLog::PrintJson(const std::string& content)
149 {
150 if (!ostream_->good()) {
151 return;
152 }
153 ostream_->write(content.c_str(), content.length());
154 ostream_->flush();
155 }
156
PrintEndDumpInfoNG(bool isElement)157 void DumpLog::PrintEndDumpInfoNG(bool isElement)
158 {
159 int32_t depth = GetDepth() + DumpLog::END_POS_TWO;
160 std::string result;
161 for (int32_t i = 0; i < depth; ++i) {
162 result.append("}");
163 }
164 if (isElement) {
165 Append(result);
166 } else {
167 PrintJson(result);
168 }
169 }
170
GetPrefix(int32_t depth)171 std::string DumpLog::GetPrefix(int32_t depth)
172 {
173 std::string prefix = "";
174 if (depth > 0) {
175 int32_t lastDepth = GetDepth();
176 if (depth == lastDepth) {
177 prefix.append("},");
178 } else if (depth > lastDepth) {
179 prefix = ",";
180 } else {
181 int32_t diff = lastDepth - depth + 1;
182 prefix.assign(diff, '}').append(",");
183 }
184 }
185 SetDepth(depth);
186 return prefix;
187 }
188
FormatDumpInfo(const std::string& str, int32_t depth)189 std::string DumpLog::FormatDumpInfo(const std::string& str, int32_t depth)
190 {
191 if (str.length() > DumpLog::MIN_JSON_LENGTH) {
192 if (depth == 0) {
193 return str.substr(0, str.length() - DumpLog::END_POS_TWO);
194 }
195 return str.substr(1, str.length() - DumpLog::END_POS_THREE);
196 }
197 return str;
198 }
199 } // namespace OHOS::Ace
200