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.h"
17
18 #include <chrono>
19 #include <iomanip>
20 #include <sstream>
21 #include <sys/time.h>
22 #include <unistd.h>
23
24 #include "def.h"
25 #include "hilog/log.h"
26 #include "hitrace/hitraceid.h"
27 #include "hitrace/trace.h"
28 #include "stringfilter.h"
29 #include "transport.h"
30
31 namespace OHOS {
32 namespace HiviewDFX {
33 namespace {
34 constexpr HiLogLabel LABEL = { LOG_CORE, 0xD002D08, "HISYSEVENT" };
35 constexpr int SECS_IN_MINUTE = 60;
36 constexpr int SECS_IN_HOUR = 3600;
37 }
38
GetMilliseconds()39 static inline uint64_t GetMilliseconds()
40 {
41 auto now = std::chrono::system_clock::now();
42 auto millisecs = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
43 return millisecs.count();
44 }
45
GetTimeZone()46 static std::string GetTimeZone()
47 {
48 struct timeval tv;
49 if (gettimeofday(&tv, NULL) != 0) {
50 HiLog::Error(LABEL, "can not get tz");
51 return "";
52 }
53 time_t sysSec = tv.tv_sec;
54 struct tm tmLocal;
55 if (localtime_r(&sysSec, &tmLocal) == nullptr) {
56 HiLog::Error(LABEL, "failed to get local time.");
57 return "";
58 }
59 struct tm tmUtc;
60 if (gmtime_r(&sysSec, &tmUtc) == nullptr) {
61 HiLog::Error(LABEL, "failed to get GMT time.");
62 return "";
63 }
64 time_t diffSec = mktime(&tmLocal) - mktime(&tmUtc);
65 int tzHour = std::abs(diffSec) / SECS_IN_HOUR;
66 if (tzHour > 12) { // max time zone is 12
67 HiLog::Error(LABEL, "failed to get hours for time zone, set to 0.");
68 tzHour = 0;
69 }
70 int tzMin = (std::abs(diffSec) % SECS_IN_HOUR) / SECS_IN_MINUTE;
71 std::stringstream ss;
72 ss << ((diffSec < 0) ? "-" : "+");
73 ss << std::setw(2) << std::setfill('0') << tzHour; // the number of digits in the hour is 2
74 ss << std::setw(2) << std::setfill('0') << tzMin; // the number of digits in the min is 2
75 return ss.str();
76 }
77
CheckKey(const std::string & key)78 int HiSysEvent::CheckKey(const std::string &key)
79 {
80 if (!StringFilter::GetInstance().IsValidName(key, MAX_PARAM_NAME_LENGTH)) {
81 return ERR_KEY_NAME_INVALID;
82 }
83 return SUCCESS;
84 }
85
CheckValue(const std::string & value)86 int HiSysEvent::CheckValue(const std::string &value)
87 {
88 if (value.length() > MAX_STRING_LENGTH) {
89 return ERR_VALUE_LENGTH_TOO_LONG;
90 }
91 return SUCCESS;
92 }
93
CheckArraySize(unsigned long size)94 int HiSysEvent::CheckArraySize(unsigned long size)
95 {
96 if (size > MAX_ARRAY_SIZE) {
97 return ERR_ARRAY_TOO_MUCH;
98 }
99 return SUCCESS;
100 }
101
GetArrayMax()102 unsigned int HiSysEvent::GetArrayMax()
103 {
104 return MAX_ARRAY_SIZE;
105 }
106
ExplainRetCode(HiSysEvent::EventBase & eventBase)107 void HiSysEvent::ExplainRetCode(HiSysEvent::EventBase &eventBase)
108 {
109 if (eventBase.retCode_ > SUCCESS) {
110 HiLog::Warn(LABEL, "some value of param discard as invalid data, error=%{public}d, message=%{public}s",
111 eventBase.retCode_, ERR_MSG_LEVEL1[eventBase.retCode_ - 1]);
112 } else if (eventBase.retCode_ < SUCCESS) {
113 HiLog::Error(LABEL, "discard data, error=%{public}d, message=%{public}s",
114 eventBase.retCode_, ERR_MSG_LEVEL0[-eventBase.retCode_ - 1]);
115 }
116 }
117
IsError(HiSysEvent::EventBase & eventBase)118 bool HiSysEvent::IsError(HiSysEvent::EventBase &eventBase)
119 {
120 if (eventBase.retCode_ < SUCCESS) {
121 return true;
122 }
123 return false;
124 }
125
IsErrorAndUpdate(int retCode,HiSysEvent::EventBase & eventBase)126 bool HiSysEvent::IsErrorAndUpdate(int retCode, HiSysEvent::EventBase &eventBase)
127 {
128 if (retCode < SUCCESS) {
129 eventBase.retCode_ = retCode;
130 return true;
131 }
132 return false;
133 }
134
IsWarnAndUpdate(int retCode,EventBase & eventBase)135 bool HiSysEvent::IsWarnAndUpdate(int retCode, EventBase &eventBase)
136 {
137 if (retCode != SUCCESS) {
138 eventBase.retCode_ = retCode;
139 return true;
140 }
141 return false;
142 }
143
UpdateAndCheckKeyNumIsOver(HiSysEvent::EventBase & eventBase)144 bool HiSysEvent::UpdateAndCheckKeyNumIsOver(HiSysEvent::EventBase &eventBase)
145 {
146 eventBase.keyCnt_++;
147 if (eventBase.keyCnt_ > MAX_PARAM_NUMBER) {
148 eventBase.retCode_ = ERR_KEY_NUMBER_TOO_MUCH;
149 return true;
150 }
151 return false;
152 }
153
AppendValue(HiSysEvent::EventBase & eventBase,const std::string & item)154 void HiSysEvent::AppendValue(HiSysEvent::EventBase &eventBase, const std::string &item)
155 {
156 std::string text = item;
157 if (item.length() > MAX_STRING_LENGTH) {
158 text = item.substr(0, MAX_STRING_LENGTH);
159 eventBase.retCode_ = ERR_VALUE_LENGTH_TOO_LONG;
160 }
161 eventBase.jsonStr_ << "\"" << StringFilter::GetInstance().EscapeToRaw(text) << "\"";
162 }
163
AppendValue(HiSysEvent::EventBase & eventBase,const char item)164 void HiSysEvent::AppendValue(HiSysEvent::EventBase &eventBase, const char item)
165 {
166 eventBase.jsonStr_ << static_cast<short>(item);
167 }
168
AppendValue(HiSysEvent::EventBase & eventBase,const unsigned char item)169 void HiSysEvent::AppendValue(HiSysEvent::EventBase &eventBase, const unsigned char item)
170 {
171 eventBase.jsonStr_ << static_cast<unsigned short>(item);
172 }
173
InnerWrite(HiSysEvent::EventBase & eventBase)174 void HiSysEvent::InnerWrite(HiSysEvent::EventBase &eventBase)
175 {
176 if (eventBase.jsonStr_.tellp() != 0) {
177 eventBase.jsonStr_.seekp(-1, std::ios_base::end);
178 }
179 }
180
SendSysEvent(HiSysEvent::EventBase & eventBase)181 void HiSysEvent::SendSysEvent(HiSysEvent::EventBase &eventBase)
182 {
183 int r = Transport::GetInstance().SendData(eventBase.jsonStr_.str());
184 if (r != SUCCESS) {
185 eventBase.retCode_ = r;
186 ExplainRetCode(eventBase);
187 }
188 }
189
AppendHexData(HiSysEvent::EventBase & eventBase,const std::string & key,uint64_t value)190 void HiSysEvent::AppendHexData(HiSysEvent::EventBase &eventBase, const std::string &key, uint64_t value)
191 {
192 eventBase.jsonStr_ << "\"" << key << "\":\"" << std::hex << value << "\"," << std::dec;
193 }
194
WritebaseInfo(HiSysEvent::EventBase & eventBase)195 void HiSysEvent::WritebaseInfo(HiSysEvent::EventBase &eventBase)
196 {
197 if (!StringFilter::GetInstance().IsValidName(eventBase.domain_, MAX_DOMAIN_LENGTH)) {
198 eventBase.retCode_ = ERR_DOMAIN_NAME_INVALID;
199 return;
200 }
201 if (!StringFilter::GetInstance().IsValidName(eventBase.eventName_, MAX_EVENT_NAME_LENGTH)) {
202 eventBase.retCode_ = ERR_EVENT_NAME_INVALID;
203 return;
204 }
205 AppendData(eventBase, "domain_", eventBase.domain_);
206 AppendData(eventBase, "name_", eventBase.eventName_);
207 AppendData(eventBase, "type_", eventBase.type_);
208 AppendData(eventBase, "time_", GetMilliseconds());
209 AppendData(eventBase, "tz_", GetTimeZone());
210 AppendData(eventBase, "pid_", getpid());
211 AppendData(eventBase, "tid_", gettid());
212 AppendData(eventBase, "uid_", getuid());
213 HiTraceId hitraceId = HiTrace::GetId();
214 if (!hitraceId.IsValid()) {
215 eventBase.keyCnt_ = 0;
216 return;
217 }
218 AppendHexData(eventBase, "traceid_", hitraceId.GetChainId());
219 AppendHexData(eventBase, "spanid_", hitraceId.GetSpanId());
220 AppendHexData(eventBase, "pspanid_", hitraceId.GetParentSpanId());
221 AppendData(eventBase, "trace_flag_", hitraceId.GetFlags());
222 eventBase.keyCnt_ = 0;
223 }
224 } // namespace HiviewDFX
225 } // namespace OHOS
226