1 /*
2 * Copyright (c) 2025 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 #include "faultlog_freeze.h"
16
17 #include <fstream>
18
19 #include "constants.h"
20 #include "faultlog_bundle_util.h"
21 #include "faultlog_formatter.h"
22 #include "faultlog_util.h"
23 #include "freeze_json_generator.h"
24 #include "hiview_logger.h"
25 #include "hisysevent.h"
26 #include "string_util.h"
27
28 namespace OHOS {
29 namespace HiviewDFX {
30 DEFINE_LOG_LABEL(0xD002D11, "Faultlogger");
31 using namespace FaultLogger;
ReportAppFreezeToAppEvent(const FaultLogInfo & info,bool isAppHicollie) const32 void FaultLogFreeze::ReportAppFreezeToAppEvent(const FaultLogInfo& info, bool isAppHicollie) const
33 {
34 HIVIEW_LOGI("Start to report freezeJson !!!");
35
36 FreezeJsonUtil::FreezeJsonCollector collector = GetFreezeJsonCollector(info);
37 std::list<std::string> externalLogList;
38 externalLogList.push_back(info.logPath);
39 std::string externalLog = FreezeJsonUtil::GetStrByList(externalLogList);
40
41 FreezeJsonParams freezeJsonParams = FreezeJsonParams::Builder()
42 .InitTime(collector.timestamp)
43 .InitUuid(collector.uuid)
44 .InitFreezeType(isAppHicollie ? "AppHicollie" : "AppFreeze")
45 .InitForeground(collector.foreground)
46 .InitBundleVersion(collector.version)
47 .InitBundleName(collector.package_name)
48 .InitProcessName(collector.process_name)
49 .InitExternalLog(externalLog)
50 .InitPid(collector.pid)
51 .InitUid(collector.uid)
52 .InitAppRunningUniqueId(collector.appRunningUniqueId)
53 .InitException(collector.exception)
54 .InitHilog(collector.hilog)
55 .InitEventHandler(collector.event_handler)
56 .InitEventHandlerSize3s(collector.event_handler_3s_size)
57 .InitEventHandlerSize6s(collector.event_handler_6s_size)
58 .InitPeerBinder(collector.peer_binder)
59 .InitThreads(collector.stack)
60 .InitMemory(collector.memory)
61 .Build();
62 EventPublish::GetInstance().PushEvent(info.id, isAppHicollie ? APP_HICOLLIE_TYPE : APP_FREEZE_TYPE,
63 HiSysEvent::EventType::FAULT, freezeJsonParams.JsonStr());
64 HIVIEW_LOGI("Report FreezeJson Successfully!");
65 }
66
GetFreezeHilogByPid(long pid) const67 std::string FaultLogFreeze::GetFreezeHilogByPid(long pid) const
68 {
69 std::list<std::string> hilogList;
70 std::string hilogStr = GetHilogByPid(pid);
71 if (hilogStr.empty()) {
72 HIVIEW_LOGE("Get FreezeJson hilog is empty!");
73 } else {
74 std::stringstream hilogStream(hilogStr);
75 std::string oneLine;
76 int count = 0;
77 while (++count <= REPORT_HILOG_LINE && std::getline(hilogStream, oneLine)) {
78 hilogList.push_back(StringUtil::EscapeJsonStringValue(oneLine));
79 }
80 }
81 return FreezeJsonUtil::GetStrByList(hilogList);
82 }
83
GetException(const std::string & name,const std::string & message) const84 std::string FaultLogFreeze::GetException(const std::string& name, const std::string& message) const
85 {
86 FreezeJsonException exception = FreezeJsonException::Builder()
87 .InitName(name)
88 .InitMessage(message)
89 .Build();
90 return exception.JsonStr();
91 }
92
GetFreezeJsonCollector(const FaultLogInfo & info) const93 FreezeJsonUtil::FreezeJsonCollector FaultLogFreeze::GetFreezeJsonCollector(const FaultLogInfo& info) const
94 {
95 FreezeJsonUtil::FreezeJsonCollector collector = {0};
96 std::string jsonFilePath = FreezeJsonUtil::GetFilePath(info.pid, info.id, info.time);
97 if (!FileUtil::FileExists(jsonFilePath)) {
98 HIVIEW_LOGE("Not Exist FreezeJsonFile: %{public}s.", jsonFilePath.c_str());
99 return collector;
100 }
101 FreezeJsonUtil::LoadCollectorFromFile(jsonFilePath, collector);
102 HIVIEW_LOGI("load FreezeJsonFile.");
103 FreezeJsonUtil::DelFile(jsonFilePath);
104
105 collector.exception = GetException(collector.stringId, collector.message);
106 collector.hilog = GetFreezeHilogByPid(collector.pid);
107 std::string procStatm = GetStrValFromMap(info.sectionMap, FaultKey::PROC_STATM);
108 collector.memory = GetMemoryStrByPid(collector.pid, procStatm);
109 collector.foreground = GetStrValFromMap(info.sectionMap, FaultKey::FOREGROUND) == "Yes";
110 collector.version = GetStrValFromMap(info.sectionMap, FaultKey::MODULE_VERSION);
111 collector.uuid = GetStrValFromMap(info.sectionMap, FaultKey::FINGERPRINT);
112
113 return collector;
114 }
115
116 namespace {
GetDightStrArr(const std::string & target)117 auto GetDightStrArr(const std::string& target)
118 {
119 std::vector<std::string> dightStrArr;
120 std::string dightStr;
121 for (char ch : target) {
122 if (isdigit(ch)) {
123 dightStr += ch;
124 continue;
125 }
126 if (!dightStr.empty()) {
127 dightStrArr.push_back(std::move(dightStr));
128 dightStr.clear();
129 }
130 }
131
132 if (!dightStr.empty()) {
133 dightStrArr.push_back(std::move(dightStr));
134 }
135
136 dightStrArr.push_back("0");
137 return dightStrArr;
138 }
139 }
140
FillProcMemory(const std::string & procStatm,long pid,uint64_t & rss,uint64_t & vss) const141 void FaultLogFreeze::FillProcMemory(const std::string& procStatm, long pid, uint64_t& rss, uint64_t& vss) const
142 {
143 std::string statmLine = procStatm;
144 if (statmLine.empty()) {
145 std::ifstream statmStream("/proc/" + std::to_string(pid) + "/statm");
146 if (!statmStream) {
147 HIVIEW_LOGE("Fail to open /proc/%{public}ld/statm errno %{public}d", pid, errno);
148 return;
149 }
150 std::getline(statmStream, statmLine);
151 HIVIEW_LOGI("/proc/%{public}ld/statm : %{public}s", pid, statmLine.c_str());
152 statmStream.close();
153 }
154
155 auto numStrArr = GetDightStrArr(statmLine);
156 if (numStrArr.size() > 1) {
157 uint64_t multiples = 4;
158 vss = multiples * static_cast<uint64_t>(std::atoll(numStrArr[0].c_str()));
159 rss = multiples * static_cast<uint64_t>(std::atoll(numStrArr[1].c_str()));
160 }
161 HIVIEW_LOGI("GET FreezeJson rss=%{public}" PRIu64", vss=%{public}" PRIu64".", rss, vss);
162 }
163
FillSystemMemory(uint64_t & sysFreeMem,uint64_t & sysAvailMem,uint64_t & sysTotalMem) const164 void FaultLogFreeze::FillSystemMemory(uint64_t& sysFreeMem, uint64_t& sysAvailMem, uint64_t& sysTotalMem) const
165 {
166 std::ifstream meminfoStream("/proc/meminfo");
167 if (!meminfoStream) {
168 HIVIEW_LOGE("Fail to open /proc/meminfo errno %{public}d", errno);
169 return;
170 }
171
172 std::string meminfoLine;
173 std::getline(meminfoStream, meminfoLine);
174 sysTotalMem = strtoull(GetDightStrArr(meminfoLine).front().c_str(), nullptr, DECIMAL_BASE);
175 std::getline(meminfoStream, meminfoLine);
176 sysFreeMem = strtoull(GetDightStrArr(meminfoLine).front().c_str(), nullptr, DECIMAL_BASE);
177 std::getline(meminfoStream, meminfoLine);
178 sysAvailMem = strtoull(GetDightStrArr(meminfoLine).front().c_str(), nullptr, DECIMAL_BASE);
179 meminfoStream.close();
180 HIVIEW_LOGI("GET FreezeJson sysFreeMem=%{public}" PRIu64 ", sysAvailMem=%{public}" PRIu64",\
181 sysTotalMem=%{public}" PRIu64".", sysFreeMem, sysAvailMem, sysTotalMem);
182 }
183
GetMemoryStrByPid(long pid,const std::string & procStatm) const184 std::string FaultLogFreeze::GetMemoryStrByPid(long pid, const std::string& procStatm) const
185 {
186 if (pid <= 0) {
187 return "";
188 }
189 uint64_t rss = 0; // statm col = 2 *4
190 uint64_t vss = 0; // statm col = 1 *4
191 FillProcMemory(procStatm, pid, rss, vss);
192
193 uint64_t sysFreeMem = 0; // meminfo row=2
194 uint64_t sysAvailMem = 0; // meminfo row=3
195 uint64_t sysTotalMem = 0; // meminfo row=1
196 FillSystemMemory(sysFreeMem, sysAvailMem, sysTotalMem);
197
198 FreezeJsonMemory freezeJsonMemory = FreezeJsonMemory::Builder().InitRss(rss).InitVss(vss).
199 InitSysFreeMem(sysFreeMem).InitSysAvailMem(sysAvailMem).InitSysTotalMem(sysTotalMem).Build();
200 return freezeJsonMemory.JsonStr();
201 }
202
ReportEventToAppEvent(const FaultLogInfo & info)203 bool FaultLogFreeze::ReportEventToAppEvent(const FaultLogInfo& info)
204 {
205 if (IsSystemProcess(info.module, info.id) || !info.reportToAppEvent) {
206 return false;
207 }
208 if (FreezeJsonUtil::IsAppHicollie(info.reason)) {
209 ReportAppFreezeToAppEvent(info, true);
210 }
211 if (info.faultLogType == FaultLogType::APP_FREEZE) {
212 ReportAppFreezeToAppEvent(info);
213 }
214 return true;
215 }
216
AddSpecificInfo(FaultLogInfo & info)217 void FaultLogFreeze::AddSpecificInfo(FaultLogInfo& info)
218 {
219 if (info.faultLogType == FaultLogType::APP_FREEZE) {
220 info.sectionMap[FaultKey::STACK] = GetThreadStack(info.logPath, info.pid);
221 AddPagesHistory(info);
222 }
223 }
224 } // namespace HiviewDFX
225 } // namespace OHOS
226