-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
sse: support Server Sent Event #3639
Conversation
Bringing @szkiba to this discussion, too, as I know the dashboard feature is already built on top of SSE, and some code exists for supporting it there, too 🙇🏻 |
Could you please point me to this code ? I see nothing related to an sse k6 js module there. And #746 is opened since almost 6 years. Meanwhile the PR is ready for review, it would be great if you can enable CI workflow to confirm all is OK. Thanks 👍 |
Hey @phymbert 👋🏻 To clarify, I was bringing @szkiba to the discussion as he might have good insights into the topic, as he's built a whole extension that relies on SSE to provide the dashboard feature. Not to question neither the rationale nor the quality of this PR 🙇🏻 The dashboard collects and aggregates metrics data from k6, and communicates them to the frontend part using SSE, I think the relevant files to look at for context are I've approved the CI to run 👍🏻 |
Thanks @oleiade for the CI run and clarification 🙇🏻. I understand failing checks are not related to these changes ? Please tell me if I have to adapt something. |
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.
As a rule, similar modules are first created as xk6 extensions. This way, anyone can use it and receive feedback. After that, if the topic is popular enough, the extension will become an experimental module. I would recommend this path here as well.
I would also consider using an SSE client library. There must be a compelling reason for the protocol implementation if there is a usable library (if it does not exist, then it should be justified why none of the existing libraries are suitable).
Rules like this are also a blocker for the adoption of the tool. That's probably why the issue has been created for 6 years. Users just consider SSE as not supported and drop k6 as an available solution. I do not see any understandable reason not to resolve the issue, adding a few lines of code, and letting people use SSE with k6. If you have relevant feedback on the code, I will integrate them, or else I keep the PR opened if people need it in the future. |
|
||
client.handleEvent("event", rt.ToValue(event)) | ||
|
||
case readErr := <-readErrChan: |
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.
Errors should also be measured with metrics, as in the http module. Instead of handling errors at the JavaScript level, it is much more convenient to set a threshold for the error metric...
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.
I kind of disagree on this - we do more or less the same for websockets. Especially as a lot of the cases it is just an error to close.
This still allows users to create custom metrics for errors, but doesn't force them.
We do have error metrics when teh connection couldn't be started though.
Also not SSE expert - so maybe not as similar 🤷
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.
Yes I follow the approach from the websockets module as it was proposed in:
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.
@mstoykov the format is well described here:
https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#event_stream_format
Pretty simple
The module will provide an `open` which will allow the user to pass a setup function to configure an `event` callback as it is done in the `ws` module with `message`. | ||
|
||
### Limitation | ||
The module will not support async io and the javascript main loop will be blocked during the http request duration. |
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.
Async support is becoming more and more important, so integrating a new module without async support is questionable. This is just my personal opinion, @mstoykov is more competent in this...
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.
Given that SSE is by default an asynchronous communication I find that this must be asynchronous as well.
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.
What do you mean by asynchronous ? it's one way server to client data flow on top of HTTP 1.1 w/ single connection. The event loop is blocked while waiting for next event, but on each new event the client callback is triggered.
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.
Take a look at xk6-mock extension code base, especially in the szkiba/muxpress library. You will find example there how to support callback running on eventloop.
var url = "https://echo.websocket.org/.sse"; | ||
var params = {"tags": {"my_tag": "hello"}}; | ||
|
||
var response = sse.open(url, params, function (client) { |
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.
An SSE connection is usually long-lived. We do not test normal operation by opening a new connection in each iteration.
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.
Not at all, see: https://platform.openai.com/docs/api-reference/streaming
I mainly use K6 at the moment to test LLM inference server:
I rather see such rules as helping to keep the code base stable.
go sdk is great i like it too. At the same time, I don't tend to reimplement every protocol, even the simplest ones, if there is a usable implementation.
The opinion of the maintainers of the k6 code base really matters here, that's why there is a code review.
I wrote a few comments, I don't know if they are relevant enough: metrics should be made about errors and not simply delegated to the JavaScript level, SSE comments should also be made available and not simply ignored, and async support should be considered. |
@szkiba Thanks for your review, I will integrate the proposed changes.
Do you have some ? I see one here: https://github.com/r3labs/sse/blob/c6d5381ee3ca63828b321c16baa008fd6c0b4564/client.go#L322-L335 IMHO we do not need to depend on a whole library for a small function, although the proposed version here must be improved (trailing new lines, empty data). @mstoykov regarding async io, could you please assist me with a code to look at it ? |
Hello, everyone 👋🏻 Firstly, I'd like to express our gratitude for the time and effort you've dedicated to implementing a missing and desirable feature for k6 with your proposal. We value contributions as such! However, after discussions among the k6 maintainers' team, we've decided not to merge this PR in the core of k6 for several reasons outlined below, which aim to clarify our reasoning and rationale behind that decision. 1. HTTP module is implicitly frozenWe're currently focusing on developing a new 2. Extensions-firstAs highlighted by @szkiba, this module is a perfect candidate for an xk6 extension: it allows for innovation, experimentation, and adding valuable APIs and features to k6 without impacting the stability of the core of k6, and relying on k6 code and constructs that are not accessible publicly (as far as I can tell). It probably needs to be communicated better at the moment, but as @szkiba outlined, our position is that anything that can start or remain an extension should probably be. We likely want to support SSE indeed, but for this reason, as well as those depicted in 3. It's not just a few lines of codeFinally, the conversation around this PR has raised important points about the perceived simplicity of integrating new code versus the long-term commitments it entails.
And later:
And the latter is a good illustration of the reason for the former. It highlights the perceived simplicity of integrating new code versus the long-term commitments it entails. While it may appear as a trivial change to do, and for us to "just" merge these 1.5k lines of code, doing so would delegate the support and maintenance of these lines of code to us. We understand that this decision might be disappointing, but it's made with the best interest of the k6 open-source project and users in mind. k6 is a widely popular and adopted open-source project. Our goal and responsibility as maintainers is to ensure our software is easily maintainable and provides the best user experience, quality, and performance. Next stepsRegarding the next steps, I sincerely think this is valuable work. I recommend making an extension out of it so that users who wish to use SSE can do so in the meantime (as we make the HTTP module ready to receive further updates). So we can learn more about its design, implementation, and performance aspects. If extensions are not an option, another option would be to start a fork of k6 in the meantime. We make releases roughly every three months, rarely break APIs, and it would be a low-effort task. As I mentioned earlier, I'd be eager to support you if you were to start an extension and pave the way for improvements to it if that's something you'd find useful and valuable. |
Thanks for the clear explanation @oleiade , I understand all the point you raised. I suggest the following approach - please tell me if I miss something:
Highly appreciated your kind feedback here 🙇🏻 |
Thanks for the change, but I do agree with @szkiba and @oleiade on this being an extension. I will try to give some code feedback either way. On top of the points by @oleiade, I will try to give more explanation on the topic of extensions and experimental modules.
|
The actual idea is that you will create the repo and continue to maintain and own it. Again big part of the extensions vs in core is about who owns and maintains the code. If it is a grafana repository we will now need to give you permission to commit and/or even worse review your commit and merge it without giving you any rights. As pointed out - we are very unlikely to put this in core in the future. Any SSE solution will likely need to be based on http v2 api to be considered. And unfortunately that is blocked on ReadableStreams API.
This arguably is a lot to explain, but a good example of something similar is gRPC stream implementation. And in general the documentation on Also general knowledge about extensions creating can be found in the docs. |
This is not what I understood from @oleiade, having an extension on my own will ridicously reduced its visibility. And again, users will just go to another solution like Gatling which supports SSE very well out of the box.
Is it a problem to open a repo to other open-source contributor outside of GrafanaLabs ? is there any technical blocking point ? What are the difference with other extension like https://github.com/grafana/xk6-websockets ? You can as all open source project later on give Thanks for the doc, I will read it out. |
Simplify the event loop parsing, add spec link. Trim trailing spaces
Hi @phymbert 👋🏻 Thank you for your patience. We've taken some further time to discuss and evaluate your proposal internally. Unfortunately, we're unable to offer hosting the extension as part of the Grafana GitHub organization. Therefore, our suggestion remains unchanged, and we recommend you create a dedicated xk6 extension repository. Regarding visibility, if that is something you'd be able, allowed, and willing to do, we often feature user and community stories on the Grafana Labs blog. We'd be interested in exploring the possibility of collaborating on a blog post to highlight your work with k6 and how the development of this extension served your requirements. Would that be something of interest to you? 🙇🏻 |
What?
Server-Sent event http client support as an experimental module.
Why?
Server sent events are more and more used nowadays and I would love k6 to support it.
Checklist
make lint
) and all checks pass.make tests
) and all tests pass.Related PR(s)/Issue(s)
Close #746