• 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 <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)67 void LogCollector::onDataRecv(std::vector<char>& data)
68 #else
69 void LogCollector::onDataRecv(const ucred& cred, std::vector<char>& data)
70 #endif
71 {
72     if (data.size() < sizeof(HilogMsg)) {
73         std::cerr << "Internal error - received data less than HilogMsg size";
74         return;
75     }
76 
77     HilogMsg& msg = *(reinterpret_cast<HilogMsg *>(data.data()));
78     // check domain id
79     if (!debug && IsValidDomain(static_cast<LogType>(msg.type), msg.domain) == false) {
80         std::cout << "Invalid domain id: 0x" << std::hex << msg.domain << std::dec << ", type:" << msg.type << endl;
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         InsertLogToBuffer(msg);
102     } while (0);
103 
104     // Log statistics
105     if (countEnable) {
106         StatsInfo info = {
107             .level = msg.level,
108             .type = msg.type,
109             .len = (msg.len - sizeof(HilogMsg) - 1 - 1), // don't count '\0' of tag and content
110             .dropped = dropped ? 1 : 0,
111             .domain = msg.domain,
112             .pid = msg.pid,
113             .tv_sec = msg.tv_sec,
114             .tv_nsec = msg.tv_nsec,
115             .mono_sec = msg.mono_sec,
116             .tag = msg.tag
117         };
118         m_hilogBuffer.CountLog(info);
119     }
120 }
121 
InsertLogToBuffer(const HilogMsg & msg)122 size_t LogCollector::InsertLogToBuffer(const HilogMsg& msg)
123 {
124     if (msg.type >= LOG_TYPE_MAX) {
125         return ERR_LOG_TYPE_INVALID;
126     }
127     return m_hilogBuffer.Insert(msg);
128 }
129 
SetLogFlowControl(bool on)130 void LogCollector::SetLogFlowControl(bool on)
131 {
132     flowControl = on;
133 }
134 
SetDebuggable(bool on)135 void LogCollector::SetDebuggable(bool on)
136 {
137     debug = on;
138 }
139 } // namespace HiviewDFX
140 } // namespace OHOS
141