• 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 "hisysevent_tool.h"
17 
18 #include <getopt.h>
19 #include <iomanip>
20 #include <iostream>
21 #include <regex>
22 #include <sstream>
23 #include <unistd.h>
24 
25 #include "hisysevent.h"
26 #include "hisysevent_tool_listener.h"
27 #include "hisysevent_tool_query.h"
28 
29 #include "ret_code.h"
30 
31 using namespace std;
32 
33 namespace OHOS {
34 namespace HiviewDFX {
35 namespace {
36 constexpr char ARG_SELECTION[] = "vrc:o:n:t:lS:s:E:e:m:dhg:";
37 constexpr uint32_t INVALID_EVENT_TYPE = 0;
38 constexpr int INVALID_ARG_OPT = -1;
39 constexpr long long DEFAULT_TIME_STAMP = -1;
40 constexpr long long SECONDS_2_MILLS = 1000;
41 
GetRuleTypeFromArg(const string & fromArgs)42 RuleType GetRuleTypeFromArg(const string& fromArgs)
43 {
44     static std::map<const string, RuleType> ruleTypeMap {
45         { "WHOLE_WORD", RuleType::WHOLE_WORD },
46         { "PREFIX", RuleType::PREFIX },
47         { "REGULAR", RuleType::REGULAR }
48     };
49     if (ruleTypeMap.find(fromArgs) != ruleTypeMap.end()) {
50         return ruleTypeMap[fromArgs];
51     }
52     return RuleType::WHOLE_WORD;
53 }
54 
GetEventTypeFromArg(const string & fromArgs)55 uint32_t GetEventTypeFromArg(const string& fromArgs)
56 {
57     static std::map<const string, HiSysEvent::EventType> eventTypeMap {
58         { "FAULT", HiSysEvent::EventType::FAULT },
59         { "STATISTIC", HiSysEvent::EventType::STATISTIC },
60         { "SECURITY", HiSysEvent::EventType::SECURITY },
61         { "BEHAVIOR", HiSysEvent::EventType::BEHAVIOR }
62     };
63     if (eventTypeMap.find(fromArgs) != eventTypeMap.end()) {
64         return static_cast<uint32_t>(eventTypeMap[fromArgs]);
65     }
66     return INVALID_EVENT_TYPE;
67 }
68 
ParseTimeStampFromArgs(const string & fromArgs)69 long long ParseTimeStampFromArgs(const string& fromArgs)
70 {
71     regex formatRegex("[0-9]{4}-"
72         "((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01])|(0[2469]|11)-(0[1-9]|[12][0-9]|30))"
73         " ([01][0-9]|2[0-3])(:[0-5][0-9]){2}");
74     smatch matchRet;
75     if (!std::regex_match(fromArgs, matchRet, formatRegex)) {
76         return DEFAULT_TIME_STAMP;
77     }
78     std::istringstream is(fromArgs);
79     struct tm time = {};
80     is >> std::get_time(&time, "%Y-%m-%d %H:%M:%S");
81     return static_cast<long long>(mktime(&time)) * SECONDS_2_MILLS;
82 }
83 
GetErrorDescription(int32_t errCode)84 std::string GetErrorDescription(int32_t errCode)
85 {
86     std::map<int32_t, std::string> errMap = {
87         { ERR_SYS_EVENT_SERVICE_NOT_FOUND, "service not found." },
88         { ERR_PARCEL_DATA_IS_NULL, "parcel data is null." },
89         { ERR_REMOTE_SERVICE_IS_NULL, "remote service is null." },
90         { ERR_CAN_NOT_WRITE_DESCRIPTOR, "descriptor wrote failed." },
91         { ERR_CAN_NOT_WRITE_PARCEL, "parcel wrote failed." },
92         { ERR_CAN_NOT_WRITE_REMOTE_OBJECT, "remote object wrote failed." },
93         { ERR_CAN_NOT_SEND_REQ, "request sent failed." },
94         { ERR_CAN_NOT_READ_PARCEL, "parcel read failed." },
95         { ERR_ADD_DEATH_RECIPIENT, "add death recipient failed." },
96         { ERR_QUERY_RULE_INVALID, "invalid query rule." },
97         { ERR_TOO_MANY_WATCHERS, "too many wathers subscribed." },
98         { ERR_QUERY_TOO_FREQUENTLY, "query too frequently." },
99     };
100     return errMap.find(errCode) == errMap.end() ?
101         "unknown error." : errMap.at(errCode);
102 }
103 
InitOptHandlers(std::map<int,OptHandler> & optHandlers)104 void InitOptHandlers(std::map<int, OptHandler>& optHandlers)
105 {
106     std::map<int, OptHandler> tmpHandlers = {
107         {'v', [] (struct ArgStuct& cmdArg, const char* optarg) {
108             cmdArg.checkValidEvent = true;
109         }}, {'r', [] (struct ArgStuct& cmdArg, const char* optarg) {
110             cmdArg.real = true;
111         }}, {'c', [] (struct ArgStuct& cmdArg, const char* optarg) {
112             cmdArg.ruleType = GetRuleTypeFromArg(optarg);
113         }}, {'o', [] (struct ArgStuct& cmdArg, const char* optarg) {
114             cmdArg.domain = optarg;
115         }}, {'n', [] (struct ArgStuct& cmdArg, const char* optarg) {
116             cmdArg.eventName = optarg;
117         }}, {'t', [] (struct ArgStuct& cmdArg, const char* optarg) {
118             cmdArg.tag = optarg;
119         }}, {'l', [] (struct ArgStuct& cmdArg, const char* optarg) {
120             cmdArg.history = true;
121         }}, {'s', [] (struct ArgStuct& cmdArg, const char* optarg) {
122             cmdArg.beginTime = strtoll(optarg, nullptr, 0);
123         }}, {'S', [] (struct ArgStuct& cmdArg, const char* optarg) {
124             cmdArg.beginTime = ParseTimeStampFromArgs(std::string(optarg));
125         }}, {'e', [] (struct ArgStuct& cmdArg, const char* optarg) {
126             cmdArg.endTime = strtoll(optarg, nullptr, 0);
127         }}, {'E', [] (struct ArgStuct& cmdArg, const char* optarg) {
128             cmdArg.endTime = ParseTimeStampFromArgs(std::string(optarg));
129         }}, {'m', [] (struct ArgStuct& cmdArg, const char* optarg) {
130             cmdArg.maxEvents = strtol(optarg, nullptr, 0);
131         }}, {'d', [] (struct ArgStuct& cmdArg, const char* optarg) {
132             cmdArg.isDebug = true;
133         }}, {'g', [] (struct ArgStuct& cmdArg, const char* optarg) {
134             cmdArg.eventType = GetEventTypeFromArg(optarg);
135         }},
136     };
137     optHandlers.insert(tmpHandlers.begin(), tmpHandlers.end());
138 }
139 }
140 
HiSysEventTool(bool autoExit)141 HiSysEventTool::HiSysEventTool(bool autoExit) : clientCmdArg {
142     false, false, "", "", "", RuleType::WHOLE_WORD,
143     false, false, -1, -1, 10000, 0}, autoExit(autoExit)
144 {
145     InitOptHandlers(optHandlers);
146 }
147 
ParseCmdLine(int argc,char ** argv)148 bool HiSysEventTool::ParseCmdLine(int argc, char** argv)
149 {
150     if (argv == nullptr) {
151         return false;
152     }
153     if (argc > 1) {
154         HandleInput(argc, argv, ARG_SELECTION);
155     }
156     return CheckCmdLine();
157 }
158 
CheckCmdLine()159 bool HiSysEventTool::CheckCmdLine()
160 {
161     if (!clientCmdArg.real && !clientCmdArg.history) {
162         return false;
163     }
164 
165     if (clientCmdArg.real && clientCmdArg.history) {
166         cout << "canot read both read && history hisysevent" << endl;
167         return false;
168     }
169 
170     if (clientCmdArg.isDebug && !clientCmdArg.real) {
171         cout << "debug must follow with real log" << endl;
172         return false;
173     }
174 
175     if (clientCmdArg.history) {
176         auto timestampValidCheck = clientCmdArg.endTime > 0
177             && clientCmdArg.beginTime > clientCmdArg.endTime;
178         if (timestampValidCheck) {
179             cout << "invalid time startTime must less than endTime(";
180             cout << clientCmdArg.beginTime << " > " << clientCmdArg.endTime << ")." << endl;
181             return false;
182         }
183     }
184     return true;
185 }
186 
HandleInput(int argc,char ** argv,const char * selection)187 void HiSysEventTool::HandleInput(int argc, char** argv, const char* selection)
188 {
189     int opt;
190     while ((opt = getopt(argc, argv, selection)) != INVALID_ARG_OPT) {
191         if (opt == 'h') {
192             DoCmdHelp();
193             if (autoExit) {
194                 _exit(0);
195             }
196         }
197         if (optHandlers.find(opt) != optHandlers.end()) {
198             optHandlers.at(opt)(clientCmdArg, optarg);
199         }
200     }
201 }
202 
DoCmdHelp()203 void HiSysEventTool::DoCmdHelp()
204 {
205     cout << "hisysevent [[-v] -r [-d | -c [WHOLE_WORD|PREFIX|REGULAR] -t <tag> "
206         << "| -c [WHOLE_WORD|PREFIX|REGULAR] -o <domain> -n <eventName> "
207         << "| -g [FAULT|STATISTIC|SECURITY|BEHAVIOR]] "
208         << "| -l [[-s <begin time> -e <end time> | -S <formatted begin time> -E <formatted end time>] "
209         << "-m <count> -c [WHOLE_WORD] -o <domain> -n <eventName> -g [FAULT|STATISTIC|SECURITY|BEHAVIOR]]]" << endl;
210     cout << "-r,    subscribe on all domains, event names and tags." << endl;
211     cout << "-r -c [WHOLE_WORD|PREFIX|REGULAR] -t <tag>"
212         << ", subscribe on tag." << endl;
213     cout << "-r -c [WHOLE_WORD|PREFIX|REGULAR] -o <domain> -n <eventName>"
214         << ", subscribe on domain and event name." << endl;
215     cout << "-r -g [FAULT|STATISTIC|SECURITY|BEHAVIOR]"
216         << ", subscribe on event type." << endl;
217     cout << "-r -d set debug mode, both options must appear at the same time." << endl;
218     cout << "-l -s <begin time> -e <end time> -m <max hisysevent count>"
219         << ", get history hisysevent log with time stamps, end time should not be "
220         << "earlier than begin time." << endl;
221     cout << "-l -S <formatted begin time> -E <formatted end time> -m <max hisysevent count>"
222         << ", get history hisysevent log with formatted time string, end time should not be "
223         << "earlier than begin time." << endl;
224     cout << "-l -c [WHOLE_WORD] -o <domain> -n <eventName> -m <max hisysevent count>"
225         << ", get history hisysevent log with domain and event name." << endl;
226     cout << "-l -g [FAULT|STATISTIC|SECURITY|BEHAVIOR] -m <max hisysevent count>"
227         << ", get history hisysevent log with event type." << endl;
228     cout << "-v,    open valid event checking mode." << endl;
229     cout << "-h,    help manual." << endl;
230 }
231 
DoAction()232 bool HiSysEventTool::DoAction()
233 {
234     if (clientCmdArg.real) {
235         auto toolListener = std::make_shared<HiSysEventToolListener>(clientCmdArg.checkValidEvent);
236         if (toolListener == nullptr) {
237             return false;
238         }
239         std::vector<ListenerRule> sysRules;
240         ListenerRule listenerRule(clientCmdArg.domain, clientCmdArg.eventName,
241             clientCmdArg.tag, clientCmdArg.ruleType, clientCmdArg.eventType);
242         sysRules.emplace_back(listenerRule);
243         auto retCode = HiSysEventManager::AddListener(toolListener, sysRules);
244         if (retCode != IPC_CALL_SUCCEED ||
245             (clientCmdArg.isDebug && HiSysEventManager::SetDebugMode(toolListener, true) != 0)) {
246             cout << "failed to subscribe system event: " << GetErrorDescription(retCode) << endl;
247         }
248         return true;
249     }
250 
251     if (clientCmdArg.history) {
252         auto queryCallBack = std::make_shared<HiSysEventToolQuery>(clientCmdArg.checkValidEvent, autoExit);
253         if (queryCallBack == nullptr) {
254             return false;
255         }
256         struct QueryArg args(clientCmdArg.beginTime, clientCmdArg.endTime, clientCmdArg.maxEvents);
257         std::vector<QueryRule> queryRules;
258         if (clientCmdArg.ruleType != RuleType::WHOLE_WORD) {
259             cout << "only \"-c WHOLE_WORD\" supported with \"hisysevent -l\" cmd." << endl;
260             return false;
261         }
262         if (!clientCmdArg.domain.empty() || !clientCmdArg.eventName.empty() ||
263             clientCmdArg.eventType != INVALID_EVENT_TYPE) {
264             QueryRule rule(clientCmdArg.domain, { clientCmdArg.eventName },
265                 clientCmdArg.ruleType, clientCmdArg.eventType);
266             queryRules.push_back(rule);
267         }
268         auto retCode = HiSysEventManager::Query(args, queryRules, queryCallBack);
269         if (retCode != IPC_CALL_SUCCEED) {
270             cout << "failed to query system event: " << GetErrorDescription(retCode) << endl;
271         }
272         return true;
273     }
274     return false;
275 }
276 
WaitClient()277 void HiSysEventTool::WaitClient()
278 {
279     unique_lock<mutex> lock(mutexClient);
280     condvClient.wait(lock);
281 }
282 
NotifyClient()283 void HiSysEventTool::NotifyClient()
284 {
285     condvClient.notify_one();
286 }
287 } // namespace HiviewDFX
288 } // namespace OHOS
289