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

Add support for websockets #53

Merged
merged 11 commits into from
Sep 26, 2017

Conversation

objectiser
Copy link
Contributor

@objectiser objectiser commented Sep 19, 2017

Fixes #25

@@ -0,0 +1,74 @@
/*
* Copyright 2016-2017 The OpenTracing Authors
Copy link
Contributor

Choose a reason for hiding this comment

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

@objectiser could you please create a PR for checking license headers?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done #54

Copy link
Contributor

Choose a reason for hiding this comment

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

thanks 👍

Copy link
Contributor

@pavolloffay pavolloffay left a comment

Choose a reason for hiding this comment

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

Just some minor comments. Could you please rebase it? I will try it in the real app.

@@ -121,6 +121,16 @@
<artifactId>artemis-jms-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not this:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

Copy link
Contributor

Choose a reason for hiding this comment

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

prefer to be consistent with the other pom

if (SimpMessageType.MESSAGE.equals(message.getHeaders().get(SIMP_MESSAGE_TYPE))) {
SpanContext context = null;
// Check if server kind
if (spanKind == Tags.SPAN_KIND_SERVER) {
Copy link
Contributor

Choose a reason for hiding this comment

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

use .equals


/**
* A TextMap carrier for use with Tracer.inject() to inject tracing context into Spring messaging
* {link {@link MessageHeaders}.
Copy link
Contributor

Choose a reason for hiding this comment

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

invalid javadoc


/**
* A TextMap carrier for use with Tracer.extract() to extract tracing context from Spring messaging
* {link {@link MessageHeaders}.
Copy link
Contributor

Choose a reason for hiding this comment

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

invalid javadoc


public TextMapExtractAdapter(final MessageHeaders headers) {
for (Map.Entry<String, Object> entry : headers.entrySet()) {
if (entry.getValue() instanceof String) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's better to get rid of this check and rather call .toString() then adding to the map

private int port;
private String url;

private static final String SEND_HELLO_MESSAGE_ENDPOINT = "/app/hello";
Copy link
Contributor

Choose a reason for hiding this comment

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

move constants to the top


@Test
public void testPreSendServerSpan() {
MessageBuilder<String> messageBuilder = MessageBuilder.<String>withPayload("Hi")
Copy link
Contributor

Choose a reason for hiding this comment

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

diamond operator can be used.


@Test
public void testPreSendClientSpan() {
MessageBuilder<String> messageBuilder = MessageBuilder.<String>withPayload("Hi")
Copy link
Contributor

Choose a reason for hiding this comment

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

diamond operator

import io.opentracing.mock.MockTracer;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes= {WebSocketConfig.class,GreetingController.class},
Copy link
Contributor

Choose a reason for hiding this comment

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

Add MockTracingAutoConfiguration to be consistent with other tests,

private List<Transport> createTransportClient() {
List<Transport> transports = new ArrayList<>(1);
transports.add(new WebSocketTransport(new StandardWebSocketClient()));
return transports;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Collections.singletonList()

@Autowired
Tracer tracer;

@Autowired(required=false)
Copy link
Contributor

Choose a reason for hiding this comment

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

This still does not look right (with logic in bean providers). Can we make it declarative on the methods or class? (you can inject directly to the method and make method conditional on a specific bean)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed - I had tried that before, but was using ConditionalOnBean(ExecutorSubscribableChannel.class) which failed - when I switched to using the bean names it worked.

Tracer tracer;

@Bean
@ConditionalOnBean(name="clientInboundChannel")
Copy link
Contributor

Choose a reason for hiding this comment

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

The string seems fragile to me? Isn't it better to use class name?

Copy link
Contributor

Choose a reason for hiding this comment

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

if they change the name of bean method it will break.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As mentioned #53 (comment) I originally tried with class but didn't work. There are two beans of the same class, so appears in such a situation the condition fails - so didn't register the channel interceptors.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to use a different approach - but had to remove Tracer.class from the ConditionalOnBean, as it only requires one class in the list to match.

Copy link
Contributor

Choose a reason for hiding this comment

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

WebSocketMessageBrokerConfigurationSupport config;

@Bean
public TracingChannelInterceptor tracingInboundChannelInterceptor() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Now it looks much better. This also worked https://paste.fedoraproject.org/paste/YcocqvZsm6TcFwlVBCoqzw/ (similar to sleuth...)

* A TextMap carrier for use with Tracer.extract() to extract tracing context from Spring messaging
* {@link MessageHeaders}.
*
* @see Tracer#extract(Format, Object)
Copy link
Contributor

Choose a reason for hiding this comment

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

I have commented before: this is an invalid javadoc you have to import format. The same is in inject adapter.

@pavolloffay
Copy link
Contributor

One thing I notice is that it creates a client span for each connected client. I don't have a reasonable knowledge in WS to judge whether it is good or bad.

However, from what know about WS is that all clients are connected to one channel and developer is responsible for a proper routing. So am not sure if we want to create a client span for each connected user.

cc @jpkrohling

screenshot of jaeger ui 4

* communications using an OpenTracing Tracer.
*
*/
public class TracingChannelInterceptor extends ChannelInterceptorAdapter implements ExecutorChannelInterceptor {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably set also a component tag.

@pavolloffay
Copy link
Contributor

anyways sleuth also creates a client span for each client.

screenshot of zipkin - traces

@objectiser
Copy link
Contributor Author

objectiser commented Sep 25, 2017

We could always provide a post processor, as in java-metrics, to have a skip pattern for the inbound/outbound connections. But may be create a separate issue for discussion?

@pavolloffay
Copy link
Contributor

But may be create a separate issue for discussion?

👍 as you want.

/**
* The span component tag value.
*/
private static final String SPRING_WEBSOCKET = "spring-websocket";
Copy link
Contributor

Choose a reason for hiding this comment

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

I think just websocket is better. Users would know framework by service name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@jpkrohling
Copy link
Contributor

However, from what know about WS is that all clients are connected to one channel and developer is responsible for a proper routing. So am not sure if we want to create a client span for each connected user.

I'm a bit lost, but assuming that you mean WebSockets in general (not Spring's, not this PR's), then that's not correct. Each client connection is a Session (channel as you called it). The server can certainly keep a list/map of sessions and propagate messages to all clients, but in the end, each client has its own session.

Copy link
Contributor

@pavolloffay pavolloffay left a comment

Choose a reason for hiding this comment

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

LGTM, there should be asserts on tags in tests.

@pavolloffay
Copy link
Contributor

I was using this https://spring.io/guides/gs/messaging-stomp-websocket/ example

@pavolloffay
Copy link
Contributor

One of the further improvements: #58 (just for linking purposes)

@pavolloffay pavolloffay merged commit 701c23a into opentracing-contrib:master Sep 26, 2017
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.

None yet

3 participants