• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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 "trace_collector_impl.h"
17 
18 #include <memory>
19 #include <mutex>
20 #include <string>
21 #include <fcntl.h>
22 #include <sys/file.h>
23 #include <unistd.h>
24 
25 #include "hiview_logger.h"
26 #include "trace_decorator.h"
27 #include "trace_strategy.h"
28 #include "trace_state_machine.h"
29 #include "trace_utils.h"
30 #include "trace_strategy_factory.h"
31 #include "hiview_zip_util.h"
32 #include "hiview_event_report.h"
33 
34 using namespace OHOS::HiviewDFX;
35 using namespace OHOS::HiviewDFX::UCollectUtil;
36 using namespace OHOS::HiviewDFX::UCollect;
37 
38 namespace OHOS {
39 namespace HiviewDFX {
40 namespace UCollectUtil {
41 namespace {
42 DEFINE_LOG_TAG("UCollectUtil-TraceCollector");
43 constexpr uid_t HIVIEW_UID = 1201;
44 const int64_t MS_TO_US = 1000;
45 
ZipShareTempTraceFile(const std::string & srcFile)46 void ZipShareTempTraceFile(const std::string &srcFile)
47 {
48     std::string tempZipFile = UNIFIED_SHARE_PATH + StringUtil::ReplaceStr(FileUtil::ExtractFileName(srcFile),
49         ".sys", ".zip");
50     std::string zipTraceFile = AddVersionInfoToZipName(tempZipFile);
51     if (FileUtil::FileExists(zipTraceFile)) {
52         HIVIEW_LOGI("dst: %{public}s already exist", zipTraceFile.c_str());
53         return;
54     }
55     CheckCurrentCpuLoad();
56     HiviewEventReport::ReportCpuScene("5");
57     HiviewZipUnit zipUnit(zipTraceFile);
58     if (int32_t ret = zipUnit.AddFileInZip(srcFile, ZipFileLevel::KEEP_NONE_PARENT_PATH); ret != 0) {
59         HIVIEW_LOGE("zip trace failed, ret: %{public}d.", ret);
60         return;
61     }
62     HIVIEW_LOGI("ZipTraceFile success: %{public}s", FileUtil::ExtractFileName(zipTraceFile).c_str());
63 }
64 }
Create()65 std::shared_ptr<TraceCollector> TraceCollector::Create()
66 {
67     static std::shared_ptr<TraceCollector> instance_ =
68         std::make_shared<TraceDecorator>(std::make_shared<TraceCollectorImpl>());
69     return instance_;
70 }
71 
DumpTraceWithDuration(TraceCaller caller,uint32_t maxDuration,uint64_t happenTime)72 CollectResult<std::vector<std::string>> TraceCollectorImpl::DumpTraceWithDuration(
73     TraceCaller caller, uint32_t maxDuration, uint64_t happenTime)
74 {
75     if (maxDuration > INT32_MAX) {
76         return StartDumpTrace(caller, INT32_MAX, happenTime);
77     }
78     return StartDumpTrace(caller, maxDuration, happenTime);
79 }
80 
DumpTraceWithFilter(TeleModule module,uint32_t maxDuration,uint64_t happenTime)81 CollectResult<std::vector<std::string>> TraceCollectorImpl::DumpTraceWithFilter(TeleModule module,
82     uint32_t maxDuration, uint64_t happenTime)
83 {
84     if (auto uid = getuid(); uid != HIVIEW_UID) {
85         HIVIEW_LOGE("Do not allow uid:%{public}d to dump trace except in hiview process", uid);
86         return {UcError::PERMISSION_CHECK_FAILED};
87     }
88     CollectResult<std::vector<std::string>> result;
89     auto strategy = TraceStrategyFactory::CreateStrategy(module, maxDuration, happenTime);
90     TraceRetInfo traceRetInfo;
91     TraceRet ret = strategy->DoDump(result.data, traceRetInfo);
92     result.retCode = GetUcError(ret);
93     HIVIEW_LOGI("caller:%{public}s retCode = %{public}d, file number = %{public}zu.", ModuleToString(module).c_str(),
94         result.retCode, result.data.size());
95     return result;
96 }
97 
FilterTraceOn(TeleModule module,uint64_t postTime)98 CollectResult<int32_t> TraceCollectorImpl::FilterTraceOn(TeleModule module, uint64_t postTime)
99 {
100     if (auto uid = getuid(); uid != HIVIEW_UID) {
101         HIVIEW_LOGE("Do not allow uid:%{public}d to invoke in hiview process", uid);
102         return {UcError::PERMISSION_CHECK_FAILED};
103     }
104     if (postTime == 0) {
105         HIVIEW_LOGI("trace on module:%{public}d", static_cast<int32_t>(module));
106         return GetUcError(TraceStateMachine::GetInstance().TraceTelemetryOn());
107     }
108     auto ret = TraceStateMachine::GetInstance().PostTelemetryOn(postTime);
109     if (ret.GetStateError() != TraceStateCode::UPDATE_TIME) {
110         HIVIEW_LOGI("module:%{public}d post on not update timer", static_cast<int32_t>(module));
111         return GetUcError(ret);
112     }
113     std::lock_guard<std::mutex> lock(postMutex_);
114     if (ffrtQueue_ == nullptr) {
115         ffrtQueue_ = std::make_unique<ffrt::queue>("telemetry_post_on");
116     }
117     if (ffrtQueue_->cancel(handle_) < 0) {
118         HIVIEW_LOGW("no task to cancel");
119     }
120     HIVIEW_LOGI("post a timeout task to ffrt delay:%{public} " PRId64 ", module:%{public}d", postTime,
121         static_cast<int32_t>(module));
122     handle_ = ffrtQueue_->submit_h([]() {
123         TraceStateMachine::GetInstance().PostTelemetryTimeOut();
124     }, ffrt::task_attr().name("post_trace_on").delay(postTime * MS_TO_US));
125     return GetUcError(ret);
126 }
127 
FilterTraceOff(TeleModule module)128 CollectResult<int32_t> TraceCollectorImpl::FilterTraceOff(TeleModule module)
129 {
130     if (auto uid = getuid(); uid != HIVIEW_UID) {
131         HIVIEW_LOGE("Do not allow uid:%{public}d to dump trace except in hiview process", uid);
132         return {UcError::PERMISSION_CHECK_FAILED};
133     }
134     HIVIEW_LOGI("module:%{public}d", static_cast<int32_t>(module));
135     return GetUcError(TraceStateMachine::GetInstance().TraceTelemetryOff());
136 }
137 
DumpTrace(TraceCaller caller)138 CollectResult<std::vector<std::string>> TraceCollectorImpl::DumpTrace(TraceCaller caller)
139 {
140     return StartDumpTrace(caller, 0, static_cast<uint64_t>(0));
141 }
142 
StartDumpTrace(TraceCaller & caller,uint32_t timeLimit,uint64_t happenTime)143 CollectResult<std::vector<std::string>> TraceCollectorImpl::StartDumpTrace(TraceCaller &caller, uint32_t timeLimit,
144     uint64_t happenTime)
145 {
146     if (auto uid = getuid(); uid != HIVIEW_UID) {
147         HIVIEW_LOGE("Do not allow uid:%{public}d to dump trace except in hiview process", uid);
148         return {UcError::PERMISSION_CHECK_FAILED};
149     }
150     CollectResult<std::vector<std::string>> result;
151     auto strategy = TraceStrategyFactory::CreateTraceStrategy(caller, timeLimit, happenTime);
152     if (strategy == nullptr) {
153         HIVIEW_LOGE("Create traceStrategy error caller:%{public}d", caller);
154         result.retCode = UcError::UNSUPPORT;
155         return result;
156     }
157     TraceRetInfo traceRetInfo;
158     TraceRet ret = strategy->DoDump(result.data, traceRetInfo);
159     result.retCode = GetUcError(ret);
160     HIVIEW_LOGI("caller:%{public}s, retCode = %{public}d, data.size = %{public}zu.", EnumToString(caller).c_str(),
161         result.retCode, result.data.size());
162     return result;
163 }
164 
RecoverTmpTrace()165 bool TraceCollectorImpl::RecoverTmpTrace()
166 {
167     if (auto uid = getuid(); uid != HIVIEW_UID) {
168         HIVIEW_LOGE("Do not allow uid:%{public}d to RecoverTmpTrace trace except in hiview process", uid);
169         return false;
170     }
171     std::vector<std::string> traceFiles;
172     FileUtil::GetDirFiles(UNIFIED_SHARE_TEMP_PATH, traceFiles, false);
173     HIVIEW_LOGI("traceFiles need recover: %{public}zu", traceFiles.size());
174     for (auto &filePath : traceFiles) {
175         std::string fileName = FileUtil::ExtractFileName(filePath);
176         HIVIEW_LOGI("unfinished trace file: %{public}s", fileName.c_str());
177         std::string originTraceFile = StringUtil::ReplaceStr("/data/log/hitrace/" + fileName, ".zip", ".sys");
178         if (!FileUtil::FileExists(originTraceFile)) {
179             HIVIEW_LOGI("source file not exist: %{public}s", originTraceFile.c_str());
180             FileUtil::RemoveFile(UNIFIED_SHARE_TEMP_PATH + fileName);
181             continue;
182         }
183         int fd = open(originTraceFile.c_str(), O_RDONLY | O_NONBLOCK);
184         if (fd == -1) {
185             HIVIEW_LOGI("open source file failed: %{public}s", originTraceFile.c_str());
186             continue;
187         }
188         fdsan_exchange_owner_tag(fd, 0, logLabelDomain);
189         // add lock before zip trace file, in case hitrace delete origin trace file.
190         if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
191             HIVIEW_LOGI("get source file lock failed: %{public}s", originTraceFile.c_str());
192             fdsan_close_with_tag(fd, logLabelDomain);
193             continue;
194         }
195         HIVIEW_LOGI("originTraceFile path: %{public}s", originTraceFile.c_str());
196         UcollectionTask traceTask = [=]() {
197             ZipShareTempTraceFile(originTraceFile);
198             flock(fd, LOCK_UN);
199             fdsan_close_with_tag(fd, logLabelDomain);
200         };
201         TraceWorker::GetInstance().HandleUcollectionTask(traceTask);
202     }
203     return true;
204 }
205 } // UCollectUtil
206 } // HiViewDFX
207 } // OHOS
208