1 /*
2 * Copyright (C) 2022-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 <asm/unistd.h>
17 #include <atomic>
18 #include <cinttypes>
19 #include <climits>
20 #include <ctime>
21 #include <cerrno>
22 #include <fcntl.h>
23 #include <fstream>
24 #include <linux/perf_event.h>
25 #include <memory>
26 #include <mutex>
27 #include <sched.h>
28 #include <sys/ioctl.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31 #include <vector>
32 #include <string>
33
34 #include "common_define.h"
35 #include "common_utils.h"
36 #include "securec.h"
37 #include "hilog/log.h"
38 #include "param/sys_param.h"
39 #include "parameter.h"
40 #include "parameters.h"
41 #include "hitrace_meter.h"
42 #include "hitrace/tracechain.h"
43
44 #ifdef LOG_DOMAIN
45 #undef LOG_DOMAIN
46 #define LOG_DOMAIN 0xD002D33
47 #endif
48 #ifdef LOG_TAG
49 #undef LOG_TAG
50 #define LOG_TAG "HitraceMeter"
51 #endif
52
53 using namespace OHOS::HiviewDFX;
54
55 namespace {
56 int g_markerFd = -1;
57 int g_appFd = -1;
58 std::once_flag g_onceFlag;
59 std::once_flag g_onceWriteMarkerFailedFlag;
60 std::atomic<CachedHandle> g_cachedHandle;
61 std::atomic<CachedHandle> g_appPidCachedHandle;
62
63 std::atomic<bool> g_isHitraceMeterDisabled(false);
64 std::atomic<bool> g_isHitraceMeterInit(false);
65 std::atomic<bool> g_needReloadPid(false);
66 std::atomic<bool> g_pidHasReload(false);
67
68 std::atomic<uint64_t> g_tagsProperty(HITRACE_TAG_NOT_READY);
69 std::atomic<uint64_t> g_appTag(HITRACE_TAG_NOT_READY);
70 std::atomic<int64_t> g_appTagMatchPid(-1);
71
72 const std::string SANDBOX_PATH = "/data/storage/el2/log/";
73 const std::string PHYSICAL_PATH = "/data/app/el2/100/log/";
74
75 constexpr int VAR_NAME_MAX_SIZE = 400;
76 constexpr int NAME_NORMAL_LEN = 512;
77 constexpr int BUFFER_LEN = 640;
78 constexpr int HITRACEID_LEN = 64;
79
80 static const int PID_BUF_SIZE = 6;
81 static char g_pid[PID_BUF_SIZE];
82 static const std::string EMPTY_TRACE_NAME;
83 static char g_appName[NAME_NORMAL_LEN + 1] = {0};
84 static std::string g_appTracePrefix = "";
85 constexpr const int COMM_STR_MAX = 14;
86 constexpr const int PID_STR_MAX = 7;
87 constexpr const int PREFIX_MAX_SIZE = 128; // comm-pid (tgid) [cpu] .... ts.tns: tracing_mark_write:
88 constexpr const int TRACE_TXT_HEADER_MAX = 1024;
89 constexpr const int CPU_CORE_NUM = 16;
90 constexpr const int DEFAULT_CACHE_SIZE = 32 * 1024;
91 constexpr const int MAX_FILE_SIZE = 500 * 1024 * 1024;
92 constexpr const int NS_TO_MS = 1000;
93 int g_tgid = -1;
94 uint64_t g_traceEventNum = 0;
95 int g_writeOffset = 0;
96 int g_fileSize = 0;
97 TraceFlag g_appFlag(FLAG_MAIN_THREAD);
98 std::atomic<uint64_t> g_fileLimitSize(0);
99 std::unique_ptr<char[]> g_traceBuffer;
100 std::recursive_mutex g_appTraceMutex;
101
102 static char g_markTypes[5] = {'B', 'E', 'S', 'F', 'C'};
103 enum MarkerType { MARKER_BEGIN, MARKER_END, MARKER_ASYNC_BEGIN, MARKER_ASYNC_END, MARKER_INT, MARKER_MAX };
104
105 const uint64_t VALID_TAGS = HITRACE_TAG_FFRT | HITRACE_TAG_COMMONLIBRARY | HITRACE_TAG_HDF | HITRACE_TAG_NET |
106 HITRACE_TAG_NWEB | HITRACE_TAG_DISTRIBUTED_AUDIO | HITRACE_TAG_FILEMANAGEMENT | HITRACE_TAG_OHOS |
107 HITRACE_TAG_ABILITY_MANAGER | HITRACE_TAG_ZCAMERA | HITRACE_TAG_ZMEDIA | HITRACE_TAG_ZIMAGE | HITRACE_TAG_ZAUDIO |
108 HITRACE_TAG_DISTRIBUTEDDATA | HITRACE_TAG_GRAPHIC_AGP | HITRACE_TAG_ACE | HITRACE_TAG_NOTIFICATION |
109 HITRACE_TAG_MISC | HITRACE_TAG_MULTIMODALINPUT | HITRACE_TAG_RPC | HITRACE_TAG_ARK | HITRACE_TAG_WINDOW_MANAGER |
110 HITRACE_TAG_DISTRIBUTED_SCREEN | HITRACE_TAG_DISTRIBUTED_CAMERA | HITRACE_TAG_DISTRIBUTED_HARDWARE_FWK |
111 HITRACE_TAG_GLOBAL_RESMGR | HITRACE_TAG_DEVICE_MANAGER | HITRACE_TAG_SAMGR | HITRACE_TAG_POWER |
112 HITRACE_TAG_DISTRIBUTED_SCHEDULE | HITRACE_TAG_DISTRIBUTED_INPUT | HITRACE_TAG_BLUETOOTH | HITRACE_TAG_APP;
113
114 const std::string TRACE_TXT_HEADER_FORMAT = R"(# tracer: nop
115 #
116 # entries-in-buffer/entries-written: %-21s #P:%-3s
117 #
118 # _-----=> irqs-off
119 # / _----=> need-resched
120 # | / _---=> hardirq/softirq
121 # || / _--=> preempt-depth
122 # ||| / delay
123 # TASK-PID TGID CPU# |||| TIMESTAMP FUNCTION
124 # | | | | |||| | |
125 )";
126
CreateCacheHandle()127 inline void CreateCacheHandle()
128 {
129 const char* devValue = "true";
130 g_cachedHandle = CachedParameterCreate(TRACE_TAG_ENABLE_FLAGS.c_str(), devValue);
131 g_appPidCachedHandle = CachedParameterCreate(TRACE_KEY_APP_PID.c_str(), devValue);
132 }
133
UpdateSysParamTags()134 inline void UpdateSysParamTags()
135 {
136 // Get the system parameters of TRACE_TAG_ENABLE_FLAGS.
137 int changed = 0;
138 if (UNEXPECTANTLY(g_cachedHandle == nullptr || g_appPidCachedHandle == nullptr)) {
139 CreateCacheHandle();
140 return;
141 }
142 const char *paramValue = CachedParameterGetChanged(g_cachedHandle, &changed);
143 if (UNEXPECTANTLY(changed == 1) && paramValue != nullptr) {
144 uint64_t tags = 0;
145 if (!OHOS::HiviewDFX::Hitrace::StringToUint64(paramValue, tags)) {
146 return;
147 }
148 g_tagsProperty = (tags | HITRACE_TAG_ALWAYS) & HITRACE_TAG_VALID_MASK;
149 }
150 int appPidChanged = 0;
151 const char *paramPid = CachedParameterGetChanged(g_appPidCachedHandle, &appPidChanged);
152 if (UNEXPECTANTLY(appPidChanged == 1) && paramPid != nullptr) {
153 int64_t appTagMatchPid = -1;
154 if (!OHOS::HiviewDFX::Hitrace::StringToInt64(paramPid, appTagMatchPid)) {
155 return;
156 }
157 g_appTagMatchPid = appTagMatchPid;
158 }
159 }
160
IsAppspawnProcess()161 bool IsAppspawnProcess()
162 {
163 std::string procName;
164 std::ifstream cmdline("/proc/self/cmdline");
165 if (cmdline.is_open()) {
166 getline(cmdline, procName, '\0');
167 cmdline.close();
168 }
169 return procName == "appspawn" || procName == "nwebspawn" || procName == "cjappspawn" || procName == "nativespawn";
170 }
171
InitPid()172 void InitPid()
173 {
174 std::string pidStr = std::to_string(getprocpid());
175 int ret = strcpy_s(g_pid, PID_BUF_SIZE, pidStr.c_str());
176 if (ret != 0) {
177 HILOG_ERROR(LOG_CORE, "pid[%{public}s] strcpy_s fail ret: %{public}d.", pidStr.c_str(), ret);
178 return;
179 }
180
181 if (!g_needReloadPid && IsAppspawnProcess()) {
182 // appspawn restarted, all app need init pid again.
183 g_needReloadPid = true;
184 }
185
186 HILOG_INFO(LOG_CORE, "pid[%{public}s] first get g_tagsProperty: %{public}s", pidStr.c_str(),
187 std::to_string(g_tagsProperty.load()).c_str());
188 }
189
ReloadPid()190 void ReloadPid()
191 {
192 std::string pidStr = std::to_string(getprocpid());
193 int ret = strcpy_s(g_pid, PID_BUF_SIZE, pidStr.c_str());
194 if (ret != 0) {
195 HILOG_ERROR(LOG_CORE, "pid[%{public}s] strcpy_s fail ret: %{public}d.", pidStr.c_str(), ret);
196 return;
197 }
198 if (!IsAppspawnProcess()) {
199 // appspawn restarted, all app need reload pid again.
200 g_pidHasReload = true;
201 }
202 }
203
204 // open file "trace_marker".
OpenTraceMarkerFile()205 void OpenTraceMarkerFile()
206 {
207 const std::string debugFile = DEBUGFS_TRACING_DIR + TRACE_MARKER_NODE;
208 const std::string traceFile = TRACEFS_DIR + TRACE_MARKER_NODE;
209 g_markerFd = open(debugFile.c_str(), O_WRONLY | O_CLOEXEC);
210 #ifdef HITRACE_UNITTEST
211 SetMarkerFd(g_markerFd);
212 #endif
213 if (g_markerFd == -1) {
214 HILOG_ERROR(LOG_CORE, "open trace file %{public}s failed: %{public}d", debugFile.c_str(), errno);
215 g_markerFd = open(traceFile.c_str(), O_WRONLY | O_CLOEXEC);
216 if (g_markerFd == -1) {
217 HILOG_ERROR(LOG_CORE, "open trace file %{public}s failed: %{public}d", traceFile.c_str(), errno);
218 g_tagsProperty = 0;
219 return;
220 }
221 }
222 // get tags and pid
223 g_tagsProperty = OHOS::system::GetUintParameter<uint64_t>(TRACE_TAG_ENABLE_FLAGS, 0);
224 CreateCacheHandle();
225 InitPid();
226
227 g_isHitraceMeterInit = true;
228 }
229
WriteFailedLog()230 void WriteFailedLog()
231 {
232 HILOG_ERROR(LOG_CORE, "write trace_marker failed, %{public}d", errno);
233 }
234
WriteToTraceMarker(const char * buf,const int count)235 void WriteToTraceMarker(const char* buf, const int count)
236 {
237 if (UNEXPECTANTLY(count <= 0 || count >= BUFFER_LEN)) {
238 HILOG_INFO(LOG_CORE, "Write trace canceled, buf size is greater than the BUFFER_LEN");
239 return;
240 }
241 if (write(g_markerFd, buf, count) < 0) {
242 std::call_once(g_onceWriteMarkerFailedFlag, WriteFailedLog);
243 }
244 }
245
AddTraceMarkerLarge(const std::string & name,MarkerType type,const int64_t value)246 void AddTraceMarkerLarge(const std::string& name, MarkerType type, const int64_t value)
247 {
248 std::string record;
249 record += g_markTypes[type];
250 record += "|";
251 record += g_pid;
252 record += "|H:";
253 HiTraceId hiTraceId = HiTraceChain::GetId();
254 if (hiTraceId.IsValid()) {
255 char buf[HITRACEID_LEN] = {0};
256 int bytes = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "[%llx,%llx,%llx]#",
257 hiTraceId.GetChainId(), hiTraceId.GetSpanId(), hiTraceId.GetParentSpanId());
258 if (EXPECTANTLY(bytes > 0)) {
259 record += buf;
260 }
261 }
262 record += name;
263 record += " ";
264 if (value != 0) {
265 record += std::to_string(value);
266 }
267 WriteToTraceMarker(record.c_str(), record.size());
268 }
269
WriteOnceLog(LogLevel loglevel,const std::string & logStr,bool & isWrite)270 void WriteOnceLog(LogLevel loglevel, const std::string& logStr, bool& isWrite)
271 {
272 if (!isWrite) {
273 switch (loglevel) {
274 case LOG_ERROR: {
275 HILOG_ERROR(LOG_CORE, "%{public}s: %{public}d(%{public}s)", logStr.c_str(), errno, strerror(errno));
276 break;
277 }
278 case LOG_INFO: {
279 HILOG_INFO(LOG_CORE, "%{public}s", logStr.c_str());
280 break;
281 }
282 default: {
283 break;
284 }
285 }
286 isWrite = true;
287 }
288 }
289
GetProcData(const char * file,char * buffer,const size_t bufferSize)290 bool GetProcData(const char* file, char* buffer, const size_t bufferSize)
291 {
292 FILE* fp = fopen(file, "r");
293 if (fp == nullptr) {
294 static bool isWriteLog = false;
295 std::string errLogStr = std::string(__func__) + ": open " + std::string(file) + " failed";
296 WriteOnceLog(LOG_ERROR, errLogStr, isWriteLog);
297 return false;
298 }
299
300 if (fgets(buffer, bufferSize, fp) == nullptr) {
301 (void)fclose(fp);
302 static bool isWriteLog = false;
303 std::string errLogStr = std::string(__func__) + ": fgets " + std::string(file) + " failed";
304 WriteOnceLog(LOG_ERROR, errLogStr, isWriteLog);
305 return false;
306 }
307
308 if (fclose(fp) != 0) {
309 static bool isWriteLog = false;
310 std::string errLogStr = std::string(__func__) + ": fclose " + std::string(file) + " failed";
311 WriteOnceLog(LOG_ERROR, errLogStr, isWriteLog);
312 return false;
313 }
314
315 return true;
316 }
317
CheckAppTraceArgs(TraceFlag flag,uint64_t tags,uint64_t limitSize)318 int CheckAppTraceArgs(TraceFlag flag, uint64_t tags, uint64_t limitSize)
319 {
320 if (flag != FLAG_MAIN_THREAD && flag != FLAG_ALL_THREAD) {
321 HILOG_ERROR(LOG_CORE, "flag(%{public}" PRId32 ") is invalid", flag);
322 return RET_FAIL_INVALID_ARGS;
323 }
324
325 if (static_cast<int64_t>(tags) < 0 || !UNEXPECTANTLY(tags & VALID_TAGS)) {
326 HILOG_ERROR(LOG_CORE, "tags(%{public}" PRId64 ") is invalid", tags);
327 return RET_FAIL_INVALID_ARGS;
328 }
329
330 if (static_cast<int64_t>(limitSize) <= 0) {
331 HILOG_ERROR(LOG_CORE, "limitSize(%{public}" PRId64 ") is invalid", limitSize);
332 return RET_FAIL_INVALID_ARGS;
333 }
334
335 return RET_SUCC;
336 }
337
SetAppFileName(std::string & destFileName,std::string & fileName)338 int SetAppFileName(std::string& destFileName, std::string& fileName)
339 {
340 destFileName = SANDBOX_PATH + "trace/";
341 mode_t permissions = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; // 0755
342 #ifdef HITRACE_UNITTEST
343 destFileName = "/data/local/tmp/";
344 #endif
345 if (access(destFileName.c_str(), F_OK) != 0 && mkdir(destFileName.c_str(), permissions) == -1) {
346 HILOG_ERROR(LOG_CORE, "failed to create dir(%{public}s):%{public}d(%{public}s)", destFileName.c_str(),
347 errno, strerror(errno));
348 return RET_FAIL_MKDIR;
349 }
350
351 if (!GetProcData("/proc/self/cmdline", g_appName, NAME_NORMAL_LEN)) {
352 HILOG_ERROR(LOG_CORE, "get app name failed, %{public}d", errno);
353 return RET_FAILD;
354 }
355
356 time_t now = time(nullptr);
357 if (now == static_cast<time_t>(-1)) {
358 HILOG_ERROR(LOG_CORE, "get time failed, %{public}d", errno);
359 return RET_FAILD;
360 }
361
362 struct tm tmTime;
363 if (localtime_r(&now, &tmTime) == nullptr) {
364 HILOG_ERROR(LOG_CORE, "localtime_r failed, %{public}d", errno);
365 return RET_FAILD;
366 }
367
368 const int yearCount = 1900;
369 const int size = sizeof(g_appName) + 32;
370 char file[size] = {0};
371 auto ret = snprintf_s(file, sizeof(file), sizeof(file) - 1, "%s_%04d%02d%02d_%02d%02d%02d.trace", g_appName,
372 tmTime.tm_year + yearCount, tmTime.tm_mon + 1, tmTime.tm_mday, tmTime.tm_hour, tmTime.tm_min, tmTime.tm_sec);
373 if (ret <= 0) {
374 HILOG_ERROR(LOG_CORE, "Format file failed, %{public}d", errno);
375 return RET_FAILD;
376 }
377
378 destFileName += std::string(file);
379 fileName = PHYSICAL_PATH + std::string(g_appName) + "/trace/" + std::string(file);
380 return RET_SUCC;
381 }
382
InitTraceHead()383 int InitTraceHead()
384 {
385 // write reserved trace header
386 std::vector<char> buffer(TRACE_TXT_HEADER_MAX, '\0');
387 int used = snprintf_s(buffer.data(), buffer.size(), buffer.size() - 1, TRACE_TXT_HEADER_FORMAT.c_str(), "", "");
388 if (used <= 0) {
389 HILOG_ERROR(LOG_CORE, "format reserved trace header failed: %{public}d(%{public}s)", errno, strerror(errno));
390 return RET_FAILD;
391 }
392 if (write(g_appFd, buffer.data(), used) != used) {
393 HILOG_ERROR(LOG_CORE, "write reserved trace header failed: %{public}d(%{public}s)", errno, strerror(errno));
394 return RET_FAILD;
395 }
396
397 g_writeOffset = 0;
398 g_fileSize = used;
399 g_traceEventNum = 0;
400
401 lseek(g_appFd, used, SEEK_SET); // Reserve space to write the file header.
402 return RET_SUCC;
403 }
404
WriteTraceToFile(char * buf,const int len)405 bool WriteTraceToFile(char* buf, const int len)
406 {
407 if (write(g_appFd, buf, len) != len) {
408 static bool isWriteLog = false;
409 WriteOnceLog(LOG_ERROR, "write app trace data failed", isWriteLog);
410 return false;
411 }
412
413 g_fileSize += len;
414 g_writeOffset = 0;
415 return true;
416 }
417
GetTraceBuffer(int size)418 char* GetTraceBuffer(int size)
419 {
420 if ((g_writeOffset + size) > DEFAULT_CACHE_SIZE && (g_writeOffset + size) < MAX_FILE_SIZE) {
421 // The remaining space is insufficient to cache the data. Write the data to the file.
422 if (!WriteTraceToFile(g_traceBuffer.get(), g_writeOffset)) {
423 return nullptr;
424 }
425 }
426
427 return g_traceBuffer.get() + g_writeOffset;
428 }
429
SetCommStr()430 void SetCommStr()
431 {
432 int size = g_appTracePrefix.size();
433 if (size >= COMM_STR_MAX) {
434 g_appTracePrefix = g_appTracePrefix.substr(size - COMM_STR_MAX, size);
435 } else {
436 g_appTracePrefix = std::string(COMM_STR_MAX - size, ' ') + g_appTracePrefix;
437 }
438 }
439
SetMainThreadInfo()440 void SetMainThreadInfo()
441 {
442 if (strlen(g_appName) == 0) {
443 if (!GetProcData("/proc/self/cmdline", g_appName, NAME_NORMAL_LEN)) {
444 HILOG_ERROR(LOG_CORE, "get app name failed, %{public}d", errno);
445 }
446 }
447
448 g_appTracePrefix = std::string(g_appName);
449 SetCommStr();
450 std::string pidStr = std::string(g_pid);
451 std::string pidFixStr = std::string(PID_STR_MAX - pidStr.length(), ' ');
452 g_appTracePrefix += "-" + pidStr + pidFixStr + " (" + pidFixStr + pidStr + ")";
453 }
454
SetAllThreadInfo(const int & tid)455 bool SetAllThreadInfo(const int& tid)
456 {
457 std::string tidStr = std::to_string(tid);
458 std::string file = "/proc/self/task/" + tidStr + "/comm";
459 char comm[NAME_NORMAL_LEN + 1] = {0};
460 if (!GetProcData(file.c_str(), comm, NAME_NORMAL_LEN)) {
461 static bool isWriteLog = false;
462 WriteOnceLog(LOG_ERROR, "get comm failed", isWriteLog);
463 return false;
464 }
465 if (comm[strlen(comm) - 1] == '\n') {
466 comm[strlen(comm) - 1] = '\0';
467 }
468 g_appTracePrefix = std::string(comm);
469 SetCommStr();
470
471 std::string pidStr = std::string(g_pid);
472 std::string tidFixStr = std::string(PID_STR_MAX - tidStr.length(), ' ');
473 std::string pidFixStr = std::string(PID_STR_MAX - pidStr.length(), ' ');
474 g_appTracePrefix += "-" + tidStr + tidFixStr + " (" + pidFixStr + pidStr + ")";
475
476 return true;
477 }
478
SetAppTraceBuffer(char * buf,const int len,MarkerType type,const std::string & name,const int64_t value)479 int SetAppTraceBuffer(char* buf, const int len, MarkerType type, const std::string& name, const int64_t value)
480 {
481 struct timespec ts = { 0, 0 };
482 clock_gettime(CLOCK_BOOTTIME, &ts);
483 int cpu = sched_getcpu();
484 if (cpu == -1) {
485 static bool isWriteLog = false;
486 WriteOnceLog(LOG_ERROR, "get cpu failed", isWriteLog);
487 return -1;
488 }
489
490 int bytes = 0;
491 if (type == MARKER_BEGIN) {
492 bytes = snprintf_s(buf, len, len - 1, " %s [%03d] .... %lu.%06lu: tracing_mark_write: B|%s|H:%s \n",
493 g_appTracePrefix.c_str(), cpu, static_cast<long>(ts.tv_sec),
494 static_cast<long>(ts.tv_nsec / NS_TO_MS), g_pid, name.c_str());
495 } else if (type == MARKER_END) {
496 bytes = snprintf_s(buf, len, len - 1, " %s [%03d] .... %lu.%06lu: tracing_mark_write: E|%s|\n",
497 g_appTracePrefix.c_str(), cpu, static_cast<long>(ts.tv_sec),
498 static_cast<long>(ts.tv_nsec / NS_TO_MS), g_pid);
499 } else {
500 char marktypestr = g_markTypes[type];
501 bytes = snprintf_s(buf, len, len - 1, " %s [%03d] .... %lu.%06lu: tracing_mark_write: %c|%s|H:%s|%lld\n",
502 g_appTracePrefix.c_str(), cpu, static_cast<long>(ts.tv_sec),
503 static_cast<long>(ts.tv_nsec / NS_TO_MS), marktypestr, g_pid, name.c_str(), value);
504 }
505
506 return bytes;
507 }
508
SetAppTrace(const int len,MarkerType type,const std::string & name,const int64_t value)509 void SetAppTrace(const int len, MarkerType type, const std::string& name, const int64_t value)
510 {
511 // get buffer
512 char* buf = GetTraceBuffer(len);
513 if (buf == nullptr) {
514 return;
515 }
516
517 int bytes = SetAppTraceBuffer(buf, len, type, name, value);
518 if (bytes > 0) {
519 g_traceEventNum += 1;
520 g_writeOffset += bytes;
521 }
522 }
523
WriteAppTraceLong(const int len,MarkerType type,const std::string & name,const int64_t value)524 void WriteAppTraceLong(const int len, MarkerType type, const std::string& name, const int64_t value)
525 {
526 // 1 write cache data.
527 if (!WriteTraceToFile(g_traceBuffer.get(), g_writeOffset)) {
528 return;
529 }
530
531 // 2 apply new memory and directly write file.
532 auto buffer = std::make_unique<char[]>(len);
533 if (buffer == nullptr) {
534 static bool isWriteLog = false;
535 WriteOnceLog(LOG_ERROR, "memory allocation failed", isWriteLog);
536 return;
537 }
538
539 int bytes = SetAppTraceBuffer(buffer.get(), len, type, name, value);
540 if (bytes > 0) {
541 if (!WriteTraceToFile(buffer.get(), bytes)) {
542 return;
543 }
544 g_traceEventNum += 1;
545 }
546 }
547
CheckFileSize(int len)548 bool CheckFileSize(int len)
549 {
550 if (static_cast<uint64_t>(g_fileSize + g_writeOffset + len) > g_fileLimitSize.load()) {
551 static bool isWriteLog = false;
552 WriteOnceLog(LOG_INFO, "File size limit exceeded, stop capture trace.", isWriteLog);
553 StopCaptureAppTrace();
554 return false;
555 }
556
557 return true;
558 }
559
WriteAppTrace(MarkerType type,const std::string & name,const int64_t value)560 void WriteAppTrace(MarkerType type, const std::string& name, const int64_t value)
561 {
562 int tid = getproctid();
563 int len = PREFIX_MAX_SIZE + name.length();
564 if (g_appFlag == FLAG_MAIN_THREAD && g_tgid == tid) {
565 if (!CheckFileSize(len)) {
566 return;
567 }
568
569 if (g_appTracePrefix.empty()) {
570 SetMainThreadInfo();
571 }
572
573 if (len <= DEFAULT_CACHE_SIZE) {
574 SetAppTrace(len, type, name, value);
575 } else {
576 WriteAppTraceLong(len, type, name, value);
577 }
578 } else if (g_appFlag == FLAG_ALL_THREAD) {
579 std::unique_lock<std::recursive_mutex> lock(g_appTraceMutex);
580 if (!CheckFileSize(len)) {
581 return;
582 }
583
584 SetAllThreadInfo(tid);
585
586 if (len <= DEFAULT_CACHE_SIZE) {
587 SetAppTrace(len, type, name, value);
588 } else {
589 WriteAppTraceLong(len, type, name, value);
590 }
591 }
592 }
593
AddHitraceMeterMarker(MarkerType type,uint64_t tag,const std::string & name,const int64_t value,const HiTraceIdStruct * hiTraceIdStruct=nullptr)594 void AddHitraceMeterMarker(MarkerType type, uint64_t tag, const std::string& name, const int64_t value,
595 const HiTraceIdStruct* hiTraceIdStruct = nullptr)
596 {
597 if (UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
598 return;
599 }
600 // attention: if appspawn encounters a crash exception, we should reload pid.
601 if (UNEXPECTANTLY(g_needReloadPid && !g_pidHasReload)) {
602 ReloadPid();
603 }
604 if (UNEXPECTANTLY(!g_isHitraceMeterInit)) {
605 struct timespec ts = { 0, 0 };
606 if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1 || ts.tv_sec < 25) { // 25 : register after boot 25s
607 return;
608 }
609 std::call_once(g_onceFlag, OpenTraceMarkerFile);
610 }
611 UpdateSysParamTags();
612 if (UNEXPECTANTLY(g_tagsProperty & tag) && g_markerFd != -1) {
613 int pid = 0;
614 if (!OHOS::HiviewDFX::Hitrace::StringToInt(g_pid, pid)) {
615 return;
616 }
617 if (tag == HITRACE_TAG_APP && g_appTagMatchPid > 0 && g_appTagMatchPid != pid) {
618 return;
619 }
620 // record fomart: "type|pid|name value".
621 char buf[BUFFER_LEN] = {0};
622 int len = name.length();
623 if (EXPECTANTLY(len <= NAME_NORMAL_LEN)) {
624 HiTraceId hiTraceId = (hiTraceIdStruct == nullptr) ? HiTraceChain::GetId() : HiTraceId(*hiTraceIdStruct);
625 bool isHiTraceIdValid = hiTraceId.IsValid();
626 int bytes = 0;
627 if (type == MARKER_BEGIN) {
628 bytes = isHiTraceIdValid ? snprintf_s(buf, sizeof(buf), sizeof(buf) - 1,
629 "B|%s|H:[%llx,%llx,%llx]#%s ", g_pid, hiTraceId.GetChainId(),
630 hiTraceId.GetSpanId(), hiTraceId.GetParentSpanId(), name.c_str())
631 : snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "B|%s|H:%s ", g_pid, name.c_str());
632 } else if (type == MARKER_END) {
633 bytes = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "E|%s|", g_pid);
634 } else {
635 char marktypestr = g_markTypes[type];
636 bytes = isHiTraceIdValid ? snprintf_s(buf, sizeof(buf), sizeof(buf) - 1,
637 "%c|%s|H:[%llx,%llx,%llx]#%s|%lld", marktypestr, g_pid,
638 hiTraceId.GetChainId(), hiTraceId.GetSpanId(), hiTraceId.GetParentSpanId(), name.c_str(), value)
639 : snprintf_s(buf, sizeof(buf), sizeof(buf) - 1,
640 "%c|%s|H:%s|%lld", marktypestr, g_pid, name.c_str(), value);
641 }
642 WriteToTraceMarker(buf, bytes);
643 } else if (EXPECTANTLY(len < BUFFER_LEN)) {
644 AddTraceMarkerLarge(name, type, value);
645 }
646 }
647 auto appTagload = g_appTag.load();
648 #ifdef HITRACE_UNITTEST
649 appTagload = HITRACE_TAG_APP;
650 #endif
651 if (UNEXPECTANTLY(appTagload != HITRACE_TAG_NOT_READY) && g_appFd != -1) {
652 WriteAppTrace(type, name, value);
653 }
654 }
655 }; // namespace
656
657 #ifdef HITRACE_UNITTEST
SetReloadPid(bool isReloadPid)658 void SetReloadPid(bool isReloadPid)
659 {
660 g_needReloadPid = isReloadPid;
661 }
662
SetpidHasReload(bool ispidHasReload)663 void SetpidHasReload(bool ispidHasReload)
664 {
665 g_pidHasReload = ispidHasReload;
666 }
667
SetAppFd(int appFd)668 void SetAppFd(int appFd)
669 {
670 g_appFd = appFd;
671 }
672
GetSetMainThreadInfo()673 void GetSetMainThreadInfo()
674 {
675 SetMainThreadInfo();
676 }
677
GetSetCommStr()678 void GetSetCommStr()
679 {
680 SetCommStr();
681 }
682
SetTraceBuffer(int size)683 void SetTraceBuffer(int size)
684 {
685 GetTraceBuffer(size);
686 }
687
SetAddTraceMarkerLarge(const std::string & name,const int64_t value)688 void SetAddTraceMarkerLarge(const std::string& name, const int64_t value)
689 {
690 AddTraceMarkerLarge(name, MARKER_BEGIN, value);
691 }
692
SetAddHitraceMeterMarker(uint64_t label,const std::string & value)693 void SetAddHitraceMeterMarker(uint64_t label, const std::string& value)
694 {
695 AddHitraceMeterMarker(MARKER_BEGIN, label, value, 0);
696 }
697
SetWriteToTraceMarker(const char * buf,const int count)698 void SetWriteToTraceMarker(const char* buf, const int count)
699 {
700 WriteToTraceMarker(buf, count);
701 }
702
SetGetProcData(const char * file)703 void SetGetProcData(const char* file)
704 {
705 GetProcData(file, g_appName, NAME_NORMAL_LEN);
706 }
707
SetHitracePerfScoped(int fd1st,int fd2nd)708 void HitracePerfScoped::SetHitracePerfScoped(int fd1st, int fd2nd)
709 {
710 if (fd1st == -1 && fd2nd == -1) {
711 fd1st_ = fd1st;
712 fd2nd_ = fd2nd;
713 }
714 GetInsCount();
715 GetCycleCount();
716 }
717
SetCachedHandleAndAppPidCachedHandle(CachedHandle cachedHandle,CachedHandle appPidCachedHandle)718 void SetCachedHandleAndAppPidCachedHandle(CachedHandle cachedHandle, CachedHandle appPidCachedHandle)
719 {
720 g_cachedHandle = cachedHandle;
721 g_appPidCachedHandle = appPidCachedHandle;
722 UpdateSysParamTags();
723 }
724
SetMarkerFd(int markerFd)725 void SetMarkerFd(int markerFd)
726 {
727 if (markerFd != -1) {
728 g_markerFd = -1;
729 }
730 }
731
SetWriteAppTrace(TraceFlag appFlag,const std::string & name,const int64_t value,bool tid)732 void SetWriteAppTrace(TraceFlag appFlag, const std::string& name, const int64_t value, bool tid)
733 {
734 if (tid) {
735 g_tgid = getproctid();
736 }
737 g_appFlag = appFlag;
738 WriteAppTrace(MARKER_BEGIN, name, value);
739 }
740
SetWriteOnceLog(LogLevel loglevel,const std::string & logStr,bool & isWrite)741 void SetWriteOnceLog(LogLevel loglevel, const std::string& logStr, bool& isWrite)
742 {
743 WriteOnceLog(loglevel, logStr, isWrite);
744 }
745
SetappTracePrefix(const std::string & appTracePrefix)746 void SetappTracePrefix(const std::string& appTracePrefix)
747 {
748 g_appTracePrefix = appTracePrefix;
749 }
750
SetMarkerType(TraceFlag appFlag,const std::string & name,const int64_t value,bool tid)751 void SetMarkerType(TraceFlag appFlag, const std::string& name, const int64_t value, bool tid)
752 {
753 if (tid) {
754 g_tgid = getproctid();
755 }
756 g_appFlag = appFlag;
757 WriteAppTrace(MARKER_ASYNC_BEGIN, name, value);
758 }
759
SetWriteAppTraceLong(const int len,const std::string & name,const int64_t value)760 void SetWriteAppTraceLong(const int len, const std::string& name, const int64_t value)
761 {
762 WriteAppTraceLong(len, MARKER_BEGIN, name, value);
763 }
764 #endif
UpdateTraceLabel(void)765 void UpdateTraceLabel(void)
766 {
767 if (!g_isHitraceMeterInit) {
768 return;
769 }
770 UpdateSysParamTags();
771 }
772
SetTraceDisabled(bool disable)773 void SetTraceDisabled(bool disable)
774 {
775 g_isHitraceMeterDisabled = disable;
776 }
777
StartTraceWrapper(uint64_t label,const char * value)778 void StartTraceWrapper(uint64_t label, const char *value)
779 {
780 std::string traceValue = value;
781 StartTrace(label, traceValue);
782 }
783
StartTrace(uint64_t label,const std::string & value,float limit UNUSED_PARAM)784 void StartTrace(uint64_t label, const std::string& value, float limit UNUSED_PARAM)
785 {
786 AddHitraceMeterMarker(MARKER_BEGIN, label, value, 0);
787 }
788
StartTraceDebug(bool isDebug,uint64_t label,const std::string & value,float limit UNUSED_PARAM)789 void StartTraceDebug(bool isDebug, uint64_t label, const std::string& value, float limit UNUSED_PARAM)
790 {
791 if (!isDebug) {
792 return;
793 }
794 AddHitraceMeterMarker(MARKER_BEGIN, label, value, 0);
795 }
796
StartTraceArgs(uint64_t label,const char * fmt,...)797 void StartTraceArgs(uint64_t label, const char *fmt, ...)
798 {
799 UpdateSysParamTags();
800 if (!(label & g_tagsProperty) || UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
801 return;
802 }
803 char name[VAR_NAME_MAX_SIZE] = { 0 };
804 va_list args;
805 va_start(args, fmt);
806 int res = vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args);
807 va_end(args);
808 if (res < 0) {
809 HILOG_ERROR(LOG_CORE, "vsnprintf_s failed: %{public}d, name: %{public}s", errno, fmt);
810 return;
811 }
812 AddHitraceMeterMarker(MARKER_BEGIN, label, name, 0);
813 }
814
StartTraceArgsDebug(bool isDebug,uint64_t label,const char * fmt,...)815 void StartTraceArgsDebug(bool isDebug, uint64_t label, const char *fmt, ...)
816 {
817 UpdateSysParamTags();
818 if (!isDebug || !(label & g_tagsProperty) || UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
819 return;
820 }
821 char name[VAR_NAME_MAX_SIZE] = { 0 };
822 va_list args;
823
824 va_start(args, fmt);
825 int res = vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args);
826 va_end(args);
827 if (res < 0) {
828 HILOG_ERROR(LOG_CORE, "vsnprintf_s failed: %{public}d, name: %{public}s", errno, fmt);
829 return;
830 }
831 AddHitraceMeterMarker(MARKER_BEGIN, label, name, 0);
832 }
833
FinishTrace(uint64_t label)834 void FinishTrace(uint64_t label)
835 {
836 AddHitraceMeterMarker(MARKER_END, label, EMPTY_TRACE_NAME, 0);
837 }
838
FinishTraceDebug(bool isDebug,uint64_t label)839 void FinishTraceDebug(bool isDebug, uint64_t label)
840 {
841 if (!isDebug) {
842 return;
843 }
844 AddHitraceMeterMarker(MARKER_END, label, EMPTY_TRACE_NAME, 0);
845 }
846
StartAsyncTrace(uint64_t label,const std::string & value,int32_t taskId,float limit UNUSED_PARAM)847 void StartAsyncTrace(uint64_t label, const std::string& value, int32_t taskId, float limit UNUSED_PARAM)
848 {
849 AddHitraceMeterMarker(MARKER_ASYNC_BEGIN, label, value, taskId);
850 }
851
StartAsyncTraceWrapper(uint64_t label,const char * value,int32_t taskId)852 void StartAsyncTraceWrapper(uint64_t label, const char *value, int32_t taskId)
853 {
854 std::string traceValue = value;
855 StartAsyncTrace(label, traceValue, taskId);
856 }
857
StartTraceChain(uint64_t label,const struct HiTraceIdStruct * hiTraceId,const char * value)858 void StartTraceChain(uint64_t label, const struct HiTraceIdStruct* hiTraceId, const char *value)
859 {
860 AddHitraceMeterMarker(MARKER_BEGIN, label, value, 0, hiTraceId);
861 }
862
StartAsyncTraceDebug(bool isDebug,uint64_t label,const std::string & value,int32_t taskId,float limit UNUSED_PARAM)863 void StartAsyncTraceDebug(bool isDebug, uint64_t label, const std::string& value, int32_t taskId,
864 float limit UNUSED_PARAM)
865 {
866 if (!isDebug) {
867 return;
868 }
869 AddHitraceMeterMarker(MARKER_ASYNC_BEGIN, label, value, taskId);
870 }
871
StartAsyncTraceArgs(uint64_t label,int32_t taskId,const char * fmt,...)872 void StartAsyncTraceArgs(uint64_t label, int32_t taskId, const char *fmt, ...)
873 {
874 UpdateSysParamTags();
875 if (!(label & g_tagsProperty) || UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
876 return;
877 }
878 char name[VAR_NAME_MAX_SIZE] = { 0 };
879 va_list args;
880
881 va_start(args, fmt);
882 int res = vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args);
883 va_end(args);
884 if (res < 0) {
885 HILOG_ERROR(LOG_CORE, "vsnprintf_s failed: %{public}d, name: %{public}s", errno, fmt);
886 return;
887 }
888 AddHitraceMeterMarker(MARKER_ASYNC_BEGIN, label, name, taskId);
889 }
890
StartAsyncTraceArgsDebug(bool isDebug,uint64_t label,int32_t taskId,const char * fmt,...)891 void StartAsyncTraceArgsDebug(bool isDebug, uint64_t label, int32_t taskId, const char *fmt, ...)
892 {
893 UpdateSysParamTags();
894 if (!isDebug || !(label & g_tagsProperty) || UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
895 return;
896 }
897 char name[VAR_NAME_MAX_SIZE] = { 0 };
898 va_list args;
899
900 va_start(args, fmt);
901 int res = vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args);
902 va_end(args);
903 if (res < 0) {
904 HILOG_ERROR(LOG_CORE, "vsnprintf_s failed: %{public}d, name: %{public}s", errno, fmt);
905 return;
906 }
907 AddHitraceMeterMarker(MARKER_ASYNC_BEGIN, label, name, taskId);
908 }
909
FinishAsyncTrace(uint64_t label,const std::string & value,int32_t taskId)910 void FinishAsyncTrace(uint64_t label, const std::string& value, int32_t taskId)
911 {
912 AddHitraceMeterMarker(MARKER_ASYNC_END, label, value, taskId);
913 }
914
FinishAsyncTraceWrapper(uint64_t label,const char * value,int32_t taskId)915 void FinishAsyncTraceWrapper(uint64_t label, const char *value, int32_t taskId)
916 {
917 std::string traceValue = value;
918 FinishAsyncTrace(label, traceValue, taskId);
919 }
920
FinishAsyncTraceDebug(bool isDebug,uint64_t label,const std::string & value,int32_t taskId)921 void FinishAsyncTraceDebug(bool isDebug, uint64_t label, const std::string& value, int32_t taskId)
922 {
923 if (!isDebug) {
924 return;
925 }
926 AddHitraceMeterMarker(MARKER_ASYNC_END, label, value, taskId);
927 }
928
FinishAsyncTraceArgs(uint64_t label,int32_t taskId,const char * fmt,...)929 void FinishAsyncTraceArgs(uint64_t label, int32_t taskId, const char *fmt, ...)
930 {
931 UpdateSysParamTags();
932 if (!(label & g_tagsProperty) || UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
933 return;
934 }
935 char name[VAR_NAME_MAX_SIZE] = { 0 };
936 va_list args;
937
938 va_start(args, fmt);
939 int res = vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args);
940 va_end(args);
941 if (res < 0) {
942 HILOG_ERROR(LOG_CORE, "vsnprintf_s failed: %{public}d, name: %{public}s", errno, fmt);
943 return;
944 }
945 AddHitraceMeterMarker(MARKER_ASYNC_END, label, name, taskId);
946 }
947
FinishAsyncTraceArgsDebug(bool isDebug,uint64_t label,int32_t taskId,const char * fmt,...)948 void FinishAsyncTraceArgsDebug(bool isDebug, uint64_t label, int32_t taskId, const char *fmt, ...)
949 {
950 UpdateSysParamTags();
951 if (!isDebug || !(label & g_tagsProperty) || UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
952 return;
953 }
954 char name[VAR_NAME_MAX_SIZE] = { 0 };
955 va_list args;
956
957 va_start(args, fmt);
958 int res = vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args);
959 va_end(args);
960 if (res < 0) {
961 HILOG_ERROR(LOG_CORE, "vsnprintf_s failed: %{public}d, name: %{public}s", errno, fmt);
962 return;
963 }
964 AddHitraceMeterMarker(MARKER_ASYNC_END, label, name, taskId);
965 }
966
MiddleTrace(uint64_t label,const std::string & beforeValue UNUSED_PARAM,const std::string & afterValue)967 void MiddleTrace(uint64_t label, const std::string& beforeValue UNUSED_PARAM, const std::string& afterValue)
968 {
969 AddHitraceMeterMarker(MARKER_END, label, EMPTY_TRACE_NAME, 0);
970 AddHitraceMeterMarker(MARKER_BEGIN, label, afterValue, 0);
971 }
972
MiddleTraceDebug(bool isDebug,uint64_t label,const std::string & beforeValue UNUSED_PARAM,const std::string & afterValue)973 void MiddleTraceDebug(bool isDebug, uint64_t label, const std::string& beforeValue UNUSED_PARAM,
974 const std::string& afterValue)
975 {
976 if (!isDebug) {
977 return;
978 }
979 AddHitraceMeterMarker(MARKER_END, label, EMPTY_TRACE_NAME, 0);
980 AddHitraceMeterMarker(MARKER_BEGIN, label, afterValue, 0);
981 }
982
CountTrace(uint64_t label,const std::string & name,int64_t count)983 void CountTrace(uint64_t label, const std::string& name, int64_t count)
984 {
985 AddHitraceMeterMarker(MARKER_INT, label, name, count);
986 }
987
CountTraceDebug(bool isDebug,uint64_t label,const std::string & name,int64_t count)988 void CountTraceDebug(bool isDebug, uint64_t label, const std::string& name, int64_t count)
989 {
990 if (!isDebug) {
991 return;
992 }
993 AddHitraceMeterMarker(MARKER_INT, label, name, count);
994 }
995
CountTraceWrapper(uint64_t label,const char * name,int64_t count)996 void CountTraceWrapper(uint64_t label, const char *name, int64_t count)
997 {
998 std::string traceName = name;
999 CountTrace(label, traceName, count);
1000 }
1001
HitraceMeterFmtScoped(uint64_t label,const char * fmt,...)1002 HitraceMeterFmtScoped::HitraceMeterFmtScoped(uint64_t label, const char *fmt, ...) : mTag(label)
1003 {
1004 UpdateSysParamTags();
1005 if (!(label & g_tagsProperty) || UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
1006 return;
1007 }
1008 char name[VAR_NAME_MAX_SIZE] = { 0 };
1009 va_list args;
1010
1011 va_start(args, fmt);
1012 int res = vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args);
1013 va_end(args);
1014 if (res < 0) {
1015 HILOG_ERROR(LOG_CORE, "vsnprintf_s failed: %{public}d, name: %{public}s", errno, fmt);
1016 return;
1017 }
1018 AddHitraceMeterMarker(MARKER_BEGIN, label, name, 0);
1019 }
1020
IsTagEnabled(uint64_t tag)1021 bool IsTagEnabled(uint64_t tag)
1022 {
1023 UpdateSysParamTags();
1024 return ((tag & g_tagsProperty) == tag);
1025 }
1026
1027 // For native process, the caller is responsible passing the full path of the fileName.
1028 // For hap application, StartCaputreAppTrace() fill fileName
1029 // as /data/app/el2/100/log/$(processname)/trace/$(processname)_$(date)_&(time).trace and return to caller.
StartCaptureAppTrace(TraceFlag flag,uint64_t tags,uint64_t limitSize,std::string & fileName)1030 int StartCaptureAppTrace(TraceFlag flag, uint64_t tags, uint64_t limitSize, std::string& fileName)
1031 {
1032 auto ret = CheckAppTraceArgs(flag, tags, limitSize);
1033 if (ret != RET_SUCC) {
1034 return ret;
1035 }
1036
1037 std::unique_lock<std::recursive_mutex> lock(g_appTraceMutex);
1038 if (g_appFd != -1) {
1039 HILOG_INFO(LOG_CORE, "CaptureAppTrace started, return");
1040 return RET_STARTED;
1041 }
1042
1043 g_traceBuffer = std::make_unique<char[]>(DEFAULT_CACHE_SIZE);
1044 if (g_traceBuffer == nullptr) {
1045 HILOG_ERROR(LOG_CORE, "memory allocation failed: %{public}d(%{public}s)", errno, strerror(errno));
1046 return RET_FAILD;
1047 }
1048
1049 g_appFlag = flag;
1050 g_appTag = tags;
1051 g_fileLimitSize = (limitSize > MAX_FILE_SIZE) ? MAX_FILE_SIZE : limitSize;
1052 g_tgid = getprocpid();
1053 g_appTracePrefix = "";
1054
1055 std::string destFileName = fileName;
1056 if (destFileName.empty()) {
1057 auto retval = SetAppFileName(destFileName, fileName);
1058 if (retval != RET_SUCC) {
1059 HILOG_ERROR(LOG_CORE, "set appFileName failed: %{public}d(%{public}s)", errno, strerror(errno));
1060 return retval;
1061 }
1062 }
1063
1064 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // 0644
1065 g_appFd = open(destFileName.c_str(), O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC, mode);
1066 if (g_appFd == -1) {
1067 HILOG_ERROR(LOG_CORE, "open destFileName failed: %{public}d(%{public}s)", errno, strerror(errno));
1068 if (errno == ENOENT) {
1069 return RET_FAIL_ENOENT;
1070 } else if (errno == EACCES) {
1071 return RET_FAIL_EACCES;
1072 } else {
1073 return RET_FAILD;
1074 }
1075 }
1076
1077 return InitTraceHead();
1078 }
1079
StopCaptureAppTrace()1080 int StopCaptureAppTrace()
1081 {
1082 std::unique_lock<std::recursive_mutex> lock(g_appTraceMutex);
1083 if (g_appFd == -1) {
1084 HILOG_INFO(LOG_CORE, "CaptureAppTrace stopped, return");
1085 return RET_STOPPED;
1086 }
1087
1088 // Write cache data
1089 WriteTraceToFile(g_traceBuffer.get(), g_writeOffset);
1090
1091 std::string eventNumStr = std::to_string(g_traceEventNum) + "/" + std::to_string(g_traceEventNum);
1092 std::vector<char> buffer(TRACE_TXT_HEADER_MAX, '\0');
1093 int used = snprintf_s(buffer.data(), buffer.size(), buffer.size() - 1, TRACE_TXT_HEADER_FORMAT.c_str(),
1094 eventNumStr.c_str(), std::to_string(CPU_CORE_NUM).c_str());
1095 if (used <= 0) {
1096 HILOG_ERROR(LOG_CORE, "format trace header failed: %{public}d(%{public}s)", errno, strerror(errno));
1097 return RET_FAILD;
1098 }
1099
1100 lseek(g_appFd, 0, SEEK_SET); // Move the write pointer to populate the file header.
1101 if (write(g_appFd, buffer.data(), used) != used) {
1102 HILOG_ERROR(LOG_CORE, "write trace header failed: %{public}d(%{public}s)", errno, strerror(errno));
1103 return RET_FAILD;
1104 }
1105
1106 g_fileSize = 0;
1107 g_writeOffset = 0;
1108 g_traceEventNum = 0;
1109 g_appTracePrefix = "";
1110 g_appTag = HITRACE_TAG_NOT_READY;
1111
1112 close(g_appFd);
1113 g_appFd = -1;
1114 g_traceBuffer.reset();
1115 g_traceBuffer = nullptr;
1116
1117 return RET_SUCC;
1118 }
1119
HitracePerfScoped(bool isDebug,uint64_t tag,const std::string & name)1120 HitracePerfScoped::HitracePerfScoped(bool isDebug, uint64_t tag, const std::string &name) : mTag_(tag), mName_(name)
1121 {
1122 if (!isDebug) {
1123 return;
1124 }
1125 struct perf_event_attr peIns;
1126 (void)memset_s(&peIns, sizeof(struct perf_event_attr), 0, sizeof(struct perf_event_attr));
1127 peIns.type = PERF_TYPE_HARDWARE;
1128 peIns.size = sizeof(struct perf_event_attr);
1129 peIns.config = PERF_COUNT_HW_INSTRUCTIONS;
1130 peIns.disabled = 1;
1131 peIns.exclude_kernel = 0;
1132 peIns.exclude_hv = 0;
1133 fd1st_ = syscall(__NR_perf_event_open, &peIns, 0, -1, -1, 0);
1134 if (fd1st_ == -1) {
1135 err_ = errno;
1136 return;
1137 }
1138 struct perf_event_attr peCycles;
1139 (void)memset_s(&peCycles, sizeof(struct perf_event_attr), 0, sizeof(struct perf_event_attr));
1140 peCycles.type = PERF_TYPE_HARDWARE;
1141 peCycles.size = sizeof(struct perf_event_attr);
1142 peCycles.config = PERF_COUNT_HW_CPU_CYCLES;
1143 peCycles.disabled = 1;
1144 peCycles.exclude_kernel = 0;
1145 peCycles.exclude_hv = 0;
1146 fd2nd_ = syscall(__NR_perf_event_open, &peCycles, 0, -1, -1, 0);
1147 if (fd2nd_ == -1) {
1148 err_ = errno;
1149 return;
1150 }
1151 ioctl(fd1st_, PERF_EVENT_IOC_RESET, 0);
1152 ioctl(fd1st_, PERF_EVENT_IOC_ENABLE, 0);
1153 ioctl(fd2nd_, PERF_EVENT_IOC_RESET, 0);
1154 ioctl(fd2nd_, PERF_EVENT_IOC_ENABLE, 0);
1155 }
1156
~HitracePerfScoped()1157 HitracePerfScoped::~HitracePerfScoped()
1158 {
1159 if (fd1st_ != -1) {
1160 ioctl(fd1st_, PERF_EVENT_IOC_DISABLE, 0);
1161 read(fd1st_, &countIns_, sizeof(long long));
1162 close(fd1st_);
1163 CountTrace(mTag_, mName_ + "-Ins", countIns_);
1164 }
1165 if (fd2nd_ != -1) {
1166 ioctl(fd2nd_, PERF_EVENT_IOC_DISABLE, 0);
1167 read(fd2nd_, &countCycles_, sizeof(long long));
1168 close(fd2nd_);
1169 CountTrace(mTag_, mName_ + "-Cycle", countCycles_);
1170 }
1171 }
1172
GetInsCount()1173 inline long long HitracePerfScoped::GetInsCount()
1174 {
1175 if (fd1st_ == -1) {
1176 return err_;
1177 }
1178 read(fd1st_, &countIns_, sizeof(long long));
1179 return countIns_;
1180 }
1181
GetCycleCount()1182 inline long long HitracePerfScoped::GetCycleCount()
1183 {
1184 if (fd2nd_ == -1) {
1185 return err_;
1186 }
1187 read(fd2nd_, &countCycles_, sizeof(long long));
1188 return countCycles_;
1189 }
1190