1 /*
2 * Copyright (c) 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 #include "bbox_detector_plugin.h"
16
17 #include <fstream>
18 #include <securec.h>
19
20 #include "common_defines.h"
21 #include "event.h"
22 #include "event_loop.h"
23 #include "file_util.h"
24 #include "hisysevent.h"
25 #include "logger.h"
26 #include "plugin_factory.h"
27 #include "sys_event_dao.h"
28 #include "smart_parser.h"
29 #include "string_util.h"
30 #include "tbox.h"
31 #include "time_util.h"
32
33
34 namespace OHOS {
35 namespace HiviewDFX {
36 using namespace std;
37 REGISTER(BBoxDetectorPlugin)
38 DEFINE_LOG_TAG("BBoxDetectorPlugin");
39
40 namespace {
41 const std::string HISIPATH = "/data/hisi_logs/";
42 const std::string BBOXPATH = "/data/log/bbox/";
43 const std::string LOGPARSECONFIG = "/system/etc/hiview";
44 const std::vector<std::string> HISTORYLOGLIST = {
45 "/data/hisi_logs/history.log",
46 "/data/log/bbox/history.log"
47 };
48 }
49
OnLoad()50 void BBoxDetectorPlugin::OnLoad()
51 {
52 SetName("BBoxDetectorPlugin");
53 SetVersion("BBoxDetector1.0");
54 #ifndef UNITTEST
55 auto eventloop = GetHiviewContext()->GetSharedWorkLoop();
56 if (eventloop != nullptr) {
57 eventloop->AddTimerEvent(nullptr, nullptr, [&]() {
58 StartBootScan();
59 }, SECONDS, false); // delay 60s
60 }
61 #endif
62 }
63
OnUnload()64 void BBoxDetectorPlugin::OnUnload()
65 {
66 HIVIEW_LOGI("BBoxDetectorPlugin OnUnload");
67 }
68
OnEvent(std::shared_ptr<Event> & event)69 bool BBoxDetectorPlugin::OnEvent(std::shared_ptr<Event> &event)
70 {
71 if (event == nullptr || event->domain_ != "KERNEL_VENDOR") {
72 return false;
73 }
74 auto sysEvent = Event::DownCastTo<SysEvent>(event);
75 HandleBBoxEvent(sysEvent);
76 return true;
77 }
78
WaitForLogs(const std::string & logDir)79 void BBoxDetectorPlugin::WaitForLogs(const std::string& logDir)
80 {
81 std::string doneFile = logDir + "/DONE";
82 if (!Tbox::WaitForDoneFile(doneFile, 60)) { // 60s
83 HIVIEW_LOGE("can not find file: %{public}s", doneFile.c_str());
84 }
85 }
86
HandleBBoxEvent(std::shared_ptr<SysEvent> & sysEvent)87 void BBoxDetectorPlugin::HandleBBoxEvent(std::shared_ptr<SysEvent> &sysEvent)
88 {
89 std::string event = sysEvent->GetEventValue("REASON");
90 std::string module = sysEvent->GetEventValue("MODULE");
91 std::string timeStr = sysEvent->GetEventValue("SUB_LOG_PATH");
92 std::string LOG_PATH = sysEvent->GetEventValue("LOG_PATH");
93 std::string name = sysEvent->GetEventValue("name_");
94
95 std::string dynamicPaths = ((!LOG_PATH.empty() && LOG_PATH[LOG_PATH.size() - 1] == '/') ?
96 LOG_PATH : LOG_PATH + '/') + timeStr;
97 #ifndef UNITTEST
98 if (IsEventProcessed(name, "LOG_PATH", dynamicPaths)) {
99 HIVIEW_LOGE("HandleBBoxEvent is processed event path is %{public}s", dynamicPaths.c_str());
100 return;
101 }
102 #endif
103 auto happenTime_ = static_cast<uint64_t>(Tbox::GetHappenTime(StringUtil::GetRleftSubstr(timeStr, "-"),
104 "(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})"));
105 sysEvent->SetEventValue("HAPPEN_TIME", happenTime_);
106
107 WaitForLogs(dynamicPaths);
108 auto eventInfos = SmartParser::Analysis(dynamicPaths, LOGPARSECONFIG, name);
109 Tbox::FilterTrace(eventInfos);
110
111 sysEvent->SetEventValue("FIRST_FRAME", eventInfos["FIRST_FRAME"].empty() ? "/" :
112 StringUtil::EscapeJsonStringValue(eventInfos["FIRST_FRAME"]));
113 sysEvent->SetEventValue("SECOND_FRAME", eventInfos["SECOND_FRAME"].empty() ? "/" :
114 StringUtil::EscapeJsonStringValue(eventInfos["SECOND_FRAME"]));
115 sysEvent->SetEventValue("LAST_FRAME", eventInfos["LAST_FRAME"].empty() ? "/ " :
116 StringUtil::EscapeJsonStringValue(eventInfos["LAST_FRAME"]));
117 sysEvent->SetEventValue("FINGERPRINT", Tbox::CalcFingerPrint(event + module + eventInfos["FIRST_FRAME"] +
118 eventInfos["SECOND_FRAME"] + eventInfos["LAST_FRAME"], 0, FP_BUFFER));
119 sysEvent->SetEventValue("LOG_PATH", dynamicPaths);
120 HIVIEW_LOGI("HandleBBoxEvent event: %{public}s is success ", name.c_str());
121 }
122
StartBootScan()123 void BBoxDetectorPlugin::StartBootScan()
124 {
125 for (auto historyLog : HISTORYLOGLIST) {
126 int num = READ_LINE_NUM;
127 string line;
128
129 if (FileUtil::FileExists(historyLog) && historyLog.find(HISIPATH) != std::string::npos) {
130 hisiHistoryPath = true;
131 }
132
133 ifstream fin(historyLog, ios::ate);
134 while (FileUtil::GetLastLine(fin, line) && num > 0) {
135 num--;
136 std::map<std::string, std::string> historyMap = GetValueFromHistory(line);
137 string name = historyMap["category"];
138 if (name.empty() || name == "NORMALBOOT") {
139 continue;
140 }
141 if (name.find(":") != std::string::npos) {
142 name = StringUtil::GetRleftSubstr(name, ":");
143 }
144 auto time_now = static_cast<int64_t>(TimeUtil::GetMilliseconds());
145 auto time_event = hisiHistoryPath ?
146 static_cast<int64_t>(TimeUtil::StrToTimeStamp(StringUtil::GetMidSubstr(line, "time [", "-"),
147 "%Y%m%d%H%M%S")) * MILLSECONDS :
148 static_cast<int64_t>(TimeUtil::StrToTimeStamp(StringUtil::GetMidSubstr(line, "time[", "-"),
149 "%Y%m%d%H%M%S")) * MILLSECONDS;
150 if (abs(time_now - abs(time_event)) > ONE_DAY ||
151 IsEventProcessed(name, "LOG_PATH", historyMap["dynamicPaths"])) {
152 continue;
153 }
154 auto happenTime_ = GetHappenTime(line, hisiHistoryPath);
155 int res = CheckAndHiSysEventWrite(name, historyMap, happenTime_);
156 HIVIEW_LOGI("BBox write history line is %{public}s write result = %{public}d", line.c_str(), res);
157 }
158 }
159 }
160
IsEventProcessed(const std::string & name,const std::string & key,const std::string & value)161 bool BBoxDetectorPlugin::IsEventProcessed(const std::string& name, const std::string& key, const std::string& value)
162 {
163 auto sysEventQuery = EventStore::SysEventDao::BuildQuery("KERNEL_VENDOR", {name});
164 std::vector<std::string> selections { EventStore::EventCol::TS };
165 EventStore::ResultSet resultSet = sysEventQuery->Select(selections).
166 Where(key, EventStore::Op::EQ, value).Execute();
167 if (resultSet.HasNext()) {
168 return true;
169 }
170
171 return false;
172 }
173
GetHappenTime(std::string & line,bool hisiHistoryPath)174 uint64_t BBoxDetectorPlugin::GetHappenTime(std::string& line, bool hisiHistoryPath)
175 {
176 auto happenTime_ = hisiHistoryPath ?
177 static_cast<uint64_t>(Tbox::GetHappenTime(StringUtil::GetMidSubstr(line, "time [", "-"),
178 "(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})")) :
179 static_cast<uint64_t>(Tbox::GetHappenTime(StringUtil::GetMidSubstr(line, "time[", "-"),
180 "(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})"));
181
182 return happenTime_;
183 }
184
CheckAndHiSysEventWrite(std::string & name,std::map<std::string,std::string> & historyMap,uint64_t & happenTime_)185 int BBoxDetectorPlugin::CheckAndHiSysEventWrite(std::string& name, std::map<std::string, std::string>& historyMap,
186 uint64_t& happenTime_)
187 {
188 int res = HiSysEventWrite(DOMAIN, name, HiSysEvent::EventType::FAULT,
189 "MODULE", historyMap["module"],
190 "REASON", historyMap["reason"],
191 "LOG_PATH", historyMap["logPath"],
192 "SUB_LOG_PATH", historyMap["subLogPath"],
193 "HAPPEN_TIME", happenTime_,
194 "SUMMARY", "bootup_keypoint:" + historyMap["bootup_keypoint"]);
195 if (res == 0 || (res < 0 && name.find("UNKNOWNS") != std::string::npos)) {
196 return res;
197 } else if (res < 0) {
198 name = "UNKNOWNS";
199 CheckAndHiSysEventWrite(name, historyMap, happenTime_);
200 }
201
202 return res;
203 }
204
GetValueFromHistory(std::string & line)205 std::map<std::string, std::string> BBoxDetectorPlugin::GetValueFromHistory(std::string& line)
206 {
207 std::map<std::string, std::string> historyMap = {
208 {"category", hisiHistoryPath ? StringUtil::GetMidSubstr(line, "category [", "]") :
209 StringUtil::GetMidSubstr(line, "category[", "]")},
210 {"module", hisiHistoryPath ? StringUtil::GetMidSubstr(line, "core [", "]") :
211 StringUtil::GetMidSubstr(line, "module[", "]")},
212 {"reason", hisiHistoryPath ? StringUtil::GetMidSubstr(line, "reason [", "]") :
213 StringUtil::GetMidSubstr(line, "event[", "]")},
214 {"bootup_keypoint", hisiHistoryPath ? StringUtil::GetMidSubstr(line, "bootup_keypoint [", "]") :
215 StringUtil::GetMidSubstr(line, "errdesc[", "]")},
216 {"dynamicPaths", hisiHistoryPath ? HISIPATH + StringUtil::GetMidSubstr(line, "time [", "]") :
217 BBOXPATH + StringUtil::GetMidSubstr(line, "time[", "]")},
218 {"logPath", hisiHistoryPath ? HISIPATH : BBOXPATH},
219 {"subLogPath", hisiHistoryPath ? StringUtil::GetMidSubstr(line, "time [", "]") :
220 StringUtil::GetMidSubstr(line, "time[", "]")}
221 };
222
223 return historyMap;
224 }
225 }
226 }
227