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

[Feature request] Support for websocket (and hibernation API) #21

Open
SamyPesse opened this issue Jul 7, 2023 · 7 comments
Open

[Feature request] Support for websocket (and hibernation API) #21

SamyPesse opened this issue Jul 7, 2023 · 7 comments
Labels
enhancement New feature or request

Comments

@SamyPesse
Copy link

After investigating more #14 (comment), it looks like this module doesn't support yet Websockets and using the DO storage in a websocket handler throws the error:

Cannot read properties of undefined (reading 'sampling') 

Probably because it's not wrapped in the async context.

It'd be great if this module could support the Websocket API with event handlers but also the new Hibernation API.

@evanderkoogh
Copy link
Owner

Ah yes, of course. I haven’t used the new hibernation API yet, so completely forgot about it.

Will try to have a look over the weekend 😃

@evanderkoogh evanderkoogh added the enhancement New feature or request label Jul 8, 2023
@evanderkoogh
Copy link
Owner

There are currently no types for the Hibernation API yet. Tracking the ticket over there in here: cloudflare/workerd#846. We don't strictly need to have the Types available, but it would certainly be nice.

@evanderkoogh
Copy link
Owner

The types have been included in the latest release, so whenever I have some time I'll get this in.

@evanderkoogh
Copy link
Owner

So.. this turns out to be a very interesting problem that I haven't really figured out. Do we want to have all the message in one websocket connection in the same trace? Or have different traces?

And even if they are in separate traces, do we want to be able to sample on a websocket connection so that either an entire one is sampled or isn't sampled?

And if the answers to either of those questions is yes, how the hell do we make that happen when the Durable Object is unloaded from memory and rehydrated? Ideally without using the limited storage options per Websocket..

@SamyPesse
Copy link
Author

Do we want to have all the message in one websocket connection in the same trace? Or have different traces?

One that could work well for us is one trace per time the DO is up and running; and one sub-trace per message.

Something like:

  • DO is initialized => DO trace starts
  • Websocket connection opens => Sub-trace for the connection starts
  • Websocket message in this connection => Sub-trace in the connection
  • Websocket connection closes => Sub-trace for the connection is ended
  • DO is hibernated => DO trace ends (I guess this one is impossible to do since there is no way to know when the DO hibernates ?)

On our side, we don't care for now about looking at traces across isolation.

@benstechlab
Copy link

I just wanted to bump on this issue. I just learned about CloudFlare's hibernateable websockets API and have refactored my app to use the new API. It's excellent and certainly the way to go!

For me a span per websocket message is probably enough (proxying the DO's webSocketMessage() function?). For long lived websockets I personally don't see the value in having a huge span that could potentially be many days long (and I could always put some other meta data into the spans for a "session correlation id" or something that isn't an otel span).

My app is also small enough that I'm not worried about sampling at this time. But if I did need sampling, sampling per websocket message is probably fine (establish some stats for how long "message X" takes to process or how often "message Y" fails, etc).

But I suppose there may be cases where people want all message for a sampled websocket to be recorded for things like an A/B test of some software implementation where you want to compare to implementations. In that case could we have some control methods exposed inside the instrumented DO to get/set the sampling state/params to influence sampling behaviour? Then it would be up to the application to persist and rehydrate the otel sampling state?

I am already using the WebSocket.serializeAttachment() and WebSocket.deserializeAttachment() methods in my code to store application state about the connected websocket - but I could easily add a small flag "isSampling" or something.

@SamyPesse
Copy link
Author

@evanderkoogh, anything we can help with on this issue?

If you have hints on the direction you'd like to take with the implementations, I can look at opening a PR

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

No branches or pull requests

3 participants