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

Time Series Annotation Layers #3521

Merged
merged 6 commits into from
Sep 28, 2017

Conversation

graceguo-supercat
Copy link

@graceguo-supercat graceguo-supercat commented Sep 25, 2017

fixes #3502
vudfmdwhhs

@coveralls
Copy link

coveralls commented Sep 25, 2017

Coverage Status

Coverage increased (+0.2%) to 69.706% when pulling cc29e51 on graceguo-supercat:annotations into 255ea69 on apache:master.

Copy link
Member

@mistercrunch mistercrunch left a comment

Choose a reason for hiding this comment

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

A few minor things, looks great!

class SelectAsyncControl extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
Copy link
Member

Choose a reason for hiding this comment

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

Many of the other controls to not maintain internal state and rely solely on the value prop and onChange to act as a controlled component. There's nothing bad with maintaining the state here but it adds a bid of complexity that is not needed.

Copy link
Author

Choose a reason for hiding this comment

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

fixed.

.attr('height', 10)
.attr('patternTransform', 'rotate(45 50 50)')
.append('line')
.attr('stroke', '#00A699')
Copy link
Member

Choose a reason for hiding this comment

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

Looked like this color is @brand-primary, any way we can use a CSS class instead of hard-coding the color here?

.attr('fill', 'url(#diagonal)')
.attr('fill-opacity', 0.1)
.attr('stroke-width', 1)
.attr('stroke', '#00A699')
Copy link
Member

Choose a reason for hiding this comment

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

same here, let's not hard code the color

@@ -0,0 +1,22 @@
"""empty message
Copy link
Member

Choose a reason for hiding this comment

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

I'm surprised to see 2 different merge migrations. Legit or mistake?

@@ -25,7 +25,7 @@

from sqlalchemy import (
Column, Integer, String, ForeignKey, Text, Boolean,
DateTime, Date, Table,
DateTime, Date, Table, Index,
Copy link
Member

Choose a reason for hiding this comment

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

Index is unused, I think I left that dirt behind in my commit...

superset/viz.py Outdated
@@ -111,6 +112,7 @@ def get_extra_filters(self):

def query_obj(self):
"""Building a query object"""
print("running query_obj============================")
Copy link
Member

Choose a reason for hiding this comment

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

Let's remove this line

.attr('class', 'd3-tip')
.direction('n')
.offset([-5, 0])
.html(d => (d && d.layer ? d.layer : ''));
Copy link
Member

Choose a reason for hiding this comment

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

I think we should surface more here, the layer name, the short and the long description.

})
.attr('height', hh)
.attr('fill', 'url(#diagonal)')
.attr('fill-opacity', 0.1)
Copy link
Member

Choose a reason for hiding this comment

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

note: I think the annotations look good on the gif, we can talk to Eli & Chris to fine tune their look if needed.

Copy link
Member

Choose a reason for hiding this comment

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

class could be called stroke-primary

@coveralls
Copy link

coveralls commented Sep 26, 2017

Coverage Status

Coverage increased (+0.06%) to 69.615% when pulling 13ace05775b1313e150a49092a867fab06bd994b on graceguo-supercat:annotations into 3949d39 on apache:master.

1 similar comment
@coveralls
Copy link

Coverage Status

Coverage increased (+0.06%) to 69.615% when pulling 13ace05775b1313e150a49092a867fab06bd994b on graceguo-supercat:annotations into 3949d39 on apache:master.

@coveralls
Copy link

coveralls commented Sep 26, 2017

Coverage Status

Coverage increased (+0.06%) to 69.615% when pulling 13ace05775b1313e150a49092a867fab06bd994b on graceguo-supercat:annotations into 3949d39 on apache:master.

- add annotation input sanity check before add and before update.
- make SelectAsyncControl component statelesis, and generic
- add annotation description in d3 tool tip
- use less variable to replace hard-coded color
@coveralls
Copy link

coveralls commented Sep 26, 2017

Coverage Status

Coverage increased (+0.06%) to 69.609% when pulling 1313151 on graceguo-supercat:annotations into 3949d39 on apache:master.

@@ -57,6 +57,7 @@ def __init__(self, datasource, form_data):
'token', 'token_' + uuid.uuid4().hex[:8])
self.metrics = self.form_data.get('metrics') or []
self.groupby = self.form_data.get('groupby') or []
self.annotation_layers = []
Copy link
Contributor

@fabianmenges fabianmenges Sep 26, 2017

Choose a reason for hiding this comment

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

I don't think annotations should be part the viz object. For most viz types that I can think of annotations don't really make sense. If you make annotations accessible from a json endpoint they can be loaded client side. This would also make the responsiveness better, annotations could be loaded async independently of the data.

Copy link
Member

Choose a reason for hiding this comment

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

Here we decided to package the annotations from the backend along with the data payload. The visualizations' render method can then assume that all of the data + annotations + context is present when rendering. Note that the annotation query is fully indexed and should take milliseconds assuming a small-ish number of annotations for the time range.

I feel like if we wanted to go async on the annotations, we'd need to change the visualization's API to define 2 different methods and somehow guarantee to call the annotation one second. It makes things much more complicated on that side of things.

Copy link
Contributor

@fabianmenges fabianmenges Sep 26, 2017

Choose a reason for hiding this comment

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

34ec8b3#diff-a85def8afdc240ac598637a26a7cdbbc I can probably clean this up a bit more, but this makes all http requests in parallel.

from .base import SupersetModelView, DeleteMixin


class AnnotationModelView(SupersetModelView, DeleteMixin): # noqa
Copy link
Contributor

Choose a reason for hiding this comment

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

How are annotations written to that table? If you cannot write them from within superset, why are you not thinking of them as just another datasource?

Copy link
Member

@mistercrunch mistercrunch Sep 26, 2017

Choose a reason for hiding this comment

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

This feature ships with the FAB CRUD UI that allows users to manually input/manage layers. FAB also exposes a CRUD REST API to maintain those programmatically, though I'm thinking at Airbnb most likely people will write Airflow jobs talking to our MySQL instance to load annotations dynamically.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think that this table should be part of the Superset DB then. The way Superset is currently designed is that it is agnostic (as long as there is a Druid/SQL connector) to where the data is stored. We have a clean separation of meta data (slice definition, configuration, users, ...) and the data that superset is operating on.
This table inverses this fundamentally and now we have to store presentation data directly inside of the superset db. Currently no time series data is stored inside of the superset database. I'm also worried that this will cause scalability issues. Now my superset meta database is going to have very different performance requirements with regard to querying time series.

If this table was only used for manually created data from a user interface you could make the argument that we are talking about a very limited amount of data which originated in superset and therefore should be stored there. But this seems not to be the case.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah it's at the frontier of data/metadata, though to me annotations are closer to metadata.

Copy link
Member

Choose a reason for hiding this comment

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

Though I agree that it would be sweet to support external data for annotations (as in your PR), let's do both. I have some thoughts on that that I'll put on your PR. The TLDR is I think we should create a new time_annotations viz_type to enforce a certain set of guaranties, as opposed to a convention on top of the table viz_type.

'annotation',
sa.Column('created_on', sa.DateTime(), nullable=True),
sa.Column('changed_on', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
Copy link
Contributor

Choose a reason for hiding this comment

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

Bigint?

Copy link
Member

Choose a reason for hiding this comment

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

hoping we never go above 2,147,483,647 annotations, saving some bytes

Copy link
Contributor

Choose a reason for hiding this comment

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

If you have automated processes writing to this table (airflow) we should change this to BIGINT. The disk space you save is only relevant in cases when you have a lot of rows, which is also when you want to have BIGINTs as your IDs.

@fabianmenges
Copy link
Contributor

I just created a couple youtube videos of the functionality of my changeset, #3518
I'd be happy to incorporate your annotation table and the ability to create "rectangular" annotations and just add it as another type of annotation. Currently my change set incorporates "Events", "Formulas", "Time Series". I could create another type "Annotation" that would pull the annotations from the Annotation table in the Superset DB. I could also then provide a UI where you can add annotations inside of Superset for that Layer.

@mistercrunch
Copy link
Member

@fabianmenges going to comment on your PR to think holistically about annotations. We spoke about your approach internally and think it's very complementary and would love to integrate all this.

@mistercrunch
Copy link
Member

mistercrunch commented Sep 26, 2017

@fabianmenges we may need to talk to sync up about annotations, we all really like the work that you've done and do want to support the stuff you added:

  • slice-defined formulas
  • slice-defined vertical lines
  • data-based annotations, using a specific slice-types with the right constraints and guarantees, reusable across slices

Throw in:

On top of this PR, which I would describe as:

  • Superset-managed Annotation Layers, to be renamed "Time Annotation Layers" to clarify, these are highly re-usage across slices.

All this should be composable.

I'd like to break down 1-2-3 from 4 potentially, though if we can agree on the vision we could make your current PR evolve into 1-2-4 combo. That's a pretty massive feature set though.

@fabianmenges
Copy link
Contributor

Lets move this to the dev mailing list...

@fabianmenges
Copy link
Contributor

Go ahead and merge this in, I can integrate the UIs in my merge request. Lets have the design discussion in the mailing list.

@mistercrunch mistercrunch merged commit d1a7a7b into apache:master Sep 28, 2017
@mistercrunch mistercrunch deleted the annotations branch September 28, 2017 03:40
timifasubaa pushed a commit to timifasubaa/incubator-superset that referenced this pull request Oct 3, 2017
* Adding annotations to backend

* Auto fetching Annotations on the backend

* Closing the loop

* Adding missing files

* annotation layers UI

for apache#3502

* a few fixes per code review.

- add annotation input sanity check before add and before update.
- make SelectAsyncControl component statelesis, and generic
- add annotation description in d3 tool tip
- use less variable to replace hard-coded color
@mistercrunch mistercrunch added 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 0.20.1 labels Feb 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 0.20.1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Time Series Annotation Layer
4 participants