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