| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726 |
- // Copyright The OpenTelemetry Authors
- // SPDX-License-Identifier: Apache-2.0
- #include "arguments.h"
- #include "go_types.h"
- #include "go_net.h"
- #include "span_context.h"
- #include "go_context.h"
- #include "uprobe.h"
- // #include "trace/start_span.h"
- // char __license[] SEC("license") = "Dual MIT/GPL";
- // #define MAX_SIZE 100
- #define MAX_CONCURRENT 50
- #define MAX_HEADERS 20
- #define MAX_HEADER_STRING 50
- #define PROTOCOL_GRPC 16
- struct grpc_request_t {
- BASE_SPAN_PROPERTIES
- char method[MAX_SIZE];
- u32 status_code;
- net_addr_t local_addr;
- u8 has_status;
- u32 stream_id;
- u64 method_size;
- };
- struct {
- __uint(type, BPF_MAP_TYPE_HASH);
- __type(key, void *);
- __type(value, struct grpc_request_t);
- __uint(max_entries, MAX_CONCURRENT);
- } grpc_events SEC(".maps");
- struct {
- __uint(type, BPF_MAP_TYPE_HASH);
- __type(key, u32);
- __type(value, struct grpc_request_t);
- __uint(max_entries, MAX_CONCURRENT);
- } streamid_to_grpc_events SEC(".maps");
- struct {
- __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
- __uint(key_size, sizeof(u32));
- __uint(value_size, sizeof(struct grpc_request_t));
- __uint(max_entries, 1);
- } grpc_storage_map SEC(".maps");
- struct hpack_header_field {
- struct go_string_ot name;
- struct go_string_ot value;
- bool sensitive;
- };
- // Injected in init
- // volatile const u64 stream_method_ptr_pos;
- // u64 stream_method_ptr_pos = 80; //需要处理多版本场景
- // volatile const u64 frame_fields_pos;
- u64 frame_fields_pos = 8; //使用固定值8即可,不再处理多版本场景。
- // volatile const u64 frame_stream_id_pod;
- u64 frame_stream_id_pod = 8; //使用固定值8即可,不再处理多版本场景。
- // volatile const u64 stream_id_pos;
- u64 stream_id_pos = 0; //使用固定值0即可,不再处理多版本场景。
- // volatile const u64 stream_ctx_pos;
- // u64 stream_ctx_pos = 32; //需要做多版本处理
- // volatile const u64 server_stream_stream_pos;
- u64 server_stream_stream_pos = 0; //1.69之前版本用不到,1.69之后版本用这个
- // volatile const bool is_new_frame_pos;
- // bool is_new_frame_pos; // < 1.60 为false,>= 1.60 为true,直接在 用户态赋值即可,不再做处理。
- // volatile const u64 status_s_pos;
- static u64 status_s_pos = 0; //使用固定值即可,不再处理多版本场景。
- // volatile const u64 status_code_pos;
- static u64 status_code_pos = 40; //使用固定值即可,不再做多版本处理
- // volatile const u64 http2server_peer_pos;
- // u64 http2server_peer_pos;
- // volatile const u64 peer_local_addr_pos;
- // u64 peer_local_addr_pos;
- // volatile const bool server_addr_supported;
- static __always_inline long
- dummy_extract_span_context_from_headers(void *stream_id, struct span_context *parent_span_context) {
- return 0;
- }
- // handleStream handles gRPC stream telemetry.
- //
- // Arguments:
- // - ctx: the pt_regs passed to the uprobe function
- // - stream_ptr: pointer to the transport.Stream tracking the stream
- // - go_context: the parsed Go context.Context
- //
- // Returns 0 on success, otherwise a negative error value in case of failure.
- static __always_inline int
- handleStream(struct pt_regs *ctx, void *stream_ptr, struct go_iface *go_context) {
- __u32 tgid = (__u32)(bpf_get_current_pid_tgid() >> 32);
- struct ebpf_proc_info *info =
- bpf_map_lookup_elem(&proc_info_map, &tgid);
- if (!info) {
- return -1;
- }
- if (go_context == NULL) {
- cw_bpf_debug("grpc:server:handleStream: NULL go_context");
- return -1;
- }
- // cw_bpf_debug("info->stream_method_ptr_pos is %d\n", info->stream_method_ptr_pos);
- if (stream_ptr == NULL) {
- cw_bpf_debug("grpc:server:handleStream: NULL stream_ptr");
- return -1;
- }
- void *key = (void *)GOROUTINE(ctx);
- void *grpcReq_event_ptr = bpf_map_lookup_elem(&grpc_events, &key);
- if (grpcReq_event_ptr != NULL) {
- cw_bpf_debug("grpc:server:handleStream: event already tracked");
- return 0;
- }
- // Get parent context if exists
- u32 stream_id = 0;
- __u32 zero = 0;
- long rc =
- bpf_probe_read_user(&stream_id, sizeof(stream_id), (void *)(stream_ptr + stream_id_pos));
- if (rc != 0) {
- cw_bpf_debug("grpc:server:handleStream: failed to read stream ID");
- return -2;
- }
- struct grpc_request_t *grpcReq = bpf_map_lookup_elem(&streamid_to_grpc_events, &stream_id);
- if (grpcReq == NULL) {
- // No parent span context, generate new span context
- u32 zero = 0;
- grpcReq = bpf_map_lookup_elem(&grpc_storage_map, &zero);
- if (grpcReq == NULL) {
- cw_bpf_debug("grpc:server:handleStream: failed to get grpcReq");
- return 0;
- }
- }
- grpcReq->start_time = bpf_ktime_get_ns();
- grpcReq->stream_id = stream_id;
- // start_span_params_t start_span_params = {
- // .ctx = ctx,
- // .sc = &grpcReq->sc,
- // .psc = &grpcReq->psc,
- // .go_context = go_context,
- // // The parent span context is set by operateHeader probe
- // .get_parent_span_context_fn = dummy_extract_span_context_from_headers,
- // .get_parent_span_context_arg = NULL,
- // };
- // start_span(&start_span_params);
- // Set attributes
- void *method_ptr = stream_ptr + info->stream_method_ptr_pos;
- bool parsed_method =
- get_go_string_from_user_ptr(method_ptr, grpcReq->method, sizeof(grpcReq->method));
- if (!parsed_method) {
- cw_bpf_debug("grpc:server:handleStream: failed to read gRPC method from stream");
- bpf_map_delete_elem(&streamid_to_grpc_events, &stream_id);
- return -3;
- }
- // cw_bpf_debug("grpc:server:handleStream: get the method is %s\n", grpcReq->method);
- // if (server_addr_supported) {
- // void *http2server = get_argument(ctx, 3);
- // if (http2server != NULL) {
- // void *local_addr_ptr = 0;
- // void *local_addr_pos = http2server + http2server_peer_pos + peer_local_addr_pos;
- // bpf_probe_read_user(
- // &local_addr_ptr, sizeof(local_addr_ptr), get_go_interface_instance(local_addr_pos));
- // get_tcp_net_addr_from_tcp_addr(ctx, &grpcReq->local_addr, (void *)(local_addr_ptr));
- // } else {
- // cw_bpf_debug("grpc:server:handleStream: failed to get http2server arg");
- // }
- // }
- // Write event
- rc = bpf_map_update_elem(&grpc_events, &key, grpcReq, 0);
- if (rc != 0) {
- cw_bpf_debug("grpc:server:handleStream: failed to update event");
- return -4;
- }
- start_tracking_span(go_context->data, &grpcReq->sc);
- //处理http请求之前,确认进程信息是否存在
- __u64 id = bpf_get_current_pid_tgid();
- __u32 pid = id >> 32;
- struct ebpf_proc_info *proc_info = bpf_map_lookup_elem(&proc_info_map, &pid);
- if (!proc_info) {
- cw_bpf_debug("[Trace End in l7][Response][HTTP]:no proc info. pid:%d \n",pid);
- return 0;
- }
- // cw_bpf_debug("start get apm data\n");
- // struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&apm_span_context_heap3, &zero);
- // if (cw_parent_span_context == NULL) {
- // return -1;
- // }
- // __builtin_memset(cw_parent_span_context, 0, sizeof(struct apm_span_context));
- // generate_random_bytes(cw_parent_span_context->trace_id, TRACE_ID_SIZE);
- // cw_save_parent_tracking_span(cw_parent_span_context);
- struct l7_request_key k = {};
- k.pid = pid;
- k.fd = 0;
- k.is_tls = 0;
- k.stream_id = stream_id;
- 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->status = STATUS_UNKNOWN;
- e->method = METHOD_UNKNOWN;
- e->statement_id = 0;
-
- // 拷贝 grpcReq->method 到 payload 并设置 payload_size
- // 手动计算字符串长度(在 eBPF 中不能使用 strlen)
- u64 method_len = 0;
- for (int i = 0; i < MAX_SIZE; i++) {
- if (grpcReq->method[i] == '\0') {
- method_len = i;
- break;
- }
- }
- // 如果没有找到 '\0',使用最大长度
- if (method_len == 0) {
- method_len = MAX_SIZE - 1;
- }
-
- grpcReq->method_size = method_len;
- e->payload_size = method_len;
- COPY_PAYLOAD(e->payload, method_len, grpcReq->method);
- // cw_bpf_debug("grpc:server:handleStream: get the payload size is %d\n", e->payload_size);
- struct apm_trace_info_t trace_info = cw_save_trace_info(id,pid, k.fd);
-
- e->trace_start = 1;
- e->trace_end = 0;
- e->trace_type = 1;
- e->protocol = PROTOCOL_TRACE;
- e->trace_id = trace_info.trace_id;
- //不发送payload
- bpf_perf_event_output(ctx, &l7_events, BPF_F_CURRENT_CPU, e, sizeof(*e));
- return 0;
- }
- // writeStatus writes the OTel status to any active spans.
- //
- // Arguments:
- // - ctx: the pt_regs passed to the uprobe function
- // - status_ptr: pointer to the status.Stream holding the status info
- //
- // Returns 0 on success, otherwise a negative error value in case of failure.
- // static __always_inline int writeStatus(struct pt_regs *ctx, void *status_ptr) {
- // if (status_ptr == NULL) {
- // cw_bpf_debug("grpc:server:writeStatus: NULL status_ptr");
- // return -1;
- // }
- // void *key = (void *)GOROUTINE(ctx);
- // struct grpc_request_t *req_ptr = bpf_map_lookup_elem(&grpc_events, &key);
- // if (req_ptr == NULL) {
- // cw_bpf_debug("grpc:server:handleStream: failed to lookup grpc request");
- // return -2;
- // }
- // void *s_ptr = 0;
- // long rc = bpf_probe_read_user(&s_ptr, sizeof(s_ptr), (void *)(status_ptr + status_s_pos));
- // if (rc != 0) {
- // cw_bpf_debug("grpc:server:handleStream: failed to read Status.s");
- // return -3;
- // }
- // // Get status code from Status.s pointer
- // rc = bpf_probe_read_user(
- // &req_ptr->status_code, sizeof(req_ptr->status_code), (void *)(s_ptr + status_code_pos));
- // if (rc != 0) {
- // cw_bpf_debug("grpc:server:handleStream: failed to read status code");
- // return -4;
- // }
- // req_ptr->has_status = true;
- // return 0;
- // }
- // This instrumentation attaches uprobe to the following function:
- // func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream, trInfo *traceInfo)
- //
- // This is only compatible with versions < 1.69.0 of the Server.
- SEC("uprobe/server_handleStream")
- int uprobe_server_handleStream(struct pt_regs *ctx) {
- // cw_bpf_debug("enter the uprobe_server_handleStream");
- u64 stream_pos = 4;
- void *stream_ptr = get_argument(ctx, stream_pos);
- // cw_bpf_debug("enter uprobe_server_handleStream\n");
- // Get key
- __u64 pid_tgid = bpf_get_current_pid_tgid();
- __u32 tgid = pid_tgid >> 32;
- struct ebpf_proc_info *proc_info =
- bpf_map_lookup_elem(&proc_info_map, &tgid);
- if(!proc_info)
- {
- cw_bpf_debug("[uprobe_HandlerFunc_ServeHTTP] no proc info");
- return 0;
- }
- struct go_iface go_context = {0};
- get_Go_context(ctx, stream_pos, proc_info->ctx_ptr_pos, false);
- return handleStream(ctx, stream_ptr, &go_context);
- }
- // UPROBE_RETURN(server_handleStream, struct grpc_request_t, grpc_events)
- SEC("uprobe/server_handleStream")
- int uprobe_server_handleStream_Returns(struct pt_regs *ctx) {
- // cw_bpf_debug("enter the uprobe_server_handleStream return");
- void *key = (void *)GOROUTINE(ctx);
- __u64 id = bpf_get_current_pid_tgid();
- __u32 zero = 0;
- __u32 fd = 0;
- __u32 pid, tid;
- __u32 http_status = 200;
- pid = id >> 32;
- tid = (__u32)id;
- // cw_bpf_debug("enter uprobe_server_handleStream_Returns\n");
- struct l7_request_key k = {};
- k.pid = pid;
- k.fd = fd;
- k.is_tls = 0;
- k.stream_id = -1;
- struct grpc_request_t *event = bpf_map_lookup_elem(&grpc_events, &key);
- if (event == NULL) {
- cw_bpf_debug("grpc:server:uprobe/server_handleStream2Return: event is NULL");
- return -5;
- }
- event->end_time = bpf_ktime_get_ns();
- // output_span_event(ctx, event, sizeof(struct grpc_request_t), &event->sc);
- stop_tracking_span(&event->sc, &event->psc);
- bpf_map_delete_elem(&grpc_events, &key);
-
- struct apm_trace_key_t trace_key = get_apm_trace_key(120 * NS_PER_SEC, true);
- struct apm_trace_info_t * start_trace_info = get_apm_trace_info_by_trace_key(trace_key);
- if (!start_trace_info) {
- return -1;
- }
- __u64 trace_id = start_trace_info->trace_id;
- __u32 event_count = cw_get_event_count(trace_id);
- cw_bpf_debug("[uprobeThread/pidpidpidpid][Trace End in l7][HTTP]pid:[%d]--[%lld]", tid, bpf_ktime_get_ns());
- cw_bpf_debug("[Trace End in l7][Response][HTTP] event_count:%d", event_count);
- cw_bpf_debug("[Trace End in l7][Response][HTTP] pid:%d,fd:%d,trace_id:%llu", tid, fd, trace_id);
- // 发送事件到用户空间 start
- struct l7_event *e = bpf_map_lookup_elem(&l7_event_heap, &zero);
- if (!e) {
- cw_clear_trace(pid, tid, fd);
- return -1;
- }
- // parent sc
- struct apm_span_context *cw_psc = cw_get_parent_tracking_span_by_trace_key(start_trace_info->trace_key);
- if(cw_psc){
- cw_copy_byte_arrays(cw_psc->trace_id, e->trace_id_from, APM_TRACE_ID_SIZE);
- cw_copy_byte_arrays(cw_psc->assumed_app_id, e->called_id, APM_ASSUMED_APP_ID_SIZE);
- cw_copy_byte_arrays(cw_psc->instance_id, e->instance_id_from, APM_INSTANCE_ID_SIZE);
- cw_copy_byte_arrays(cw_psc->app_id, e->app_id_from, APM_APP_ID_SIZE);
- cw_copy_byte_arrays(cw_psc->span_id, e->span_id_from, APM_SPAN_ID_SIZE);
- cw_copy_byte_arrays(cw_psc->type_from, e->type_from, APM_TYPE_FROM_SIZE);
- }
- // struct l7_request *req = bpf_map_lookup_elem(&active_l7_requests, &k);
- // if (!req)
- // {
- // cw_clear_trace(pid, tid, fd);
- // return 0;
- // }
- // e->start_at = req->ns;
- e->start_at = event->start_time;
- // cw_bpf_debug("req->ns:%llu",req->ns);
- e->end_at = bpf_ktime_get_ns();
- e->duration = e->end_at - e->start_at;
- 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_type = 1;
- e->trace_id = trace_id;
- e->payload_size = 0;
- e->event_count = event_count;
-
- e->payload_size = event->method_size;
- COPY_PAYLOAD(e->payload, event->method_size, event->method);
- // bpf_map_delete_elem(&active_l7_requests, &k);
- // 清除事件计数
- bpf_map_delete_elem(&trace_event_count_heap, &trace_id);
- // 清除业务层trace信息
- clear_parent_span_context_by_trace_key(start_trace_info->trace_key);
- // 清除trace信息
- cw_clear_trace(pid, tid, fd);
- // cw_bpf_debug("socket accept bytes_sent cid.pid=%d, cid.fd=%d\n", cid.pid, cid.fd);
- // struct accept_connection *accept_conn = bpf_map_lookup_elem(&active_accepts, &cid);
- // if (accept_conn) {
- // cw_bpf_debug("socket accept bytes_sent after cid.pid=%d, cid.fd=%d\n", cid.pid, cid.fd);
- // cw_bpf_debug("rock enter the accept_conn function cid.pid=%d, cid.fd=%d\n", cid.pid, cid.fd);
- // e->sport = accept_conn->sport;
- // e->dport = accept_conn->dport;
- // __builtin_memcpy(&e->saddr, &accept_conn->saddr, sizeof(e->saddr));
- // __builtin_memcpy(&e->daddr, &accept_conn->daddr, sizeof(e->daddr));
- // }
- //不发送payload
- bpf_perf_event_output(ctx, &l7_events, BPF_F_CURRENT_CPU, e, sizeof(*e));
- // cw_bpf_debug("stop get apm data\n");
- return 0;
- }
- // This instrumentation attaches uprobe to the following function:
- // func (s *Server) handleStream(t transport.ServerTransport, stream *transport.ServerStream)
- // https://github.com/grpc/grpc-go/blob/317271b232677b7869576a49855b01b9f4775d67/server.go#L1735
- //
- // This is only compatible with versions > 1.69.0 of the Server.
- SEC("uprobe/server_handleStream2")
- int uprobe_server_handleStream2(struct pt_regs *ctx) {
- __u32 tgid = (__u32)(bpf_get_current_pid_tgid() >> 32);
- struct ebpf_proc_info *info =
- bpf_map_lookup_elem(&proc_info_map, &tgid);
- if (!info) {
- return -1;
- }
- cw_bpf_debug("info->stream_ctx_pos is %d\n", info->stream_ctx_pos);
- u64 server_stream_pos = 4;
- // cw_bpf_debug("enter uprobe_server_handleStream2\n");
- void *server_stream_ptr = get_argument(ctx, server_stream_pos);
- if (server_stream_ptr == NULL) {
- cw_bpf_debug("grpc:server:uprobe/server_handleStream2: failed to get ServerStream arg");
- return -1;
- }
- void *stream_ptr;
- long rc = bpf_probe_read_user(
- &stream_ptr, sizeof(stream_ptr), (void *)(server_stream_ptr + server_stream_stream_pos));
- if (rc != 0) {
- cw_bpf_debug("grpc:server:uprobe/server_handleStream2: failed to read stream_ptr");
- return -2;
- }
- struct go_iface go_context = {0};
- rc = bpf_probe_read_user(
- &go_context.type, sizeof(go_context.type), (void *)(stream_ptr + info->stream_ctx_pos));
- if (rc != 0) {
- cw_bpf_debug("grpc:server:uprobe/server_handleStream2: failed to read context type");
- return -3;
- }
- rc = bpf_probe_read_user(&go_context.data,
- sizeof(go_context.data),
- get_go_interface_instance(stream_ptr + info->stream_ctx_pos));
- if (rc != 0) {
- cw_bpf_debug("grpc:server:uprobe/server_handleStream2: failed to read context data");
- return -4;
- }
- return handleStream(ctx, stream_ptr, &go_context);
- }
- // This instrumentation attaches a return uprobe to the following function:
- // func (s *Server) handleStream(t transport.ServerTransport, stream *transport.ServerStream)
- // https://github.com/grpc/grpc-go/blob/317271b232677b7869576a49855b01b9f4775d67/server.go#L1735
- //
- // This is only compatible with versions > 1.69.0 of the Server.
- SEC("uprobe/server_handleStream2")
- int uprobe_server_handleStream2_Returns(struct pt_regs *ctx) {
- u64 server_stream_pos = 4;
- void *server_stream_ptr = get_argument(ctx, server_stream_pos);
- void *key = NULL;
- if (server_stream_ptr == NULL) {
- // We might fail to get the pointer for versions of Go which use register ABI, as this function does not return anything.
- // This is not an error in that case so we can just go to the lookup which will happen by goroutine.
- goto lookup;
- }
- void *stream_ptr;
- long rc = bpf_probe_read_user(
- &stream_ptr, sizeof(stream_ptr), (void *)(server_stream_ptr + server_stream_stream_pos));
- if (rc != 0) {
- cw_bpf_debug("grpc:server:uprobe/server_handleStream2Return: failed to read stream_ptr");
- return -2;
- }
- lookup:
- key = (void *)GOROUTINE(ctx);
- struct grpc_request_t *event = bpf_map_lookup_elem(&grpc_events, &key);
- if (event == NULL) {
- cw_bpf_debug("grpc:server:uprobe/server_handleStream2Return: event is NULL");
- return -5;
- }
- event->end_time = bpf_ktime_get_ns();
- // output_span_event(ctx, event, sizeof(struct grpc_request_t), &event->sc);
- stop_tracking_span(&event->sc, &event->psc);
- bpf_map_delete_elem(&grpc_events, &key);
- __u64 id = bpf_get_current_pid_tgid();
- __u32 zero = 0;
- __u32 fd = 0;
- __u32 pid, tid;
- __u32 http_status = 200;
- pid = id >> 32;
- tid = (__u32)id;
- // cw_bpf_debug("enter uprobe_server_handleStream_Returns\n");
- struct l7_request_key k = {};
- k.pid = pid;
- k.fd = fd;
- k.is_tls = 0;
- k.stream_id = -1;
- struct apm_trace_key_t trace_key = get_apm_trace_key(120 * NS_PER_SEC, true);
- struct apm_trace_info_t * start_trace_info = get_apm_trace_info_by_trace_key(trace_key);
- if (!start_trace_info) {
- return -1;
- }
- __u64 trace_id = start_trace_info->trace_id;
- __u32 event_count = cw_get_event_count(trace_id);
- cw_bpf_debug("[uprobeThread/pidpidpidpid][Trace End in l7][HTTP]pid:[%d]--[%lld]", tid, bpf_ktime_get_ns());
- cw_bpf_debug("[Trace End in l7][Response][HTTP] event_count:%d", event_count);
- cw_bpf_debug("[Trace End in l7][Response][HTTP] pid:%d,fd:%d,trace_id:%llu", tid, fd, trace_id);
- // 发送事件到用户空间 start
- struct l7_event *e = bpf_map_lookup_elem(&l7_event_heap, &zero);
- if (!e) {
- cw_clear_trace(pid, tid, fd);
- return -1;
- }
- // parent sc
- struct apm_span_context *cw_psc = cw_get_parent_tracking_span_by_trace_key(start_trace_info->trace_key);
- if(cw_psc){
- cw_copy_byte_arrays(cw_psc->trace_id, e->trace_id_from, APM_TRACE_ID_SIZE);
- cw_copy_byte_arrays(cw_psc->assumed_app_id, e->called_id, APM_ASSUMED_APP_ID_SIZE);
- cw_copy_byte_arrays(cw_psc->instance_id, e->instance_id_from, APM_INSTANCE_ID_SIZE);
- cw_copy_byte_arrays(cw_psc->app_id, e->app_id_from, APM_APP_ID_SIZE);
- cw_copy_byte_arrays(cw_psc->span_id, e->span_id_from, APM_SPAN_ID_SIZE);
- cw_copy_byte_arrays(cw_psc->type_from, e->type_from, APM_TYPE_FROM_SIZE);
- }
- // struct l7_request *req = bpf_map_lookup_elem(&active_l7_requests, &k);
- // if (!req)
- // {
- // cw_clear_trace(pid, tid, fd);
- // return 0;
- // }
- // e->start_at = req->ns;
- e->start_at = event->start_time;
- // cw_bpf_debug("req->ns:%llu",req->ns);
- e->end_at = bpf_ktime_get_ns();
- e->duration = e->end_at - e->start_at;
- 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_type = 1;
- e->trace_id = trace_id;
- e->payload_size = 0;
- e->event_count = event_count;
-
- e->payload_size = event->method_size;
- COPY_PAYLOAD(e->payload, event->method_size, event->method);
- // bpf_map_delete_elem(&active_l7_requests, &k);
- // 清除事件计数
- bpf_map_delete_elem(&trace_event_count_heap, &trace_id);
- // 清除业务层trace信息
- clear_parent_span_context_by_trace_key(start_trace_info->trace_key);
- // 清除trace信息
- cw_clear_trace(pid, tid, fd);
- // cw_bpf_debug("socket accept bytes_sent cid.pid=%d, cid.fd=%d\n", cid.pid, cid.fd);
- // struct accept_connection *accept_conn = bpf_map_lookup_elem(&active_accepts, &cid);
- // if (accept_conn) {
- // cw_bpf_debug("socket accept bytes_sent after cid.pid=%d, cid.fd=%d\n", cid.pid, cid.fd);
- // cw_bpf_debug("rock enter the accept_conn function cid.pid=%d, cid.fd=%d\n", cid.pid, cid.fd);
- // e->sport = accept_conn->sport;
- // e->dport = accept_conn->dport;
- // __builtin_memcpy(&e->saddr, &accept_conn->saddr, sizeof(e->saddr));
- // __builtin_memcpy(&e->daddr, &accept_conn->daddr, sizeof(e->daddr));
- // }
- //不发送payload
- bpf_perf_event_output(ctx, &l7_events, BPF_F_CURRENT_CPU, e, sizeof(*e));
- // cw_bpf_debug("stop get apm data\n");
- return 0;
- }
- // func (d *http2Server) operateHeader(frame *http2.MetaHeadersFrame) error
- // for version 1.60 and above:
- // func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeadersFrame, handle func(*Stream)) error
- SEC("uprobe/http2Server_operateHeader")
- int uprobe_http2Server_operateHeader(struct pt_regs *ctx) {
- // cw_bpf_debug("enter the uprobe_http2Server_operateHeader");
- __u32 tgid = (__u32)(bpf_get_current_pid_tgid() >> 32);
- struct ebpf_proc_info *info =
- bpf_map_lookup_elem(&proc_info_map, &tgid);
- if (!info) {
- return -1;
- }
- s32 find_w3c = 0;
- void *arg4 = get_argument(ctx, 4);
- void *arg2 = get_argument(ctx, 2);
- void *frame_ptr = info->is_new_frame_pos ? arg4 : arg2;
- struct go_slice header_fields = {};
- bpf_probe_read(&header_fields, sizeof(header_fields), (void *)(frame_ptr + frame_fields_pos));
- char key[CW_HEADER_KEY_LENGTH + 1] = "cwtrace";
- // 确保字符串以 null 结尾
- key[CW_HEADER_KEY_LENGTH] = '\0';
- // cw_bpf_debug("enter the uprobe_http2Server_operateHeader\n");
-
- __u32 zero = 0;
- struct apm_span_context *cw_parent_span_context = bpf_map_lookup_elem(&apm_span_context_heap3, &zero);
- if (cw_parent_span_context == NULL) {
- return -1;
- }
- __builtin_memset(cw_parent_span_context, 0, sizeof(struct apm_span_context));
-
- // 优化循环:减少复杂度,提前退出
- for (s32 i = 0; i < MAX_HEADERS && i < header_fields.len; i++) {
- struct hpack_header_field hf = {};
- long res = bpf_probe_read(&hf, sizeof(hf), (void *)(header_fields.ptr + (i * sizeof(hf))));
- if (res != 0) {
- continue; // 读取失败,跳过
- }
-
- // 简化条件判断
- if (hf.name.len != CW_HEADER_KEY_LENGTH || hf.value.len != CW_HEADER_VAL_LENGTH) {
- continue;
- }
- // cw_bpf_debug("found traceparent header name is %s", hf.name.str);
- // cw_bpf_debug("found traceparent header value is %s", hf.value.str);
-
- char current_key[CW_HEADER_KEY_LENGTH + 1];
- if (bpf_probe_read(current_key, sizeof(current_key), hf.name.str) != 0) {
- continue;
- }
- // cw_bpf_debug("---found traceparent header name is %s", hf.name.str);
- // cw_bpf_debug("+++found traceparent header value is %s", hf.value.str);
- current_key[CW_HEADER_KEY_LENGTH] = '\0';
- // cw_bpf_debug("---11111found cwtrace key is %s", key);
- // cw_bpf_debug("+++11111found cwtrace current_key is %s", current_key);
- // 简化字符串比较
- // if (bpf_memcmp(key, current_key, 6) == 0) {
- if (current_key[0] == 'c' && current_key[1] == 'w' && current_key[2] == 't' && current_key[3] == 'r' && current_key[4] == 'a' && current_key[5] == 'c' && current_key[6] == 'e') {
- find_w3c = 1;
- // cw_bpf_debug("found traceparent header");
- // 执行字符串到span context的转换
- cw_string_to_span_context(hf.value.str, cw_parent_span_context);
- // cw_bpf_debug("11111found traceparent header value is %s", hf.value.str);
- break; // 找到后立即退出
- }
- }
- if (find_w3c == 0)
- {
- generate_random_bytes(cw_parent_span_context->trace_id, TRACE_ID_SIZE);
- cw_bpf_debug("enter uprobe_http2Server_operateHeader, generate the traceid\n");
- }
- cw_save_parent_tracking_span(cw_parent_span_context);
- return 0;
- }
- // func (ht *http2Server) WriteStatus(s *Stream, st *status.Status)
- // https://github.com/grpc/grpc-go/blob/bcf9171a20e44ed81a6eb152e3ca9e35b2c02c5d/internal/transport/http2_server.go#L1049
- //
- // This is only compatible with versions > 1.40 and < 1.69.0 of the Server.
- // SEC("uprobe/http2Server_WriteStatus")
- // int uprobe_http2Server_WriteStatus(struct pt_regs *ctx) {
- // // cw_bpf_debug("enter uprobe_http2Server_WriteStatus\n");
- // void *status_ptr = get_argument(ctx, 3);
- // return writeStatus(ctx, status_ptr);
- // }
- // // func (ht *http2Server) writeStatus(s *Stream, st *status.Status)
- // // https://github.com/grpc/grpc-go/blob/317271b232677b7869576a49855b01b9f4775d67/internal/transport/http2_server.go#L1045
- // //
- // // This is only compatible with versions > 1.69.0 of the Server.
- // SEC("uprobe/http2Server_WriteStatus2")
- // int uprobe_http2Server_WriteStatus2(struct pt_regs *ctx) {
- // // cw_bpf_debug("enter uprobe_http2Server_WriteStatus2\n");
- // u64 server_stream_pos = 2;
- // void *server_stream_ptr = get_argument(ctx, server_stream_pos);
- // if (server_stream_ptr == NULL) {
- // cw_bpf_debug("grpc:server:uprobe/http2Server_WriteStatus2: failed to get ServerStream arg");
- // return -1;
- // }
- // void *stream_ptr;
- // long rc = bpf_probe_read_user(
- // &stream_ptr, sizeof(stream_ptr), (void *)(server_stream_ptr + server_stream_stream_pos));
- // if (rc != 0) {
- // cw_bpf_debug("grpc:server:uprobe/http2Server_WriteStatus2: failed to read stream_ptr");
- // return -2;
- // }
- // void *status_ptr = get_argument(ctx, 3);
- // return writeStatus(ctx, status_ptr);
- // }
|