• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.data(), "r"), pclose);
70     CHECK_TRUE(pipe, false, "BytraceCall::RunCommand: create popen FAILED!");
71 
72     std::array<char, READ_BUFFER_SIZE> buffer;
73     std::string result;
74     while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
75         result += buffer.data();
76     }
77     PROFILER_LOG_INFO(LOG_CORE, "%s:runCommand result: %s", __func__, result.data());
78     return true;
79 }
80 
BeginTrace()81 bool BeginTrace()
82 {
83     // two case: real-time and offline type.
84     std::string beginCmd;
85     if (g_bytraceInfo->isRoot) {
86         beginCmd = "su root ";
87     }
88     beginCmd += "bytrace ";
89     if (g_bytraceInfo->buffSize != 0) {
90         beginCmd += " -b " + std::to_string(g_bytraceInfo->buffSize);
91     }
92     if (!g_bytraceInfo->clockType.empty()) {
93         beginCmd += " --trace_clock " + g_bytraceInfo->clockType;
94     }
95     // real-time: time is set 0.
96     if (g_bytraceInfo->time == 0) {
97         // if time is not set 1s(must >= 1), bytrace tool will use 5s by default.
98         beginCmd += " -t 1 ";
99         beginCmd += " --trace_begin ";
100     } else {
101         beginCmd += " -t " + std::to_string(g_bytraceInfo->time);
102         beginCmd += " -o ";
103         beginCmd += g_bytraceInfo->outFile;
104         beginCmd += " ";
105     }
106     for (const std::string& category : g_bytraceInfo->categoryVec) {
107         beginCmd += category;
108         beginCmd += " ";
109     }
110     return RunCommand(beginCmd);
111 }
112 
StopTrace()113 bool StopTrace()
114 {
115     std::string finishCmd;
116     if (g_bytraceInfo->isRoot) {
117         finishCmd = "su root ";
118     }
119     finishCmd += "bytrace --trace_finish --trace_dump";
120     if (g_bytraceInfo->outFile.empty()) {
121         g_bytraceInfo->outFile = DEFAULT_FILE;
122     }
123     finishCmd += " -o ";
124     finishCmd += g_bytraceInfo->outFile;
125     return RunCommand(finishCmd);
126 }
127 } // namespace
128 
BytracePluginSessionStart(const uint8_t * configData,const uint32_t configSize)129 int BytracePluginSessionStart(const uint8_t* configData, const uint32_t configSize)
130 {
131     std::lock_guard<std::mutex> guard(g_taskMutex);
132     BytracePluginConfig config;
133     int res = config.ParseFromArray(configData, configSize);
134     CHECK_TRUE(res, 0, "BytracePluginSessionStart, parse config FAILED! configSize: %u", configSize);
135     g_bytraceInfo = std::make_unique<BytraceInfo>();
136     ParseConfig(config);
137     res = BeginTrace();
138     CHECK_TRUE(res, 0, "BytracePluginSessionStart, bytrace begin FAILED!");
139     return 0;
140 }
141 
BytracePluginSessionStop()142 int BytracePluginSessionStop()
143 {
144     std::lock_guard<std::mutex> guard(g_taskMutex);
145     // real-time type need finish trace.
146     if (g_bytraceInfo->time == 0) {
147         int res = StopTrace();
148         CHECK_TRUE(res, 0, "BytracePluginSessionStop, bytrace finish FAILED!");
149     }
150     g_bytraceInfo = nullptr;
151     return 0;
152 }
153 
BytraceRegisterWriterStruct(const WriterStruct * writer)154 int BytraceRegisterWriterStruct(const WriterStruct* writer)
155 {
156     PROFILER_LOG_INFO(LOG_CORE, "%s:writer %p", __func__, writer);
157     return 0;
158 }
159 
160 static PluginModuleCallbacks g_callbacks = {
161     .onPluginSessionStart = BytracePluginSessionStart,
162     .onPluginReportResult = nullptr,
163     .onPluginSessionStop = BytracePluginSessionStop,
164     .onRegisterWriterStruct = BytraceRegisterWriterStruct,
165 };
166 
167 EXPORT_API PluginModuleStruct g_pluginModule = {
168     .callbacks = &g_callbacks,
169     .name = "bytrace_plugin",
170     .version = "1.02",
171     .resultBufferSizeHint = MAX_BUFFER_SIZE,
172 };