|
|
@@ -12,6 +12,8 @@
|
|
|
#define PROTOCOL_HTTP2 11
|
|
|
#define PROTOCOL_DUBBO2 12
|
|
|
|
|
|
+#define PROTOCOL_TRACE 200
|
|
|
+
|
|
|
#define STATUS_UNKNOWN 0
|
|
|
#define STATUS_OK 200
|
|
|
#define STATUS_FAILED 500
|
|
|
@@ -51,6 +53,9 @@
|
|
|
#include "nats.c"
|
|
|
#include "http2.c"
|
|
|
#include "dubbo2.c"
|
|
|
+#include "apm_trace.c"
|
|
|
+
|
|
|
+__u32 filterPid = 69161;
|
|
|
|
|
|
struct l7_event {
|
|
|
__u64 fd;
|
|
|
@@ -63,6 +68,9 @@ struct l7_event {
|
|
|
__u16 padding;
|
|
|
__u32 statement_id;
|
|
|
__u64 payload_size;
|
|
|
+ __u64 trace_id;
|
|
|
+ __u32 trace_start;
|
|
|
+ __u32 trace_end;
|
|
|
char payload[MAX_PAYLOAD_SIZE];
|
|
|
};
|
|
|
|
|
|
@@ -145,15 +153,15 @@ struct trace_event_raw_sys_exit_rw__stub {
|
|
|
long int ret;
|
|
|
};
|
|
|
|
|
|
-struct iovec {
|
|
|
+struct l7_iovec {
|
|
|
char* buf;
|
|
|
__u64 size;
|
|
|
};
|
|
|
|
|
|
-struct user_msghdr {
|
|
|
+struct l7_user_msghdr {
|
|
|
void *msg_name;
|
|
|
int msg_namelen;
|
|
|
- struct iovec *msg_iov;
|
|
|
+ struct l7_iovec *msg_iov;
|
|
|
__u64 msg_iovlen;
|
|
|
};
|
|
|
|
|
|
@@ -177,8 +185,8 @@ void send_event(void *ctx, struct l7_event *e, __u32 pid, __u64 fd) {
|
|
|
}
|
|
|
|
|
|
static inline __attribute__((__always_inline__))
|
|
|
-__u64 read_iovec(char *iovec, __u64 iovlen, __u64 ret, char *buf) {
|
|
|
- struct iovec iov = {};
|
|
|
+__u64 read_iovec(char *l7_iovec, __u64 iovlen, __u64 ret, char *buf) {
|
|
|
+ struct l7_iovec iov = {};
|
|
|
__u64 max = (ret) ? MIN(ret, MAX_PAYLOAD_SIZE) : MAX_PAYLOAD_SIZE;
|
|
|
__u64 offset = 0;
|
|
|
__u64 size = 0;
|
|
|
@@ -187,7 +195,7 @@ __u64 read_iovec(char *iovec, __u64 iovlen, __u64 ret, char *buf) {
|
|
|
if (i >= iovlen) {
|
|
|
break;
|
|
|
}
|
|
|
- if (bpf_probe_read(&iov, sizeof(iov), (void *)(iovec+i*sizeof(iov)))) {
|
|
|
+ if (bpf_probe_read(&iov, sizeof(iov), (void *)(l7_iovec+i*sizeof(iov)))) {
|
|
|
return 0;
|
|
|
}
|
|
|
if (iov.size <= 0) {
|
|
|
@@ -211,7 +219,14 @@ static inline __attribute__((__always_inline__))
|
|
|
int trace_enter_write(void *ctx, __u64 fd, __u16 is_tls, char *buf, __u64 size, __u64 iovlen) {
|
|
|
__u64 id = bpf_get_current_pid_tgid();
|
|
|
__u32 zero = 0;
|
|
|
+ __u32 pid, tid;
|
|
|
+ __u32 http_status ;
|
|
|
|
|
|
+ pid = id >> 32;
|
|
|
+ tid = (__u32)id;
|
|
|
+ if (pid != filterPid) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
char* payload = buf;
|
|
|
if (iovlen) {
|
|
|
payload = bpf_map_lookup_elem(&iovec_buf_heap, &zero);
|
|
|
@@ -239,7 +254,54 @@ int trace_enter_write(void *ctx, __u64 fd, __u16 is_tls, char *buf, __u64 size,
|
|
|
k.is_tls = is_tls;
|
|
|
k.stream_id = -1;
|
|
|
|
|
|
+ bpf_printk("enter-payload:%s|type:%s|FD:%d\n",payload,"type",k.fd);
|
|
|
+
|
|
|
+ if (is_http_response(payload, &http_status))
|
|
|
+ {
|
|
|
+ bpf_printk("[Response][HTTP]:TGID:%d|type:%s|FD:%d\n", k.pid, "type", k.fd);
|
|
|
+ struct trace_key_t trace_key = get_trace_key(pid, tid);
|
|
|
+ __u64 trace_id = get_trace_id(pid, tid);
|
|
|
+ bpf_printk("trace_id:%llu", trace_id);
|
|
|
+ // 清除trace信息
|
|
|
+ bpf_map_delete_elem(&trace_info_heap, &trace_key);
|
|
|
+
|
|
|
+ // 发送事件到用户空间 start
|
|
|
+ struct l7_event *e = bpf_map_lookup_elem(&l7_event_heap, &zero);
|
|
|
+ if (!e) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ struct l7_request *req = bpf_map_lookup_elem(&active_l7_requests, &k);
|
|
|
+ if (!req)
|
|
|
+ {
|
|
|
+ bpf_printk("[Response][HTTP]:no req-----------");
|
|
|
+ bpf_printk("[Response][HTTP]:pid:%d|tid:%d",k.pid,k.fd);
|
|
|
+ bpf_printk("[Response][HTTP]:is_tls:%d|tid:%d",k.is_tls,k.stream_id);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ bpf_printk("[Response][HTTP]:req->ns:%d\n",req->ns);
|
|
|
+
|
|
|
+ e->duration = bpf_ktime_get_ns() - req->ns;
|
|
|
+ bpf_printk("[Response][HTTP]:duration->ns:%d\n",e->duration);
|
|
|
+ e->protocol = PROTOCOL_TRACE;
|
|
|
+ e->status = http_status;
|
|
|
+ e->pid = k.pid;
|
|
|
+ e->fd = k.fd;
|
|
|
+ // e->connection_timestamp = get_connection_timestamp(k.pid, k.fd);
|
|
|
+ e->trace_start = 0;
|
|
|
+ e->trace_end = 1;
|
|
|
+ e->trace_id = trace_id;
|
|
|
+ bpf_printk("[Response][HTTP]:status:%d",e->status);
|
|
|
+ e->payload_size = size;
|
|
|
+ COPY_PAYLOAD(e->payload, size, payload);
|
|
|
+ bpf_map_delete_elem(&active_l7_requests, &k);
|
|
|
+ bpf_perf_event_output(ctx, &l7_events, BPF_F_CURRENT_CPU, e, sizeof(*e));
|
|
|
+ // 发送事件到用户空间 end
|
|
|
+ bpf_printk("HTTP_END");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
if (is_http_request(payload)) {
|
|
|
+ bpf_printk("[Enter][HTTP]:TGID:%d|FD:%d\n",k.pid,k.fd);
|
|
|
req->protocol = PROTOCOL_HTTP;
|
|
|
} else if (is_postgres_query(payload, size, &req->request_type)) {
|
|
|
if (req->request_type == POSTGRES_FRAME_CLOSE) {
|
|
|
@@ -256,10 +318,12 @@ int trace_enter_write(void *ctx, __u64 fd, __u16 is_tls, char *buf, __u64 size,
|
|
|
}
|
|
|
req->protocol = PROTOCOL_POSTGRES;
|
|
|
} else if (is_redis_query(payload, size)) {
|
|
|
+ bpf_printk("[Enter][Redis]:TGID:%d|type:%s|FD:%d\n",k.pid,"type",k.fd);
|
|
|
req->protocol = PROTOCOL_REDIS;
|
|
|
} else if (is_memcached_query(payload, size)) {
|
|
|
req->protocol = PROTOCOL_MEMCACHED;
|
|
|
} else if (is_mysql_query(payload, size, &req->request_type)) {
|
|
|
+ bpf_printk("[Enter][Mysql]:TGID:%d|type:%s|FD:%d\n",k.pid,"type",k.fd);
|
|
|
if (req->request_type == MYSQL_COM_STMT_CLOSE) {
|
|
|
struct l7_event *e = bpf_map_lookup_elem(&l7_event_heap, &zero);
|
|
|
if (!e) {
|
|
|
@@ -335,12 +399,19 @@ int trace_enter_read(__u64 id, __u64 fd, char *buf, __u64 *ret, __u64 iovlen) {
|
|
|
args.buf = buf;
|
|
|
args.ret = ret;
|
|
|
args.iovlen = iovlen;
|
|
|
+ __u32 pid = id >> 32;
|
|
|
bpf_map_update_elem(&active_reads, &id, &args, BPF_ANY);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
static inline __attribute__((__always_inline__))
|
|
|
int trace_exit_read(void *ctx, __u64 id, __u32 pid, __u16 is_tls, long int ret) {
|
|
|
+ __u32 tid = (__u32)id;
|
|
|
+
|
|
|
+ if (pid != filterPid) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
struct read_args *args = bpf_map_lookup_elem(&active_reads, &id);
|
|
|
if (!args) {
|
|
|
return 0;
|
|
|
@@ -383,11 +454,54 @@ int trace_exit_read(void *ctx, __u64 id, __u32 pid, __u16 is_tls, long int ret)
|
|
|
if (!e) {
|
|
|
return 0;
|
|
|
}
|
|
|
+ e->fd = k.fd;
|
|
|
+ e->pid = k.pid;
|
|
|
e->protocol = PROTOCOL_UNKNOWN;
|
|
|
e->status = STATUS_UNKNOWN;
|
|
|
e->method = METHOD_UNKNOWN;
|
|
|
e->statement_id = 0;
|
|
|
e->payload_size = 0;
|
|
|
+// bpf_printk("exit-payload:%s|type:%s\n",payload,type);
|
|
|
+
|
|
|
+ // 被调用方http入口
|
|
|
+ if (is_http_request(payload)) {
|
|
|
+ struct l7_request *req = bpf_map_lookup_elem(&l7_request_heap, &zero);
|
|
|
+ if (!req)
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ } else
|
|
|
+ {
|
|
|
+ req->protocol = PROTOCOL_HTTP;
|
|
|
+ req->payload_size = ret;
|
|
|
+ req->ns = bpf_ktime_get_ns();
|
|
|
+ COPY_PAYLOAD(req->payload, ret, payload);
|
|
|
+ // bpf_printk("[Receive][HTTP]:pid:%d|tid:%d",k.pid,k.fd);
|
|
|
+ // bpf_printk("[Receive][HTTP]:is_tls:%d|tid:%d",k.is_tls,k.stream_id);
|
|
|
+ bpf_map_update_elem(&active_l7_requests, &k, req, BPF_NOEXIST);
|
|
|
+ }
|
|
|
+
|
|
|
+ bpf_printk("[Receive][HTTP]:TGID:%d|type:%s|FD:%d\n",k.pid,"type",k.fd);
|
|
|
+ bpf_printk("[Receive][HTTP] payload1:%s|type:%s\n",payload,"type");
|
|
|
+
|
|
|
+ struct trace_key_t trace_key = {};
|
|
|
+ struct trace_info_t trace_info = {};
|
|
|
+ trace_key.tgid = pid;
|
|
|
+ trace_key.pid = tid;
|
|
|
+ __u64 uid_base = bpf_ktime_get_ns();
|
|
|
+ trace_info.trace_id = bpf_get_current_pid_tgid() + uid_base;
|
|
|
+ e->trace_start = 1;
|
|
|
+ e->trace_end = 0;
|
|
|
+ e->protocol = PROTOCOL_TRACE;
|
|
|
+ e->trace_id = trace_info.trace_id;
|
|
|
+ e->payload_size = ret;
|
|
|
+ COPY_PAYLOAD(e->payload, ret, payload);
|
|
|
+
|
|
|
+ // 入口方法缓存 bpf_map_update_elem(map, key, value, options)
|
|
|
+ bpf_map_update_elem(&trace_info_heap, &trace_key, &trace_info, BPF_NOEXIST);
|
|
|
+ bpf_perf_event_output(ctx, &l7_events, BPF_F_CURRENT_CPU, e, sizeof(*e));
|
|
|
+ bpf_printk("[Receive][HTTP] to user space");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
if (is_rabbitmq_consume(payload, ret)) {
|
|
|
e->protocol = PROTOCOL_RABBITMQ;
|
|
|
@@ -430,6 +544,7 @@ int trace_exit_read(void *ctx, __u64 id, __u32 pid, __u16 is_tls, long int ret)
|
|
|
|
|
|
bpf_map_delete_elem(&active_l7_requests, &k);
|
|
|
if (e->protocol == PROTOCOL_HTTP) {
|
|
|
+ bpf_printk("[Response][HTTP]:TGID:%d|type:%s|FD:%d\n",k.pid,"type",k.fd);
|
|
|
response = is_http_response(payload, &e->status);
|
|
|
} else if (e->protocol == PROTOCOL_POSTGRES) {
|
|
|
response = is_postgres_response(payload, ret, &e->status);
|
|
|
@@ -437,10 +552,15 @@ int trace_exit_read(void *ctx, __u64 id, __u32 pid, __u16 is_tls, long int ret)
|
|
|
e->method = METHOD_STATEMENT_PREPARE;
|
|
|
}
|
|
|
} else if (e->protocol == PROTOCOL_REDIS) {
|
|
|
+ bpf_printk("[Response][Redis]:TGID:%d|type:%s|FD:%d\n",k.pid,"",k.fd);
|
|
|
response = is_redis_response(payload, ret, &e->status);
|
|
|
} else if (e->protocol == PROTOCOL_MEMCACHED) {
|
|
|
response = is_memcached_response(payload, ret, &e->status);
|
|
|
} else if (e->protocol == PROTOCOL_MYSQL) {
|
|
|
+ bpf_printk("[Response][Mysql]:TGID:%d|type:%s|FD:%d\n",k.pid,"type",k.fd);
|
|
|
+ __u64 trace_id = get_trace_id(pid, tid);
|
|
|
+ bpf_printk("[Mysql] trace_id:%llu", trace_id);
|
|
|
+ e->trace_id = trace_id;
|
|
|
response = is_mysql_response(payload, ret, req->request_type, &e->statement_id, &e->status);
|
|
|
if (req->request_type == MYSQL_COM_STMT_PREPARE) {
|
|
|
e->method = METHOD_STATEMENT_PREPARE;
|
|
|
@@ -486,7 +606,7 @@ int sys_enter_writev(struct trace_event_raw_sys_enter_rw__stub* ctx) {
|
|
|
|
|
|
SEC("tracepoint/syscalls/sys_enter_sendmsg")
|
|
|
int sys_enter_sendmsg(struct trace_event_raw_sys_enter_rw__stub* ctx) {
|
|
|
- struct user_msghdr msghdr = {};
|
|
|
+ struct l7_user_msghdr msghdr = {};
|
|
|
if (bpf_probe_read(&msghdr, sizeof(msghdr), (void *)ctx->buf)) {
|
|
|
return 0;
|
|
|
}
|
|
|
@@ -513,7 +633,7 @@ int sys_enter_readv(struct trace_event_raw_sys_enter_rw__stub* ctx) {
|
|
|
SEC("tracepoint/syscalls/sys_enter_recvmsg")
|
|
|
int sys_enter_recvmsg(struct trace_event_raw_sys_enter_rw__stub* ctx) {
|
|
|
__u64 id = bpf_get_current_pid_tgid();
|
|
|
- struct user_msghdr msghdr = {};
|
|
|
+ struct l7_user_msghdr msghdr = {};
|
|
|
if (bpf_probe_read(&msghdr, sizeof(msghdr), (void *)ctx->buf)) {
|
|
|
return 0;
|
|
|
}
|