1 /*
2 * Copyright (c) 2023-2025 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_decorator.h"
17
18 #include "file_util.h"
19 #include "string_util.h"
20 #include "trace_utils.h"
21 #include "decorator_util.h"
22
23 namespace OHOS {
24 namespace HiviewDFX {
25 namespace UCollectUtil {
26 constexpr char UC_HITRACE_API_STAT_TITLE[] = "Hitrace API detail statistics:";
27 constexpr char UC_HITRACE_API_STAT_ITEM[] =
28 "Caller FailCall OverCall TotalCall AvgLatency(us) MaxLatency(us) TotalTimeSpent(us)";
29 constexpr char UC_HITRACE_TRAFFIC_TITLE[] = "Hitrace Traffic statistics:";
30 constexpr char UC_HITRACE_TRAFFIC_ITEM[] =
31 "Caller TraceFile RawSize(b) ZipSize(b) HandleTime(us)";
32 constexpr char TRACE_TRAFFIC_LOG_PATH[] = "/data/log/hiview/unified_collection/ucollection_trace_traffic.log";
33
34 TraceStatWrapper TraceDecorator::traceStatWrapper_;
35
GetRawTraceSize(const std::string & file)36 uint64_t GetRawTraceSize(const std::string &file)
37 {
38 std::string originTracePath;
39 if (StringUtil::EndWith(file, ".zip")) {
40 std::string fileNameWithoutVersion = StringUtil::GetRleftSubstr(FileUtil::ExtractFileName(file), "@");
41 originTracePath = "/data/log/hitrace/" + fileNameWithoutVersion + ".sys";
42 } else {
43 std::string fileNameWithoutPrefix = StringUtil::GetRightSubstr(FileUtil::ExtractFileName(file), "_");
44 originTracePath = "/data/log/hitrace/" + fileNameWithoutPrefix;
45 }
46 std::string realPath;
47 if (!FileUtil::PathToRealPath(originTracePath, realPath)) {
48 return 0;
49 }
50 return FileUtil::GetFileSize(realPath);
51 }
52
DumpTrace(UCollect::TraceCaller caller)53 CollectResult<std::vector<std::string>> TraceDecorator::DumpTrace(UCollect::TraceCaller caller)
54 {
55 auto task = [this, &caller] { return traceCollector_->DumpTrace(caller); };
56 return Invoke(task, caller);
57 }
58
DumpTraceWithDuration(UCollect::TraceCaller caller,uint32_t timeLimit,uint64_t happenTime)59 CollectResult<std::vector<std::string>> TraceDecorator::DumpTraceWithDuration(UCollect::TraceCaller caller,
60 uint32_t timeLimit, uint64_t happenTime)
61 {
62 auto task = [this, &caller, &timeLimit, &happenTime] {
63 return traceCollector_->DumpTraceWithDuration(caller, timeLimit, happenTime);
64 };
65 return Invoke(task, caller);
66 }
67
DumpTraceWithFilter(UCollect::TeleModule module,uint32_t timeLimit,uint64_t happenTime)68 CollectResult<std::vector<std::string>> TraceDecorator::DumpTraceWithFilter(UCollect::TeleModule module,
69 uint32_t timeLimit, uint64_t happenTime)
70 {
71 return traceCollector_->DumpTraceWithFilter(module, timeLimit, happenTime);
72 }
73
FilterTraceOn(UCollect::TeleModule module,uint64_t postTime)74 CollectResult<int32_t> TraceDecorator::FilterTraceOn(UCollect::TeleModule module, uint64_t postTime)
75 {
76 return traceCollector_->FilterTraceOn(module, postTime);
77 }
78
FilterTraceOff(UCollect::TeleModule module)79 CollectResult<int32_t> TraceDecorator::FilterTraceOff(UCollect::TeleModule module)
80 {
81 return traceCollector_->FilterTraceOff(module);
82 }
83
RecoverTmpTrace()84 bool TraceDecorator::RecoverTmpTrace()
85 {
86 return traceCollector_->RecoverTmpTrace();
87 }
88
SaveStatSpecialInfo()89 void TraceDecorator::SaveStatSpecialInfo()
90 {
91 WriteLinesToFile({""}, false, UC_STAT_LOG_PATH); // a blank line after common stat info
92 std::map<std::string, TraceStatInfo> traceStatInfo = traceStatWrapper_.GetTraceStatInfo();
93 std::list<std::string> traceFormattedStatInfo = {UC_HITRACE_API_STAT_TITLE, UC_HITRACE_API_STAT_ITEM};
94 for (const auto& record : traceStatInfo) {
95 traceFormattedStatInfo.push_back(record.second.ToString());
96 }
97 WriteLinesToFile(traceFormattedStatInfo, true, UC_STAT_LOG_PATH);
98 }
99
ResetStatInfo()100 void TraceDecorator::ResetStatInfo()
101 {
102 traceStatWrapper_.ResetStatInfo();
103 }
104
WriteTrafficAfterHandle(const TraceTrafficInfo & trace_traffic)105 void TraceDecorator::WriteTrafficAfterHandle(const TraceTrafficInfo& trace_traffic)
106 {
107 if (!Parameter::IsBetaVersion() && !Parameter::IsUCollectionSwitchOn()) {
108 return;
109 }
110 static std::mutex mtx;
111 std::lock_guard<std::mutex> lock(mtx);
112 traceStatWrapper_.WriteTrafficToLogFile(trace_traffic.ToString());
113 }
114
UpdateTraceStatInfo(uint64_t startTime,uint64_t endTime,UCollect::TraceCaller & caller,const CollectResult<std::vector<std::string>> & result)115 void TraceStatWrapper::UpdateTraceStatInfo(uint64_t startTime, uint64_t endTime, UCollect::TraceCaller& caller,
116 const CollectResult<std::vector<std::string>>& result)
117 {
118 bool isCallSucc = (result.retCode == UCollect::UcError::SUCCESS);
119 bool isOverCall = (result.retCode == UCollect::UcError::TRACE_OVER_FLOW);
120 uint64_t latency = (endTime - startTime > 0) ? (endTime - startTime) : 0;
121 std::string callerStr = EnumToString(caller);
122 TraceStatItem item = {.caller = callerStr, .isCallSucc = isCallSucc,
123 .isOverCall = isOverCall, .latency = latency};
124 UpdateAPIStatInfo(item);
125 }
126
UpdateAPIStatInfo(const TraceStatItem & item)127 void TraceStatWrapper::UpdateAPIStatInfo(const TraceStatItem& item)
128 {
129 std::lock_guard<std::mutex> lock(traceMutex_);
130 if (traceStatInfos_.find(item.caller) == traceStatInfos_.end()) {
131 TraceStatInfo statInfo = {
132 .caller = item.caller,
133 .failCall = (item.isCallSucc || item.isOverCall) ? 0 : 1,
134 .overCall = item.isOverCall ? 1 : 0,
135 .totalCall = 1,
136 .avgLatency = item.latency,
137 .maxLatency = item.latency,
138 .totalTimeSpend = item.latency,
139 };
140 traceStatInfos_.insert(std::make_pair(item.caller, statInfo));
141 return;
142 }
143
144 TraceStatInfo& statInfo = traceStatInfos_[item.caller];
145 statInfo.totalCall += 1;
146 statInfo.failCall += ((item.isCallSucc || item.isOverCall) ? 0 : 1);
147 statInfo.overCall += (item.isOverCall ? 1 : 0);
148 statInfo.totalTimeSpend += item.latency;
149 if (statInfo.maxLatency < item.latency) {
150 statInfo.maxLatency = item.latency;
151 }
152 uint32_t succCall = statInfo.totalCall;
153 if (succCall > 0) {
154 statInfo.avgLatency = statInfo.totalTimeSpend / succCall;
155 }
156 }
157
GetTraceStatInfo()158 std::map<std::string, TraceStatInfo> TraceStatWrapper::GetTraceStatInfo()
159 {
160 std::lock_guard<std::mutex> lock(traceMutex_);
161 return traceStatInfos_;
162 }
163
WriteTrafficToLogFile(const std::string & trafficInfo)164 void TraceStatWrapper::WriteTrafficToLogFile(const std::string& trafficInfo)
165 {
166 std::list<std::string> trafficFormattedInfo;
167 if (date_ != GetCurrentDate() || !FileUtil::FileExists(TRACE_TRAFFIC_LOG_PATH)) {
168 WriteLinesToFile({""}, false, TRACE_TRAFFIC_LOG_PATH);
169 date_ = GetCurrentDate();
170 WriteLinesToFile({UC_STAT_DATE, date_}, true, TRACE_TRAFFIC_LOG_PATH);
171 trafficFormattedInfo = {UC_HITRACE_TRAFFIC_TITLE, UC_HITRACE_TRAFFIC_ITEM};
172 }
173 trafficFormattedInfo.push_back(trafficInfo);
174 WriteLinesToFile(trafficFormattedInfo, false, TRACE_TRAFFIC_LOG_PATH);
175 }
176
ResetStatInfo()177 void TraceStatWrapper::ResetStatInfo()
178 {
179 std::lock_guard<std::mutex> lock(traceMutex_);
180 traceStatInfos_.clear();
181 }
182 } // namespace UCollectUtil
183 } // namespace HiviewDFX
184 } // namespace OHOS
185