• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 <atomic>
16 #include <cinttypes>
17 #include <climits>
18 #include <fcntl.h>
19 #include <fstream>
20 #include <mutex>
21 #include <unistd.h>
22 #include <vector>
23 #include "bytrace.h"
24 #include "hilog/log.h"
25 #include "parameter.h"
26 #include "parameters.h"
27 
28 using namespace std;
29 using namespace OHOS::HiviewDFX;
30 
31 #define EXPECTANTLY(exp) (__builtin_expect(!!(exp), true))
32 #define UNEXPECTANTLY(exp) (__builtin_expect(!!(exp), false))
33 
34 namespace {
35 int g_markerFd = -1;
36 std::once_flag g_onceFlag;
37 
38 std::atomic<bool> g_isBytraceInit(false);
39 std::atomic<uint64_t> g_tagsProperty(BYTRACE_TAG_NOT_READY);
40 
41 const std::string KEY_TRACE_TAG = "debug.bytrace.tags.enableflags";
42 const std::string KEY_APP_NUMBER = "debug.bytrace.app_number";
43 const std::string KEY_RO_DEBUGGABLE = "ro.debuggable";
44 
45 constexpr int NAME_MAX_SIZE = 1000;
46 static std::vector<std::string> g_markTypes = {"B", "E", "S", "F", "C"};
47 enum MarkerType { MARKER_BEGIN, MARKER_END, MARKER_ASYNC_BEGIN, MARKER_ASYNC_END, MARKER_INT, MARKER_MAX };
48 
49 constexpr uint64_t BYTRACE_TAG = 0xd03301;
50 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, BYTRACE_TAG, "BytraceCore"};
51 
ParameterChange(const char * key,const char * value,void * context)52 static void ParameterChange(const char* key, const char* value, void* context)
53 {
54     HiLog::Info(LABEL, "ParameterChange %{public}s", key);
55     UpdateTraceLabel();
56 }
57 
IsAppValid()58 bool IsAppValid()
59 {
60     // Judge if application-level tracing is enabled.
61     if (OHOS::system::GetBoolParameter(KEY_RO_DEBUGGABLE, 0)) {
62         std::ifstream fs;
63         fs.open("/proc/self/cmdline");
64         if (!fs.is_open()) {
65             fprintf(stderr, "IsAppValid, open /proc/self/cmdline failed.\n");
66             return false;
67         }
68 
69         std::string lineStr;
70         std::getline(fs, lineStr);
71         std::string keyPrefix = "debug.bytrace.app_";
72         int nums = OHOS::system::GetIntParameter<int>(KEY_APP_NUMBER, 0);
73         for (int i = 0; i < nums; i++) {
74             std::string keyStr = keyPrefix + std::to_string(i);
75             std::string val = OHOS::system::GetParameter(keyStr, "");
76             if (val == "*" || val == lineStr) {
77                 fs.close();
78                 return true;
79             }
80         }
81     }
82     return false;
83 }
84 
GetSysParamTags()85 uint64_t GetSysParamTags()
86 {
87     // Get the system parameters of KEY_TRACE_TAG.
88     uint64_t tags = OHOS::system::GetUintParameter<uint64_t>(KEY_TRACE_TAG, 0);
89     if (tags == 0) {
90         // HiLog::Error(LABEL, "GetUintParameter %s error.\n", KEY_TRACE_TAG.c_str());
91         return 0;
92     }
93 
94     IsAppValid();
95     return (tags | BYTRACE_TAG_ALWAYS) & BYTRACE_TAG_VALID_MASK;
96 }
97 
98 // open file "trace_marker".
OpenTraceMarkerFile()99 void OpenTraceMarkerFile()
100 {
101     const std::string debugFile = "/sys/kernel/debug/tracing/trace_marker";
102     const std::string traceFile = "/sys/kernel/tracing/trace_marker";
103     g_markerFd = open(debugFile.c_str(), O_WRONLY | O_CLOEXEC);
104     if (g_markerFd == -1) {
105         g_markerFd = open(traceFile.c_str(), O_WRONLY | O_CLOEXEC);
106         if (g_markerFd == -1) {
107             HiLog::Error(LABEL, "open trace file %{public}s failed: %{public}s", traceFile.c_str(), strerror(errno));
108             g_tagsProperty = 0;
109             return;
110         }
111     }
112     g_tagsProperty = GetSysParamTags();
113 
114     if (WatchParameter(KEY_TRACE_TAG.c_str(), ParameterChange, nullptr) != 0) {
115         HiLog::Error(LABEL, "WatchParameter %{public}s failed", KEY_TRACE_TAG.c_str());
116         return;
117     }
118     g_isBytraceInit = true;
119 }
120 }; // namespace
121 
AddBytraceMarker(MarkerType type,uint64_t tag,const std::string & name,const std::string & value)122 void AddBytraceMarker(MarkerType type, uint64_t tag, const std::string& name, const std::string& value)
123 {
124     if (UNEXPECTANTLY(!g_isBytraceInit)) {
125         std::call_once(g_onceFlag, OpenTraceMarkerFile);
126     }
127     if (UNEXPECTANTLY(g_tagsProperty & tag)) {
128         // record fomart: "type|pid|name value".
129         std::string record = g_markTypes[type] + "|";
130         record += std::to_string(getpid()) + "|";
131         record += (name.size() < NAME_MAX_SIZE) ? name : name.substr(0, NAME_MAX_SIZE);
132         record += " " + value;
133         if (write(g_markerFd, record.c_str(), record.size()) < 0) {
134             HiLog::Error(LABEL, "write trace_marker failed, %{public}s", strerror(errno));
135         }
136     }
137 }
138 
UpdateTraceLabel()139 void UpdateTraceLabel()
140 {
141     if (!g_isBytraceInit) {
142         return;
143     }
144     g_tagsProperty = GetSysParamTags();
145 }
146 
StartTrace(uint64_t label,const string & value,float limit)147 void StartTrace(uint64_t label, const string& value, float limit)
148 {
149     string traceName = "H:" + value;
150     AddBytraceMarker(MARKER_BEGIN, label, traceName, "");
151 }
152 
StartTraceDebug(uint64_t label,const string & value,float limit)153 void StartTraceDebug(uint64_t label, const string& value, float limit)
154 {
155 #if (TRACE_LEVEL >= DEBUG_LEVEL)
156     string traceName = "H:" + value + GetHiTraceInfo();
157     AddBytraceMarker(MARKER_BEGIN, label, traceName, "");
158 #endif
159 }
160 
FinishTrace(uint64_t label)161 void FinishTrace(uint64_t label)
162 {
163     AddBytraceMarker(MARKER_END, label, "", "");
164 }
165 
FinishTraceDebug(uint64_t label)166 void FinishTraceDebug(uint64_t label)
167 {
168 #if (TRACE_LEVEL >= DEBUG_LEVEL)
169     AddBytraceMarker(MARKER_END, label, "", "");
170 #endif
171 }
172 
StartAsyncTrace(uint64_t label,const string & value,int32_t taskId,float limit)173 void StartAsyncTrace(uint64_t label, const string& value, int32_t taskId, float limit)
174 {
175     string traceName = "H:" + value;
176     AddBytraceMarker(MARKER_ASYNC_BEGIN, label, traceName, std::to_string(taskId));
177 }
178 
StartAsyncTraceDebug(uint64_t label,const string & value,int32_t taskId,float limit)179 void StartAsyncTraceDebug(uint64_t label, const string& value, int32_t taskId, float limit)
180 {
181 #if (TRACE_LEVEL >= DEBUG_LEVEL)
182     string traceName = "H:" + value;
183     AddBytraceMarker(MARKER_ASYNC_BEGIN, label, traceName, std::to_string(taskId));
184 #endif
185 }
186 
FinishAsyncTrace(uint64_t label,const string & value,int32_t taskId)187 void FinishAsyncTrace(uint64_t label, const string& value, int32_t taskId)
188 {
189     string traceName = "H:" + value;
190     AddBytraceMarker(MARKER_ASYNC_END, label, traceName, std::to_string(taskId));
191 }
192 
FinishAsyncTraceDebug(uint64_t label,const string & value,int32_t taskId)193 void FinishAsyncTraceDebug(uint64_t label, const string& value, int32_t taskId)
194 {
195 #if (TRACE_LEVEL >= DEBUG_LEVEL)
196     string traceName = "H:" + value;
197     AddBytraceMarker(MARKER_ASYNC_END, label, traceName, std::to_string(taskId));
198 #endif
199 }
200 
MiddleTrace(uint64_t label,const string & beforeValue,const std::string & afterValue)201 void MiddleTrace(uint64_t label, const string& beforeValue, const std::string& afterValue)
202 {
203     string traceName = "H:" + afterValue;
204     AddBytraceMarker(MARKER_END, label, "", "");
205     AddBytraceMarker(MARKER_BEGIN, label, traceName, "");
206 }
207 
MiddleTraceDebug(uint64_t label,const string & beforeValue,const std::string & afterValue)208 void MiddleTraceDebug(uint64_t label, const string& beforeValue, const std::string& afterValue)
209 {
210 #if (TRACE_LEVEL >= DEBUG_LEVEL)
211     string traceName = "H:" + afterValue + GetTraceInfo();
212     AddBytraceMarker(MARKER_END, label, "", "");
213     AddBytraceMarker(MARKER_BEGIN, label, traceName, "");
214 #endif
215 }
216 
CountTrace(uint64_t label,const string & name,int64_t count)217 void CountTrace(uint64_t label, const string& name, int64_t count)
218 {
219     string traceName = "H:" + name;
220     AddBytraceMarker(MARKER_INT, label, traceName, std::to_string(count));
221 }
222 
CountTraceDebug(uint64_t label,const string & name,int64_t count)223 void CountTraceDebug(uint64_t label, const string& name, int64_t count)
224 {
225 #if (TRACE_LEVEL >= DEBUG_LEVEL)
226     string traceName = "H:" + name;
227     AddBytraceMarker(MARKER_INT, label, traceName, std::to_string(count));
228 #endif
229 }
230