1 /*
2 * Copyright (c) 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 #include <fcntl.h>
16 #include <map>
17 #include <mutex>
18 #include <sys/file.h>
19 #include <unistd.h>
20
21 #include "trace_manager.h"
22
23 #include "file_util.h"
24 #include "hilog/log.h"
25 #include "hitrace_dump.h"
26 #include "hiview_logger.h"
27 #include "string_util.h"
28 #include "parameter_ex.h"
29 #include "trace_collector.h"
30 #include "trace_utils.h"
31 #include "trace_worker.h"
32
33 using OHOS::HiviewDFX::Hitrace::TraceErrorCode;
34 using OHOS::HiviewDFX::UCollect::UcError;
35 using OHOS::HiviewDFX::Hitrace::TraceMode;
36
37 namespace OHOS {
38 namespace HiviewDFX {
39 namespace {
40 DEFINE_LOG_TAG("UCollectUtil-TraceCollector");
41 std::mutex g_traceLock;
42 TraceMode g_recoverMode = Parameter::IsBetaVersion() ? TraceMode::SERVICE_MODE : TraceMode::CLOSE;
43 const std::string UNIFIED_SHARE_PATH = "/data/log/hiview/unified_collection/trace/share/";
44 const std::string UNIFIED_SHARE_TEMP_PATH = UNIFIED_SHARE_PATH + "temp/";
45 }
46
OpenSnapshotTrace(const std::vector<std::string> & tagGroups)47 int32_t TraceManager::OpenSnapshotTrace(const std::vector<std::string> &tagGroups)
48 {
49 std::lock_guard<std::mutex> lock(g_traceLock);
50 HIVIEW_LOGI("start to open snapshot trace.");
51 // service mode
52 if (OHOS::HiviewDFX::Hitrace::GetTraceMode() ==
53 OHOS::HiviewDFX::Hitrace::TraceMode::SERVICE_MODE) {
54 HIVIEW_LOGE("now is snapshot status, open snapshot failed.");
55 return UcError::TRACE_CALL_ERROR;
56 }
57
58 // recording mode
59 if (OHOS::HiviewDFX::Hitrace::GetTraceMode() ==
60 OHOS::HiviewDFX::Hitrace::TraceMode::CMD_MODE) {
61 HIVIEW_LOGE("now is recording status, open snapshot failed.");
62 return UcError::TRACE_IS_OCCUPIED;
63 }
64
65 TraceErrorCode ret = OHOS::HiviewDFX::Hitrace::OpenTrace(tagGroups);
66 if (ret == TraceErrorCode::SUCCESS) {
67 g_recoverMode = TraceMode::SERVICE_MODE;
68 }
69 return TransCodeToUcError(ret);
70 }
71
OpenRecordingTrace(const std::string & args)72 int32_t TraceManager::OpenRecordingTrace(const std::string &args)
73 {
74 std::lock_guard<std::mutex> lock(g_traceLock);
75 HIVIEW_LOGI("start to open recording trace.");
76 // recording mode
77 if (OHOS::HiviewDFX::Hitrace::GetTraceMode() ==
78 OHOS::HiviewDFX::Hitrace::TraceMode::CMD_MODE) {
79 HIVIEW_LOGE("now is recording status, open recording failed.");
80 return UcError::TRACE_IS_OCCUPIED;
81 }
82
83 // service mode
84 if (OHOS::HiviewDFX::Hitrace::GetTraceMode() ==
85 OHOS::HiviewDFX::Hitrace::TraceMode::SERVICE_MODE) {
86 HIVIEW_LOGI("TraceMode is switching: snapshot close, recording open.");
87 OHOS::HiviewDFX::Hitrace::CloseTrace();
88 }
89
90 TraceErrorCode ret = OHOS::HiviewDFX::Hitrace::OpenTrace(args);
91 return TransCodeToUcError(ret);
92 }
93
CloseTrace()94 int32_t TraceManager::CloseTrace()
95 {
96 std::lock_guard<std::mutex> lock(g_traceLock);
97 HIVIEW_LOGI("start to close trace.");
98 TraceErrorCode ret = OHOS::HiviewDFX::Hitrace::CloseTrace();
99 g_recoverMode = TraceMode::CLOSE;
100 return TransCodeToUcError(ret);
101 }
102
RecoverTrace()103 int32_t TraceManager::RecoverTrace()
104 {
105 std::lock_guard<std::mutex> lock(g_traceLock);
106 HIVIEW_LOGI("start to recover trace.");
107 TraceErrorCode ret = OHOS::HiviewDFX::Hitrace::CloseTrace();
108
109 if (g_recoverMode == TraceMode::SERVICE_MODE) {
110 HIVIEW_LOGI("recover trace to Snapshot.");
111 const std::vector<std::string> tagGroups = {"scene_performance"};
112 TraceErrorCode ret = OHOS::HiviewDFX::Hitrace::OpenTrace(tagGroups);
113 return TransCodeToUcError(ret);
114 }
115 HIVIEW_LOGI("recover trace to close.");
116
117 return TransCodeToUcError(ret);
118 }
119
GetTraceMode()120 int32_t TraceManager::GetTraceMode()
121 {
122 return OHOS::HiviewDFX::Hitrace::GetTraceMode();
123 }
124
RecoverTmpTrace()125 void TraceManager::RecoverTmpTrace()
126 {
127 std::vector<std::string> traceFiles;
128 FileUtil::GetDirFiles(UNIFIED_SHARE_TEMP_PATH, traceFiles, false);
129 HIVIEW_LOGI("traceFiles need recover: %{public}zu", traceFiles.size());
130 for (auto &filePath : traceFiles) {
131 std::string fileName = FileUtil::ExtractFileName(filePath);
132 HIVIEW_LOGI("unfinished trace file: %{public}s", fileName.c_str());
133 std::string originTraceFile = StringUtil::ReplaceStr("/data/log/hitrace/" + fileName, ".zip", ".sys");
134 if (!FileUtil::FileExists(originTraceFile)) {
135 HIVIEW_LOGI("source file not exist: %{public}s", originTraceFile.c_str());
136 FileUtil::RemoveFile(UNIFIED_SHARE_TEMP_PATH + fileName);
137 continue;
138 }
139 int fd = open(originTraceFile.c_str(), O_RDONLY | O_NONBLOCK);
140 if (fd == -1) {
141 HIVIEW_LOGI("open source file failed: %{public}s", originTraceFile.c_str());
142 continue;
143 }
144 // add lock before zip trace file, in case hitrace delete origin trace file.
145 if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
146 HIVIEW_LOGI("get source file lock failed: %{public}s", originTraceFile.c_str());
147 close(fd);
148 continue;
149 }
150 HIVIEW_LOGI("originTraceFile path: %{public}s", originTraceFile.c_str());
151 UcollectionTask traceTask = [=]() {
152 ZipTraceFile(originTraceFile, UNIFIED_SHARE_PATH + fileName);
153 flock(fd, LOCK_UN);
154 close(fd);
155 };
156 TraceWorker::GetInstance().HandleUcollectionTask(traceTask);
157 }
158 }
159 } // HiviewDFX
160 } // OHOS
161