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

Live: broadcast events when dashboard is saved #27583

Merged
merged 39 commits into from
Oct 1, 2020
Merged

Conversation

ryantxu
Copy link
Member

@ryantxu ryantxu commented Sep 14, 2020

When the "live" feature flag is enabled and a dashboard is saved, an event is broadcast to everyone looking at that dashboard.

If the viewer is in edit mode, or has local edits, we show a popup asking what to do. Otherwise the dashboard is updated automatically.

dash

Copy link
Member

@torkelo torkelo left a comment

Choose a reason for hiding this comment

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

Left some comments, but before I read your description in detail. so missed your own comment on the router thing :)

this subscribes to a channel for each dashboard -- this would let use out-of-the-box centrifuge presence features for dashboards. Alternatively we could have a single channel and manage the notifications internally (not too hard and may be better)

Any pros / cons? I assume a centrifuge channel is just an internal thing for routing events? (so not a new websocket connection). And don't we have to use that in order route events efficiently? (So we do not need implement our own event routing so only browsers who are interested in specific events get's them). For example we only want browsers who have a specific dashboard open to get events related to it, not get events for all open dashboards. So given that I think we need to use a channel per dashboard right?

public/app/features/live/pageTracker.ts Outdated Show resolved Hide resolved
packages/grafana-runtime/src/services/live.ts Outdated Show resolved Hide resolved
pkg/services/live/events.go Outdated Show resolved Hide resolved
@bergquist
Copy link
Contributor

🕺

@ryantxu
Copy link
Member Author

ryantxu commented Sep 15, 2020

Any pros / cons?

Yes -- i went in circles on this and yes one channel for each dashboard is the right approach.

@torkelo -- I made a bunch of improvements since you looked, I would love feedback :)

@ryantxu ryantxu added this to the 7.3 milestone Sep 15, 2020
@bergquist
Copy link
Contributor

I certainly find this an interesting feature. Hard to say exactly what the default behavior should be for the viewer who gets the new version pushed.

@torkelo
Copy link
Member

torkelo commented Sep 17, 2020

Sorry for no follow-up review, 7.2 release and fixes have been pressing. And after that, the annotation/exemplar architecture is higher prio

@ryantxu ryantxu mentioned this pull request Sep 17, 2020
2 tasks
type dashboardEvent struct {
UID string `json:"uid"`
Action string `json:"action"` // saved, editing
UserID int64 `json:"userId,omitempty"`
Copy link
Member

Choose a reason for hiding this comment

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

Working with event systems before, it's always nice if the events are information-rich and more usable standalone.

It would mean including more dashboard & user info here like dashboard name, (maybe a user object, that includes id, login, email, avatarUrl) makes consuming and using these events much easier without requiring further API calls.

Copy link
Member Author

Choose a reason for hiding this comment

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

We could add the whole json model... But I think we would still need to do a full refresh in the current system regardless. If only dashboard were an observable 🙂

Copy link
Member

Choose a reason for hiding this comment

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

I was more thinking of other uses for this event (like an admin viewing a list of activity), and for the modal, we might want to show the user name & profile image of the user who updated the same dashboard you have.

So ash much meta info about the entities in the event is usually good. Could also be used by a search or cache subsystem for example to update index state and for that we do not want to issue further db/api calls.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm happy to add more info now -- but since this is an internal event, I think we should wait and add more info when we have a real use for it.

Copy link
Member Author

Choose a reason for hiding this comment

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

I was more thinking of other uses for this event

That is info that should be attached on the 'presense' side -- that still needs to be explored some more, but I fear this PR is getting too big as is :)

Comment on lines +84 to +86
if (event.message.sessionId === sessionId) {
return; // skip internal messages
}
Copy link
Member

Choose a reason for hiding this comment

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

is there away to filter this out in liveSrv?

Copy link
Member

@torkelo torkelo left a comment

Choose a reason for hiding this comment

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

Nice! left a few nits. But yea the typing looks a bit messy.

const dashboardConfig: LiveChannelConfig = {
path: '${uid}',
description: 'Dashboard change events',
variables: [{ value: 'uid', label: '${uid}', description: 'unique id for a dashboard' }],
Copy link
Member

Choose a reason for hiding this comment

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

how are dashboardConfig.variables used?

Copy link
Member Author

Choose a reason for hiding this comment

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

idea here is that this is mostly documentation for what variables exist and what they need to be. Looking now, we should likely remove this until it has something concrete, but I want to be careful that the path based routing has some way to be more constrained


return (
<Modal
isOpen={!!!dismiss}
Copy link
Member

Choose a reason for hiding this comment

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

is this not the same as !dismiss ?

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed -- looks like ! and !!! are identical for a boolean value, but different if the value can be undefined of falsey

Copy link
Contributor

Choose a reason for hiding this comment

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

You could use !Boolean(dismiss)

Comment on lines 59 to 68
const radioClass = css`
cursor: pointer;
width: 100%;
padding: 20px;
background: ${config.theme.colors.dropdownBg};

&:hover {
background: ${config.theme.colors.formCheckboxBgCheckedHover};
}
`;
Copy link
Member

Choose a reason for hiding this comment

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

this feels like a new design system component. Not sure what to do for this PR if there is no current component that fits.

For a new component & we should use useTheme & useStyles

ryantxu and others added 2 commits September 30, 2020 10:47
@@ -104,3 +96,17 @@ export class DashboardChangedModal extends PureComponent<Props, State> {
);
}
}

const getStyles = (theme: GrafanaTheme) => {
Copy link
Member

Choose a reason for hiding this comment

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

use stylesFactory here so we only build the styles once

pkg/services/live/features/testdata.go Outdated Show resolved Hide resolved
g.running = true

// Run in the background
go g.runRandomCSV()
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this threadsafe? For example if nothing is subscribed to yet, but then two or more clients subscribe at around the same time is there any guarantee that multiple threads running runRandomCSV won't be started?

func (b *GrafanaLive) Publish(channel string, data []byte) bool {
_, err := b.node.Publish(channel, data)
// GetChannelHandler gives threadsafe access to the channel
func (g *GrafanaLive) GetChannelHandler(channel string) (models.ChannelHandler, error) {
Copy link
Member Author

Choose a reason for hiding this comment

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

@marefr -- can you audit this function? It is called frequently and potentially from multiple threads.

@kaydelaney
Copy link
Contributor

kaydelaney commented Oct 1, 2020

Looking good! Just left some small comments.
One last thing: Is "Presense" intentional or is that a typo that should be changed to "Presence"

ryantxu and others added 5 commits October 1, 2020 08:19
Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com>
Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com>
Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com>
@ryantxu
Copy link
Member Author

ryantxu commented Oct 1, 2020

Is "Presense" intentional or is that a typo that should be changed to "Presence"

dooh -- just dyslexia and poor spelling. Thanks!

Copy link
Member

@torkelo torkelo left a comment

Choose a reason for hiding this comment

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

Yay, so awesome to get to nice things like this 🚀
tenor

@ryantxu ryantxu merged commit 8a5fc00 into master Oct 1, 2020
@ryantxu ryantxu deleted the live-dashboard-update branch October 1, 2020 17:46
ryantxu added a commit that referenced this pull request Nov 18, 2020
Co-authored-by: kay delaney <45561153+kaydelaney@users.noreply.github.com>
Co-authored-by: Torkel Ödegaard <torkel@grafana.org>
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

5 participants