DataDog / browser-sdk

Datadog Browser SDK
Apache License 2.0
291 stars 130 forks source link

💡 Connect RUM and Traces for Websocket transactions #2019

Open jordanh opened 1 year ago

jordanh commented 1 year ago

Our SPA application transacts as much as it can via graphql over Websockets. Currently, the JS browers-sdk only sends the trace id, parent id, and trace flags as headers via wrapping fetch and XmlHttpRequest.

We have a bit of an issue in that we don't call fetch to set up the socket, but try to upgrade the initial connection (before datadog wraps the method) and so the headers are not available to us.

The flow we have in mind is:

Perhaps one day we'd also like #1638 to group these actions logically, but it isn't necessary today

Is it possible for us to do this with the SDK today (that is to say, did I miss something reading the docs and code), or would some changes be necessary to support stateful, Websocket-based SPAs?

bcaudan commented 1 year ago

Hi @jordanh,

When attempting to connect at https://action.parabol.co/, I'm seeing some graphql requests that don't have trace headers but those don't use the websocket API.

Does your issue concern this kind of request or do you have usage of the websocket API somewhere in your application?

jordanh commented 1 year ago

Oh man, @bcaudan, thank you for looking into this.

If you create an account, land on any route and hit refresh the behavior you should see is:

1) A service worker loads the route and other assets via a service worker 2) The browser upgrades the connection to a websocket connection by setting the browser location to a new URL (wss://...) (incidentally, our app is open-source, here's where that happens)

Based on the way we're doing things, we don't really have a spare, vanilla fetch() request we can use to inject the datadog headers and send them along to our server. We could refactor or create a special request just for datadog...but in this case the SDK feels like it's trying to do too much for us. What we'd really like is a way to just ask the SDK for the appropriate headers and shove them as a message in our regular WebSocket stream.

Would something like that be possible?

bcaudan commented 1 year ago

What we'd really like is a way to just ask the SDK for the appropriate headers and shove them as a message in our regular WebSocket stream.

Unfortunatelly, those headers need to also be sent with the corresponding RUM events in order to connect RUM and traces. For now, the browser-sdk doesn't instrument WebSocket but it is something that we would want to support in the fullness of time.

jordanh commented 1 year ago

Thanks you for the answer!

Out of curiosity, what would be necessary here? Something like:

Would any additional changes to the SDK be necessary?

bcaudan commented 1 year ago

For minimal changes, probably providing APIs to start/stop a resource event which should also return tracing infos in order to pass them in web socket messages could work. However, we may want to address web socket messages a bit differently than classical RUM resource event in order to have more web socket specific data. So, definitely more thoughts to have on our side with indeed some changes to the SDK.

jordanh commented 1 year ago

What if we branched and did a bit of testing in this direction? We could share what we learn in order to inform better SDK changes in the future.

I could ask you a few questions, and we could be off to the races...

Elia85 commented 1 year ago

Hi everyone! So did someone came out with a solution about instrumenting websocket calls too? Thank you

VivaLaPanda commented 1 year ago

I'm stuck on this as well. Just some way to manually construct a new trace in web and handle the context sharing myself would be great.

paco-sparta commented 1 month ago

:bump: