12498b56bSopenharmony_ci/* 22498b56bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 32498b56bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 42498b56bSopenharmony_ci * you may not use this file except in compliance with the License. 52498b56bSopenharmony_ci * You may obtain a copy of the License at 62498b56bSopenharmony_ci * 72498b56bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 82498b56bSopenharmony_ci * 92498b56bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 102498b56bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 112498b56bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 122498b56bSopenharmony_ci * See the License for the specific language governing permissions and 132498b56bSopenharmony_ci * limitations under the License. 142498b56bSopenharmony_ci */ 152498b56bSopenharmony_ci 162498b56bSopenharmony_ci#include <cstdlib> 172498b56bSopenharmony_ci#include <cstring> 182498b56bSopenharmony_ci#include <cinttypes> 192498b56bSopenharmony_ci#include <iostream> 202498b56bSopenharmony_ci#include <string> 212498b56bSopenharmony_ci#include <thread> 222498b56bSopenharmony_ci#include <string_view> 232498b56bSopenharmony_ci 242498b56bSopenharmony_ci#include "log_kmsg.h" 252498b56bSopenharmony_ci#include "flow_control.h" 262498b56bSopenharmony_ci#include "log_domains.h" 272498b56bSopenharmony_ci#include "log_collector.h" 282498b56bSopenharmony_ci 292498b56bSopenharmony_cinamespace OHOS { 302498b56bSopenharmony_cinamespace HiviewDFX { 312498b56bSopenharmony_ciusing namespace std; 322498b56bSopenharmony_ci 332498b56bSopenharmony_civoid LogCollector::InsertDropInfo(const HilogMsg &msg, int droppedCount) 342498b56bSopenharmony_ci{ 352498b56bSopenharmony_ci string dropLog = to_string(droppedCount) + " line(s) dropped!"; 362498b56bSopenharmony_ci constexpr auto tag = "LOGLIMITD"sv; 372498b56bSopenharmony_ci std::vector<char> buffer(sizeof(HilogMsg) + tag.size() + dropLog.size() + 1, '\0'); 382498b56bSopenharmony_ci HilogMsg *dropMsg = reinterpret_cast<HilogMsg *>(buffer.data()); 392498b56bSopenharmony_ci if (dropMsg != nullptr) { 402498b56bSopenharmony_ci dropMsg->len = buffer.size(); 412498b56bSopenharmony_ci dropMsg->version = msg.version; 422498b56bSopenharmony_ci dropMsg->type = msg.type; 432498b56bSopenharmony_ci dropMsg->level = msg.level; 442498b56bSopenharmony_ci dropMsg->tagLen = tag.size(); 452498b56bSopenharmony_ci dropMsg->tv_sec = msg.tv_sec; 462498b56bSopenharmony_ci dropMsg->tv_nsec = msg.tv_nsec; 472498b56bSopenharmony_ci dropMsg->mono_sec = msg.mono_sec; 482498b56bSopenharmony_ci dropMsg->pid = msg.pid; 492498b56bSopenharmony_ci dropMsg->tid = msg.tid; 502498b56bSopenharmony_ci dropMsg->domain = msg.domain; 512498b56bSopenharmony_ci 522498b56bSopenharmony_ci auto remainSize = buffer.size() - sizeof(HilogMsg); 532498b56bSopenharmony_ci if (memcpy_s(dropMsg->tag, remainSize, tag.data(), tag.size())) { 542498b56bSopenharmony_ci std::cerr << "Can't copy tag info of Drop Info message\n"; 552498b56bSopenharmony_ci } 562498b56bSopenharmony_ci 572498b56bSopenharmony_ci remainSize -= tag.size(); 582498b56bSopenharmony_ci auto logTextPtr = dropMsg->tag + tag.size(); // log text is behind tag data 592498b56bSopenharmony_ci if (memcpy_s(logTextPtr, remainSize, dropLog.data(), dropLog.size() + 1)) { 602498b56bSopenharmony_ci std::cerr << "Can't copy log text info of Drop Info message\n"; 612498b56bSopenharmony_ci } 622498b56bSopenharmony_ci 632498b56bSopenharmony_ci InsertLogToBuffer(*dropMsg); 642498b56bSopenharmony_ci } 652498b56bSopenharmony_ci} 662498b56bSopenharmony_ci#ifndef __RECV_MSG_WITH_UCRED_ 672498b56bSopenharmony_civoid LogCollector::onDataRecv(std::vector<char>& data, int dataLen) 682498b56bSopenharmony_ci#else 692498b56bSopenharmony_civoid LogCollector::onDataRecv(const ucred& cred, std::vector<char>& data, int dataLen) 702498b56bSopenharmony_ci#endif 712498b56bSopenharmony_ci{ 722498b56bSopenharmony_ci if (dataLen < sizeof(HilogMsg)) { 732498b56bSopenharmony_ci return; 742498b56bSopenharmony_ci } 752498b56bSopenharmony_ci HilogMsg& msg = *(reinterpret_cast<HilogMsg *>(data.data())); 762498b56bSopenharmony_ci if (dataLen != msg.len) { 772498b56bSopenharmony_ci return; 782498b56bSopenharmony_ci } 792498b56bSopenharmony_ci // check domain id 802498b56bSopenharmony_ci if (IsValidDomain(static_cast<LogType>(msg.type), msg.domain) == false) { 812498b56bSopenharmony_ci return; 822498b56bSopenharmony_ci } 832498b56bSopenharmony_ci#ifdef __RECV_MSG_WITH_UCRED_ 842498b56bSopenharmony_ci msg.pid = cred.pid; 852498b56bSopenharmony_ci#endif 862498b56bSopenharmony_ci bool dropped = false; 872498b56bSopenharmony_ci // Domain flow control 882498b56bSopenharmony_ci do { 892498b56bSopenharmony_ci int ret = 0; 902498b56bSopenharmony_ci if (msg.type != static_cast<uint16_t>(LOG_APP) && flowControl && !debug) { 912498b56bSopenharmony_ci ret = FlowCtrlDomain(msg); 922498b56bSopenharmony_ci } 932498b56bSopenharmony_ci if (ret < 0) { 942498b56bSopenharmony_ci // dropping message 952498b56bSopenharmony_ci dropped = true; 962498b56bSopenharmony_ci break; 972498b56bSopenharmony_ci } else if (ret > 0) { 982498b56bSopenharmony_ci // >0 means a new statistic period start, "ret" is the number of dropping lines in last period 992498b56bSopenharmony_ci InsertDropInfo(msg, ret); 1002498b56bSopenharmony_ci } 1012498b56bSopenharmony_ci // If insert msg fail, return 0 1022498b56bSopenharmony_ci if (InsertLogToBuffer(msg) == 0) { 1032498b56bSopenharmony_ci return; 1042498b56bSopenharmony_ci } 1052498b56bSopenharmony_ci } while (0); 1062498b56bSopenharmony_ci 1072498b56bSopenharmony_ci // Log statistics 1082498b56bSopenharmony_ci if (countEnable) { 1092498b56bSopenharmony_ci if (*(msg.tag + msg.tagLen - 1) != '\0') { 1102498b56bSopenharmony_ci return; 1112498b56bSopenharmony_ci } 1122498b56bSopenharmony_ci StatsInfo info = { 1132498b56bSopenharmony_ci .level = msg.level, 1142498b56bSopenharmony_ci .type = msg.type, 1152498b56bSopenharmony_ci .len = (msg.len - sizeof(HilogMsg) - 1 - 1), // don't count '\0' of tag and content 1162498b56bSopenharmony_ci .dropped = dropped ? 1 : 0, 1172498b56bSopenharmony_ci .domain = msg.domain, 1182498b56bSopenharmony_ci .pid = msg.pid, 1192498b56bSopenharmony_ci .tv_sec = msg.tv_sec, 1202498b56bSopenharmony_ci .tv_nsec = msg.tv_nsec, 1212498b56bSopenharmony_ci .mono_sec = msg.mono_sec, 1222498b56bSopenharmony_ci .tag = msg.tag 1232498b56bSopenharmony_ci }; 1242498b56bSopenharmony_ci m_hilogBuffer.CountLog(info); 1252498b56bSopenharmony_ci } 1262498b56bSopenharmony_ci} 1272498b56bSopenharmony_ci 1282498b56bSopenharmony_cisize_t LogCollector::InsertLogToBuffer(const HilogMsg& msg) 1292498b56bSopenharmony_ci{ 1302498b56bSopenharmony_ci bool isFull = false; 1312498b56bSopenharmony_ci return m_hilogBuffer.Insert(msg, isFull); 1322498b56bSopenharmony_ci} 1332498b56bSopenharmony_ci 1342498b56bSopenharmony_civoid LogCollector::SetLogFlowControl(bool on) 1352498b56bSopenharmony_ci{ 1362498b56bSopenharmony_ci flowControl = on; 1372498b56bSopenharmony_ci} 1382498b56bSopenharmony_ci 1392498b56bSopenharmony_civoid LogCollector::SetDebuggable(bool on) 1402498b56bSopenharmony_ci{ 1412498b56bSopenharmony_ci debug = on; 1422498b56bSopenharmony_ci} 1432498b56bSopenharmony_ci} // namespace HiviewDFX 1442498b56bSopenharmony_ci} // namespace OHOS 145