• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 "event_logger.h"
16 
17 #include "securec.h"
18 
19 #include <sys/epoll.h>
20 #include <sys/inotify.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <sys/wait.h>
24 #include <unistd.h>
25 
26 #include "common_utils.h"
27 #include "event_source.h"
28 #include "file_util.h"
29 #include "parameter_ex.h"
30 #include "plugin_factory.h"
31 #include "string_util.h"
32 #include "sys_event.h"
33 #include "sys_event_dao.h"
34 
35 #include "event_log_action.h"
36 #include "event_logger_config.h"
37 namespace OHOS {
38 namespace HiviewDFX {
39 REGISTER(EventLogger);
40 DEFINE_LOG_LABEL(0xD002D01, "EventLogger");
41 
OnEvent(std::shared_ptr<Event> & onEvent)42 bool EventLogger::OnEvent(std::shared_ptr<Event> &onEvent)
43 {
44     if (onEvent == nullptr) {
45         HIVIEW_LOGE("event == nullptr");
46         return false;
47     }
48 
49     auto sysEvent = Event::DownCastTo<SysEvent>(onEvent);
50     HIVIEW_LOGI("event coming! id:0x%{public}x, eventName:%{public}s",
51         sysEvent->eventId_, sysEvent->eventName_.c_str());
52     HIVIEW_LOGI("event jsonExtraInfo is %{public}s", sysEvent->jsonExtraInfo_.c_str());
53 
54     EventLoggerConfig::EventLoggerConfigData configOut;
55     auto logConfig = std::make_unique<EventLoggerConfig>();
56     bool existence = logConfig->FindConfigLine(sysEvent->eventId_, sysEvent->eventName_, configOut);
57     if (!existence) {
58         HIVIEW_LOGE("event: id:0x%{public}x, eventName:%{public}s does not exist in the EventLoggerConfig",
59             sysEvent->eventId_,  sysEvent->eventName_.c_str());
60         PostEvent(sysEvent);
61         return false;
62     }
63 
64     sysEvent->eventName_ = configOut.name;
65     sysEvent->SetValue("eventLog_action", configOut.action);
66     sysEvent->SetValue("eventLog_interval", configOut.interval);
67     StartLogCollect(sysEvent);
68 
69     PostEvent(sysEvent);
70     return true;
71 }
72 
StartLogCollect(std::shared_ptr<SysEvent> event)73 void EventLogger::StartLogCollect(std::shared_ptr<SysEvent> event)
74 {
75     HIVIEW_LOGI("event: id:0x%{public}x, eventName:%{public}s called.",
76         event->eventId_,  event->eventName_.c_str());
77     if (!JudgmentRateLimiting(event)) {
78         return;
79     }
80 
81     std::string idStr = event->eventName_.empty() ? std::to_string(event->eventId_) : event->eventName_;
82     auto timeStr = std::to_string(event->happenTime_);
83     uint64_t logTime = std::time(nullptr);
84     std::string logFile = idStr + "-" + GetFormatTime(logTime) + ".log";
85 
86     int fd = logStore_->CreateLogFile(logFile);
87     if (fd < 0) {
88         HIVIEW_LOGE("create log file %{public}s failed, %{public}d", logFile.c_str(), fd);
89         return;
90     }
91     WriteCommonHead(fd, event);
92     auto eventLogAction = std::make_unique<EventLogAction>(fd, event);
93     eventLogAction->Init();
94     eventLogAction->CaptureAction();
95     close(fd);
96     UpdateDB(event, logFile);
97 }
98 
PostEvent(std::shared_ptr<SysEvent> event)99 bool EventLogger::PostEvent(std::shared_ptr<SysEvent> event)
100 {
101     auto eventPtr = std::make_shared<SysEvent>(*(event.get()));
102     GetHiviewContext()->PostUnorderedEvent(shared_from_this(), eventPtr);
103     return true;
104 }
105 
WriteCommonHead(int fd,std::shared_ptr<SysEvent> event)106 bool EventLogger::WriteCommonHead(int fd, std::shared_ptr<SysEvent> event)
107 {
108     long pid = event->GetEventIntValue("PID");
109     pid = pid ? pid : event->GetPid();
110     long uid = event->GetEventIntValue("UID");
111     uid = uid ? uid : event->GetUid();
112     FileUtil::SaveStringToFd(fd, event->eventName_ + "\n");
113     std::string str = "PID = " + std::to_string(pid);
114     FileUtil::SaveStringToFd(fd, str + "\n");
115     str = "UID = " + std::to_string(uid);
116     FileUtil::SaveStringToFd(fd, str + "\n");
117     event->GetEventValue("PACKAGE_NAME");
118     event->GetEventValue("PROCESS_NAME");
119     event->GetEventValue("PLATFORM");
120     event->SetEventValue("MSG", StringUtil::ReplaceStr(event->GetEventValue("MSG"), "\\n", "\n"));
121     event->GetEventValue("MSG");
122 
123     std::map<std::string, std::string> eventPairs = event->GetKeyValuePairs();
124     HIVIEW_LOGD("KeyValuePairs num is %{public}d", eventPairs.size());
125     for (auto tmp : eventPairs) {
126         HIVIEW_LOGD("KeyValuePairs %{public}s , %{public}s", tmp.first.c_str(), tmp.second.c_str());
127         std::string str = tmp.first + " = " + tmp.second + "\n";
128         FileUtil::SaveStringToFd(fd, str);
129     }
130     return true;
131 }
132 
JudgmentRateLimiting(std::shared_ptr<SysEvent> event)133 bool EventLogger::JudgmentRateLimiting(std::shared_ptr<SysEvent> event)
134 {
135     auto interval = event->GetIntValue("eventLog_interval");
136     if (interval == 0) {
137         return true;
138     }
139 
140     long pid = event->GetEventIntValue("PID");
141     pid = pid ? pid : event->GetPid();
142     std::string eventName = event->eventName_;
143     std::string eventPid = std::to_string(pid);
144 
145     std::time_t now = std::time(0);
146     for (auto it = eventTagTime_.begin(); it != eventTagTime_.end();) {
147         if (it->first.find(eventName) != it->first.npos) {
148             if ((now - it->second) >= interval) {
149                 it = eventTagTime_.erase(it);
150                 continue;
151             }
152         }
153         ++it;
154     }
155 
156     std::string tagTimeName = eventName + eventPid;
157     auto it = eventTagTime_.find(tagTimeName);
158     if (it != eventTagTime_.end()) {
159         if ((now - it->second) < interval) {
160             HIVIEW_LOGE("event: id:0x%{public}d, eventName:%{public}s pid:%{public}s. \
161                 interval:%{public}ld There's not enough interval",
162                 event->eventId_, eventName.c_str(), eventPid.c_str(), interval);
163             return false;
164         }
165     }
166     eventTagTime_[tagTimeName] = now;
167     HIVIEW_LOGI("event: id:0x%{public}d, eventName:%{public}s pid:%{public}s. \
168         interval:%{public}ld normal interval",
169         event->eventId_, eventName.c_str(), eventPid.c_str(), interval);
170     return true;
171 }
172 
GetFormatTime(uint64_t timestamp) const173 std::string EventLogger::GetFormatTime(uint64_t timestamp) const
174 {
175     struct tm tm;
176     time_t ts;
177     /* 20: the length of 'YYYYmmddHHMMSS' */
178     int strLen = 20;
179     ts = timestamp;
180     localtime_r(&ts, &tm);
181     char buf[strLen];
182 
183     (void)memset_s(buf, strLen, 0, strLen);
184     strftime(buf, strLen - 1, "%Y%m%d%H%M%S", &tm);
185     return std::string(buf, strlen(buf));
186 }
187 
UpdateDB(std::shared_ptr<SysEvent> event,std::string logFile)188 bool EventLogger::UpdateDB(std::shared_ptr<SysEvent> event, std::string logFile)
189 {
190     HIVIEW_LOGI("call");
191     EventStore::SysEventQuery eventQuery = EventStore::SysEventDao::BuildQuery();
192     EventStore::ResultSet set = eventQuery.Select( {EventStore::EventCol::TS} )
193         .Where(EventStore::EventCol::TS, EventStore::Op::EQ, static_cast<int64_t>(event->happenTime_))
194         .And(EventStore::EventCol::DOMAIN, EventStore::Op::EQ, event->domain_)
195         .And(EventStore::EventCol::NAME, EventStore::Op::EQ, event->eventName_)
196         .Execute();
197     if (set.GetErrCode() != 0) {
198         HIVIEW_LOGE("failed to get db, error:%{public}d.", set.GetErrCode());
199         return false;
200     }
201     if (set.HasNext()) {
202         auto record = set.Next();
203         if (record->GetSeq() == event->GetSeq()) {
204             HIVIEW_LOGI("Seq match success.");
205             if (logFile == "nolog") {
206                 HIVIEW_LOGI("set info_ with nolog into db.");
207                 event->SetEventValue(EventStore::EventCol::INFO, "nolog", false);
208             } else {
209                 auto logPath = R"~(logPath:)~" + LOGGER_EVENT_LOG_PATH  + "/" + logFile;
210                 event->SetEventValue(EventStore::EventCol::INFO, logPath, true);
211             }
212 
213             auto retCode = EventStore::SysEventDao::Update(event, false);
214             if (retCode == 0) {
215                 return true;
216             }
217         }
218     }
219     HIVIEW_LOGE("eventLog LogPath update to DB failed!");
220     return false;
221 }
222 
OnLoad()223 void EventLogger::OnLoad()
224 {
225     HIVIEW_LOGI("EventLogger OnLoad.");
226     SetName("EventLogger");
227     SetVersion("1.0");
228     logStore_->SetMaxSize(MAX_FOLDER_SIZE);
229     logStore_->SetMinKeepingFileNumber(MAX_FILE_NUM);
230     logStore_->Init();
231     std::shared_ptr<EventLoop> tmp = GetWorkLoop();
232     tmp->AddFileDescriptorEventCallback("EventLoggerFd",
233         std::static_pointer_cast<EventLogger>(shared_from_this()));
234 }
235 
OnUnload()236 void EventLogger::OnUnload()
237 {
238     HIVIEW_LOGD("called");
239 }
240 
CanProcessEvent(std::shared_ptr<Event> event)241 bool EventLogger::CanProcessEvent(std::shared_ptr<Event> event)
242 {
243     if (event == nullptr) {
244         return false;
245     }
246     if (event->eventId_ > EVENT_MAX_ID) {
247         return false;
248     }
249     return true;
250 }
251 
CreateAndPublishEvent(std::string & dirPath,std::string & fileName)252 void EventLogger::CreateAndPublishEvent(std::string& dirPath, std::string& fileName)
253 {
254     HIVIEW_LOGD("called");
255     std::shared_ptr<Plugin> sysEventSourcePlugin = GetHiviewContext()->GetPluginByName("SysEventSource");
256     std::shared_ptr<EventSource> sysEventSource = std::static_pointer_cast<EventSource>(sysEventSourcePlugin);
257     if (dirPath == MONITOR_STACK_LOG_PATH) {
258         uint8_t count = 0;
259         for (auto& i : MONITOR_STACK_FLIE_NAME) {
260             if (fileName.find(i) != fileName.npos) {
261                 ++count;
262                 break;
263             }
264         }
265 
266         if (count == 0) {
267             return;
268         }
269 
270         SysEventCreator eventCreator("RELIABILITY", "STACK", SysEventCreator::FAULT);
271         std::shared_ptr<SysEvent> event = std::make_shared<SysEvent>("eventLogger",
272             static_cast<PipelineEventProducer *>(sysEventSource.get()), eventCreator);
273         event->domain_ = "RELIABILITY";
274         event->SetEventValue("domain_", "RELIABILITY");
275         event->eventName_ = "STACK";
276         event->SetEventValue("name_", "STACK");
277 
278         std::string logPath = dirPath + "/" + fileName;
279         if (!FileUtil::FileExists(logPath)) {
280             HIVIEW_LOGE("file %{public}s not exist", logPath.c_str());
281         }
282         std::string tmpStr = R"~(logPath:)~" + logPath;
283         event->SetEventValue(EventStore::EventCol::INFO, tmpStr);
284         sysEventSource->PublishPipelineEvent(event);
285     }
286 }
287 
OnFileDescriptorEvent(int fd,int type)288 bool EventLogger::OnFileDescriptorEvent(int fd, int type)
289 {
290     HIVIEW_LOGD("fd:%{public}d, type:%{public}d, inotifyFd_:%{public}d.\n", fd, type, inotifyFd_);
291     const int bufSize = 2048;
292     char buffer[bufSize] = {0};
293     char *offset = nullptr;
294     struct inotify_event *event = nullptr;
295     if (inotifyFd_ < 0) {
296         HIVIEW_LOGE("Invalid inotify fd:%{public}d", inotifyFd_);
297         return false;
298     }
299     int len = read(inotifyFd_, buffer, bufSize);
300     if (len < 0) {
301         HIVIEW_LOGE("failed to read event");
302         return false;
303     }
304 
305     offset = buffer;
306     event = (struct inotify_event *)buffer;
307     while ((reinterpret_cast<char *>(event) - buffer) < len) {
308         const auto& it = fileMap_.find(event->wd);
309         if (it == fileMap_.end()) {
310             continue;
311         }
312 
313         if (event->name[event->len - 1] != '\0') {
314             event->name[event->len - 1] = '\0';
315         }
316         std::string fileName = std::string(event->name);
317         CreateAndPublishEvent(it->second, fileName);
318 
319         int tmpLen = sizeof(struct inotify_event) + event->len;
320         event = (struct inotify_event *)(offset + tmpLen);
321         offset += tmpLen;
322     }
323     return true;
324 }
325 
GetPollFd()326 int32_t EventLogger::GetPollFd()
327 {
328     HIVIEW_LOGD("call");
329     if (inotifyFd_ > 0) {
330         return inotifyFd_;
331     }
332 
333     inotifyFd_ = inotify_init();
334     if (inotifyFd_ == -1) {
335         HIVIEW_LOGE("failed to init inotify: %s.\n", strerror(errno));
336         return -1;
337     }
338 
339     for (const std::string& i : MONITOR_LOG_PATH) {
340         int wd = inotify_add_watch(inotifyFd_, i.c_str(), IN_CLOSE_WRITE | IN_MOVED_TO);
341         if (wd < 0) {
342             HIVIEW_LOGE("failed to add watch entry : %s(%s).\n", strerror(errno), i.c_str());
343             continue;
344         }
345         fileMap_[wd] = i;
346     }
347 
348     if (fileMap_.empty()) {
349         close(inotifyFd_);
350         inotifyFd_ = -1;
351     }
352     return inotifyFd_;
353 }
354 
GetPollType()355 int32_t EventLogger::GetPollType()
356 {
357     return EPOLLIN;
358 }
359 } // namesapce HiviewDFX
360 } // namespace OHOS
361