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 <cstdlib>
17 #include <cstring>
18 #include <cinttypes>
19 #include <iostream>
20 #include <string>
21 #include <thread>
22 #include <string_view>
23
24 #include "log_kmsg.h"
25 #include "flow_control.h"
26 #include "log_domains.h"
27 #include "log_collector.h"
28
29 namespace OHOS {
30 namespace HiviewDFX {
31 using namespace std;
32
InsertDropInfo(const HilogMsg & msg,int droppedCount)33 void LogCollector::InsertDropInfo(const HilogMsg &msg, int droppedCount)
34 {
35 string dropLog = to_string(droppedCount) + " line(s) dropped!";
36 constexpr auto tag = "LOGLIMITD"sv;
37 std::vector<char> buffer(sizeof(HilogMsg) + tag.size() + dropLog.size() + 1, '\0');
38 HilogMsg *dropMsg = reinterpret_cast<HilogMsg *>(buffer.data());
39 if (dropMsg != nullptr) {
40 dropMsg->len = buffer.size();
41 dropMsg->version = msg.version;
42 dropMsg->type = msg.type;
43 dropMsg->level = msg.level;
44 dropMsg->tag_len = tag.size();
45 dropMsg->tv_sec = msg.tv_sec;
46 dropMsg->tv_nsec = msg.tv_nsec;
47 dropMsg->mono_sec = msg.mono_sec;
48 dropMsg->pid = msg.pid;
49 dropMsg->tid = msg.tid;
50 dropMsg->domain = msg.domain;
51
52 auto remainSize = buffer.size() - sizeof(HilogMsg);
53 if (memcpy_s(dropMsg->tag, remainSize, tag.data(), tag.size())) {
54 std::cerr << "Can't copy tag info of Drop Info message\n";
55 }
56
57 remainSize -= tag.size();
58 auto logTextPtr = dropMsg->tag + tag.size(); // log text is behind tag data
59 if (memcpy_s(logTextPtr, remainSize, dropLog.data(), dropLog.size() + 1)) {
60 std::cerr << "Can't copy log text info of Drop Info message\n";
61 }
62
63 InsertLogToBuffer(*dropMsg);
64 }
65 }
66 #ifndef __RECV_MSG_WITH_UCRED_
onDataRecv(std::vector<char> & data,int dataLen)67 void LogCollector::onDataRecv(std::vector<char>& data, int dataLen)
68 #else
69 void LogCollector::onDataRecv(const ucred& cred, std::vector<char>& data, int dataLen)
70 #endif
71 {
72 if (dataLen < sizeof(HilogMsg)) {
73 return;
74 }
75 HilogMsg& msg = *(reinterpret_cast<HilogMsg *>(data.data()));
76 if (dataLen != msg.len) {
77 return;
78 }
79 // check domain id
80 if (IsValidDomain(static_cast<LogType>(msg.type), msg.domain) == false) {
81 return;
82 }
83 #ifdef __RECV_MSG_WITH_UCRED_
84 msg.pid = cred.pid;
85 #endif
86 bool dropped = false;
87 // Domain flow control
88 do {
89 int ret = 0;
90 if (msg.type != static_cast<uint16_t>(LOG_APP) && flowControl && !debug) {
91 ret = FlowCtrlDomain(msg);
92 }
93 if (ret < 0) {
94 // dropping message
95 dropped = true;
96 break;
97 } else if (ret > 0) {
98 // >0 means a new statistic period start, "ret" is the number of dropping lines in last period
99 InsertDropInfo(msg, ret);
100 }
101 // If insert msg fail, return 0
102 if (InsertLogToBuffer(msg) == 0) {
103 return;
104 }
105 } while (0);
106
107 // Log statistics
108 if (countEnable) {
109 if (*(msg.tag + msg.tag_len - 1) != '\0') {
110 return;
111 }
112 StatsInfo info = {
113 .level = msg.level,
114 .type = msg.type,
115 .len = (msg.len - sizeof(HilogMsg) - 1 - 1), // don't count '\0' of tag and content
116 .dropped = dropped ? 1 : 0,
117 .domain = msg.domain,
118 .pid = msg.pid,
119 .tv_sec = msg.tv_sec,
120 .tv_nsec = msg.tv_nsec,
121 .mono_sec = msg.mono_sec,
122 .tag = msg.tag
123 };
124 m_hilogBuffer.CountLog(info);
125 }
126 }
127
InsertLogToBuffer(const HilogMsg & msg)128 size_t LogCollector::InsertLogToBuffer(const HilogMsg& msg)
129 {
130 return m_hilogBuffer.Insert(msg);
131 }
132
SetLogFlowControl(bool on)133 void LogCollector::SetLogFlowControl(bool on)
134 {
135 flowControl = on;
136 }
137
SetDebuggable(bool on)138 void LogCollector::SetDebuggable(bool on)
139 {
140 debug = on;
141 }
142 } // namespace HiviewDFX
143 } // namespace OHOS
144