1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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 "bytrace_module.h"
16
17 #include <array>
18 #include <poll.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <sys/wait.h>
22 #include <unistd.h>
23 #include <vector>
24
25 #include "bytrace_plugin_config.pb.h"
26 #include "logging.h"
27 #include "securec.h"
28
29 namespace {
30 constexpr uint32_t MAX_BUFFER_SIZE = 4 * 1024 * 1024;
31 constexpr uint32_t READ_BUFFER_SIZE = 4096;
32 const std::string DEFAULT_FILE = "/local/data/tmp/bytrace.txt";
33
34 std::mutex g_taskMutex;
35
36 struct BytraceInfo {
37 bool isRoot;
38 uint32_t buffSize;
39 uint32_t time;
40 std::string clockType;
41 std::string outFile;
42 std::vector<std::string> categoryVec;
43 };
44 std::unique_ptr<BytraceInfo> g_bytraceInfo = nullptr;
45
ParseConfig(const BytracePluginConfig & config)46 void ParseConfig(const BytracePluginConfig& config)
47 {
48 if (config.buffe_size() != 0) {
49 g_bytraceInfo->buffSize = config.buffe_size();
50 }
51 g_bytraceInfo->time = config.time();
52 g_bytraceInfo->isRoot = config.is_root();
53 if (!config.clock().empty()) {
54 g_bytraceInfo->clockType = config.clock();
55 }
56 if (!config.outfile_name().empty()) {
57 g_bytraceInfo->outFile = config.outfile_name();
58 }
59 if (!config.categories().empty()) {
60 for (std::string category : config.categories()) {
61 g_bytraceInfo->categoryVec.push_back(category);
62 }
63 }
64 }
65
RunCommand(const std::string & cmd)66 bool RunCommand(const std::string& cmd)
67 {
68 PROFILER_LOG_INFO(LOG_CORE, "%s:start running commond: %s", __func__, cmd.c_str());
69 return true;
70 }
71
BeginTrace()72 bool BeginTrace()
73 {
74 // two case: real-time and offline type.
75 std::string beginCmd;
76 if (g_bytraceInfo->isRoot) {
77 beginCmd = "su root ";
78 }
79 beginCmd += "bytrace ";
80 if (g_bytraceInfo->buffSize != 0) {
81 beginCmd += " -b " + std::to_string(g_bytraceInfo->buffSize);
82 }
83 if (!g_bytraceInfo->clockType.empty()) {
84 beginCmd += " --trace_clock " + g_bytraceInfo->clockType;
85 }
86 // real-time: time is set 0.
87 if (g_bytraceInfo->time == 0) {
88 // if time is not set 1s(must >= 1), bytrace tool will use 5s by default.
89 beginCmd += " -t 1 ";
90 beginCmd += " --trace_begin ";
91 } else {
92 beginCmd += " -t " + std::to_string(g_bytraceInfo->time);
93 beginCmd += " -o ";
94 beginCmd += g_bytraceInfo->outFile;
95 beginCmd += " ";
96 }
97 for (const std::string& category : g_bytraceInfo->categoryVec) {
98 beginCmd += category;
99 beginCmd += " ";
100 }
101 return RunCommand(beginCmd);
102 }
103
StopTrace()104 bool StopTrace()
105 {
106 std::string finishCmd;
107 if (g_bytraceInfo->isRoot) {
108 finishCmd = "su root ";
109 }
110 finishCmd += "bytrace --trace_finish --trace_dump";
111 if (g_bytraceInfo->outFile.empty()) {
112 g_bytraceInfo->outFile = DEFAULT_FILE;
113 }
114 finishCmd += " -o ";
115 finishCmd += g_bytraceInfo->outFile;
116 return RunCommand(finishCmd);
117 }
118 } // namespace
119
BytracePluginSessionStart(const uint8_t * configData,const uint32_t configSize)120 int BytracePluginSessionStart(const uint8_t* configData, const uint32_t configSize)
121 {
122 std::lock_guard<std::mutex> guard(g_taskMutex);
123 BytracePluginConfig config;
124 int res = config.ParseFromArray(configData, configSize);
125 CHECK_TRUE(res, 0, "BytracePluginSessionStart, parse config FAILED! configSize: %u", configSize);
126 g_bytraceInfo = std::make_unique<BytraceInfo>();
127 ParseConfig(config);
128 res = BeginTrace();
129 CHECK_TRUE(res, 0, "BytracePluginSessionStart, bytrace begin FAILED!");
130 return 0;
131 }
132
BytracePluginSessionStop()133 int BytracePluginSessionStop()
134 {
135 std::lock_guard<std::mutex> guard(g_taskMutex);
136 // real-time type need finish trace.
137 if (g_bytraceInfo->time == 0) {
138 int res = StopTrace();
139 CHECK_TRUE(res, 0, "BytracePluginSessionStop, bytrace finish FAILED!");
140 }
141 g_bytraceInfo = nullptr;
142 return 0;
143 }
144
BytraceRegisterWriterStruct(const WriterStruct * writer)145 int BytraceRegisterWriterStruct(const WriterStruct* writer)
146 {
147 PROFILER_LOG_INFO(LOG_CORE, "%s:writer %p", __func__, writer);
148 return 0;
149 }
150
151 static PluginModuleCallbacks g_callbacks = {
152 .onPluginSessionStart = BytracePluginSessionStart,
153 .onPluginReportResult = nullptr,
154 .onPluginSessionStop = BytracePluginSessionStop,
155 .onRegisterWriterStruct = BytraceRegisterWriterStruct,
156 };
157
158 EXPORT_API PluginModuleStruct g_pluginModule = {
159 .callbacks = &g_callbacks,
160 .name = "bytrace_plugin",
161 .version = "1.02",
162 .resultBufferSizeHint = MAX_BUFFER_SIZE,
163 };