106f6ba60Sopenharmony_ci/* 206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. 306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License. 506f6ba60Sopenharmony_ci * You may obtain a copy of the License at 606f6ba60Sopenharmony_ci * 706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 806f6ba60Sopenharmony_ci * 906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and 1306f6ba60Sopenharmony_ci * limitations under the License. 1406f6ba60Sopenharmony_ci */ 1506f6ba60Sopenharmony_ci#include "hisysevent_plugin.h" 1606f6ba60Sopenharmony_ci#include "hisysevent_plugin_result.pbencoder.h" 1706f6ba60Sopenharmony_ci 1806f6ba60Sopenharmony_ci#include <cinttypes> 1906f6ba60Sopenharmony_ci#include <csignal> 2006f6ba60Sopenharmony_ci#include <cstdio> 2106f6ba60Sopenharmony_ci#include <fcntl.h> 2206f6ba60Sopenharmony_ci#include <sstream> 2306f6ba60Sopenharmony_ci#include <sys/syscall.h> 2406f6ba60Sopenharmony_ci#include <sys/types.h> 2506f6ba60Sopenharmony_ci#include <sys/wait.h> 2606f6ba60Sopenharmony_ci#include <unistd.h> 2706f6ba60Sopenharmony_ci 2806f6ba60Sopenharmony_cinamespace { 2906f6ba60Sopenharmony_ciusing namespace OHOS::Developtools::Profiler; 3006f6ba60Sopenharmony_ciconstexpr int PIPE_SIZE = 256 * 1024; 3106f6ba60Sopenharmony_ciconstexpr int MAX_STRING_LEN = 256 * 1024; 3206f6ba60Sopenharmony_ciconstexpr int MIN_STRING_LEN = 10; 3306f6ba60Sopenharmony_ciconstexpr int BYTE_BUFFER_SIZE = 1024; 3406f6ba60Sopenharmony_ci} // namespace 3506f6ba60Sopenharmony_ci 3606f6ba60Sopenharmony_ciHisyseventPlugin::HisyseventPlugin() : fp_(nullptr, nullptr) {} 3706f6ba60Sopenharmony_ci 3806f6ba60Sopenharmony_ciHisyseventPlugin::~HisyseventPlugin() 3906f6ba60Sopenharmony_ci{ 4006f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__); 4106f6ba60Sopenharmony_ci Stop(); 4206f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "END %s: success!", __func__); 4306f6ba60Sopenharmony_ci} 4406f6ba60Sopenharmony_ci 4506f6ba60Sopenharmony_ciint HisyseventPlugin::SetWriter(WriterStruct* writer) 4606f6ba60Sopenharmony_ci{ 4706f6ba60Sopenharmony_ci resultWriter_ = writer; 4806f6ba60Sopenharmony_ci 4906f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "END %s: success!", __func__); 5006f6ba60Sopenharmony_ci return 0; 5106f6ba60Sopenharmony_ci} 5206f6ba60Sopenharmony_ci 5306f6ba60Sopenharmony_ciint HisyseventPlugin::Start(const uint8_t* configData, uint32_t configSize) 5406f6ba60Sopenharmony_ci{ 5506f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__); 5606f6ba60Sopenharmony_ci CHECK_NOTNULL(configData, -1, "NOTE %s: param invalid", __func__); 5706f6ba60Sopenharmony_ci 5806f6ba60Sopenharmony_ci CHECK_TRUE(protoConfig_.ParseFromArray(configData, configSize) > 0, -1, 5906f6ba60Sopenharmony_ci "NOTE HisyseventPlugin: ParseFromArray failed"); 6006f6ba60Sopenharmony_ci 6106f6ba60Sopenharmony_ci PROFILER_LOG_DEBUG(LOG_CORE, "config sourse data:%s domain:%s event:%s", protoConfig_.msg().c_str(), 6206f6ba60Sopenharmony_ci protoConfig_.subscribe_domain().c_str(), protoConfig_.subscribe_event().c_str()); 6306f6ba60Sopenharmony_ci 6406f6ba60Sopenharmony_ci CHECK_TRUE(InitHisyseventCmd(), -1, "HisyseventPlugin: Init HisyseventCmd failed"); 6506f6ba60Sopenharmony_ci 6606f6ba60Sopenharmony_ci fp_ = std::unique_ptr<FILE, std::function<int (FILE*)>>( 6706f6ba60Sopenharmony_ci COMMON::CustomPopen(fullCmd_, "r", pipeFds_, childPid_, true), [this](FILE* fp) -> int { 6806f6ba60Sopenharmony_ci return COMMON::CustomPclose(fp, pipeFds_, childPid_, true); 6906f6ba60Sopenharmony_ci }); 7006f6ba60Sopenharmony_ci 7106f6ba60Sopenharmony_ci CHECK_NOTNULL(fp_.get(), -1, "HisyseventPlugin: fullCmd_ Failed, errno(%d)", errno); 7206f6ba60Sopenharmony_ci CHECK_NOTNULL(resultWriter_, -1, "HisyseventPlugin: Writer is no set!!"); 7306f6ba60Sopenharmony_ci CHECK_NOTNULL(resultWriter_->write, -1, "HisyseventPlugin: Writer.write is no set!!"); 7406f6ba60Sopenharmony_ci CHECK_NOTNULL(resultWriter_->flush, -1, "HisyseventPlugin: Writer.flush is no set!!"); 7506f6ba60Sopenharmony_ci id_ = 1; 7606f6ba60Sopenharmony_ci running_ = true; 7706f6ba60Sopenharmony_ci workThread_ = std::thread([this] { this->Run(); }); 7806f6ba60Sopenharmony_ci 7906f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "END %s: success!", __func__); 8006f6ba60Sopenharmony_ci return 0; 8106f6ba60Sopenharmony_ci} 8206f6ba60Sopenharmony_ci 8306f6ba60Sopenharmony_ciint HisyseventPlugin::Stop() 8406f6ba60Sopenharmony_ci{ 8506f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__); 8606f6ba60Sopenharmony_ci running_ = false; 8706f6ba60Sopenharmony_ci COMMON::CustomPUnblock(pipeFds_); 8806f6ba60Sopenharmony_ci 8906f6ba60Sopenharmony_ci if (workThread_.joinable()) { 9006f6ba60Sopenharmony_ci workThread_.join(); 9106f6ba60Sopenharmony_ci } 9206f6ba60Sopenharmony_ci 9306f6ba60Sopenharmony_ci if (fp_ != nullptr) { 9406f6ba60Sopenharmony_ci fp_.reset(); 9506f6ba60Sopenharmony_ci } 9606f6ba60Sopenharmony_ci 9706f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "END %s: success!", __func__); 9806f6ba60Sopenharmony_ci return 0; 9906f6ba60Sopenharmony_ci} 10006f6ba60Sopenharmony_ci 10106f6ba60Sopenharmony_civoid HisyseventPlugin::Run(void) 10206f6ba60Sopenharmony_ci{ 10306f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__); 10406f6ba60Sopenharmony_ci std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(MAX_STRING_LEN); 10506f6ba60Sopenharmony_ci 10606f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, 10706f6ba60Sopenharmony_ci "NOTE hisysevent_plugin_result.proto->HisyseventInfo:dataProto;Ready to output the result!"); 10806f6ba60Sopenharmony_ci 10906f6ba60Sopenharmony_ci fcntl(fileno(fp_.get()), F_SETPIPE_SZ, PIPE_SIZE); 11006f6ba60Sopenharmony_ci int aPipeSize = fcntl(fileno(fp_.get()), F_GETPIPE_SZ); 11106f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "{fp = %d, aPipeSize=%d, PIPE_SIZE=%d}", fileno(fp_.get()), aPipeSize, PIPE_SIZE); 11206f6ba60Sopenharmony_ci 11306f6ba60Sopenharmony_ci std::unique_ptr<HisyseventInfo> dataProto = nullptr; 11406f6ba60Sopenharmony_ci std::unique_ptr<ProtoEncoder::HisyseventInfo> hisyseventInfo = nullptr; 11506f6ba60Sopenharmony_ci if (resultWriter_->isProtobufSerialize) { 11606f6ba60Sopenharmony_ci dataProto = std::make_unique<HisyseventInfo>(); 11706f6ba60Sopenharmony_ci } else { 11806f6ba60Sopenharmony_ci hisyseventInfo = std::make_unique<ProtoEncoder::HisyseventInfo>(resultWriter_->startReport(resultWriter_)); 11906f6ba60Sopenharmony_ci } 12006f6ba60Sopenharmony_ci 12106f6ba60Sopenharmony_ci while (running_) { 12206f6ba60Sopenharmony_ci char* cptr = nullptr; 12306f6ba60Sopenharmony_ci if (fgets(reinterpret_cast<char*>(buffer.get()), MAX_STRING_LEN, fp_.get()) != nullptr) { 12406f6ba60Sopenharmony_ci cptr = reinterpret_cast<char*>(buffer.get()); 12506f6ba60Sopenharmony_ci } 12606f6ba60Sopenharmony_ci if (cptr == nullptr) { 12706f6ba60Sopenharmony_ci continue; 12806f6ba60Sopenharmony_ci } 12906f6ba60Sopenharmony_ci if (resultWriter_->isProtobufSerialize) { 13006f6ba60Sopenharmony_ci if (!ParseSyseventLineInfo(cptr, strlen(cptr), dataProto.get())) { 13106f6ba60Sopenharmony_ci continue; 13206f6ba60Sopenharmony_ci } 13306f6ba60Sopenharmony_ci 13406f6ba60Sopenharmony_ci if (dataProto->ByteSizeLong() >= BYTE_BUFFER_SIZE) { 13506f6ba60Sopenharmony_ci WriteResult(dataProto.get()); 13606f6ba60Sopenharmony_ci dataProto->clear_info(); 13706f6ba60Sopenharmony_ci } 13806f6ba60Sopenharmony_ci } else { 13906f6ba60Sopenharmony_ci if (!ParseSyseventLineInfo(cptr, strlen(cptr), hisyseventInfo.get())) { 14006f6ba60Sopenharmony_ci continue; 14106f6ba60Sopenharmony_ci } 14206f6ba60Sopenharmony_ci 14306f6ba60Sopenharmony_ci if (hisyseventInfo->Size() >= BYTE_BUFFER_SIZE) { 14406f6ba60Sopenharmony_ci FlushDataOptimize(hisyseventInfo.get()); 14506f6ba60Sopenharmony_ci hisyseventInfo.reset(); 14606f6ba60Sopenharmony_ci hisyseventInfo = 14706f6ba60Sopenharmony_ci std::make_unique<ProtoEncoder::HisyseventInfo>(resultWriter_->startReport(resultWriter_)); 14806f6ba60Sopenharmony_ci } 14906f6ba60Sopenharmony_ci } 15006f6ba60Sopenharmony_ci } 15106f6ba60Sopenharmony_ci 15206f6ba60Sopenharmony_ci if (resultWriter_->isProtobufSerialize) { 15306f6ba60Sopenharmony_ci WriteResult(dataProto.get()); 15406f6ba60Sopenharmony_ci dataProto.reset(); 15506f6ba60Sopenharmony_ci } else { 15606f6ba60Sopenharmony_ci FlushDataOptimize(hisyseventInfo.get()); 15706f6ba60Sopenharmony_ci hisyseventInfo.reset(); 15806f6ba60Sopenharmony_ci } 15906f6ba60Sopenharmony_ci 16006f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "END %s: success!", __func__); 16106f6ba60Sopenharmony_ci} 16206f6ba60Sopenharmony_ci 16306f6ba60Sopenharmony_cistd::string HisyseventPlugin::GetFullCmd() 16406f6ba60Sopenharmony_ci{ 16506f6ba60Sopenharmony_ci std::string cmd; 16606f6ba60Sopenharmony_ci 16706f6ba60Sopenharmony_ci if (!fullCmd_.empty()) { 16806f6ba60Sopenharmony_ci size_t i = 0; 16906f6ba60Sopenharmony_ci size_t dataLen = fullCmd_.size() > 1 ? fullCmd_.size() - 1 : 0; 17006f6ba60Sopenharmony_ci for (size_t cmdSize = dataLen; i < cmdSize; i++) { 17106f6ba60Sopenharmony_ci cmd.append(fullCmd_[i]).append(" "); 17206f6ba60Sopenharmony_ci } 17306f6ba60Sopenharmony_ci cmd.append(fullCmd_[i]); 17406f6ba60Sopenharmony_ci } 17506f6ba60Sopenharmony_ci return cmd; 17606f6ba60Sopenharmony_ci} 17706f6ba60Sopenharmony_ci 17806f6ba60Sopenharmony_ciinline bool HisyseventPlugin::InitHisyseventCmd() 17906f6ba60Sopenharmony_ci{ 18006f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__); 18106f6ba60Sopenharmony_ci if (!fullCmd_.empty()) { 18206f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "fullCmd_ is dirty.Then clear()."); 18306f6ba60Sopenharmony_ci fullCmd_.clear(); 18406f6ba60Sopenharmony_ci } 18506f6ba60Sopenharmony_ci 18606f6ba60Sopenharmony_ci fullCmd_.emplace_back("/system/bin/hisysevent"); // exe file path 18706f6ba60Sopenharmony_ci fullCmd_.emplace_back("hisysevent"); // exe file name 18806f6ba60Sopenharmony_ci fullCmd_.emplace_back("-rd"); 18906f6ba60Sopenharmony_ci 19006f6ba60Sopenharmony_ci if (!protoConfig_.subscribe_domain().empty()) { 19106f6ba60Sopenharmony_ci fullCmd_.emplace_back("-o"); 19206f6ba60Sopenharmony_ci fullCmd_.emplace_back(protoConfig_.subscribe_domain()); 19306f6ba60Sopenharmony_ci } 19406f6ba60Sopenharmony_ci if (!protoConfig_.subscribe_event().empty()) { 19506f6ba60Sopenharmony_ci fullCmd_.emplace_back("-n"); 19606f6ba60Sopenharmony_ci fullCmd_.emplace_back(protoConfig_.subscribe_event()); 19706f6ba60Sopenharmony_ci } 19806f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "END %s: success!", __func__); 19906f6ba60Sopenharmony_ci return true; 20006f6ba60Sopenharmony_ci} 20106f6ba60Sopenharmony_ci 20206f6ba60Sopenharmony_citemplate <typename T> 20306f6ba60Sopenharmony_ciinline bool HisyseventPlugin::ParseSyseventLineInfo(const char* data, size_t len, T hisyseventInfoProto) 20406f6ba60Sopenharmony_ci{ 20506f6ba60Sopenharmony_ci CHECK_TRUE(data != nullptr && len >= MIN_STRING_LEN, false, "NOTE %s: param invalid", __func__); 20606f6ba60Sopenharmony_ci size_t dataLen = strlen(data) > 1 ? strlen(data) - 1 : 0; 20706f6ba60Sopenharmony_ci if (google::protobuf::internal::IsStructurallyValidUTF8(data, dataLen)) { 20806f6ba60Sopenharmony_ci auto* info = hisyseventInfoProto->add_info(); 20906f6ba60Sopenharmony_ci info->set_id(id_); 21006f6ba60Sopenharmony_ci size_t len = strlen(data) > 1 ? strlen(data) - 1 : 0; 21106f6ba60Sopenharmony_ci info->set_context(data, len); // - \n 21206f6ba60Sopenharmony_ci id_++; 21306f6ba60Sopenharmony_ci } else { 21406f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "NOTE HisyseventPlugin: hisysevent context include invalid UTF-8 data"); 21506f6ba60Sopenharmony_ci return false; 21606f6ba60Sopenharmony_ci } 21706f6ba60Sopenharmony_ci return true; 21806f6ba60Sopenharmony_ci} 21906f6ba60Sopenharmony_ci 22006f6ba60Sopenharmony_citemplate <typename T> inline bool HisyseventPlugin::WriteResult(const T hisyseventInfoProto) 22106f6ba60Sopenharmony_ci{ 22206f6ba60Sopenharmony_ci // Cmd result resize and SerializeToArray and after save to protoBuffer_ ;Then write and flush;Then clear_info 22306f6ba60Sopenharmony_ci protoBuffer_.resize(hisyseventInfoProto->ByteSizeLong()); 22406f6ba60Sopenharmony_ci hisyseventInfoProto->SerializeToArray(protoBuffer_.data(), protoBuffer_.size()); 22506f6ba60Sopenharmony_ci // SerializeToArray after data=%s",protoBuffer_.data() 22606f6ba60Sopenharmony_ci resultWriter_->write(resultWriter_, protoBuffer_.data(), protoBuffer_.size()); 22706f6ba60Sopenharmony_ci resultWriter_->flush(resultWriter_); 22806f6ba60Sopenharmony_ci return true; 22906f6ba60Sopenharmony_ci} 23006f6ba60Sopenharmony_ci 23106f6ba60Sopenharmony_citemplate <typename T> void HisyseventPlugin::FlushDataOptimize(const T hisyseventInfoProto) 23206f6ba60Sopenharmony_ci{ 23306f6ba60Sopenharmony_ci int messageLen = hisyseventInfoProto->Finish(); 23406f6ba60Sopenharmony_ci resultWriter_->finishReport(resultWriter_, messageLen); 23506f6ba60Sopenharmony_ci resultWriter_->flush(resultWriter_); 23606f6ba60Sopenharmony_ci} 237