1 /*
2 * Copyright (c) 2021-2023 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
16 #include "hiview_service.h"
17
18 #include <cinttypes>
19 #include <cstdio>
20 #include <fcntl.h>
21 #include <sys/sendfile.h>
22 #include <sys/stat.h>
23
24 #include "file_util.h"
25 #include "hiview_platform.h"
26 #include "hiview_service_adapter.h"
27 #include "logger.h"
28 #include "trace_manager.h"
29
30 namespace OHOS {
31 namespace HiviewDFX {
32 DEFINE_LOG_TAG("HiView-Service");
33 namespace {
34 constexpr int MIN_SUPPORT_CMD_SIZE = 1;
35 constexpr int32_t ERR_DEFAULT = -1;
36 }
37
HiviewService()38 HiviewService::HiviewService()
39 {
40 traceCollector_ = UCollectUtil::TraceCollector::Create();
41 }
42
StartService()43 void HiviewService::StartService()
44 {
45 std::unique_ptr<HiviewServiceAdapter> adapter = std::make_unique<HiviewServiceAdapter>();
46 adapter->StartService(this);
47 }
48
DumpRequestDispatcher(int fd,const std::vector<std::string> & cmds)49 void HiviewService::DumpRequestDispatcher(int fd, const std::vector<std::string> &cmds)
50 {
51 if (fd < 0) {
52 HIVIEW_LOGW("invalid fd.");
53 return;
54 }
55
56 if (cmds.size() == 0) {
57 DumpLoadedPluginInfo(fd);
58 return;
59 }
60
61 // hidumper hiviewdfx -d
62 if ((cmds.size() == MIN_SUPPORT_CMD_SIZE) && (cmds[0] == "-d")) {
63 DumpDetailedInfo(fd);
64 return;
65 }
66
67 // hidumper hiviewdfx -p
68 if ((cmds.size() >= MIN_SUPPORT_CMD_SIZE) && (cmds[0] == "-p")) {
69 DumpPluginInfo(fd, cmds);
70 return;
71 }
72
73 PrintUsage(fd);
74 return;
75 }
76
DumpPluginInfo(int fd,const std::vector<std::string> & cmds) const77 void HiviewService::DumpPluginInfo(int fd, const std::vector<std::string> &cmds) const
78 {
79 std::string pluginName = "";
80 const int pluginNameSize = 2;
81 const int pluginNamePos = 1;
82 std::vector<std::string> newCmd;
83 if (cmds.size() >= pluginNameSize) {
84 pluginName = cmds[pluginNamePos];
85 newCmd.insert(newCmd.begin(), cmds.begin() + pluginNamePos, cmds.end());
86 }
87
88 auto &platform = HiviewPlatform::GetInstance();
89 auto const &curPluginMap = platform.GetPluginMap();
90 for (auto const &entry : curPluginMap) {
91 auto const &pluginPtr = entry.second;
92 if (pluginPtr == nullptr) {
93 continue;
94 }
95
96 if (pluginName.empty()) {
97 pluginPtr->Dump(fd, newCmd);
98 continue;
99 }
100
101 if (pluginPtr->GetName() == pluginName) {
102 pluginPtr->Dump(fd, newCmd);
103 break;
104 }
105 }
106 }
107
DumpDetailedInfo(int fd)108 void HiviewService::DumpDetailedInfo(int fd)
109 {
110 if (parser_ != nullptr) {
111 parser_.reset();
112 }
113 DumpLoadedPluginInfo(fd);
114 parser_ = std::make_unique<AuditLogParser>();
115 parser_->StartParse();
116 std::string timeScope = parser_->GetAuditLogTimeScope();
117 dprintf(fd, "%s\n", timeScope.c_str());
118 DumpPluginUsageInfo(fd);
119 DumpThreadUsageInfo(fd);
120 DumpPipelineUsageInfo(fd);
121 parser_.reset();
122 }
123
DumpLoadedPluginInfo(int fd) const124 void HiviewService::DumpLoadedPluginInfo(int fd) const
125 {
126 auto &platform = HiviewPlatform::GetInstance();
127 auto const &curPluginMap = platform.GetPluginMap();
128 dprintf(fd, "Current Loaded Plugins:\n");
129 for (auto const &entry : curPluginMap) {
130 auto const &pluginName = entry.first;
131 if (entry.second != nullptr) {
132 dprintf(fd, "PluginName:%s ", pluginName.c_str());
133 dprintf(fd, "IsDynamic:%s ",
134 (entry.second->GetType() == Plugin::PluginType::DYNAMIC) ? "True" : "False");
135 dprintf(fd, "Version:%s ", (entry.second->GetVersion().c_str()));
136 dprintf(fd,
137 "ThreadName:%s\n",
138 ((entry.second->GetWorkLoop() == nullptr) ? "Null" : entry.second->GetWorkLoop()->GetName().c_str()));
139 }
140 }
141 dprintf(fd, "Dump Plugin Loaded Info Done.\n\n");
142 }
143
DumpPluginUsageInfo(int fd)144 void HiviewService::DumpPluginUsageInfo(int fd)
145 {
146 auto &platform = HiviewPlatform::GetInstance();
147 auto const &curPluginMap = platform.GetPluginMap();
148 for (auto const &entry : curPluginMap) {
149 auto pluginName = entry.first;
150 if (entry.second != nullptr) {
151 DumpPluginUsageInfo(fd, pluginName);
152 }
153 }
154 }
155
DumpPluginUsageInfo(int fd,const std::string & pluginName) const156 void HiviewService::DumpPluginUsageInfo(int fd, const std::string &pluginName) const
157 {
158 if (parser_ == nullptr) {
159 return;
160 }
161 auto logList = parser_->GetPluginSummary(pluginName);
162 dprintf(fd, "Following events processed By Plugin %s:\n", pluginName.c_str());
163 for (auto &log : logList) {
164 dprintf(fd, " %s.\n", log.c_str());
165 }
166 dprintf(fd, "Dump Plugin Usage Done.\n\n");
167 }
168
DumpThreadUsageInfo(int fd) const169 void HiviewService::DumpThreadUsageInfo(int fd) const
170 {
171 auto &platform = HiviewPlatform::GetInstance();
172 auto const &curThreadMap = platform.GetWorkLoopMap();
173 dprintf(fd, "Start Dump ThreadInfo:\n");
174 for (auto const &entry : curThreadMap) {
175 if (entry.second != nullptr) {
176 std::string name = entry.second->GetName();
177 DumpThreadUsageInfo(fd, name);
178 }
179 }
180 dprintf(fd, "Dump ThreadInfo Done.\n\n");
181 }
182
DumpThreadUsageInfo(int fd,const std::string & threadName) const183 void HiviewService::DumpThreadUsageInfo(int fd, const std::string &threadName) const
184 {
185 if (parser_ == nullptr) {
186 return;
187 }
188 auto logList = parser_->GetThreadSummary(threadName);
189 dprintf(fd, "Following events processed on Thread %s:\n", threadName.c_str());
190 for (auto &log : logList) {
191 dprintf(fd, " %s.\n", log.c_str());
192 }
193 }
194
DumpPipelineUsageInfo(int fd) const195 void HiviewService::DumpPipelineUsageInfo(int fd) const
196 {
197 auto &platform = HiviewPlatform::GetInstance();
198 auto const &curPipelineMap = platform.GetPipelineMap();
199 dprintf(fd, "Start Dump Pipeline Info:\n");
200 for (auto const &entry : curPipelineMap) {
201 auto pipeline = entry.first;
202 DumpPipelineUsageInfo(fd, pipeline);
203 }
204 }
205
DumpPipelineUsageInfo(int fd,const std::string & pipelineName) const206 void HiviewService::DumpPipelineUsageInfo(int fd, const std::string &pipelineName) const
207 {
208 if (parser_ == nullptr) {
209 return;
210 }
211 auto logList = parser_->GetPipelineSummary(pipelineName);
212 dprintf(fd, "Following events processed on Pipeline %s:\n", pipelineName.c_str());
213 for (auto &log : logList) {
214 dprintf(fd, " %s.\n", log.c_str());
215 }
216 dprintf(fd, "Dump Pipeline Usage Info Done.\n\n");
217 }
218
PrintUsage(int fd) const219 void HiviewService::PrintUsage(int fd) const
220 {
221 dprintf(fd, "Hiview Plugin Platform dump options:\n");
222 dprintf(fd, "hidumper hiviewdfx [-d(etail)]\n");
223 dprintf(fd, " [-p(lugin) pluginName]\n");
224 }
225
CopyFile(const std::string & srcFilePath,const std::string & destFilePath)226 int32_t HiviewService::CopyFile(const std::string& srcFilePath, const std::string& destFilePath)
227 {
228 int srcFd = open(srcFilePath.c_str(), O_RDONLY);
229 if (srcFd == -1) {
230 HIVIEW_LOGE("failed to open source file, src=%{public}s", srcFilePath.c_str());
231 return ERR_DEFAULT;
232 }
233 struct stat st{};
234 if (fstat(srcFd, &st) == -1) {
235 HIVIEW_LOGE("failed to stat file.");
236 close(srcFd);
237 return ERR_DEFAULT;
238 }
239 int destFd = open(destFilePath.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH);
240 if (destFd == -1) {
241 HIVIEW_LOGE("failed to open destination file, des=%{public}s", destFilePath.c_str());
242 close(srcFd);
243 return ERR_DEFAULT;
244 }
245 off_t offset = 0;
246 int cycleNum = 0;
247 while (offset < st.st_size) {
248 size_t count = static_cast<size_t>((st.st_size - offset) > SSIZE_MAX ? SSIZE_MAX : st.st_size - offset);
249 ssize_t ret = sendfile(destFd, srcFd, &offset, count);
250 if (cycleNum > 0) {
251 HIVIEW_LOGI("sendfile cycle num:%{public}d, ret:%{public}zd, offset:%{public}lld, size:%{public}lld",
252 cycleNum, ret, static_cast<long long>(offset), static_cast<long long>(st.st_size));
253 }
254 cycleNum++;
255 if (ret < 0 || offset > st.st_size) {
256 HIVIEW_LOGE("sendfile fail, ret:%{public}zd, offset:%{public}lld, size:%{public}lld",
257 ret, static_cast<long long>(offset), static_cast<long long>(st.st_size));
258 close(srcFd);
259 close(destFd);
260 return ERR_DEFAULT;
261 }
262 }
263 close(srcFd);
264 close(destFd);
265 return 0;
266 }
267
Copy(const std::string & srcFilePath,const std::string & destFilePath)268 int32_t HiviewService::Copy(const std::string& srcFilePath, const std::string& destFilePath)
269 {
270 return CopyFile(srcFilePath, destFilePath);
271 }
272
Move(const std::string & srcFilePath,const std::string & destFilePath)273 int32_t HiviewService::Move(const std::string& srcFilePath, const std::string& destFilePath)
274 {
275 int copyResult = CopyFile(srcFilePath, destFilePath);
276 if (copyResult != 0) {
277 HIVIEW_LOGW("copy file failed, result: %{public}d", copyResult);
278 return copyResult;
279 }
280 bool result = FileUtil::RemoveFile(srcFilePath);
281 HIVIEW_LOGI("move file, delete src result: %{public}d", result);
282 if (!result) {
283 bool destResult = FileUtil::RemoveFile(destFilePath);
284 HIVIEW_LOGI("move file, delete dest result: %{public}d", destResult);
285 return ERR_DEFAULT;
286 }
287 return 0;
288 }
289
Remove(const std::string & filePath)290 int32_t HiviewService::Remove(const std::string& filePath)
291 {
292 bool result = FileUtil::RemoveFile(filePath);
293 HIVIEW_LOGI("remove file, result:%{public}d", result);
294 return 0;
295 }
296
OpenSnapshotTrace(const std::vector<std::string> & tagGroups)297 CollectResult<int32_t> HiviewService::OpenSnapshotTrace(const std::vector<std::string>& tagGroups)
298 {
299 TraceManager manager;
300 int32_t openRet = manager.OpenSnapshotTrace(tagGroups);
301 if (openRet != UCollect::UcError::SUCCESS) {
302 HIVIEW_LOGW("failed to open trace in snapshort mode.");
303 }
304 CollectResult<int32_t> ret;
305 ret.retCode = UCollect::UcError(openRet);
306 return ret;
307 }
308
DumpSnapshotTrace(UCollectUtil::TraceCollector::Caller caller)309 CollectResult<std::vector<std::string>> HiviewService::DumpSnapshotTrace(UCollectUtil::TraceCollector::Caller caller)
310 {
311 HIVIEW_LOGI("caller[%{public}d] dump trace in snapshot mode.", static_cast<int32_t>(caller));
312 CollectResult<std::vector<std::string>> dumpRet = traceCollector_->DumpTrace(caller);
313 if (dumpRet.retCode != UCollect::UcError::SUCCESS) {
314 HIVIEW_LOGE("failed to dump the trace in snapshort mode.");
315 }
316 return dumpRet;
317 }
318
OpenRecordingTrace(const std::string & tags)319 CollectResult<int32_t> HiviewService::OpenRecordingTrace(const std::string& tags)
320 {
321 TraceManager manager;
322 int32_t openRet = manager.OpenRecordingTrace(tags);
323 if (openRet != UCollect::UcError::SUCCESS) {
324 HIVIEW_LOGW("failed to open trace in recording mode.");
325 }
326 CollectResult<int32_t> ret;
327 ret.retCode = UCollect::UcError(openRet);
328 return ret;
329 }
330
RecordingTraceOn()331 CollectResult<int32_t> HiviewService::RecordingTraceOn()
332 {
333 CollectResult<int32_t> traceOnRet = traceCollector_->TraceOn();
334 if (traceOnRet.retCode != UCollect::UcError::SUCCESS) {
335 HIVIEW_LOGE("failed to turn on the trace in recording mode.");
336 }
337 return traceOnRet;
338 }
339
RecordingTraceOff()340 CollectResult<std::vector<std::string>> HiviewService::RecordingTraceOff()
341 {
342 CollectResult<std::vector<std::string>> traceOffRet = traceCollector_->TraceOff();
343 if (traceOffRet.retCode != UCollect::UcError::SUCCESS) {
344 HIVIEW_LOGE("failed to turn off the trace in recording mode.");
345 return traceOffRet;
346 }
347 TraceManager manager;
348 auto recoverRet = manager.RecoverTrace();
349 if (recoverRet != UCollect::UcError::SUCCESS) {
350 HIVIEW_LOGE("failed to recover the trace after trace off in recording mode.");
351 traceOffRet.retCode = UCollect::UcError::UNSUPPORT;
352 }
353 return traceOffRet;
354 }
355
CloseTrace()356 CollectResult<int32_t> HiviewService::CloseTrace()
357 {
358 TraceManager manager;
359 int32_t closeRet = manager.CloseTrace();
360 if (closeRet != UCollect::UcError::SUCCESS) {
361 HIVIEW_LOGW("failed to close the trace.");
362 }
363 CollectResult<int32_t> ret;
364 ret.retCode = UCollect::UcError(closeRet);
365 return ret;
366 }
367
RecoverTrace()368 CollectResult<int32_t> HiviewService::RecoverTrace()
369 {
370 TraceManager manager;
371 int32_t recoverRet = manager.RecoverTrace();
372 if (recoverRet != UCollect::UcError::SUCCESS) {
373 HIVIEW_LOGW("failed to recover the trace.");
374 }
375 CollectResult<int32_t> ret;
376 ret.retCode = UCollect::UcError(recoverRet);
377 return ret;
378 }
379 } // namespace HiviewDFX
380 } // namespace OHOS
381