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