• 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_log_task.h"
16 
17 #include <unistd.h>
18 
19 #include "securec.h"
20 
21 #include "common_utils.h"
22 #include "logger.h"
23 #include "string_util.h"
24 
25 #include "binder_catcher.h"
26 #include "open_stacktrace_catcher.h"
27 #include "peer_binder_catcher.h"
28 #include "command_catcher.h"
29 namespace OHOS {
30 namespace HiviewDFX {
31 namespace {
32 const std::string SYSTEM_STACK[] = {
33     "foundation",
34 };
35 }
36 DEFINE_LOG_LABEL(0xD002D01, "EventLogger-EventLogTask");
EventLogTask(int fd,std::shared_ptr<SysEvent> event)37 EventLogTask::EventLogTask(int fd, std::shared_ptr<SysEvent> event)
38     : targetFd_(fd),
39       event_(event),
40       maxLogSize_(DEFAULT_LOG_SIZE),
41       taskLogSize_(0),
42       status_(Status::TASK_RUNNABLE)
43 {
44     cmdCatcher_ = nullptr;
45     captureList_.insert(std::pair<std::string, capture>("s", std::bind(&EventLogTask::AppStackCapture, this)));
46     captureList_.insert(std::pair<std::string, capture>("S", std::bind(&EventLogTask::SystemStackCapture, this)));
47     captureList_.insert(std::pair<std::string, capture>("b", std::bind(&EventLogTask::BinderLogCapture, this)));
48     captureList_.insert(std::pair<std::string, capture>("cmd:c", std::bind(&EventLogTask::CpuUsageCapture, this)));
49     captureList_.insert(std::pair<std::string, capture>("cmd:m", std::bind(&EventLogTask::MemoryUsageCapture, this)));
50     captureList_.insert(std::pair<std::string, capture>("cmd:w", std::bind(&EventLogTask::WMSUsageCapture, this)));
51     captureList_.insert(std::pair<std::string, capture>("cmd:a", std::bind(&EventLogTask::AMSUsageCapture, this)));
52     captureList_.insert(std::pair<std::string, capture>("cmd:p", std::bind(&EventLogTask::PMSUsageCapture, this)));
53 }
54 
AddLog(const std::string & cmd)55 void EventLogTask::AddLog(const std::string &cmd)
56 {
57     if (tasks_.size() == 0) {
58         status_ = Status::TASK_RUNNABLE;
59     }
60 
61     if (captureList_.find(cmd) != captureList_.end()) {
62         captureList_[cmd]();
63         return;
64     }
65     PeerBinderCapture(cmd);
66 }
67 
StartCompose()68 EventLogTask::Status EventLogTask::StartCompose()
69 {
70     // nothing to do, return success
71     if (status_ != Status::TASK_RUNNABLE) {
72         return status_;
73     }
74     status_ = Status::TASK_RUNNING;
75     // nothing to do, return success
76     if (tasks_.size() == 0) {
77         return Status::TASK_SUCCESS;
78     }
79 
80     auto dupedFd = dup(targetFd_);
81     uint32_t catcherIndex = 0;
82     for (auto& catcher : tasks_) {
83         catcherIndex++;
84         if (dupedFd < 0) {
85             status_ = Status::TASK_FAIL;
86             AddStopReason(targetFd_, catcher, "Fail to dup file descriptor, exit!");
87             return TASK_FAIL;
88         }
89 
90         AddSeparator(dupedFd, catcher);
91         int curLogSize = catcher->Catch(dupedFd);
92         if (ShouldStopLogTask(dupedFd, catcherIndex, curLogSize, catcher)) {
93             break;
94         }
95     }
96     close(dupedFd);
97 
98     if (status_ == Status::TASK_RUNNING) {
99         status_ = Status::TASK_SUCCESS;
100     }
101     return status_;
102 }
103 
ShouldStopLogTask(int fd,uint32_t curTaskIndex,int curLogSize,std::shared_ptr<EventLogCatcher> catcher)104 bool EventLogTask::ShouldStopLogTask(int fd, uint32_t curTaskIndex, int curLogSize,
105     std::shared_ptr<EventLogCatcher> catcher)
106 {
107     if (status_ == Status::TASK_TIMEOUT) {
108         HIVIEW_LOGE("Break Log task, parent has timeout.");
109         return true;
110     }
111 
112     bool encounterErr = (curLogSize < 0);
113     bool hasFinished = (curTaskIndex == tasks_.size());
114     if (!encounterErr) {
115         taskLogSize_ += curLogSize;
116     }
117 
118     if (taskLogSize_ > maxLogSize_ && !hasFinished) {
119         AddStopReason(fd, catcher, "Exceed max log size");
120         status_ = Status::TASK_EXCEED_SIZE;
121         return true;
122     }
123 
124     if (encounterErr) {
125         AddStopReason(fd, catcher, "Log catcher not successful");
126         HIVIEW_LOGE("catcher %{public}s, Log catcher not successful", catcher->GetDescription().c_str());
127     }
128     return false;
129 }
130 
AddStopReason(int fd,std::shared_ptr<EventLogCatcher> catcher,const std::string & reason)131 void EventLogTask::AddStopReason(int fd, std::shared_ptr<EventLogCatcher> catcher, const std::string& reason)
132 {
133     char buf[BUF_SIZE_512] = {0};
134     int ret = -1;
135     if (catcher != nullptr) {
136         catcher->Stop();
137         // sleep 1s for syncing log to the fd, then we could append failure reason ?
138         sleep(1);
139         std::string summary = catcher->GetDescription();
140         ret = snprintf_s(buf, BUF_SIZE_512, BUF_SIZE_512 - 1, "\nTask stopped when running catcher:%s, Reason:%s \n",
141                          summary.c_str(), reason.c_str());
142     } else {
143         ret = snprintf_s(buf, BUF_SIZE_512, BUF_SIZE_512 - 1, "\nTask stopped, Reason:%s \n", reason.c_str());
144     }
145 
146     if (ret > 0) {
147         write(fd, buf, strnlen(buf, BUF_SIZE_512));
148         fsync(fd);
149     }
150 }
151 
AddSeparator(int fd,std::shared_ptr<EventLogCatcher> catcher) const152 void EventLogTask::AddSeparator(int fd, std::shared_ptr<EventLogCatcher> catcher) const
153 {
154     char buf[BUF_SIZE_512] = {0};
155     std::string summary = catcher->GetDescription();
156     if (summary.empty()) {
157         HIVIEW_LOGE("summary.empty() catcher is %{public}s", catcher->GetName().c_str());
158         return;
159     }
160 
161     int ret = snprintf_s(buf, BUF_SIZE_512, BUF_SIZE_512 - 1, "\n%s:\n", summary.c_str());
162     if (ret > 0) {
163         write(fd, buf, strnlen(buf, BUF_SIZE_512));
164         fsync(fd);
165     }
166 }
167 
GetTaskStatus() const168 EventLogTask::Status EventLogTask::GetTaskStatus() const
169 {
170     return status_;
171 }
172 
GetLogSize() const173 long EventLogTask::GetLogSize() const
174 {
175     return taskLogSize_;
176 }
177 
GetCmdCatcher()178 std::shared_ptr<CommandCatcher> EventLogTask::GetCmdCatcher()
179 {
180     if (cmdCatcher_ != nullptr) {
181         return cmdCatcher_;
182     }
183 
184     auto capture = std::make_shared<CommandCatcher>();
185     int pid = event_->GetEventIntValue("PID");
186     pid = pid ? pid : event_->GetPid();
187     capture->Initialize(event_->GetEventValue("PACKAGE_NAME"), pid, 0);
188     tasks_.push_back(capture);
189     cmdCatcher_ = capture;
190     return cmdCatcher_;
191 }
192 
AppStackCapture()193 void EventLogTask::AppStackCapture()
194 {
195     auto capture = std::make_shared<OpenStacktraceCatcher>();
196     int pid = event_->GetEventIntValue("PID");
197     pid = pid ? pid : event_->GetPid();
198     capture->Initialize(event_->GetEventValue("PACKAGE_NAME"), pid, 0);
199     tasks_.push_back(capture);
200 }
201 
SystemStackCapture()202 void EventLogTask::SystemStackCapture()
203 {
204     for (auto packageName : SYSTEM_STACK) {
205         auto capture = std::make_shared<OpenStacktraceCatcher>();
206         capture->Initialize(packageName, 0, 0);
207         tasks_.push_back(capture);
208     }
209 }
210 
BinderLogCapture()211 void EventLogTask::BinderLogCapture()
212 {
213     auto capture = std::make_shared<BinderCatcher>();
214     capture->Initialize("", 0, 0);
215     tasks_.push_back(capture);
216 }
217 
PeerBinderCapture(const std::string & cmd)218 bool EventLogTask::PeerBinderCapture(const std::string &cmd)
219 {
220     auto find = cmd.find("pb");
221     if (find == cmd.npos) {
222         return false;
223     }
224 
225     std::vector<std::string> cmdList;
226     StringUtil::SplitStr(cmd, ":", cmdList, true);
227     if (cmdList.front() != "pb") {
228         return false;
229     }
230 
231     int layer = 0;
232     int pid = event_->GetEventIntValue("PID");
233     pid = pid ? pid : event_->GetPid();
234     StringUtil::StrToInt(cmdList.back(), layer);
235     HIVIEW_LOGI("pid:%{public}d, value:%{public}d ", pid, layer);
236 
237     auto capture = std::make_shared<PeerBinderCatcher>();
238     capture->Initialize("", pid, layer);
239     capture->Init(event_, "");
240     tasks_.push_back(capture);
241 
242     return true;
243 }
244 
WMSUsageCapture()245 void EventLogTask::WMSUsageCapture()
246 {
247     auto cmdCatcher = GetCmdCatcher();
248     std::vector<std::string> cmd = {"hidumper", "-s", "WindowManagerService", "-a", "-a"};
249     cmdCatcher->AddCmd(cmd);
250 }
251 
AMSUsageCapture()252 void EventLogTask::AMSUsageCapture()
253 {
254     auto cmdCatcher = GetCmdCatcher();
255     std::vector<std::string> cmd = {"hidumper", "-s", "AbilityManagerService", "-a", "-a"};
256     cmdCatcher->AddCmd(cmd);
257 }
258 
CpuUsageCapture()259 void EventLogTask::CpuUsageCapture()
260 {
261     auto cmdCatcher = GetCmdCatcher();
262     std::vector<std::string> cmd = {"hidumper", "--cpuusage"};
263     cmdCatcher->AddCmd(cmd);
264 }
265 
MemoryUsageCapture()266 void EventLogTask::MemoryUsageCapture()
267 {
268     auto cmdCatcher = GetCmdCatcher();
269     std::vector<std::string> cmd = {"hidumper", "--mem", std::to_string(cmdCatcher->GetPid())};
270     cmdCatcher->AddCmd(cmd);
271 }
272 
PMSUsageCapture()273 void EventLogTask::PMSUsageCapture()
274 {
275     auto cmdCatcher = GetCmdCatcher();
276     std::vector<std::string> cmd = {"hidumper", "-s", "PowerManagerService", "-a", "-s"};
277     cmdCatcher->AddCmd(cmd);
278     std::vector<std::string> cmd1 = {"hidumper", "-s", "DisplayPowerManagerService"};
279     cmdCatcher->AddCmd(cmd1);
280 }
281 } // namespace HiviewDFX
282 } // namespace OHOS