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