瀏覽代碼

Feature #TASK_QT-22149 EBPF-euspace JVM TLS适配

Tom 1 年之前
父節點
當前提交
ad79b3a021

+ 10 - 0
containers/apm_stack_dispatch.go

@@ -164,6 +164,16 @@ func (c *Container) jvmStackTrace(tracer *ebpftracer.Tracer, pid uint32) error {
 	p.stackUprobes = append(p.stackUprobes, jvmStackProbes...)
 	p.stackStatus.StackUprobesSuccess()
 
+	// 目前ssl的挂载跟随stack的控制逻辑 todo  增加一个标识来判定是否需要挂载ssl-uprobe
+	jvmSslProbes, err := tracer.AttachJVMSslUprobes(pid, c.AppInfo)
+	if err != nil {
+		p.stackStatus.SslUprobesFailure()
+		klog.WithError(err).Errorf("[jvmStackTrace] Failed attach jvm ssl.")
+		return err
+	}
+	p.stackUprobes = append(p.stackUprobes, jvmSslProbes...)
+	p.stackStatus.SslUprobesSuccess()
+
 	return nil
 }
 

+ 1 - 0
ebpftracer/ebpf/config.h

@@ -64,6 +64,7 @@ enum {
 	PROG_DATA_JAVA_FIND_HOST_UP_IDX,
 	PROG_DATA_JAVA_BUILD_HEADER_UP_IDX,
 	PROG_DATA_GO_UPDATE_HEADER_UP_IDX,
+	PROG_DATA_JAVA_SSL_L7_HTTP_TRACE_ID_UP_IDX,
 	PROG_UP_NUM
 };
 

+ 1 - 0
ebpftracer/ebpf/ebpf.c

@@ -61,6 +61,7 @@
 
 #include "utrace/java/net/server.probe.bpf.c"
 #include "utrace/java/net/client.probe.bpf.c"
+#include "utrace/java/net/jvmssl.probe.bpf.c"
 
 // TODO 支持arm64后打开
 #if defined(__x86_64__)

+ 341 - 26
ebpftracer/ebpf/l7/l7.c

@@ -867,8 +867,8 @@ int trace_exit_read(void *ctx, __u64 id, __u32 pid, __u16 is_tls, long int ret)
         //     __sync_fetch_and_add(&accept_conn->bytes_received, total_size);
         // }
 
-        //bpf_tail_call PROGUP(l7_http_request)
-        cw_bpf_debug("======== PROG_DATA_L7_HTTP_TRACE_ID_UP_IDX ========== __KERNEL_FROM < 512 pid:[%d] ",tid);
+        //-- 在http请求入口生成 横向串联的trace_id --
+        //bpf_tail_call PROGTP(l7_http_trace_id)
         bpf_tail_call(ctx, &NAME(progs_jmp_tp_map), PROG_DATA_L7_HTTP_TRACE_ID_TP_IDX);
          return 0;
     }
@@ -1216,6 +1216,340 @@ int trace_exit_read(void *ctx, __u64 id, __u32 pid, __u16 is_tls, long int ret)
     return 0;
 }
 
+//copy from trace_exit_read
+static inline __attribute__((__always_inline__))
+int jvm_ssl_trace_exit_read(void *ctx, __u64 id, __u32 pid, __u16 is_tls, long int ret) {
+    __u32 tid =  (__u32)id;
+
+    if (load_filter_pid() != 0 && pid != load_filter_pid()) {
+        return 0;
+    }
+
+    struct read_args *args = bpf_map_lookup_elem(&active_reads, &id);
+    if (!args) {
+        return 0;
+    }
+    struct l7_request_key k = {};
+    k.pid = pid;
+    k.fd = args->fd;
+    k.is_tls = is_tls;
+    k.stream_id = -1;
+
+    bpf_map_delete_elem(&active_reads, &id);
+
+    if (ret <= 0) {
+        return 0;
+    }
+    if (args->ret) {
+        if (bpf_probe_read(&ret, sizeof(ret), (void*)args->ret)) {
+            return 0;
+        };
+        if (ret <= 0) {
+            return 0;
+        }
+    }
+    __u64 total_size = ret;
+    int zero = 0;
+    char* payload = args->buf;
+//    if (args->iovlen) {
+//        payload = bpf_map_lookup_elem(&iovec_buf_heap, &zero);
+//        if (!payload) {
+//            return 0;
+//        }
+//        total_size = 0;
+//        ret = read_iovec(args->buf, args->iovlen, ret, payload, &total_size);
+//        if (!ret) {
+//            return 0;
+//        }
+//    }
+
+    struct l7_event *e = bpf_map_lookup_elem(&l7_event_heap, &zero);
+    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;
+    e->trace_id = 0;
+
+
+    struct connection_id cid = {};
+    cid.pid = pid;
+    cid.fd = args->fd;
+    // 被调用方http入口
+    // 作为服务端在走。coroot 原有逻辑是没有的
+    if (is_http_request(payload)) {
+
+        //处理http请求之前,确认进程信息是否存在
+        struct ebpf_proc_info *proc_info = bpf_map_lookup_elem(&proc_info_map, &pid);
+        if (!proc_info) {
+            cw_bpf_debug("[Receive][HTTP]:no proc info. pid:%d",k.pid);
+            return 0;
+        }
+
+        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);
+            // cw_bpf_debug("[Receive][HTTP]:pid:%d|tid:%d",k.pid,k.fd);
+            // cw_bpf_debug("[Receive][HTTP]:is_tls:%d|tid:%d",k.is_tls,k.stream_id);
+            bpf_map_update_elem(&active_l7_requests, &k, req, BPF_NOEXIST);
+        }
+
+//		// trace info
+        struct apm_trace_info_t trace_info = cw_save_trace_info(id,pid, k.fd);
+//	    __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;
+        cw_bpf_debug("\n");
+        cw_bpf_debug("[Trace Start in l7][HTTP]pid:[%d]--[%lld]--trace_id:%llu\n", tid, bpf_ktime_get_ns(),trace_info.trace_id);
+        cw_bpf_debug("[Trace Start in l7][Receive][HTTP]pid:[%d]|GOID:[%d]|FD:%d|Trace:%llu\n", tid, trace_info.trace_key.goid,k.fd);
+        e->payload_size = ret;
+        COPY_PAYLOAD(e->payload, ret, payload);
+
+        bpf_perf_event_output(ctx, &l7_events, BPF_F_CURRENT_CPU, e, sizeof(*e));
+        cw_bpf_debug("[Receive][HTTP] to user space");
+
+        //-- 在http请求入口生成 横向串联的trace_id --
+        //bpf_tail_call PROGUP(java_ssl_l7_http_trace_id)
+        bpf_tail_call(ctx, &NAME(progs_jmp_up_map), PROG_DATA_JAVA_SSL_L7_HTTP_TRACE_ID_UP_IDX);
+        return 0;
+    }
+
+    struct connection *conn = bpf_map_lookup_elem(&active_connections, &cid);
+    if (args && !conn) {
+        bpf_map_delete_elem(&active_reads, &id);
+        return 0;
+    }
+
+    /// coroot 是以客户端为主体做统计的,所以这里是客户端逻辑
+    if (!is_tls) {
+        __sync_fetch_and_add(&conn->bytes_received, total_size);
+        if(conn->first_read_time == 0){
+            conn->first_read_time = bpf_ktime_get_ns();
+        }
+        conn->new_read_time = bpf_ktime_get_ns();
+    }
+
+    if (is_rabbitmq_consume(payload, ret)) {
+        e->protocol = PROTOCOL_RABBITMQ;
+        e->method = METHOD_CONSUME;
+        send_event(ctx, e, cid, conn);
+        return 0;
+    }
+    if (nats_method(payload, ret) == METHOD_CONSUME) {
+        e->protocol = PROTOCOL_NATS;
+        e->method = METHOD_CONSUME;
+        send_event(ctx, e, cid, conn);
+        return 0;
+    }
+
+    struct l7_request *req = bpf_map_lookup_elem(&active_l7_requests, &k);
+    int response = 0;
+    if (!req) {
+        return 0;
+    }
+
+    e->protocol = req->protocol;
+    e->payload_size = req->payload_size;
+    COPY_PAYLOAD(e->payload, req->payload_size, req->payload);
+    bpf_map_delete_elem(&active_l7_requests, &k);
+//	cw_bpf_debug("delete req--------:[0x%x] k.pid:%d, k.fd:%d",b[4],k.pid,k.fd);
+
+    if (e->protocol == PROTOCOL_HTTP) {
+//		__u64 trace_id = req->trace_id;
+        e->trace_id = req->trace_id;
+        cw_bpf_debug("l7.c addr is --------:%d,%s",conn->sport,conn->saddr);
+        e->component_sport = conn->sport;
+        e->component_dport = conn->dport;
+        __builtin_memcpy(&e->component_saddr, &conn->saddr, sizeof(e->component_saddr));
+        __builtin_memcpy(&e->component_daddr, &conn->daddr, sizeof(e->component_daddr));
+//	    struct  apm_span_context * sc = cw_get_current_tracking_span();
+//	    if (sc) {
+        cw_copy_byte_arrays(req->assumed_app_id, e->assumed_app_id, APM_ASSUMED_APP_ID_SIZE);
+        cw_copy_byte_arrays(req->span_id, e->span_id, APM_SPAN_ID_SIZE);
+//		    for (int i = 0; i < APM_ASSUMED_APP_ID_SIZE; i++) {
+//			    cw_bpf_debug("assumed_app_id-assumed_app_id[%d] = %02x", i, req->assumed_app_id[i]);
+//		    }
+//	    for (int i = 0; i < APM_SPAN_ID_SIZE; i++) {
+//			    cw_bpf_debug("cw_get_current_tracking_span-span_id[%d] = %02x", i, req->span_id[i]);
+//		    }
+//	    }
+        //        cw_bpf_debug("[Response][HTTP222]:thread_id:%d|type:%s|FD:%d\n",k.pid,"",k.fd);
+//        cw_bpf_debug("[Response][HTTP222] trace_id:%llu", trace_id);
+//        // 请求报文
+//	    cw_bpf_debug("[Response][HTTP222] req-payload:%s",e->payload);
+//        // 响应报文
+//        cw_bpf_debug("[Response][HTTP222] resp-payload:%s",payload);
+
+        response = is_http_response(payload, &e->status);
+//	    cw_bpf_debug("[Kernel End][HTTP]:pid:[%d]|CURRENT-GOID:[%llu]|trace_id:[%llu]---------\n", tid, get_current_goroutine(),e->trace_id);
+
+    } else if (e->protocol == PROTOCOL_POSTGRES) {
+//        __u64 trace_id = get_apm_trace_id(pid, tid);
+//        cw_bpf_debug("[postgres sql] trace_id:%llu", trace_id);
+//		e->trace_id = req->trace_id;
+        e->component_sport = conn->sport;
+        e->component_dport = conn->dport;
+        __builtin_memcpy(&e->component_saddr, &conn->saddr, sizeof(e->component_saddr));
+        __builtin_memcpy(&e->component_daddr, &conn->daddr, sizeof(e->component_daddr));
+        response = is_postgres_response(payload, ret, &e->status);
+        if (req->request_type == POSTGRES_FRAME_PARSE) {
+            e->method = METHOD_STATEMENT_PREPARE;
+        }
+    } else if (e->protocol == PROTOCOL_REDIS) {
+        cw_bpf_debug("[Response][Redis]:TGID:%d|type:%s|FD:%d\n", k.pid, "", k.fd);
+//		__u64 trace_id = get_apm_trace_id(pid, tid);
+//		e->trace_id = req->trace_id;
+        cw_bpf_debug("[Redis] trace_id:%llu", req->trace_id);
+        e->component_sport = conn->sport;
+        e->component_dport = conn->dport;
+        __builtin_memcpy(&e->component_saddr, &conn->saddr, sizeof(e->component_saddr));
+        __builtin_memcpy(&e->component_daddr, &conn->daddr, sizeof(e->component_daddr));
+        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) {
+        cw_bpf_debug("[Response][Mysql]:thread_id:%d\n", tid);
+//		__u64 trace_id = get_apm_trace_id(pid, tid);
+//        cw_bpf_debug("[Mysql] trace_id:%llu", trace_id);
+//		e->trace_id = trace_id;
+
+        //response package parsing partial data (such as by header)
+        if(ret == MYSQL_PACKAGE_HEADER_LEN) {
+            //sava header to ctx and return
+            char resp_packet_header[MYSQL_PACKAGE_HEADER_LEN];
+            bpf_probe_read(resp_packet_header,MYSQL_PACKAGE_HEADER_LEN, payload);
+            bpf_map_update_elem(&active_l7_requests_mysql_resp_header_ctx, &k, resp_packet_header, BPF_ANY);
+            bpf_map_update_elem(&active_l7_requests, &k, req, BPF_ANY);
+            return 0 ;
+        }
+
+        e->component_sport = conn->sport;
+        e->component_dport = conn->dport;
+        __builtin_memcpy(&e->component_saddr, &conn->saddr, sizeof(e->component_saddr));
+        __builtin_memcpy(&e->component_daddr, &conn->daddr, sizeof(e->component_daddr));
+
+        char* resp_packet_header = bpf_map_lookup_elem(&active_l7_requests_mysql_resp_header_ctx, &k);
+        if(resp_packet_header) {
+            char resp_combined_packet[5];
+            bpf_probe_read(resp_combined_packet,MYSQL_PACKAGE_HEADER_LEN, resp_packet_header);
+            bpf_probe_read(&resp_combined_packet[4],1, payload);
+            response = is_mysql_response(resp_combined_packet,sizeof(resp_combined_packet), req->request_type, &e->statement_id, &e->status);
+            if(response) {
+                bpf_map_delete_elem(&active_l7_requests_mysql_resp_header_ctx, &k);
+            }
+        } else {
+            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;
+        }
+    } else if (e->protocol == PROTOCOL_DM) {
+//        cw_bpf_debug("[Response][DM] start -------->");
+        struct l7_request_dm_ctx *dm_ctx = bpf_map_lookup_elem(&active_l7_requests_dm_ctx, &k);
+        if (!dm_ctx) {
+            return 0;
+        }
+//		__u64 trace_id = get_apm_trace_id(pid, tid);
+//		e->trace_id = req->trace_id;
+//	    cw_bpf_debug("[Response][DM] trace_id:%llu", trace_id);
+        e->component_sport = conn->sport;
+        e->component_dport = conn->dport;
+        __builtin_memcpy(&e->component_saddr, &conn->saddr, sizeof(e->component_saddr));
+        __builtin_memcpy(&e->component_daddr, &conn->daddr, sizeof(e->component_daddr));
+
+        response = is_dm_response(payload, ret, req->request_type, &dm_ctx->status);
+//	    cw_bpf_debug("[Response][DM]  is_dm_response status ---------- %d",dm_ctx->status);
+
+        if (response) {
+            req->ns = dm_ctx->req_start_at_ns;
+            e->status = dm_ctx->status;
+            e->payload_size = dm_ctx->query_sql_payload_size;
+            COPY_PAYLOAD(e->payload, dm_ctx->query_sql_payload_size, dm_ctx->query_sql_payload);
+            bpf_map_delete_elem(&active_l7_requests_dm_ctx, &k);
+//             cw_bpf_debug("[Response][DM]  is response ,delete  active_l7_requests_dm_ctx -- req->request_type<0x%x> , e->payload_size:[%d]",req->request_type,e->payload_size);
+        }
+//        else {
+//             cw_bpf_debug("[Response][DM]  not response req->request_type <0x%x>",req->request_type);
+//        }
+
+//        cw_bpf_debug("[Response][DM] end <---------\n");
+    } else if (e->protocol == PROTOCOL_MONGO) {
+        response = is_mongo_response(payload, ret, req->partial);
+        if (response == 2) { // partial
+            struct l7_request *r = bpf_map_lookup_elem(&l7_request_heap, &zero);
+            if (!r) {
+                return 0;
+            }
+            r->partial = 1;
+            r->protocol = e->protocol;
+            r->ns = req->ns;
+            r->payload_size = req->payload_size;
+            COPY_PAYLOAD(r->payload, req->payload_size, req->payload);
+            bpf_map_update_elem(&active_l7_requests, &k, r, BPF_ANY);
+            return 0;
+        }
+    } else if (e->protocol == PROTOCOL_KAFKA) {
+        response = is_kafka_response(payload, req->request_id);
+    } else if (e->protocol == PROTOCOL_DUBBO2) {
+        response = is_dubbo2_response(payload, &e->status);
+    }
+
+    if (!response) {
+        return 0;
+    }
+    if (e->trace_id == 0){
+        e->trace_id = get_apm_trace_id(pid,tid);
+    }
+    e->end_at = bpf_ktime_get_ns();
+    e->start_at = req->ns;
+    e->duration = e->end_at - e->start_at;
+    send_event(ctx, e, cid, conn);
+    return 0;
+}
+
+static inline __attribute__((__always_inline__))
+int setTraceIdToPscByL7Request(){
+    __u32 key = 0;
+
+    struct l7_request *req = bpf_map_lookup_elem(&l7_request_heap, &key);
+    if (!req) {
+        return 0;
+    }
+
+    struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&apm_span_context_heap3, &key);
+    if (cw_parent_span_context == NULL) {
+        return -1;
+    }
+    __builtin_memset(cw_parent_span_context, 0, sizeof(struct apm_span_context));
+
+    __u32 offset = has_cw_header(req->payload);
+    if (offset > 0) {
+        cw_string_to_span_context(&req->payload[offset], cw_parent_span_context);
+    } else {
+        generate_random_bytes(cw_parent_span_context->trace_id, TRACE_ID_SIZE);
+    }
+    // 保存 trace_id 到psc
+    cw_save_parent_tracking_span(cw_parent_span_context);
+    cw_bpf_debug("[Trace Start in l7][HTTP] trace_id:[%llu]\n", cw_parent_span_context->trace_id);
+    return 0;
+}
+
 SEC("tracepoint/syscalls/sys_enter_write")
 int sys_enter_write(struct trace_event_raw_sys_enter_rw__stub* ctx) {
     return trace_enter_write(ctx, ctx->fd, 0, ctx->buf, ctx->size, 0);
@@ -1335,30 +1669,11 @@ int sys_exit_recvfrom(struct trace_event_raw_sys_exit_rw__stub* ctx) {
 
 //bpf_prog_tp__l7_http_trace_id
 PROGTP(l7_http_trace_id)(void * ctx){
+    return setTraceIdToPscByL7Request();
+}
 
-    int zero1 = 0;
 
-    struct l7_request *req = bpf_map_lookup_elem(&l7_request_heap, &zero1);
-    if (!req) {
-        return 0;
-    }
-// ---------- 在http请求入口生成 横向串联的trace_id start ----------
-    __u32 key = 0;
-    __u32 offset = has_cw_header(req->payload);
-    struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&apm_span_context_heap3, &key);
-    if (cw_parent_span_context == NULL) {
-        return -1;
-    }
-    __builtin_memset(cw_parent_span_context, 0, sizeof(struct apm_span_context));
-
-    if (offset > 0) {
-        cw_string_to_span_context(&req->payload[offset], cw_parent_span_context);
-    } else {
-        generate_random_bytes(cw_parent_span_context->trace_id, TRACE_ID_SIZE);
-    }
-    // 保存 trace_id 到psc
-    cw_save_parent_tracking_span(cw_parent_span_context);
-    cw_bpf_debug("[Trace Start in l7][HTTP] trace_id:[%llu]\n", cw_parent_span_context->trace_id);
-    // ---------- 在http请求入口生成 横向串联的trace_id end ----------
-    return 0;
+//bpf_prog_up__java_ssl_l7_http_trace_id
+PROGUP(java_ssl_l7_http_trace_id)(void * ctx){
+   return setTraceIdToPscByL7Request();
 }

+ 81 - 0
ebpftracer/ebpf/utrace/java/net/jvmssl.probe.bpf.c

@@ -0,0 +1,81 @@
+#include "java_common.h"
+
+//rdx(加密前报文)/rcx(报文长度)/r8(fd)为约定的有效参数信息
+
+//解密后的报文处理
+//"Java_com_cloudwise_agent_common_natives_TraceNative_setSslSocketRead"
+SEC("uprobe/setSslSocketRead")
+int setSslSocketRead(struct pt_regs *ctx) {
+    //buf_size为数据报文长度(协议相关的header+body)
+    __u64 buf_size = PT_REGS_PARM4(ctx);
+    if(buf_size == 0){
+        return 0;
+    }
+    //bpf_printk("=====[SslRead] buf_size :%d",buf_size);
+
+    char* rdx_ptr = (char*)PT_REGS_PARM3(ctx);
+    if (!rdx_ptr) {
+        return 0;
+    }
+    //bpf_printk("=====[SslRead] rdx_ptr: %llx", rdx_ptr);
+
+    char* buf;
+    if (bpf_probe_read(&buf, sizeof(buf), rdx_ptr)) {
+        return 0;
+    }
+    if (!buf) {
+        return 0;
+    }
+    //bpf_printk("=====[SslRead] buf: %llx", buf);
+
+    //前16个固定字节为不关注的
+    buf = buf + 16;
+    //bpf_printk("=====  buf+16: %llx", buf);
+
+    __u32 fd = (__u32) PT_REGS_PARM5(ctx);
+    //bpf_printk("=====[SslRead] fd:[%d] \n",fd);
+
+    __u64 pid_tgid = bpf_get_current_pid_tgid();
+    __u32 pid = pid_tgid >> 32;
+
+    //设置active_reads,此场景无返回值、无缓冲区设置为0
+    trace_enter_read(pid_tgid, pid, fd, buf, 0, 0);
+    //此场景is_tls为1,返回值应为buf_size
+    return jvm_ssl_trace_exit_read(ctx, pid_tgid, pid, 1, buf_size);
+}
+
+//加密前的报文处理
+//"Java_com_cloudwise_agent_common_natives_TraceNative_setSslSocketWriter"
+SEC("uprobe/setSslSocketWriter")
+int setSslSocketWriter(struct pt_regs *ctx) {
+    //buf_size为数据报文长度(协议相关的header+body)
+    __u64 buf_size = PT_REGS_PARM4(ctx);
+    if(buf_size == 0){
+        return 0;
+    }
+    //bpf_printk("=====[SslWriter] buf_size :%d",buf_size);
+    char* rdx_ptr = (char*)PT_REGS_PARM3(ctx);
+    if (!rdx_ptr) {
+        return 0;
+    }
+    //bpf_printk("=====[SslWriter] rdx_ptr: %llx", rdx_ptr);
+
+    char* buf;
+    if (bpf_probe_read(&buf, sizeof(buf), rdx_ptr)) {
+        return 0;
+    }
+    if (!buf) {
+        return 0;
+    }
+    //bpf_printk("=====[SslWriter] buf: %llx", buf);
+
+    //前16个固定字节为不关注的
+    buf = buf + 16;
+    //bpf_printk("=====  buf+16: %llx", buf);
+
+    __u32 fd = (__u32) PT_REGS_PARM5(ctx);
+    //bpf_printk("=====[SslWriter] fd:[%d] \n",fd);
+
+    //is_tls为1,无缓冲区设置为0
+    return trace_enter_write(ctx, fd, 1, buf, buf_size, 0);
+}

+ 41 - 0
ebpftracer/stack.go

@@ -211,3 +211,44 @@ func FindNativeSoFromMapped(pid uint32, prefix, suffix string) (string, error) {
 
 	return "", fmt.Errorf("no matching path found")
 }
+
+func (t *Tracer) AttachJVMSslUprobes(pid uint32, appInfo AppInfo) ([]link.Link, error) {
+
+	klog.Infoln("[Jvm ssl uprobe] start")
+	//tmp/NativeAgentSo2297066477572820801.tmp
+	nativeAgentPath, err := FindNativeSoFromMapped(pid, "NativeAgentSo", ".tmp")
+	if err != nil {
+		klog.Error(err)
+		return nil, err
+	}
+
+	klog.Infof("[Jvm ssl uprobe] nativeAgentPath %s \n", nativeAgentPath)
+
+	var links []link.Link
+	ex, err := link.OpenExecutable(nativeAgentPath)
+	if err != nil {
+		klog.Errorf("[Jvm ssl uprobe] open executable failed:%s \n", err.Error())
+		return nil, err
+	}
+
+	setSslSocketRead := "Java_com_cloudwise_agent_common_natives_TraceNative_setSslSocketRead"
+	klog.Infof("[Jvm ssl uprobe] to attach [%s] ", setSslSocketRead)
+	uplink, err := ex.Uprobe(setSslSocketRead, t.uprobes["setSslSocketRead"], &link.UprobeOptions{Offset: 0x0, PID: int(pid)})
+	if err != nil {
+		klog.Errorf("[Jvm ssl uprobe] attach [%s] failed: %s, uplink:[%v] \n", setSslSocketRead, err.Error(), uplink)
+		return nil, err
+	} else {
+		links = append(links, uplink)
+	}
+
+	setSslSocketWriter := "Java_com_cloudwise_agent_common_natives_TraceNative_setSslSocketWriter"
+	klog.Infof("[Jvm ssl uprobe] to attach [%s] ", setSslSocketWriter)
+	uplink, err = ex.Uprobe(setSslSocketWriter, t.uprobes["setSslSocketWriter"], &link.UprobeOptions{Offset: 0x0, PID: int(pid)})
+	if err != nil {
+		klog.Errorf("[Jvm ssl uprobe] attach [%s] failed: %s, uplink:[%v] \n", setSslSocketWriter, err.Error(), uplink)
+		return nil, err
+	} else {
+		links = append(links, uplink)
+	}
+	return links, nil
+}

+ 3 - 1
ebpftracer/tracer/socket.go

@@ -69,8 +69,10 @@ func insert_output_prog_to_map(collection *ebpf.Collection) {
 	__insert_output_prog_to_map(collection, MAP_PROGS_JMP_UP_NAME, PROG_JAVA_FIND_HOST_FOR_UP, PROG_DATA_JAVA_FIND_HOST_UP_IDX)
 	__insert_output_prog_to_map(collection, MAP_PROGS_JMP_UP_NAME, PROG_JAVA_BUILD_HEADER_FOR_UP, PROG_DATA_JAVA_BUILD_HEADER_UP_IDX)
 	__insert_output_prog_to_map(collection, MAP_PROGS_JMP_UP_NAME, PROG_GO_UPDATE_HEADER_FOR_UP, PROG_DATA_GO_UPDATE_HEADER_UP_IDX)
-	//add for l7.c -> is_http_request(payload) -> bpf_tail_call
+	//add for l7.c -> trace_exit_read -> is_http_request(payload) -> bpf_tail_call
 	__insert_output_prog_to_map(collection, MAP_PROGS_JMP_TP_NAME, PROG_L7_HTTP_TRACE_ID_FOR_TP, PROG_DATA_L7_HTTP_TRACE_ID_TP_IDX)
+	//add for l7.c -> jvm_ssl_trace_exit_read -> is_http_request(payload) -> bpf_tail_call
+	__insert_output_prog_to_map(collection, MAP_PROGS_JMP_UP_NAME, PROG_JAVA_SSL_L7_HTTP_TRACE_ID_FOR_UP, PROG_DATA_JAVA_SSL_L7_HTTP_TRACE_ID_UP_IDX)
 }
 
 func __insert_output_prog_to_map(collection *ebpf.Collection, mapName string, progName string, key uint32) {

+ 1 - 1
pkg/go.opentelemetry.io/otel/exporters/otlp/otlptrace/apm_exporter.go

@@ -226,7 +226,7 @@ func tracetransformData(sdl []tracesdk.ReadOnlySpan) map[int][]RootDataT {
 
 	//Transform the categorized map into a slice
 	data, _ := json.Marshal(sendDataMap)
-	klog.Debug(string(data))
+	klog.Info(string(data))
 	//fmt.Println(len(sendData))
 	//fmt.Println("sdl len:", len(sdl))
 	return sendDataMap

+ 16 - 14
utils/modelse/bpf_struct.go

@@ -27,20 +27,21 @@ const (
 
 	MAP_PROC_INFO_MAP_NAME = "proc_info_map"
 	// This prog is designed to handle data transfer
-	PROGUP                         = "bpf_prog_up__"
-	PROGKP                         = "bpf_prog_kp__"
-	PROGTP                         = "bpf_prog_tp__"
-	PROG_DATA_SUBMIT_NAME_FOR_KP   = PROGKP + "data_submit"
-	PROG_DATA_SUBMIT_NAME_FOR_TP   = PROGTP + "data_submit"
-	PROG_OUTPUT_DATA_NAME_FOR_KP   = PROGKP + "output_data"
-	PROG_OUTPUT_DATA_NAME_FOR_TP   = PROGTP + "output_data"
-	PROG_IO_EVENT_NAME_FOR_TP      = PROGTP + "io_event"
-	PROG_SAVE_SC_DATA_FOR_UP       = PROGUP + "java_save_sc"
-	PROG_JAVA_UPDATE_HEADER_FOR_UP = PROGUP + "java_update_header"
-	PROG_JAVA_FIND_HOST_FOR_UP     = PROGUP + "java_find_host"
-	PROG_JAVA_BUILD_HEADER_FOR_UP  = PROGUP + "java_build_header"
-	PROG_GO_UPDATE_HEADER_FOR_UP   = PROGUP + "go_update_header"
-	PROG_L7_HTTP_TRACE_ID_FOR_TP   = PROGTP + "l7_http_trace_id"
+	PROGUP                                = "bpf_prog_up__"
+	PROGKP                                = "bpf_prog_kp__"
+	PROGTP                                = "bpf_prog_tp__"
+	PROG_DATA_SUBMIT_NAME_FOR_KP          = PROGKP + "data_submit"
+	PROG_DATA_SUBMIT_NAME_FOR_TP          = PROGTP + "data_submit"
+	PROG_OUTPUT_DATA_NAME_FOR_KP          = PROGKP + "output_data"
+	PROG_OUTPUT_DATA_NAME_FOR_TP          = PROGTP + "output_data"
+	PROG_IO_EVENT_NAME_FOR_TP             = PROGTP + "io_event"
+	PROG_SAVE_SC_DATA_FOR_UP              = PROGUP + "java_save_sc"
+	PROG_JAVA_UPDATE_HEADER_FOR_UP        = PROGUP + "java_update_header"
+	PROG_JAVA_FIND_HOST_FOR_UP            = PROGUP + "java_find_host"
+	PROG_JAVA_BUILD_HEADER_FOR_UP         = PROGUP + "java_build_header"
+	PROG_GO_UPDATE_HEADER_FOR_UP          = PROGUP + "go_update_header"
+	PROG_L7_HTTP_TRACE_ID_FOR_TP          = PROGTP + "l7_http_trace_id"
+	PROG_JAVA_SSL_L7_HTTP_TRACE_ID_FOR_UP = PROGUP + "java_ssl_l7_http_trace_id"
 )
 
 const (
@@ -63,6 +64,7 @@ const (
 	PROG_DATA_JAVA_FIND_HOST_UP_IDX
 	PROG_DATA_JAVA_BUILD_HEADER_UP_IDX
 	PROG_DATA_GO_UPDATE_HEADER_UP_IDX
+	PROG_DATA_JAVA_SSL_L7_HTTP_TRACE_ID_UP_IDX
 	PROG_UPROBE_NUM
 )
 

+ 21 - 2
utils/modelse/stack_status.go

@@ -11,6 +11,9 @@ const (
 
 	StackUprobesSuccess StackStatus = 1 << 1
 	StackUprobesFailure StackStatus = 0 << 1
+
+	SslUprobesSuccess StackStatus = 1 << 2
+	SslUprobesFailure StackStatus = 0 << 2
 )
 
 func (s StackStatus) IsJattachSuccess() bool {
@@ -45,7 +48,23 @@ func (s *StackStatus) StackUprobesClose() {
 	*s &^= StackUprobesSuccess
 }
 
+func (s StackStatus) IsSslUprobesSuccess() bool {
+	return s&SslUprobesSuccess != SslUprobesFailure
+}
+
+func (s *StackStatus) SslUprobesSuccess() {
+	*s |= SslUprobesSuccess
+}
+
+func (s *StackStatus) SslUprobesFailure() {
+	*s &^= SslUprobesSuccess
+}
+
+func (s *StackStatus) SslUprobesClose() {
+	*s &^= SslUprobesSuccess
+}
+
 func (s StackStatus) String() string {
-	return fmt.Sprintf("native:%v|uprobe:%v",
-		s.IsJattachSuccess(), s.IsStackUprobesSuccess())
+	return fmt.Sprintf("native:%v|uprobe:%v|ssl_uprobe:%v",
+		s.IsJattachSuccess(), s.IsStackUprobesSuccess(), s.IsSslUprobesSuccess())
 }