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

Spring Integration javaagent instrumentation #3295

Merged

Conversation

mateuszrzeszutek
Copy link
Member

No description provided.

Comment on lines 3 to 8
ext {
// context "leak" here is intentional: spring-integration instrumentation will always override
// "local" span context with one extracted from the incoming message
doNotFailOnContextLeak = true
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a consequence of always using the context extracted from the incoming message; we completely ignore the "local" current context, but that's fine in that case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... our debugContextLeakIfEnabled should not be called at all in case of CONSUMER spans. This is not spring integration specific problem.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's called for all spans, span kind does not matter.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but the logic of not failing the test should be the same for all CONSUMER spans.

gradle/instrumentation.gradle Outdated Show resolved Hide resolved
Comment on lines 3 to 8
ext {
// context "leak" here is intentional: spring-integration instrumentation will always override
// "local" span context with one extracted from the incoming message
doNotFailOnContextLeak = true
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... our debugContextLeakIfEnabled should not be called at all in case of CONSUMER spans. This is not spring integration specific problem.

@mateuszrzeszutek
Copy link
Member Author

After discussing this with @iNikem I've changed the way spans are created by the spring-integration instrumentation:

  • If there's an ongoing CONSUMER (or SERVER, as it's also a top-level span) this instrumentation will not attempt to extract context from the incoming message, it will only propagate/inject the current context to the message. That is because if there's already a CONSUMER span then some other messaging instrumentation must have created it (and if there's a SERVER span, then most likely it means that spring-integration is not used in a messaging scenario)
  • If there's no ongoing CONSUMER (or SERVER) span, this instrumentation will extract the parent span context from the incoming message and create a new CONSUMER span, and propagate it by injecting the context to the message. This situation should occur when spring-integration code is the first one to receive a message produced in some other process, and there's no other messaging instrumentation.

Comment on lines 51 to 63
// spring-cloud-stream-binder-rabbit listener puts all messages into a BlockingQueue immediately after receiving
// that's why the rabbitmq CONSUMER span will never have any child span (and propagate context, actually)
// and that's why spring-integration creates another CONSUMER span
span(4) {
name ~/testTopic.anonymous.[-\w]+ process/
childOf span(3)
kind CONSUMER
}
span(5) {
name "testConsumer.input"
childOf span(3)
kind CONSUMER
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two CONSUMER spans here are a necessity: turns out spring-cloud-stream for rabbitmq uses a listener that puts all incoming messages into a BlockingQueue immediately after receiving them; there's no way to propagate context through that... (BTW, this explains why @RabbitListener did not work for some people)

So when spring-integration instrumentation kicks in, it sees no CONSUMER span, so it creates a new one - a child of the remote PRODUCER span.

Comment on lines 92 to +94
case SERVER:
suppressed = ServerSpan.fromContextOrNull(parentContext) != null;
case CONSUMER:
suppressed = ServerSpan.exists(parentContext) || ConsumerSpan.exists(parentContext);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SERVER and CONSUMER spans are now both treated as "local-root" type of spans; by default, you can't have both of them in a single process, in a single trace, since they both represent the receiving side.
This is a pretty significant change, please tell me WDYT.

@mateuszrzeszutek mateuszrzeszutek force-pushed the spring-messaging-javaagent branch from 9434914 to 84bfb99 Compare June 15, 2021 13:24
}
}
span(5) {
name "testConsumer.input"
Copy link
Member

@trask trask Jun 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think by message semantic conventions this should be testConsumer.input process

}
}
span(3) {
name "testTopic -> testTopic send"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think messaging semantic conventions suggest this should be just testTopic send

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That span comes from rabbit instrumentation, do you mind if I create an issue for this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that we should review rabbitmq integration's usage of semantic convention anyway. There are some other strange things here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attributes {}
}
span(2) {
name "exchange.declare"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you comment in the test which spans are from spring integration instrumentation and which are from rabbitmq instrumentation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, will do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants