From be46fd60c52084d80eb66362c08c3fbf2155abbd Mon Sep 17 00:00:00 2001 From: zheng Date: Thu, 2 Feb 2023 11:37:58 +0800 Subject: [PATCH] Support Attach Agent for NoAPM Java Application (#431) Signed-off-by: huxiangyuan --- CHANGELOG.md | 1 + collector/docker/Dockerfile | 5 +- collector/docker/DockerfileLocalProbe | 5 +- collector/docker/build-asyncprofiler.sh | 24 ++++++ .../component/controller/profile_module.go | 43 +++++++++++ .../component/receiver/cgoreceiver/cgo_func.h | 2 + probe/src/cgo/cgo_func.cpp | 3 + probe/src/cgo/cgo_func.h | 2 + probe/src/cgo/kindling.cpp | 77 +++++++++++++++++++ probe/src/cgo/kindling.h | 6 ++ 10 files changed, 164 insertions(+), 4 deletions(-) create mode 100755 collector/docker/build-asyncprofiler.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c30230d4..83b9a1b0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ## Unreleased ### New features +- Support Attach Agent for NoAPM Java Application. ([#431](https://github.com/KindlingProject/kindling/pull/431)) ### Enhancements - Add an option edge_events_window_size to allow users to reduce the size of the files by narrowing the time window where seats the edge events. ([#437](https://github.com/KindlingProject/kindling/pull/437)) diff --git a/collector/docker/Dockerfile b/collector/docker/Dockerfile index 687e9ecb8..c201d8d60 100644 --- a/collector/docker/Dockerfile +++ b/collector/docker/Dockerfile @@ -5,8 +5,9 @@ RUN yum install -y qt5-qtbase-devel RUN yum install -y gdb COPY gdb_print.sh /app/ RUN curl https://k8s-bpf-probes-public.oss-cn-hangzhou.aliyuncs.com/kindling-falcolib-probe-v0.6.0.tar.gz -o kindling-falcolib-probe.tar.gz -RUN curl -O https://k8s-bpf-probes-public.oss-cn-hangzhou.aliyuncs.com/async-profiler-kindling-v1.0.1.tar.gz -RUN tar -zvxf async-profiler-kindling-v1.0.1.tar.gz + +COPY build-asyncprofiler.sh /app/ +RUN sh build-asyncprofiler.sh COPY libso/libkindling.so /lib64/ COPY libso/* /usr/lib64/ diff --git a/collector/docker/DockerfileLocalProbe b/collector/docker/DockerfileLocalProbe index 4d7228386..60bad09c8 100644 --- a/collector/docker/DockerfileLocalProbe +++ b/collector/docker/DockerfileLocalProbe @@ -5,8 +5,9 @@ RUN yum install -y qt5-qtbase-devel RUN yum install -y gdb COPY gdb_print.sh /app/ COPY kindling-falcolib-probe.tar.gz ./ -RUN curl -O https://k8s-bpf-probes-public.oss-cn-hangzhou.aliyuncs.com/async-profiler-kindling-v1.0.1.tar.gz -RUN tar -zvxf async-profiler-kindling-v1.0.1.tar.gz + +COPY build-asyncprofiler.sh /app/ +RUN sh build-asyncprofiler.sh COPY libso/libkindling.so /lib64/ COPY libso/* /usr/lib64/ diff --git a/collector/docker/build-asyncprofiler.sh b/collector/docker/build-asyncprofiler.sh new file mode 100755 index 000000000..d39d96772 --- /dev/null +++ b/collector/docker/build-asyncprofiler.sh @@ -0,0 +1,24 @@ +ASYNC_PROFILER=async-profiler-1.0.2-linux-x64.tar.gz +KINDLING_JAVA=kindling-java-1.0.2.tar.gz +APM_ALL=apm-all-3.1.0.jar + +SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_BIN")" > /dev/null 2>&1; pwd -P)" +if [ ! -d "$SCRIPT_DIR/async-profiler" ];then + curl -O https://k8s-bpf-probes-public.oss-cn-hangzhou.aliyuncs.com/$ASYNC_PROFILER + tar -zvxf $ASYNC_PROFILER + rm -f $ASYNC_PROFILER +fi + +if [ ! -d "$SCRIPT_DIR/async-profiler/agent/kindling-java" ];then + curl -O https://k8s-bpf-probes-public.oss-cn-hangzhou.aliyuncs.com/$KINDLING_JAVA + tar -zxvf $KINDLING_JAVA + mkdir -p $SCRIPT_DIR/async-profiler/agent + mv kindling-java $SCRIPT_DIR/async-profiler/agent/ + rm -f $KINDLING_JAVA +fi + +if [ ! -f "$SCRIPT_DIR/async-profiler/agent/apm-all/apm-all.jar" ];then + mkdir -p $SCRIPT_DIR/async-profiler/agent/apm-all + cd $SCRIPT_DIR/async-profiler/agent/apm-all + curl -o apm-all.jar https://k8s-bpf-probes-public.oss-cn-hangzhou.aliyuncs.com/$APM_ALL +fi \ No newline at end of file diff --git a/collector/pkg/component/controller/profile_module.go b/collector/pkg/component/controller/profile_module.go index 2cb2e60b3..71d283346 100644 --- a/collector/pkg/component/controller/profile_module.go +++ b/collector/pkg/component/controller/profile_module.go @@ -14,6 +14,7 @@ import ( "errors" "fmt" "time" + "unsafe" "github.com/Kindling-project/kindling/collector/pkg/component" ) @@ -88,6 +89,26 @@ func (p *Profile) GetModuleKey() string { return p.Name() } +func startAttachAgent(pid int) string { + result := C.startAttachAgent(C.int(pid)) + errorMsg := C.GoString(result) + C.free(unsafe.Pointer(result)) + if len(errorMsg) > 0 { + return errorMsg + } + return "" +} + +func stopAttachAgent(pid int) string { + result := C.stopAttachAgent(C.int(pid)) + errorMsg := C.GoString(result) + C.free(unsafe.Pointer(result)) + if len(errorMsg) > 0 { + return errorMsg + } + return "" +} + func startDebug(pid int, tid int) error { C.startProfileDebug(C.int(pid), C.int(tid)) return nil @@ -123,6 +144,28 @@ func (p *Profile) HandRequest(req *ControlRequest) *ControlResponse { Code: NoError, Msg: "stop success", } + case "start_attach_agent": + if errMsg := startAttachAgent(req.Pid); errMsg != "" { + return &ControlResponse{ + Code: StartWithError, + Msg: errMsg, + } + } + return &ControlResponse{ + Code: NoError, + Msg: "start success", + } + case "stop_attach_agent": + if errMsg := stopAttachAgent(req.Pid); errMsg != "" { + return &ControlResponse{ + Code: StopWithError, + Msg: errMsg, + } + } + return &ControlResponse{ + Code: NoError, + Msg: "stop success", + } case "status": var status string switch p.Status() { diff --git a/collector/pkg/component/receiver/cgoreceiver/cgo_func.h b/collector/pkg/component/receiver/cgoreceiver/cgo_func.h index a4ad75cf2..ab3be155a 100644 --- a/collector/pkg/component/receiver/cgoreceiver/cgo_func.h +++ b/collector/pkg/component/receiver/cgoreceiver/cgo_func.h @@ -13,6 +13,8 @@ int getKindlingEvent(void **kindlingEvent); int subEventForGo(char* eventName, char* category, void *params); int startProfile(); int stopProfile(); +char* startAttachAgent(int pid); +char* stopAttachAgent(int pid); void startProfileDebug(int pid, int tid); void stopProfileDebug(); void getCaptureStatistics(); diff --git a/probe/src/cgo/cgo_func.cpp b/probe/src/cgo/cgo_func.cpp index 2432c7b16..69f7f1123 100644 --- a/probe/src/cgo/cgo_func.cpp +++ b/probe/src/cgo/cgo_func.cpp @@ -14,6 +14,9 @@ int getKindlingEvent(void** kindlingEvent) { return getEvent(kindlingEvent); } int startProfile() { return start_profile(); } int stopProfile() { return stop_profile(); } +char* startAttachAgent(int pid) { return start_attach_agent(pid); } +char* stopAttachAgent(int pid) { return stop_attach_agent(pid); } + void subEventForGo(char* eventName, char* category, void *params) { sub_event(eventName, category, (event_params_for_subscribe *)params); } void startProfileDebug(int pid, int tid) { start_profile_debug(pid, tid); } diff --git a/probe/src/cgo/cgo_func.h b/probe/src/cgo/cgo_func.h index f566df09b..dfb6ded65 100644 --- a/probe/src/cgo/cgo_func.h +++ b/probe/src/cgo/cgo_func.h @@ -13,6 +13,8 @@ int getKindlingEvent(void** kindlingEvent); void subEventForGo(char* eventName, char* category, void* params); int startProfile(); int stopProfile(); +char* startAttachAgent(int pid); +char* stopAttachAgent(int pid); void startProfileDebug(int pid, int tid); void stopProfileDebug(); void getCaptureStatistics(); diff --git a/probe/src/cgo/kindling.cpp b/probe/src/cgo/kindling.cpp index 5ea892b85..aff07d892 100644 --- a/probe/src/cgo/kindling.cpp +++ b/probe/src/cgo/kindling.cpp @@ -934,6 +934,83 @@ void attach_pid(char* pid, bool is_new_start, bool is_attach, bool is_all_attach } } +void attach_agent(int64_t pid, char* error_message, bool is_attach) { + char result_buf[1024], command[1024]; + string attach_command_prefix; + if (is_attach) { + attach_command_prefix = "./async-profiler/jattach.sh start "; + } else { + attach_command_prefix = "./async-profiler/jattach.sh stop "; + } + attach_command_prefix.append(std::to_string(pid)); + strcpy(command, attach_command_prefix.c_str()); + + FILE* fp; + fp = popen(command, "r"); + if (NULL == fp) { + perror("popen execute failed!\n"); + strcpy(error_message, "popen execute failed"); + return; + } + if (is_attach) { + cout << "------" + << " start attach agent for pid " << pid << "------" << endl; + } else { + cout << "------" + << " start detach agent for pid " << pid << "------" << endl; + } + + char* error_msg; + while (fgets(result_buf, sizeof(result_buf), fp) != NULL) { + if ('\n' == result_buf[strlen(result_buf) - 1]) { + result_buf[strlen(result_buf) - 1] = '\0'; + } + error_msg = strstr(result_buf, "[ERROR] "); + if (error_msg) { + strcpy(error_message, error_msg); + } + printf("%s\r\n", result_buf); + } + + int rc = pclose(fp); + if (-1 == rc) { + perror("close command fp failed!\n"); + strcpy(error_message, "close command fp failed"); + return; + } else { + printf("command:【%s】command process status:【%d】command return value:【%d】\r\n", command, + rc, WEXITSTATUS(rc)); + } + + if (is_attach) { + cout << "------end attach agent for pid " << pid << "------" << endl; + } else { + cout << "------end detach agent for pid " << pid << "------" << endl; + } +} + +char* start_attach_agent(int64_t pid) { + char* error_message = (char*) malloc(1024 * sizeof(char)); + error_message[0] = '\0'; + if (!inspector) { + strcpy(error_message, "Please start profile first"); + } else { + attach_agent(pid, error_message, true); + } + return error_message; +} + +char* stop_attach_agent(int64_t pid) { + char* error_message = (char*) malloc(1024 * sizeof(char)); + error_message[0] = '\0'; + if (!inspector) { + strcpy(error_message, "Please start profile first"); + } else { + attach_agent(pid, error_message, false); + } + return error_message; +} + int start_profile() { if (!inspector) { return -1; diff --git a/probe/src/cgo/kindling.h b/probe/src/cgo/kindling.h index 27e1aa825..6ca4fec37 100644 --- a/probe/src/cgo/kindling.h +++ b/probe/src/cgo/kindling.h @@ -42,6 +42,12 @@ void print_profile_debug_info(sinsp_evt* sevt); void attach_pid(char* pid, bool is_new_start, bool is_attach, bool is_all_attach, bool is_ps); +char* start_attach_agent(int64_t pid); + +char* stop_attach_agent(int64_t pid); + +void attach_agent(int64_t pid, char* error_message, bool is_attach); + void get_capture_statistics(); uint16_t get_protocol(scap_l4_proto proto);