Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Attach Agent for NoAPM Java Application #431

Merged
merged 5 commits into from
Feb 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

## Unreleased
### New features
- Support Attach Agent for NoAPM Java Application. ([#431](https://github.com/KindlingProject/kindling/pull/431))

### Enhancements
- When using the file writer in `cameraexporter`, we rotate files in chronological order now and rotate half of files one time. ([#420](https://github.com/KindlingProject/kindling/pull/420))
Expand Down
5 changes: 3 additions & 2 deletions collector/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand Down
5 changes: 3 additions & 2 deletions collector/docker/DockerfileLocalProbe
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand Down
24 changes: 24 additions & 0 deletions collector/docker/build-asyncprofiler.sh
Original file line number Diff line number Diff line change
@@ -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
43 changes: 43 additions & 0 deletions collector/pkg/component/controller/profile_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"errors"
"fmt"
"time"
"unsafe"

"github.com/Kindling-project/kindling/collector/pkg/component"
)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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() {
Expand Down
2 changes: 2 additions & 0 deletions collector/pkg/component/receiver/cgoreceiver/cgo_func.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
3 changes: 3 additions & 0 deletions probe/src/cgo/cgo_func.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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); }

Expand Down
2 changes: 2 additions & 0 deletions probe/src/cgo/cgo_func.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
77 changes: 77 additions & 0 deletions probe/src/cgo/kindling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,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;
}

Fixed Show fixed Hide fixed
int start_profile() {
if (!inspector) {
return -1;
Expand Down
6 changes: 6 additions & 0 deletions probe/src/cgo/kindling.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down