• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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