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