mirror of
https://gitee.com/openharmony/developtools_profiler
synced 2024-11-23 06:50:12 +00:00
arkts-plugin 插件日落
Signed-off-by:wenlong12<wenlong12@huawei.com> Signed-off-by: wenlong_12 <wenlong12@huawei.com>
This commit is contained in:
parent
51c25d2b29
commit
69760e0e9a
@ -18,7 +18,6 @@ group("hiprofiler_targets") {
|
||||
deps = [
|
||||
"cmds:hiprofiler_cmd",
|
||||
"plugins/api:hiprofiler_plugins",
|
||||
"plugins/arkts_plugin:arktsplugin",
|
||||
"plugins/cpu_plugin:cpudataplugin",
|
||||
"plugins/diskio_plugin:diskiodataplugin",
|
||||
"plugins/ffrt_profiler/client:libffrt_profiler",
|
||||
@ -62,7 +61,6 @@ group("unittest") {
|
||||
"base/test:unittest",
|
||||
"cmds/test:unittest",
|
||||
"plugins/api/test:unittest",
|
||||
"plugins/arkts_plugin/test:unittest",
|
||||
"plugins/cpu_plugin/test:unittest",
|
||||
"plugins/diskio_plugin/test:unittest",
|
||||
"plugins/ffrt_profiler/test:unittest",
|
||||
|
@ -37,7 +37,6 @@ ohos_executable("hiprofiler_cmd") {
|
||||
"${OHOS_PROFILER_DIR}/device/base:hiprofiler_base",
|
||||
"${OHOS_PROFILER_DIR}/protos/services:profiler_service_proto",
|
||||
"${OHOS_PROFILER_DIR}/protos/services:profiler_service_type_source",
|
||||
"${OHOS_PROFILER_DIR}/protos/types/plugins/arkts_plugin:arkts_plugin_cpp_standard",
|
||||
"${OHOS_PROFILER_DIR}/protos/types/plugins/cpu_data:cpu_plugin_config_cpp_standard",
|
||||
"${OHOS_PROFILER_DIR}/protos/types/plugins/diskio_data:diskio_plugin_config_cpp_standard",
|
||||
"${OHOS_PROFILER_DIR}/protos/types/plugins/ffrt_profiler:ffrt_profiler_cpp_standard",
|
||||
|
19
device/cmds/src/parse_plugin_config.cpp
Executable file → Normal file
19
device/cmds/src/parse_plugin_config.cpp
Executable file → Normal file
@ -23,7 +23,6 @@
|
||||
#include "hilog_plugin_config_standard.pb.h"
|
||||
#include "hiperf_plugin_config_standard.pb.h"
|
||||
#include "hisysevent_plugin_config_standard.pb.h"
|
||||
#include "arkts_plugin_config_standard.pb.h"
|
||||
#include "memory_plugin_common_standard.pb.h"
|
||||
#include "memory_plugin_config_standard.pb.h"
|
||||
#include "native_hook_config_standard.pb.h"
|
||||
@ -128,8 +127,6 @@ bool ParsePluginConfig::SetSerializePluginsConfig(const std::string& pluginName,
|
||||
ret = SetSerializeHiperfConfig(pluginName, pluginConfig);
|
||||
} else if (pluginName == "hisysevent-plugin") {
|
||||
ret = SetSerializeHisyseventConfig(pluginName, pluginConfig);
|
||||
} else if (pluginName == "arkts-plugin") {
|
||||
ret = SetSerializeArkTSConfig(pluginName, pluginConfig);
|
||||
} else if (pluginName == "xpower-plugin") {
|
||||
ret = SetSerializeXpowerConfig(pluginName, pluginConfig);
|
||||
} else if (pluginName == "gpu-plugin") {
|
||||
@ -369,22 +366,6 @@ bool ParsePluginConfig::SetSerializeHisyseventConfig(const std::string& pluginNa
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParsePluginConfig::SetSerializeArkTSConfig(const std::string& pluginName, ProfilerPluginConfig& pluginConfig)
|
||||
{
|
||||
std::string configData = pluginConfigMap[pluginName];
|
||||
auto arkTSConfigNolite = std::make_unique<ForStandard::ArkTSConfig>();
|
||||
if (!parser_.ParseFromString(configData, arkTSConfigNolite.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> configDataVec(arkTSConfigNolite->ByteSizeLong());
|
||||
if (arkTSConfigNolite->SerializeToArray(configDataVec.data(), configDataVec.size()) <= 0) {
|
||||
return false;
|
||||
}
|
||||
pluginConfig.set_config_data(static_cast<const void*>(configDataVec.data()), configDataVec.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParsePluginConfig::SetSerializeXpowerConfig(const std::string& pluginName, ProfilerPluginConfig& pluginConfig)
|
||||
{
|
||||
std::string configData = pluginConfigMap[pluginName];
|
||||
|
@ -33,7 +33,6 @@ ohos_unittest("hiprofiler_cmd_ut") {
|
||||
"${OHOS_PROFILER_DIR}/device/base:hiprofiler_base",
|
||||
"${OHOS_PROFILER_DIR}/protos/services:profiler_service_proto",
|
||||
"${OHOS_PROFILER_DIR}/protos/services:profiler_service_type_source",
|
||||
"${OHOS_PROFILER_DIR}/protos/types/plugins/arkts_plugin:arkts_plugin_cpp_standard",
|
||||
"${OHOS_PROFILER_DIR}/protos/types/plugins/cpu_data:cpu_plugin_config_cpp_standard",
|
||||
"${OHOS_PROFILER_DIR}/protos/types/plugins/diskio_data:diskio_plugin_config_cpp_standard",
|
||||
"${OHOS_PROFILER_DIR}/protos/types/plugins/ffrt_profiler:ffrt_profiler_cpp_standard",
|
||||
|
@ -368,36 +368,6 @@ public:
|
||||
return cmdStr;
|
||||
}
|
||||
|
||||
std::string CreateSplitArktsCommand(const std::string &outFile, const std::string &arktsSplitFile, int time) const
|
||||
{
|
||||
std::string cmdStr =
|
||||
"hiprofiler_cmd -s -k \\\n"
|
||||
"-c - \\\n";
|
||||
cmdStr += "-o " + outFile + " \\\n";
|
||||
cmdStr += "-t " + std::to_string(time) + " \\\n"
|
||||
"<<CONFIG\n"
|
||||
"request_id: 1\n"
|
||||
"session_config {\n"
|
||||
" buffers {\n"
|
||||
" pages: 16384\n"
|
||||
" }\n"
|
||||
" split_file: true\n"
|
||||
"}\n"
|
||||
"plugin_configs {\n"
|
||||
" plugin_name: \"arkts-plugin\"\n"
|
||||
" config_data {\n"
|
||||
" pid: 1\n"
|
||||
" capture_numeric_value: true\n"
|
||||
" track_allocations: false\n"
|
||||
" enable_cpu_profiler: true\n"
|
||||
" cpu_profiler_interval: 1000\n"
|
||||
" split_outfile_name: \"" + arktsSplitFile + "\"\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"CONFIG\n";
|
||||
return cmdStr;
|
||||
}
|
||||
|
||||
std::string CreateSplitHiperfCommand(const std::string &outFile, const std::string &perfFile,
|
||||
const std::string &perfSplitFile, int time) const
|
||||
{
|
||||
@ -779,31 +749,6 @@ HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0200, Function | MediumTest | Lev
|
||||
system(cmd.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: hiprofiler_cmd
|
||||
* @tc.desc: Test hiprofiler_cmd with split arkts file.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(HiprofilerCmdTest, DFX_DFR_Hiprofiler_0210, Function | MediumTest | Level1)
|
||||
{
|
||||
std::string outFileName = "split_arkts";
|
||||
std::string outFile = DEFAULT_PATH + outFileName + ".htrace";
|
||||
std::string arktsSplitFile = "/data/local/tmp/split_arkts_data.htrace";
|
||||
std::string content = "";
|
||||
int time = 10;
|
||||
std::string cmd = CreateSplitArktsCommand(outFile, arktsSplitFile, time);
|
||||
EXPECT_TRUE(RunCommand(cmd, content));
|
||||
|
||||
EXPECT_NE(access(outFile.c_str(), F_OK), 0);
|
||||
|
||||
cmd = "ls " + DEFAULT_PATH + outFileName + "*_1.htrace";
|
||||
EXPECT_TRUE(RunCommand(cmd, content));
|
||||
EXPECT_STRNE(content.c_str(), "");
|
||||
|
||||
EXPECT_EQ(access(arktsSplitFile.c_str(), F_OK), 0);
|
||||
cmd = "rm " + DEFAULT_PATH + outFileName + "*.htrace";
|
||||
system(cmd.c_str());
|
||||
}
|
||||
/**
|
||||
* @tc.name: hiprofiler_cmd
|
||||
* @tc.desc: Test hiprofiler_cmd with split hiperf file.
|
||||
|
@ -81,7 +81,6 @@ HWTEST_F(ParsePluginConfigTest, TestParsePluginConfig, TestSize.Level1)
|
||||
"hiperf-plugin",
|
||||
"hisysevent-plugin",
|
||||
"hiebpf-plugin",
|
||||
"arkts-plugin",
|
||||
"invalid-plugin",
|
||||
};
|
||||
for (const std::string &pluginName : pluginNames) {
|
||||
|
@ -162,16 +162,6 @@
|
||||
<option name="push" value="../hiebpf/test/resources/elf64.stripped -> /data/test/resources/testdata/" src="res"/>
|
||||
</preparer>
|
||||
</target>
|
||||
<target name="arktsplugin_ut">
|
||||
<preparer>
|
||||
<option name="push" value="plugins/arkts_plugin/test/resources/entry-default-signed.hap -> /data/local/tmp/" src="res"/>
|
||||
<option name="shell" value="bm install -r -p /data/local/tmp/entry-default-signed.hap"/>
|
||||
<option name="shell" value="aa start -a EntryAbility -b cn.openharmony.rebound_project"/>
|
||||
</preparer>
|
||||
<cleaner>
|
||||
<option name="uninstall" value="cn.openharmony.rebound_project"/>
|
||||
</cleaner>
|
||||
</target>
|
||||
<target name="ftrace_plugin_ut">
|
||||
<preparer>
|
||||
<option name="push" value="plugins/ftrace_plugin/test/unittest/resource/test_raw_0 -> /data/local/tmp/" src="res"/>
|
||||
|
@ -1,69 +0,0 @@
|
||||
# Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/ohos.gni")
|
||||
import("../../base/config.gni")
|
||||
|
||||
ohos_source_set("arkts_source") {
|
||||
sources = [
|
||||
"${OHOS_PROFILER_DIR}/device/services/profiler_service/src/trace_file_helper.cpp",
|
||||
"${OHOS_PROFILER_DIR}/device/services/profiler_service/src/trace_file_writer.cpp",
|
||||
"src/arkts_module.cpp",
|
||||
"src/arkts_plugin.cpp",
|
||||
]
|
||||
include_dirs = [
|
||||
"include",
|
||||
"../../base/include/",
|
||||
"${OHOS_PROFILER_DIR}/interfaces/kits",
|
||||
"${OHOS_PROFILER_DIR}/device/base/include",
|
||||
"${OHOS_PROFILER_DIR}/device/plugins/api/include",
|
||||
"${OHOS_PROFILER_DIR}/device/services/profiler_service/src",
|
||||
]
|
||||
deps = [
|
||||
"${OHOS_PROFILER_DIR}/proto_encoder:proto_encoder_source",
|
||||
"${OHOS_PROFILER_DIR}/protos/services:common_types_lite_proto",
|
||||
"${OHOS_PROFILER_DIR}/protos/types/plugins/arkts_plugin:arkts_plugin_data_cpp",
|
||||
"../../base:hiprofiler_base",
|
||||
]
|
||||
|
||||
defines = [ "LITE_PROTO" ]
|
||||
if (current_toolchain != host_toolchain) {
|
||||
defines += [ "HAVE_HILOG" ]
|
||||
external_deps = [
|
||||
"bounds_checking_function:libsec_shared",
|
||||
"hilog:libhilog_base",
|
||||
"openssl:libcrypto_shared",
|
||||
"protobuf:protobuf_lite",
|
||||
]
|
||||
}
|
||||
public_configs = [ "${OHOS_PROFILER_DIR}/device/base:hiprofiler_test_config" ]
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
part_name = "${OHOS_PROFILER_PART_NAME}"
|
||||
}
|
||||
|
||||
ohos_shared_library("arktsplugin") {
|
||||
output_name = "arktsplugin"
|
||||
version_script = "libarkts_plugin.map"
|
||||
deps = [ ":arkts_source" ]
|
||||
if (current_toolchain != host_toolchain) {
|
||||
defines = [ "HAVE_HILOG" ]
|
||||
external_deps = [
|
||||
"bounds_checking_function:libsec_shared",
|
||||
"hilog:libhilog_base",
|
||||
"openssl:libcrypto_shared",
|
||||
]
|
||||
}
|
||||
install_enable = true
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
part_name = "${OHOS_PROFILER_PART_NAME}"
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ARKTS_PLUGIN_H
|
||||
#define ARKTS_PLUGIN_H
|
||||
|
||||
#include "arkts_plugin_config.pb.h"
|
||||
#include "plugin_module_api.h"
|
||||
#include "schedule_task_manager.h"
|
||||
#include "trace_file_writer.h"
|
||||
|
||||
struct WebSocketFrame {
|
||||
uint8_t fin;
|
||||
uint8_t opCode;
|
||||
uint8_t mask;
|
||||
char maskingKey[5];
|
||||
uint64_t payloadLen;
|
||||
std::unique_ptr<char[]> payload;
|
||||
};
|
||||
|
||||
class ArkTSPlugin {
|
||||
public:
|
||||
ArkTSPlugin() = default;
|
||||
~ArkTSPlugin() = default;
|
||||
int32_t Start(const uint8_t* configData, uint32_t configSize);
|
||||
int32_t Stop();
|
||||
void SetWriter(WriterStruct* writer);
|
||||
|
||||
private:
|
||||
void Snapshot();
|
||||
void FlushData(const std::string& command = "");
|
||||
bool ClientConnectUnixWebSocket(const std::string& sockName, uint32_t timeoutLimit = 0);
|
||||
bool ClientSendWSUpgradeReq();
|
||||
bool ClientRecvWSUpgradeRsp();
|
||||
bool ClientSendReq(const std::string& message);
|
||||
void Close();
|
||||
bool SetWebSocketTimeOut(int32_t fd, uint32_t timeoutLimit);
|
||||
std::string Decode();
|
||||
bool HandleFrame(WebSocketFrame& wsFrame);
|
||||
bool DecodeMessage(WebSocketFrame& wsFrame);
|
||||
uint64_t NetToHostLongLong(char* buf, uint32_t len);
|
||||
bool Recv(int32_t client, char* buf, size_t totalLen, int32_t flags) const;
|
||||
int32_t EnableTimeline();
|
||||
int32_t EnableSnapshot();
|
||||
int32_t EnableCpuProfiler();
|
||||
|
||||
private:
|
||||
ArkTSConfig protoConfig_;
|
||||
WriterStruct* resultWriter_{nullptr};
|
||||
int32_t pid_{0};
|
||||
std::vector<char> buffer_;
|
||||
std::string snapshotCmd_;
|
||||
std::string timelineCmd_;
|
||||
int32_t client_{-1};
|
||||
enum SocketState : uint8_t {
|
||||
UNINITED,
|
||||
INITED,
|
||||
CONNECTED,
|
||||
};
|
||||
std::atomic<SocketState> socketState_{SocketState::UNINITED};
|
||||
uint8_t commandResult_{0};
|
||||
ScheduleTaskManager scheduleTaskManager_;
|
||||
int32_t snapshotScheduleTaskFd_;
|
||||
std::shared_ptr<TraceFileWriter> splitTraceWriter_ {nullptr};
|
||||
};
|
||||
|
||||
#endif // ARKTS_PLUGIN_H
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
global:
|
||||
extern "C++" {
|
||||
"g_pluginModule";
|
||||
};
|
||||
local:
|
||||
*;
|
||||
};
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
#include "arkts_plugin.h"
|
||||
|
||||
namespace {
|
||||
constexpr uint32_t MAX_BUFFER_SIZE = 4 * 1024 * 1024;
|
||||
std::mutex g_taskMutex;
|
||||
std::unique_ptr<ArkTSPlugin> g_plugin = nullptr;
|
||||
} // namespace
|
||||
|
||||
static int ArkTSPluginSessionStart(const uint8_t* configData, uint32_t configSize)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(g_taskMutex);
|
||||
g_plugin->Start(configData, configSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ArkTSPluginSessionStop()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(g_taskMutex);
|
||||
g_plugin->Stop();
|
||||
g_plugin = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ArkTSPluginRegisterWriterStruct(WriterStruct* writer)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(g_taskMutex);
|
||||
g_plugin = std::make_unique<ArkTSPlugin>();
|
||||
g_plugin->SetWriter(writer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PluginModuleCallbacks g_callbacks = {
|
||||
.onPluginSessionStart = ArkTSPluginSessionStart,
|
||||
.onPluginReportResult = 0,
|
||||
.onPluginSessionStop = ArkTSPluginSessionStop,
|
||||
.onRegisterWriterStruct = (RegisterWriterStructCallback)ArkTSPluginRegisterWriterStruct,
|
||||
};
|
||||
|
||||
EXPORT_API PluginModuleStruct g_pluginModule = {
|
||||
.callbacks = &g_callbacks,
|
||||
.name = "arkts-plugin",
|
||||
.version = "1.01",
|
||||
.resultBufferSizeHint = MAX_BUFFER_SIZE,
|
||||
};
|
@ -1,579 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "arkts_plugin.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <cstdlib>
|
||||
#include <regex>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "arkts_plugin_result.pb.h"
|
||||
#include "logging.h"
|
||||
#include "securec.h"
|
||||
|
||||
namespace {
|
||||
const std::string PANDA = "PandaDebugger";
|
||||
const std::string SNAPSHOT_HEAD =
|
||||
R"({"id":1,"method":"HeapProfiler.takeHeapSnapshot","params":{"reportProgress":true,"captureNumericValue":)";
|
||||
const std::string SNAPSHOT_TAIL = R"(,"exposeInternals":false}})";
|
||||
const std::string TIMELINE_HEAD =
|
||||
R"({"id":1,"method":"HeapProfiler.startTrackingHeapObjects","params":{"trackAllocations":)";
|
||||
const std::string TIMELINE_TAIL = "}}";
|
||||
const std::string TIMELINE_STOP =
|
||||
R"({"id":2,"method":"HeapProfiler.stopTrackingHeapObjects","params":{"reportProgress":true}})";
|
||||
const std::string CPU_PROFILER_INTERVAL_HEAD =
|
||||
R"({"id":3,"method":"Profiler.setSamplingInterval","params":{"interval":)";
|
||||
const std::string CPU_PROFILER_INTERVAL_TAIL = R"(}})";
|
||||
const std::string CPU_PROFILER_START = R"({"id":3,"method":"Profiler.start","params":{}})";
|
||||
const std::string CPU_PROFILER_STOP = R"({"id":3,"method":"Profiler.stop","params":{}})";
|
||||
constexpr uint8_t TIMELINE_START_SUCCESS = 0x1;
|
||||
constexpr uint8_t CPU_PROFILER_START_SUCCESS = 0x2;
|
||||
const std::string RESPONSE_FLAG_HEAD = R"({"id":)";
|
||||
const std::string RESPONSE_FLAG_TAIL = R"(,"result":{}})";
|
||||
const std::string REGEX_PATTERN = R"("id":(\d+))";
|
||||
const std::string ARKTS_SCHEDULE = R"(ArkTS_Snapshot)";
|
||||
enum class HeapType : int32_t {
|
||||
INVALID = -1,
|
||||
SNAPSHOT,
|
||||
TIMELINE,
|
||||
};
|
||||
constexpr char CLIENT_WEBSOCKET_UPGRADE_REQ[] =
|
||||
"GET / HTTP/1.1\r\n"
|
||||
"Connection: Upgrade\r\n"
|
||||
"Pragma: no-cache\r\n"
|
||||
"Cache-Control: no-cache\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
"Sec-WebSocket-Version: 13\r\n"
|
||||
"Accept-Encoding: gzip, deflate, br\r\n"
|
||||
"Sec-WebSocket-Key: 64b4B+s5JDlgkdg7NekJ+g==\r\n"
|
||||
"Sec-WebSocket-Extensions: permessage-deflate\r\n";
|
||||
constexpr int32_t CLIENT_WEBSOCKET_UPGRADE_RSP_LEN = 129;
|
||||
constexpr int32_t SOCKET_MASK_LEN = 4;
|
||||
constexpr char MASK_KEY[SOCKET_MASK_LEN + 1] = "abcd";
|
||||
constexpr uint32_t TIME_OUT = 5;
|
||||
constexpr uint32_t TIME_BASE = 1000;
|
||||
constexpr int32_t SOCKET_SUCCESS = 0;
|
||||
constexpr int32_t SOCKET_HEADER_LEN = 2;
|
||||
constexpr int32_t PAYLOAD_LEN = 2;
|
||||
constexpr int32_t EXTEND_PAYLOAD_LEN = 8;
|
||||
constexpr uint32_t CPU_PROFILER_INTERVAL_DEFAULT = 1000;
|
||||
} // namespace
|
||||
|
||||
int32_t ArkTSPlugin::Start(const uint8_t* configData, uint32_t configSize)
|
||||
{
|
||||
if (protoConfig_.ParseFromArray(configData, configSize) <= 0) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "%s:parseFromArray failed!", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!protoConfig_.split_outfile_name().empty()) {
|
||||
splitTraceWriter_ = std::make_shared<TraceFileWriter>(protoConfig_.split_outfile_name());
|
||||
splitTraceWriter_->WriteStandalonePluginData(
|
||||
std::string(g_pluginModule.name) + "_config",
|
||||
std::string(reinterpret_cast<const char *>(configData),
|
||||
configSize));
|
||||
splitTraceWriter_->SetTimeSource();
|
||||
}
|
||||
|
||||
pid_ = protoConfig_.pid();
|
||||
if (pid_ <= 0) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "%s: pid is less than or equal to 0", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ClientConnectUnixWebSocket(std::to_string(pid_) + PANDA, TIME_OUT)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ClientSendWSUpgradeReq()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ClientRecvWSUpgradeRsp()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (protoConfig_.enable_cpu_profiler()) {
|
||||
if (EnableCpuProfiler() != 0) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "arkts plugin cpu profiler start failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (static_cast<int32_t>(protoConfig_.type())) {
|
||||
case static_cast<int32_t>(HeapType::SNAPSHOT): {
|
||||
return EnableSnapshot();
|
||||
}
|
||||
case static_cast<int32_t>(HeapType::TIMELINE): {
|
||||
return EnableTimeline();
|
||||
}
|
||||
case static_cast<int32_t>(HeapType::INVALID): {
|
||||
PROFILER_LOG_INFO(LOG_CORE, "arkts plugin memory type is INVALID");
|
||||
return 0;
|
||||
}
|
||||
default: {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "arkts plugin start type error");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t ArkTSPlugin::EnableTimeline()
|
||||
{
|
||||
std::string timelineCmd = TIMELINE_HEAD + (protoConfig_.track_allocations() ? "true" : "false") + TIMELINE_TAIL;
|
||||
if (!ClientSendReq(timelineCmd)) {
|
||||
return -1;
|
||||
}
|
||||
FlushData(timelineCmd);
|
||||
commandResult_ |= TIMELINE_START_SUCCESS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ArkTSPlugin::EnableSnapshot()
|
||||
{
|
||||
if (protoConfig_.interval() == 0) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "%s:scheduleTask interval == 0 error!", __func__);
|
||||
return -1;
|
||||
}
|
||||
snapshotCmd_ = SNAPSHOT_HEAD + (protoConfig_.capture_numeric_value() ? "true" : "false") + SNAPSHOT_TAIL;
|
||||
auto callback = std::bind(&ArkTSPlugin::Snapshot, this);
|
||||
snapshotScheduleTaskFd_ = scheduleTaskManager_.ScheduleTask(callback, protoConfig_.interval() * TIME_BASE);
|
||||
if (snapshotScheduleTaskFd_ == -1) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "%s:scheduleTask failed!", __func__);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ArkTSPlugin::EnableCpuProfiler()
|
||||
{
|
||||
std::string interval = CPU_PROFILER_INTERVAL_HEAD
|
||||
+ (protoConfig_.cpu_profiler_interval() == 0 ?
|
||||
std::to_string(CPU_PROFILER_INTERVAL_DEFAULT) : std::to_string(protoConfig_.cpu_profiler_interval()))
|
||||
+ CPU_PROFILER_INTERVAL_TAIL;
|
||||
if (!ClientSendReq(interval)) {
|
||||
return -1;
|
||||
}
|
||||
FlushData(interval);
|
||||
|
||||
if (!ClientSendReq(CPU_PROFILER_START)) {
|
||||
return -1;
|
||||
}
|
||||
FlushData(CPU_PROFILER_START);
|
||||
commandResult_ |= CPU_PROFILER_START_SUCCESS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ArkTSPlugin::Stop()
|
||||
{
|
||||
switch (static_cast<int32_t>(protoConfig_.type())) {
|
||||
case static_cast<int32_t>(HeapType::SNAPSHOT): {
|
||||
scheduleTaskManager_.UnscheduleTask(snapshotScheduleTaskFd_);
|
||||
break;
|
||||
}
|
||||
case static_cast<int32_t>(HeapType::TIMELINE): {
|
||||
if (commandResult_ & TIMELINE_START_SUCCESS) {
|
||||
if (!ClientSendReq(TIMELINE_STOP)) {
|
||||
break;
|
||||
}
|
||||
FlushData(TIMELINE_STOP);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case static_cast<int32_t>(HeapType::INVALID): {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "arkts plugin stop type error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (protoConfig_.enable_cpu_profiler() && (commandResult_ & CPU_PROFILER_START_SUCCESS)) {
|
||||
if (ClientSendReq(CPU_PROFILER_STOP)) {
|
||||
FlushData();
|
||||
}
|
||||
}
|
||||
Close();
|
||||
|
||||
if (!protoConfig_.split_outfile_name().empty()) { // write split file.
|
||||
CHECK_NOTNULL(splitTraceWriter_, -1, "%s: writer is nullptr, WriteStandaloneFile failed", __func__);
|
||||
splitTraceWriter_->SetDurationTime();
|
||||
splitTraceWriter_->Finish();
|
||||
splitTraceWriter_.reset();
|
||||
splitTraceWriter_ = nullptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ArkTSPlugin::SetWriter(WriterStruct* writer)
|
||||
{
|
||||
resultWriter_ = writer;
|
||||
}
|
||||
|
||||
void ArkTSPlugin::Snapshot()
|
||||
{
|
||||
CHECK_NOTNULL(resultWriter_, NO_RETVAL, "%s: resultWriter_ nullptr", __func__);
|
||||
if (!ClientSendReq(snapshotCmd_)) {
|
||||
return;
|
||||
}
|
||||
FlushData(snapshotCmd_);
|
||||
}
|
||||
|
||||
void ArkTSPlugin::FlushData(const std::string& command)
|
||||
{
|
||||
std::string endFlag;
|
||||
if (!command.empty()) {
|
||||
std::regex pattern(REGEX_PATTERN);
|
||||
std::smatch match;
|
||||
if (std::regex_search(command, match, pattern)) {
|
||||
endFlag = RESPONSE_FLAG_HEAD + match[1].str() + RESPONSE_FLAG_TAIL;
|
||||
}
|
||||
}
|
||||
if (!protoConfig_.split_outfile_name().empty()) {
|
||||
CHECK_NOTNULL(splitTraceWriter_, NO_RETVAL, "%s: writer is nullptr, WriteStandaloneFile failed", __func__);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
std::string recv = Decode();
|
||||
if (recv.empty()) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "%s: recv is empty", __func__);
|
||||
break;
|
||||
}
|
||||
ArkTSResult data;
|
||||
data.set_result(recv.c_str(), recv.size());
|
||||
buffer_.resize(data.ByteSizeLong());
|
||||
data.SerializeToArray(buffer_.data(), buffer_.size());
|
||||
|
||||
if (protoConfig_.split_outfile_name().empty()) {
|
||||
resultWriter_->write(resultWriter_, buffer_.data(), buffer_.size());
|
||||
resultWriter_->flush(resultWriter_);
|
||||
} else { // write split file.
|
||||
splitTraceWriter_->WriteStandalonePluginData(
|
||||
std::string(g_pluginModule.name),
|
||||
std::string(buffer_.data(), buffer_.size()),
|
||||
std::string(g_pluginModule.version));
|
||||
}
|
||||
|
||||
if (endFlag.empty() || recv == endFlag) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!protoConfig_.split_outfile_name().empty()) {
|
||||
splitTraceWriter_->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
bool ArkTSPlugin::ClientConnectUnixWebSocket(const std::string& sockName, uint32_t timeoutLimit)
|
||||
{
|
||||
if (socketState_ != SocketState::UNINITED) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client has inited");
|
||||
return true;
|
||||
}
|
||||
|
||||
client_ = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (client_ < SOCKET_SUCCESS) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client socket failed, error = %d, , desc = %s", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
// set send and recv timeout limit
|
||||
if (!SetWebSocketTimeOut(client_, timeoutLimit)) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client SetWebSocketTimeOut failed, error = %d, desc = %s",
|
||||
errno, strerror(errno));
|
||||
close(client_);
|
||||
client_ = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sockaddr_un serverAddr;
|
||||
if (memset_s(&serverAddr, sizeof(serverAddr), 0, sizeof(serverAddr)) != EOK) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client memset_s serverAddr failed, error = %d, desc = %s",
|
||||
errno, strerror(errno));
|
||||
close(client_);
|
||||
client_ = -1;
|
||||
return false;
|
||||
}
|
||||
serverAddr.sun_family = AF_UNIX;
|
||||
if (strcpy_s(serverAddr.sun_path + 1, sizeof(serverAddr.sun_path) - 1, sockName.c_str()) != EOK) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client strcpy_s serverAddr.sun_path failed, error = %d, , desc = %s",
|
||||
errno, strerror(errno));
|
||||
close(client_);
|
||||
client_ = -1;
|
||||
return false;
|
||||
}
|
||||
serverAddr.sun_path[0] = '\0';
|
||||
|
||||
uint32_t len = offsetof(struct sockaddr_un, sun_path) + strlen(sockName.c_str()) + 1;
|
||||
int ret = connect(client_, reinterpret_cast<struct sockaddr*>(&serverAddr), static_cast<int32_t>(len));
|
||||
if (ret != SOCKET_SUCCESS) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client connect failed, error, error = %d, , desc = %s", errno, strerror(errno));
|
||||
close(client_);
|
||||
client_ = -1;
|
||||
return false;
|
||||
}
|
||||
socketState_ = SocketState::INITED;
|
||||
PROFILER_LOG_INFO(LOG_CORE, "client connect success...");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArkTSPlugin::ClientSendWSUpgradeReq()
|
||||
{
|
||||
if (socketState_ == SocketState::UNINITED) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client has not inited");
|
||||
return false;
|
||||
}
|
||||
if (socketState_ == SocketState::CONNECTED) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client has connected");
|
||||
return true;
|
||||
}
|
||||
|
||||
int msgLen = strlen(CLIENT_WEBSOCKET_UPGRADE_REQ);
|
||||
int32_t sendLen = send(client_, CLIENT_WEBSOCKET_UPGRADE_REQ, msgLen, 0);
|
||||
if (sendLen != msgLen) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client send wsupgrade req failed, error = %d, desc = %s", errno, strerror(errno));
|
||||
socketState_ = SocketState::UNINITED;
|
||||
shutdown(client_, SHUT_RDWR);
|
||||
close(client_);
|
||||
client_ = -1;
|
||||
return false;
|
||||
}
|
||||
PROFILER_LOG_INFO(LOG_CORE, "client send wsupgrade req success");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArkTSPlugin::ClientRecvWSUpgradeRsp()
|
||||
{
|
||||
if (socketState_ == SocketState::UNINITED) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client has not inited");
|
||||
return false;
|
||||
}
|
||||
if (socketState_ == SocketState::CONNECTED) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "ClientRecvWSUpgradeRsp::client has connected");
|
||||
return true;
|
||||
}
|
||||
|
||||
char recvBuf[CLIENT_WEBSOCKET_UPGRADE_RSP_LEN + 1] = {0};
|
||||
int32_t bufLen = recv(client_, recvBuf, CLIENT_WEBSOCKET_UPGRADE_RSP_LEN, 0);
|
||||
if (bufLen != CLIENT_WEBSOCKET_UPGRADE_RSP_LEN) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client recv wsupgrade rsp failed, error = %d, desc = %s", errno, strerror(errno));
|
||||
socketState_ = SocketState::UNINITED;
|
||||
shutdown(client_, SHUT_RDWR);
|
||||
close(client_);
|
||||
client_ = -1;
|
||||
return false;
|
||||
}
|
||||
socketState_ = SocketState::CONNECTED;
|
||||
PROFILER_LOG_INFO(LOG_CORE, "client recv wsupgrade rsp success");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArkTSPlugin::ClientSendReq(const std::string& message)
|
||||
{
|
||||
if (socketState_ != SocketState::CONNECTED) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client has not connected");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t msgLen = message.length();
|
||||
std::unique_ptr<char[]> msgBuf = std::make_unique<char[]>(msgLen + 15); // 15: the maximum expand length
|
||||
char* sendBuf = msgBuf.get();
|
||||
uint32_t sendMsgLen = 0;
|
||||
sendBuf[0] = 0x81; // 0x81: the text message sent by the server should start with '0x81'.
|
||||
uint32_t mask = 1;
|
||||
// Depending on the length of the messages, client will use shift operation to get the res
|
||||
// and store them in the buffer.
|
||||
if (msgLen <= 125) { // 125: situation 1 when message's length <= 125
|
||||
sendBuf[1] = msgLen | (mask << 7); // 7: mask need shift left by 7 bits
|
||||
sendMsgLen = 2; // 2: the length of header frame is 2;
|
||||
} else if (msgLen < 65536) { // 65536: message's length
|
||||
sendBuf[1] = 126 | (mask << 7); // 126: payloadLen according to the spec; 7: mask shift left by 7 bits
|
||||
sendBuf[2] = ((msgLen >> 8) & 0xff); // 8: shift right by 8 bits => res * (256^1)
|
||||
sendBuf[3] = (msgLen & 0xff); // 3: store len's data => res * (256^0)
|
||||
sendMsgLen = 4; // 4: the length of header frame is 4
|
||||
} else {
|
||||
sendBuf[1] = 127 | (mask << 7); // 127: payloadLen according to the spec; 7: mask shift left by 7 bits
|
||||
for (int32_t i = 2; i <= 5; i++) { // 2 ~ 5: unused bits
|
||||
sendBuf[i] = 0;
|
||||
}
|
||||
sendBuf[6] = ((msgLen & 0xff000000) >> 24); // 6: shift 24 bits => res * (256^3)
|
||||
sendBuf[7] = ((msgLen & 0x00ff0000) >> 16); // 7: shift 16 bits => res * (256^2)
|
||||
sendBuf[8] = ((msgLen & 0x0000ff00) >> 8); // 8: shift 8 bits => res * (256^1)
|
||||
sendBuf[9] = (msgLen & 0x000000ff); // 9: res * (256^0)
|
||||
sendMsgLen = 10; // 10: the length of header frame is 10
|
||||
}
|
||||
|
||||
if (memcpy_s(sendBuf + sendMsgLen, SOCKET_MASK_LEN, MASK_KEY, SOCKET_MASK_LEN) != EOK) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client memcpy_s MASK_KEY failed, error = %d, desc = %s", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
sendMsgLen += SOCKET_MASK_LEN;
|
||||
|
||||
std::string maskMessage;
|
||||
for (uint64_t i = 0; i < msgLen; i++) {
|
||||
uint64_t j = i % SOCKET_MASK_LEN;
|
||||
maskMessage.push_back(message[i] ^ MASK_KEY[j]);
|
||||
}
|
||||
if (memcpy_s(sendBuf + sendMsgLen, msgLen, maskMessage.c_str(), msgLen) != EOK) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client memcpy_s maskMessage failed, error = %d, desc = %s",
|
||||
errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
msgBuf[sendMsgLen + msgLen] = '\0';
|
||||
|
||||
if (send(client_, sendBuf, sendMsgLen + msgLen, 0) != static_cast<int>(sendMsgLen + msgLen)) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client send msg req failed, error = %d, desc = %s", errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
PROFILER_LOG_INFO(LOG_CORE, "ClientRecvWSUpgradeRsp::client send msg req success...");
|
||||
return true;
|
||||
}
|
||||
|
||||
void ArkTSPlugin::Close()
|
||||
{
|
||||
if (socketState_ == SocketState::UNINITED) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client has not inited");
|
||||
return;
|
||||
}
|
||||
shutdown(client_, SHUT_RDWR);
|
||||
close(client_);
|
||||
client_ = -1;
|
||||
socketState_ = SocketState::UNINITED;
|
||||
}
|
||||
|
||||
bool ArkTSPlugin::SetWebSocketTimeOut(int32_t fd, uint32_t timeoutLimit)
|
||||
{
|
||||
if (timeoutLimit > 0) {
|
||||
struct timeval timeout = {timeoutLimit, 0};
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) != SOCKET_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) != SOCKET_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string ArkTSPlugin::Decode()
|
||||
{
|
||||
if (socketState_ != SocketState::CONNECTED) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "client has not connected");
|
||||
return {};
|
||||
}
|
||||
char recvbuf[SOCKET_HEADER_LEN + 1];
|
||||
if (!Recv(client_, recvbuf, SOCKET_HEADER_LEN, 0)) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "Decode failed, client websocket disconnect");
|
||||
socketState_ = SocketState::INITED;
|
||||
shutdown(client_, SHUT_RDWR);
|
||||
close(client_);
|
||||
client_ = -1;
|
||||
return {};
|
||||
}
|
||||
recvbuf[SOCKET_HEADER_LEN] = '\0';
|
||||
WebSocketFrame wsFrame;
|
||||
int32_t index = 0;
|
||||
wsFrame.fin = static_cast<uint8_t>(recvbuf[index] >> 7); // 7: shift right by 7 bits to get the fin
|
||||
wsFrame.opCode = static_cast<uint8_t>(recvbuf[index] & 0xf);
|
||||
if (wsFrame.opCode == 0x1) { // 0x1: 0x1 means a text frame
|
||||
index++;
|
||||
wsFrame.mask = static_cast<uint8_t>((recvbuf[index] >> 7) & 0x1); // 7: to get the mask
|
||||
wsFrame.payloadLen = recvbuf[index] & 0x7f;
|
||||
HandleFrame(wsFrame);
|
||||
return wsFrame.payload.get();
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
uint64_t ArkTSPlugin::NetToHostLongLong(char* buf, uint32_t len)
|
||||
{
|
||||
uint64_t result = 0;
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
result |= static_cast<unsigned char>(buf[i]);
|
||||
if ((i + 1) < len) {
|
||||
result <<= 8; // 8: result need shift left 8 bits in order to big endian convert to int
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ArkTSPlugin::HandleFrame(WebSocketFrame& wsFrame)
|
||||
{
|
||||
if (wsFrame.payloadLen == 126) { // 126: the payloadLen read from frame
|
||||
char recvbuf[PAYLOAD_LEN + 1] = {0};
|
||||
if (!Recv(client_, recvbuf, PAYLOAD_LEN, 0)) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "HandleFrame: Recv payloadLen == 126 failed");
|
||||
return false;
|
||||
}
|
||||
recvbuf[PAYLOAD_LEN] = '\0';
|
||||
uint16_t msgLen = 0;
|
||||
if (memcpy_s(&msgLen, sizeof(recvbuf), recvbuf, sizeof(recvbuf) - 1) != EOK) {
|
||||
return false;
|
||||
}
|
||||
wsFrame.payloadLen = ntohs(msgLen);
|
||||
} else if (wsFrame.payloadLen > 126) { // 126: the payloadLen read from frame
|
||||
char recvbuf[EXTEND_PAYLOAD_LEN + 1] = {0};
|
||||
if (!Recv(client_, recvbuf, EXTEND_PAYLOAD_LEN, 0)) {
|
||||
PROFILER_LOG_ERROR(LOG_CORE, "HandleFrame: Recv payloadLen > 127 failed");
|
||||
return false;
|
||||
}
|
||||
recvbuf[EXTEND_PAYLOAD_LEN] = '\0';
|
||||
wsFrame.payloadLen = NetToHostLongLong(recvbuf, EXTEND_PAYLOAD_LEN);
|
||||
}
|
||||
return DecodeMessage(wsFrame);
|
||||
}
|
||||
|
||||
bool ArkTSPlugin::DecodeMessage(WebSocketFrame& wsFrame)
|
||||
{
|
||||
if (wsFrame.payloadLen == 0 || wsFrame.payloadLen > UINT64_MAX) {
|
||||
return false;
|
||||
}
|
||||
wsFrame.payload = std::make_unique<char[]>(wsFrame.payloadLen + 1);
|
||||
if (wsFrame.mask == 1) {
|
||||
CHECK_TRUE(Recv(client_, wsFrame.maskingKey, SOCKET_MASK_LEN, 0), false,
|
||||
"DecodeMessage: Recv maskingKey failed");
|
||||
wsFrame.maskingKey[SOCKET_MASK_LEN] = '\0';
|
||||
|
||||
char buf[wsFrame.payloadLen + 1];
|
||||
CHECK_TRUE(Recv(client_, buf, wsFrame.payloadLen, 0), false, "DecodeMessage: Recv message with mask failed");
|
||||
buf[wsFrame.payloadLen] = '\0';
|
||||
|
||||
for (uint64_t i = 0; i < wsFrame.payloadLen; i++) {
|
||||
uint64_t j = i % SOCKET_MASK_LEN;
|
||||
wsFrame.payload.get()[i] = buf[i] ^ wsFrame.maskingKey[j];
|
||||
}
|
||||
} else {
|
||||
if (!Recv(client_, wsFrame.payload.get(), wsFrame.payloadLen, 0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
wsFrame.payload.get()[wsFrame.payloadLen] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArkTSPlugin::Recv(int32_t client, char* buf, size_t totalLen, int32_t flags) const
|
||||
{
|
||||
size_t recvLen = 0;
|
||||
while (recvLen < totalLen) {
|
||||
ssize_t len = recv(client, buf + recvLen, totalLen - recvLen, flags);
|
||||
CHECK_TRUE(len > 0, false, "Recv payload in while failed, websocket disconnect");
|
||||
recvLen += static_cast<size_t>(len);
|
||||
}
|
||||
buf[totalLen] = '\0';
|
||||
return true;
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
# Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/test.gni")
|
||||
import("../../../base/config.gni")
|
||||
|
||||
module_output_path = "${OHOS_PROFILER_TEST_MODULE_OUTPUT_PATH}/device"
|
||||
config("module_private_config") {
|
||||
visibility = [ ":*" ]
|
||||
if (current_toolchain != host_toolchain) {
|
||||
defines = [ "HAVE_HILOG" ]
|
||||
}
|
||||
}
|
||||
|
||||
ohos_unittest("arktsplugin_ut") {
|
||||
module_out_path = module_output_path
|
||||
sources = [ "unittest/arkts_plugin_unittest.cpp" ]
|
||||
deps = [
|
||||
"${OHOS_PROFILER_DIR}/device/plugins/arkts_plugin:arkts_source",
|
||||
"${OHOS_PROFILER_DIR}/protos/services:common_types_lite_proto",
|
||||
"${OHOS_PROFILER_DIR}/protos/types/plugins/arkts_plugin:arkts_plugin_data_cpp",
|
||||
]
|
||||
include_dirs = [
|
||||
"../include",
|
||||
"${OHOS_PROFILER_DIR}/interfaces/kits",
|
||||
"${OHOS_PROFILER_DIR}/device/base/include",
|
||||
"${OHOS_PROFILER_DIR}/device/plugins/api/include",
|
||||
"${OHOS_PROFILER_DIR}/device/services/profiler_service/src",
|
||||
]
|
||||
cflags = [
|
||||
"-Wno-inconsistent-missing-override",
|
||||
"-Dprivate=public", #allow test code access private members
|
||||
]
|
||||
external_deps = [
|
||||
"bounds_checking_function:libsec_shared",
|
||||
"googletest:gtest",
|
||||
"hilog:libhilog_base",
|
||||
"openssl:libcrypto_shared",
|
||||
"protobuf:protobuf_lite",
|
||||
]
|
||||
configs = [ ":module_private_config" ]
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
part_name = "${OHOS_PROFILER_PART_NAME}"
|
||||
resource_config_file = "${OHOS_PROFILER_DIR}/device/ohos_test.xml"
|
||||
}
|
||||
|
||||
group("unittest") {
|
||||
testonly = true
|
||||
deps = [ ":arktsplugin_ut" ]
|
||||
}
|
Binary file not shown.
@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cinttypes>
|
||||
#include <gtest/gtest.h>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <fcntl.h>
|
||||
#include <string>
|
||||
#include <regex>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "arkts_plugin.h"
|
||||
#include "common.h"
|
||||
#include "plugin_module_api.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
|
||||
namespace {
|
||||
constexpr int SLEEP_TIME = 5;
|
||||
class ArkTSPluginTest : public ::testing::Test {
|
||||
public:
|
||||
ArkTSPluginTest()
|
||||
{
|
||||
sleep(SLEEP_TIME); // Wait for the application to start successfully.
|
||||
const std::string processName = "cn.openharmony.rebound_project";
|
||||
COMMON::IsProcessExist(processName, pid_);
|
||||
HILOG_BASE_INFO(LOG_CORE, "ArkTSPluginTest pid: %d", pid_);
|
||||
}
|
||||
~ArkTSPluginTest() {}
|
||||
static void SetUpTestCase() {}
|
||||
static void TearDownTestCase() {}
|
||||
int32_t pid_{0};
|
||||
};
|
||||
|
||||
std::vector<uint8_t> SetArkTSConfig(
|
||||
ArkTSConfig &protoConfig, int32_t pid, ArkTSConfig::HeapType type,
|
||||
uint32_t interval, bool capture_numeric_value, bool track_allocations,
|
||||
bool enable_cpu_profiler, uint32_t cpu_profiler_interval = 1000)
|
||||
{
|
||||
protoConfig.set_pid(pid);
|
||||
protoConfig.set_type(type);
|
||||
protoConfig.set_interval(interval);
|
||||
protoConfig.set_capture_numeric_value(capture_numeric_value);
|
||||
protoConfig.set_track_allocations(track_allocations);
|
||||
protoConfig.set_enable_cpu_profiler(enable_cpu_profiler);
|
||||
protoConfig.set_cpu_profiler_interval(cpu_profiler_interval);
|
||||
|
||||
std::vector<uint8_t> configData(protoConfig.ByteSizeLong());
|
||||
protoConfig.SerializeToArray(configData.data(), configData.size());
|
||||
return configData;
|
||||
}
|
||||
|
||||
long WriteFunc(WriterStruct* writer, const void* data, size_t size)
|
||||
{
|
||||
if (writer == nullptr || data == nullptr || size == 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool FlushFunc(WriterStruct* writer)
|
||||
{
|
||||
if (writer == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: arkts plugin
|
||||
* @tc.desc: arkts plugin test boundary values.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ArkTSPluginTest, TestStartFunction, TestSize.Level1)
|
||||
{
|
||||
ArkTSPlugin arkTSPlugin;
|
||||
ArkTSConfig protoConfig;
|
||||
|
||||
std::vector<uint8_t> configData = SetArkTSConfig(protoConfig, -1, ArkTSConfig::INVALID, 0, false, false, false);
|
||||
arkTSPlugin.Start(configData.data(), configData.size());
|
||||
|
||||
configData.clear();
|
||||
configData = SetArkTSConfig(protoConfig, 1, ArkTSConfig::INVALID, 0, false, false, false);
|
||||
arkTSPlugin.Start(configData.data(), configData.size());
|
||||
|
||||
configData.clear();
|
||||
configData = SetArkTSConfig(protoConfig, pid_, ArkTSConfig::INVALID, 0, false, false, false);
|
||||
arkTSPlugin.Start(configData.data(), configData.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: arkts plugin
|
||||
* @tc.desc: arkts plugin test memory timeline.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ArkTSPluginTest, TestTimeline, TestSize.Level1)
|
||||
{
|
||||
ArkTSPlugin arkTSPlugin;
|
||||
ArkTSConfig protoConfig;
|
||||
WriterStruct writer = {WriteFunc, FlushFunc};
|
||||
|
||||
std::vector<uint8_t> configData = SetArkTSConfig(protoConfig, pid_, ArkTSConfig::TIMELINE, 0, false, true, false);
|
||||
arkTSPlugin.SetWriter(&writer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: arkts plugin
|
||||
* @tc.desc: arkts plugin test cpu profiler.
|
||||
* @tc.type: FUNC
|
||||
*/
|
||||
HWTEST_F(ArkTSPluginTest, TestCpuProfiler, TestSize.Level1)
|
||||
{
|
||||
ArkTSPlugin arkTSPlugin;
|
||||
ArkTSConfig protoConfig;
|
||||
WriterStruct writer = {WriteFunc, FlushFunc};
|
||||
std::vector<uint8_t> configData = SetArkTSConfig(protoConfig, pid_, ArkTSConfig::INVALID, 0, false, false, true);
|
||||
arkTSPlugin.SetWriter(&writer);
|
||||
}
|
||||
} // namespace
|
@ -1,105 +0,0 @@
|
||||
# Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build/ohos.gni")
|
||||
import("../../../protos.gni")
|
||||
|
||||
arkts_plugin_data_sources = [
|
||||
"./arkts_plugin_config.proto",
|
||||
"./arkts_plugin_result.proto",
|
||||
]
|
||||
|
||||
#######################################################
|
||||
proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//")
|
||||
proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir)
|
||||
|
||||
arkts_plugin_data_codegen = []
|
||||
arkts_plugin_data_codegen_standard = []
|
||||
arkts_plugin_data_codegen_encoder = []
|
||||
arkts_plugin_data_codegen_all = []
|
||||
foreach(proto, arkts_plugin_data_sources) {
|
||||
name = get_path_info(proto, "name")
|
||||
arkts_plugin_data_codegen += [
|
||||
"$proto_out_dir/$name.pb.h",
|
||||
"$proto_out_dir/$name.pb.cc",
|
||||
]
|
||||
arkts_plugin_data_codegen_standard += [
|
||||
"$proto_out_dir/${name}_standard.pb.h",
|
||||
"$proto_out_dir/${name}_standard.pb.cc",
|
||||
]
|
||||
arkts_plugin_data_codegen_encoder += [
|
||||
"$proto_out_dir/$name.pbencoder.h",
|
||||
"$proto_out_dir/$name.pbencoder.cc",
|
||||
]
|
||||
}
|
||||
arkts_plugin_data_codegen_all += arkts_plugin_data_codegen
|
||||
arkts_plugin_data_codegen_all += arkts_plugin_data_codegen_standard
|
||||
arkts_plugin_data_codegen_all += arkts_plugin_data_codegen_encoder
|
||||
|
||||
config("arkts_plugin_include_config") {
|
||||
include_dirs = [ "$proto_out_dir" ]
|
||||
}
|
||||
|
||||
#######################################################
|
||||
action("arkts_plugin_data_cpp_gen") {
|
||||
script = "${OHOS_PROFILER_DIR}/build/protoc.sh"
|
||||
sources = arkts_plugin_data_sources
|
||||
outputs = arkts_plugin_data_codegen_all
|
||||
args = [
|
||||
"$libc_dir_proto",
|
||||
"$root_output_dir_proto",
|
||||
"$proto_rel_out_dir",
|
||||
"--cpp_out",
|
||||
"$proto_rel_out_dir",
|
||||
"--proto_path",
|
||||
rebase_path(".", root_build_dir),
|
||||
]
|
||||
args += rebase_path(sources, root_build_dir)
|
||||
deps = [ "${OHOS_PROFILER_DIR}/device/services/ipc:protoencoder_plugin(${host_toolchain})" ]
|
||||
external_deps = [ "protobuf:protoc(${host_toolchain})" ]
|
||||
}
|
||||
|
||||
ohos_source_set("arkts_plugin_data_cpp") {
|
||||
deps = [ ":arkts_plugin_data_cpp_gen" ]
|
||||
external_deps = [
|
||||
"protobuf:protobuf",
|
||||
"protobuf:protobuf_lite",
|
||||
]
|
||||
include_dirs = [ "$proto_out_dir" ]
|
||||
public_configs = [ ":arkts_plugin_include_config" ]
|
||||
sources = arkts_plugin_data_codegen
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
part_name = "${OHOS_PROFILER_PART_NAME}"
|
||||
}
|
||||
|
||||
ohos_source_set("arkts_plugin_data_encoder") {
|
||||
deps = [ ":arkts_plugin_data_cpp_gen" ]
|
||||
include_dirs = [ "$proto_out_dir" ]
|
||||
public_configs = [ ":arkts_plugin_include_config" ]
|
||||
sources = arkts_plugin_data_codegen_encoder
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
part_name = "${OHOS_PROFILER_PART_NAME}"
|
||||
}
|
||||
|
||||
ohos_source_set("arkts_plugin_cpp_standard") {
|
||||
deps = [ ":arkts_plugin_data_cpp_gen" ]
|
||||
external_deps = [
|
||||
"protobuf:protobuf",
|
||||
"protobuf:protobuf_lite",
|
||||
]
|
||||
include_dirs = [ "$proto_out_dir" ]
|
||||
public_configs = [ ":arkts_plugin_include_config" ]
|
||||
sources = arkts_plugin_data_codegen_standard
|
||||
subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}"
|
||||
part_name = "${OHOS_PROFILER_PART_NAME}"
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
// Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
syntax = "proto3";
|
||||
option java_package = "ohos.devtools.datasources.transport.grpc.service";
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
message ArkTSConfig {
|
||||
enum HeapType {
|
||||
SNAPSHOT = 0;
|
||||
TIMELINE = 1;
|
||||
INVALID = -1; // Disable capturing memory data.
|
||||
}
|
||||
int32 pid = 1;
|
||||
HeapType type = 2;
|
||||
|
||||
// When the 'snapshot' mode is enabled in memory, it denotes the data fetching interval, measured in seconds.
|
||||
uint32 interval = 3;
|
||||
bool capture_numeric_value = 4;
|
||||
bool track_allocations = 5;
|
||||
bool enable_cpu_profiler = 6;
|
||||
|
||||
// When the CPU profiler mode is active, it signifies the data capturing interval, measured in microseconds,
|
||||
// with a default value of 1000 microseconds.
|
||||
uint32 cpu_profiler_interval = 7;
|
||||
string split_outfile_name = 8;
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
// Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
syntax = "proto3";
|
||||
option java_package = "ohos.devtools.datasources.transport.grpc.service";
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
message ArkTSResult {
|
||||
bytes result = 1;
|
||||
}
|
Loading…
Reference in New Issue
Block a user