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