• 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 
16 #include "command_line.h"
17 #include "google/protobuf/text_format.h"
18 #include "profiler_service.grpc.pb.h"
19 
20 #include <grpcpp/grpcpp.h>
21 
22 #include <cinttypes>
23 #include <cstdio>
24 #include <cstring>
25 #include <fstream>
26 #include <ostream>
27 #include <vector>
28 
29 #include <arpa/inet.h>
30 #include <ifaddrs.h>
31 #include <netinet/in.h>
32 #include <sys/types.h>
33 #include <unistd.h>
34 
35 namespace {
36 constexpr int ADDR_BUFFER_SIZE = 128;
37 constexpr int MS_PER_S = 1000;
38 constexpr uint16_t SERVICE_PORT = 50051;
39 constexpr uint32_t US_PER_MS = 1000;
40 
41 uint32_t g_sampleDuration = 0;
42 
GetLoopbackAddress()43 std::string GetLoopbackAddress()
44 {
45     char addressBuffer[ADDR_BUFFER_SIZE] = "";
46     struct ifaddrs* ifAddrStruct = nullptr;
47     void* tmpAddrPtr = nullptr;
48 
49     getifaddrs(&ifAddrStruct);
50     while (ifAddrStruct != nullptr) {
51         if (ifAddrStruct->ifa_addr->sa_family == AF_INET) {
52             // is a valid IP4 Address
53             tmpAddrPtr = &((reinterpret_cast<struct sockaddr_in*>(ifAddrStruct->ifa_addr))->sin_addr);
54             inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
55             if (strcmp(addressBuffer, "127.0.0.1") == 0) {
56                 break;
57             }
58         } else if (ifAddrStruct->ifa_addr->sa_family == AF_INET6) { // check it is IP6
59             // is a valid IP6 Address
60             tmpAddrPtr = &((reinterpret_cast<struct sockaddr_in*>(ifAddrStruct->ifa_addr))->sin_addr);
61             inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
62         }
63         ifAddrStruct = ifAddrStruct->ifa_next;
64     }
65 
66     freeifaddrs(ifAddrStruct);
67     return addressBuffer;
68 }
69 
GetServicePort()70 uint16_t GetServicePort()
71 {
72     return SERVICE_PORT;
73 }
74 
ReadFileToString(const std::string & fileName)75 std::string ReadFileToString(const std::string& fileName)
76 {
77     std::ifstream inputString(fileName, std::ios::in);
78     if (!inputString) {
79         printf("can't open %s\n", fileName.c_str());
80         return "";
81     }
82     std::string content(std::istreambuf_iterator<char>(inputString), {});
83     return content;
84 }
85 
ReadConfigContent(const std::string & configFile)86 std::string ReadConfigContent(const std::string& configFile)
87 {
88     std::string content;
89     if (configFile == "-") { // Read configuration information from standard input
90         std::string line;
91         while (std::getline(std::cin, line)) {
92             content += line + "\n";
93         }
94     } else {
95         content = ReadFileToString(configFile);
96     }
97     return content;
98 }
99 
MakeCreateRequest(const std::string & configFile,const std::string & keepSecond,const std::string & outputFile)100 std::unique_ptr<CreateSessionRequest> MakeCreateRequest(const std::string& configFile,
101                                                         const std::string& keepSecond,
102                                                         const std::string& outputFile)
103 {
104     auto request = std::make_unique<CreateSessionRequest>();
105     if (!request) {
106         return nullptr;
107     }
108 
109     std::string content = ReadConfigContent(configFile);
110     if (content.empty()) {
111         printf("config file empty!");
112         return nullptr;
113     }
114     printf("================================\n");
115     printf("CONFIG: read %zu bytes from %s:\n%s", content.size(), configFile.c_str(), content.c_str());
116     if (!google::protobuf::TextFormat::ParseFromString(content, request.get())) {
117         printf("config file [%s] parse FAILED!\n", configFile.c_str());
118         return nullptr;
119     }
120 
121     auto sessionConfig = request->mutable_session_config();
122     if (!sessionConfig) {
123         return nullptr;
124     }
125 
126     request->set_request_id(1);
127     printf("--------------------------------\n");
128     printf("keepSecond: %s,\noutputFileName: %s\n", keepSecond.c_str(), outputFile.c_str());
129     if (!keepSecond.empty()) {
130         int ks = std::stoi(keepSecond);
131         if (ks > 0) {
132             sessionConfig->set_sample_duration(ks * MS_PER_S);
133         }
134     }
135     if (!outputFile.empty()) {
136         sessionConfig->set_result_file(outputFile);
137     }
138 
139     g_sampleDuration = sessionConfig->sample_duration();
140     content.clear();
141     if (!google::protobuf::TextFormat::PrintToString(*request.get(), &content)) {
142         printf("config message format FAILED!\n");
143         return nullptr;
144     }
145     printf("--------------------------------\n");
146     printf("CONFIG: final config content:\n%s", content.c_str());
147     printf("================================\n");
148     return request;
149 }
150 
GetProfilerServiceStub()151 std::unique_ptr<IProfilerService::Stub> GetProfilerServiceStub()
152 {
153     std::string serviceUri = GetLoopbackAddress() + ":" + std::to_string(GetServicePort());
154     auto grpcChannel = grpc::CreateChannel(serviceUri, grpc::InsecureChannelCredentials());
155     if (grpcChannel == nullptr) {
156         printf("FAIL\nCreate gRPC channel failed!\n");
157         return nullptr;
158     }
159     return IProfilerService::NewStub(grpcChannel);
160 }
161 
CreateSession(const std::string & configFile,const std::string & keepSecond,const std::string & outputFile)162 uint32_t CreateSession(const std::string& configFile, const std::string& keepSecond, const std::string& outputFile)
163 {
164     auto profilerStub = GetProfilerServiceStub();
165     if (profilerStub == nullptr) {
166         printf("FAIL\nGet profiler service stub failed!\n");
167         return 0;
168     }
169 
170     auto request = MakeCreateRequest(configFile, keepSecond, outputFile);
171     if (!request) {
172         printf("FAIL\nMakeCreateRequest failed!\n");
173         return 0;
174     }
175 
176     CreateSessionResponse createResponse;
177     grpc::ClientContext createSessionContext;
178     grpc::Status status = profilerStub->CreateSession(&createSessionContext, *request, &createResponse);
179     if (!status.ok()) {
180         printf("FAIL\nCreateSession FAIL\n");
181         return 0;
182     }
183 
184     return createResponse.session_id();
185 }
186 
DoCapture(const std::string & configFile,const std::string & keepSecond,const std::string & outputFile)187 bool DoCapture(const std::string& configFile, const std::string& keepSecond, const std::string& outputFile)
188 {
189     uint32_t sessionId = CreateSession(configFile, keepSecond, outputFile);
190     auto profilerStub = GetProfilerServiceStub();
191     if (profilerStub == nullptr) {
192         printf("FAIL\nGet profiler service stub failed!\n");
193         return false;
194     }
195 
196     StartSessionRequest startRequest;
197     StartSessionResponse startResponse;
198     startRequest.set_request_id(0);
199     startRequest.set_session_id(sessionId);
200     grpc::ClientContext startContext;
201     grpc::Status status = profilerStub->StartSession(&startContext, startRequest, &startResponse);
202     if (!status.ok()) {
203         printf("FAIL\nStartSession FAIL\n");
204         return false;
205     }
206 
207     printf("tracing %u ms....\n", g_sampleDuration);
208     usleep(g_sampleDuration * US_PER_MS);
209 
210     StopSessionRequest stopRequest;
211     StopSessionResponse stopResponse;
212     grpc::ClientContext stopContext;
213     stopRequest.set_session_id(sessionId);
214     status = profilerStub->StopSession(&stopContext, stopRequest, &stopResponse);
215     if (!status.ok()) {
216         printf("FAIL\nStopSession FAIL\n");
217         return false;
218     }
219     printf("StopSession done!\n");
220 
221     DestroySessionRequest destroyRequest;
222     DestroySessionResponse destroyResponse;
223     grpc::ClientContext destroyContext;
224     destroyRequest.set_session_id(sessionId);
225     status = profilerStub->DestroySession(&destroyContext, destroyRequest, &destroyResponse);
226     if (!status.ok()) {
227         printf("FAIL\nDestroySession FAIL\n");
228         return false;
229     }
230     printf("DestroySession done!\n");
231     return true;
232 }
233 } // namespace
234 
main(int argc,char * argv[])235 int main(int argc, char* argv[])
236 {
237     CommandLine* pCmdLine = &CommandLine::GetInstance();
238 
239     bool isGetGrpcAddr = false;
240     pCmdLine->AddParamSwitch("--getport", "-q", isGetGrpcAddr, "get grpc address");
241 
242     std::string configFile;
243     pCmdLine->AddParamText("--config", "-c", configFile, "start trace by config file");
244 
245     std::string traceKeepSecond;
246     pCmdLine->AddParamText("--time", "-t", traceKeepSecond, "trace time");
247 
248     std::string outputFile;
249     pCmdLine->AddParamText("--out", "-o", outputFile, "output file name");
250 
251     bool isHelp = false;
252     pCmdLine->AddParamSwitch("--help", "-h", isHelp, "make some help");
253 
254     std::vector<std::string> argvVector;
255     for (int i = 0; i < argc; i++) {
256         argvVector.push_back(argv[i]);
257     }
258     if (argc < 1 || pCmdLine->AnalyzeParam(argvVector) < 0 || isHelp) {
259         pCmdLine->PrintHelp();
260         exit(0);
261     }
262     if (isGetGrpcAddr) { // handle get port
263         auto profilerStub = GetProfilerServiceStub();
264         if (profilerStub == nullptr) {
265             printf("FAIL\nGet profiler service stub failed!\n");
266             return -1;
267         }
268 
269         GetCapabilitiesRequest request;
270         GetCapabilitiesResponse response;
271         request.set_request_id(0);
272 
273         grpc::ClientContext context;
274         grpc::Status status = profilerStub->GetCapabilities(&context, request, &response);
275         if (!status.ok()) {
276             printf("FAIL\nService not started\n");
277             return -1;
278         }
279 
280         printf("OK\n");
281         printf("ip:%s\n", GetLoopbackAddress().c_str());
282         printf("port:%u\n", GetServicePort());
283         return 0;
284     }
285 
286     if (configFile.empty()) { // normal case
287         printf("FAIL\nconfig file argument must sepcified!");
288         return 1;
289     }
290     // do capture work
291     if (DoCapture(configFile, traceKeepSecond, outputFile)) {
292         printf("DONE\n");
293     }
294 
295     return 0;
296 }
297