-
Notifications
You must be signed in to change notification settings - Fork 118
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
feat: support rocketMQ #231
base: main
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
@hengyoush I am currently encountering problems while executing, and there may be issues with the changes I made. Can you help me take a look? sudo ./kyanos watch rocketmq --debug-output rocketmq --remote-ports 9876,8080 --protocol-log-level 5
ERRO[0000] load gotls uprobe failed: load program: invalid argument:
0: R1=ctx() R10=fp0
; int probe_entry_tls_conn_read(struct pt_regs* ctx) {
0: (bf) r8 = r1 ; R1=ctx() R8_w=ctx()
; uint64_t id = bpf_get_current_pid_tgid();
1: (85) call bpf_get_current_pid_tgid#14 ; R0_w=scalar()
; uint32_t tgid = id >> 32;
2: (77) r0 >>= 32 ; R0_w=scalar(smin=0,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff))
; uint32_t tgid = id >> 32;
|
I forgot to regenerate the BPF directory. |
yes,I need try to regenerate it. |
…oush#221) * docs: introduce prettier and md-padding to format docs Signed-off-by: spencercjh <[email protected]> * fix: make github alerts work Signed-off-by: spencercjh <[email protected]> * fix: make all markdown extensions work Signed-off-by: spencercjh <[email protected]> * fix: reformat new codes from main Signed-off-by: spencercjh <[email protected]> --------- Signed-off-by: spencercjh <[email protected]>
…d in server side (hengyoush#232) fix: add fallback logic to calculate totaltime when nicin event missed in server side (hengyoush#232)
@hengyoush After updated and still have a problem, did my changes affect it? sudo ./kyanos watch |
No worries. I think your changes should not cause this error, this error is only the gotls probe loading failure, will not affect the function you are developing now, I will check this problem later. @XmchxUp What your kernel version? |
|
I tested your branch on my ubuntu24.04(kernel version: static __inline void assign_arg(void* arg, size_t arg_size, struct location_t loc, const void* sp,
uint64_t* regs) {
if (loc.type == kLocationTypeStack) {
bpf_probe_read(arg, arg_size, sp + loc.offset);
} else if (loc.type == kLocationTypeRegisters) {
if (loc.offset >= 0) {
if (loc.offset <= (1<<10)) {
bpf_probe_read(arg, arg_size, (char*)regs + loc.offset);
}
}
}
} |
agent/protocol/rocketmq/rocketmq.go
Outdated
} | ||
|
||
func (r *RocketMQMessage) FormatToString() string { | ||
return fmt.Sprintf("base=[%s] command=[%s] payload=[%s]", r.FrameBase.String(), "todo", r.Body) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the TODO here expected?
I mean because it's a draft PR
agent/protocol/rocketmq/rocketmq.go
Outdated
if !ok { | ||
return protocol.ParseResult{ | ||
ParseState: protocol.Ignore, | ||
ReadBytes: frameSize, | ||
} | ||
} else { | ||
message.FrameBase = fb | ||
return protocol.ParseResult{ | ||
ParseState: protocol.Success, | ||
ReadBytes: frameSize, | ||
ParsedMessages: []protocol.ParsedMessage{message}, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be simplified
if !ok { | |
return protocol.ParseResult{ | |
ParseState: protocol.Ignore, | |
ReadBytes: frameSize, | |
} | |
} else { | |
message.FrameBase = fb | |
return protocol.ParseResult{ | |
ParseState: protocol.Success, | |
ReadBytes: frameSize, | |
ParsedMessages: []protocol.ParsedMessage{message}, | |
} | |
} | |
if !ok { | |
return protocol.ParseResult{ | |
ParseState: protocol.Ignore, | |
ReadBytes: frameSize, | |
} | |
} | |
message.FrameBase = fb | |
return protocol.ParseResult{ | |
ParseState: protocol.Success, | |
ReadBytes: frameSize, | |
ParsedMessages: []protocol.ParsedMessage{message}, | |
} |
agent/protocol/rocketmq/rocketmq.go
Outdated
} | ||
|
||
func (parser *RocketMQStreamParser) parseHeader(headerBody []byte, serializedType byte) (*RocketMQMessage, error) { | ||
fmt.Println(serializedType) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one looks alike a left behind debug
agent/protocol/rocketmq/rocketmq.go
Outdated
func (parser *RocketMQStreamParser) parseHeader(headerBody []byte, serializedType byte) (*RocketMQMessage, error) { | ||
fmt.Println(serializedType) | ||
message := &RocketMQMessage{} | ||
if serializedType == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return the error currently in the else here if serializedType != 0
And simplify the dozen line if statement
agent/protocol/rocketmq/rocketmq.go
Outdated
if len(buffer) < 8 { | ||
return protocol.ParseResult{ | ||
ParseState: protocol.NeedsMoreData, | ||
} | ||
} | ||
|
||
frameSize := int(binary.BigEndian.Uint32(buffer[:4])) | ||
if frameSize > len(buffer) { | ||
return protocol.ParseResult{ParseState: protocol.NeedsMoreData} | ||
} | ||
|
||
headerLength := binary.BigEndian.Uint32(buffer[4:8]) | ||
headerDataLen := headerLength & 0xFFFFFF | ||
serializedType := byte((headerLength >> 24) & 0xFF) | ||
|
||
if len(buffer) < 8+int(headerDataLen) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thr 4 and 8 are magical numbers here. I would like to suggest you to add constants
agent/protocol/rocketmq/rocketmq.go
Outdated
if len(headerBody) < 18 { | ||
return nil, errors.New("invalid header size") | ||
} | ||
|
||
message.RequestCode = int16(binary.BigEndian.Uint16(headerBody[:2])) | ||
message.LanguageFlag = headerBody[2] | ||
message.VersionFlag = int16(binary.BigEndian.Uint16(headerBody[3:5])) | ||
message.Opaque = int32(binary.BigEndian.Uint32(headerBody[5:9])) | ||
message.RequestFlag = int32(binary.BigEndian.Uint32(headerBody[9:13])) | ||
message.RemarkLength = int32(binary.BigEndian.Uint32(headerBody[13:17])) | ||
|
||
if int(message.RemarkLength) > len(headerBody[17:]) { | ||
return nil, errors.New("invalid remark length") | ||
} | ||
message.Remark = headerBody[17 : 17+message.RemarkLength] | ||
propertiesStart := 17 + message.RemarkLength |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here about magical number 3,5,13,17
"kyanos/agent/protocol" | ||
) | ||
|
||
var _ protocol.ParsedMessage = &RocketMQMessage{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you are validating the struct respect the interface.
This one and the previous one you do in the other files could be in tests file.
I'm unsure the compiler clean them in the final binary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ccoVeille Thanks for the REVIEW, but currently in the stage of learning as I go along with the implementation 😅 |
common.ProtocolParserLog.Warnf("Unmatched requests remain: %d", len(reqMap)) | ||
} | ||
|
||
return records |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the end of Match, you need to clean up reqStream
and respStream
, otherwise, reqStream
/respStream
will contain requests or responses that have already been matched.:
- It is recommended to clear all
respStream
entries (and also the map) at the end of the Match function because the request is unlikely to appear again. - For
reqStream
, clean up those that have already been successfully matched. - Additionally, consider removing a request from
reqStream
if it has not received a response for a long time, such as if it exceeds a certain time without a matched response.
return message, nil | ||
} | ||
|
||
func (r *RocketMQStreamParser) FindBoundary(streamBuffer *buffer.StreamBuffer, messageType protocol.MessageType, startPos int) int { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The judgment here is too simple. There are two suggestions:
- Can you add logic similar to protocol inference?
- Generally, the response's Opaque corresponds to a request with the same Opaque. So, when finding the boundary, you can check if the response's Opaque has appeared in previous request parsing (you can add a Map in RocketMQStreamParser to record the Opaque of requests that have already appeared, and then clean it in Match). If it has not appeared, it is considered illegal and should continue searching.
Closes #189