1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "appcapture_perf.h"
16
17 #include <mutex>
18 #include <algorithm>
19 #include <string>
20
21 #include "hisysevent.h"
22 #include "lperf.h"
23 #include "hilog_tag_wrapper.h"
24
25 namespace OHOS {
26 namespace AppExecFwk {
27 const int32_t CAPTURE_DURATION = 1000;
28 const int32_t FREQ = 100;
29 const int32_t ERROR = -1;
30 const int32_t NO_ERROR = 0;
31
GetInstance()32 AppCapturePerf &AppCapturePerf::GetInstance()
33 {
34 static AppCapturePerf instance_;
35 return instance_;
36 }
37
SplitStr(const std::string & s,char delimiter)38 std::vector<std::string> AppCapturePerf::SplitStr(const std::string &s, char delimiter)
39 {
40 std::vector<std::string> tokens;
41 std::string token;
42 std::istringstream tokenStream(s);
43 while (std::getline(tokenStream, token, delimiter)) {
44 tokens.push_back(token);
45 }
46 return tokens;
47 }
48
CapturePerf(const FaultData & faultData)49 int32_t AppCapturePerf::CapturePerf(const FaultData &faultData)
50 {
51 std::lock_guard<std::mutex> lock(singletonMutex_);
52
53 int64_t perfId = 0;
54 auto ret = std::from_chars(faultData.timeoutMarkers.c_str(),
55 faultData.timeoutMarkers.c_str() + faultData.timeoutMarkers.size(), perfId);
56 if (ret.ec != std::errc()) {
57 TAG_LOGE(AAFwkTag::APPDFR, "perfId stoi(%{public}s) failed", faultData.timeoutMarkers.c_str());
58 return ERROR;
59 }
60
61 std::vector<int32_t> tids;
62 std::vector<std::string> threads = SplitStr(faultData.errorObject.stack, ',');
63 for (uint32_t i = 0; i < threads.size(); i++) {
64 if (threads[i] == "") {
65 continue;
66 }
67 int32_t tid = -1;
68 auto res = std::from_chars(threads[i].c_str(), threads[i].c_str() + threads[i].size(), tid);
69 if (res.ec != std::errc()) {
70 TAG_LOGE(AAFwkTag::APPDFR, "tid conversion failed");
71 }
72 tids.push_back(tid);
73 }
74 if (tids.empty()) {
75 TAG_LOGE(AAFwkTag::APPDFR, "No valid thread IDs found");
76 return ERROR;
77 }
78 int res = 0;
79 auto &instance = Developtools::HiPerf::HiPerfLocal::Lperf::GetInstance();
80 res = instance.StartProcessStackSampling(tids, FREQ, CAPTURE_DURATION, false);
81 if (res != 0) {
82 TAG_LOGE(AAFwkTag::APPDFR, "hiperf stack capture failed");
83 }
84 std::vector<std::string> perf;
85 for (uint32_t i = 0; i < tids.size(); i++) {
86 std::string info;
87 res = instance.CollectSampleStackByTid(tids[i], info);
88 if (res != 0) {
89 perf.push_back("");
90 continue;
91 }
92 perf.push_back(info);
93 }
94 instance.FinishProcessStackSampling();
95 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::AAFWK, "CPU_LOAD_CAPTURE_STACK",
96 HiviewDFX::HiSysEvent::EventType::STATISTIC, "APP_NAME", faultData.errorObject.name,
97 "TIDS", tids, "PERF", perf, "PERFID", perfId);
98 return NO_ERROR;
99 }
100
101 } // namespace AppExecFwk
102 } // namespace OHOS