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

[Ingest UI] WaffleMap #21871

Conversation

simianhacker
Copy link
Member

@simianhacker simianhacker commented Aug 10, 2018

After pulling in upstream I realized that this PR was also damaged in yesterday's VS Code/Git/Merge snafu. The original PR was located at #21744


This PR adds the basic functionality for the Waffle Map to the Infra UI. Currently there is nothing configurable via the UI. The options are hard coded in the withMap container query, this will change as the UI features are developed to support it.

image

How to test in browser:

  1. Point Kibana at the demo-stack Kibana instance via config/kibana.dev.yml (reach out to @simianhacker for actual configuration)
  2. Click on infra icon. You should see something very close to above.

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Copy link
Member

@weltenwort weltenwort left a comment

Choose a reason for hiding this comment

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

Thanks for moving over the files. I've commented on a few problems with the usage of the generated query types and the schema below.

InfraSource,
InfraTimerangeInput,
} from '../../../common/graphql/types';
import { InfraWaffleMapGroup } from '../../lib/lib';
import { nodesToWaffleMap } from './nodes_to_wafflemap';
import { query } from './query';
Copy link
Member

Choose a reason for hiding this comment

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

The query imported here is named Query. That's a very conflict-prone name, especially since it will end up in the generated types. How about we call it something like

export const mapQuery = gql`
  query MapQuery(...) {
    ...
  }
`;

Then the generated query namespace would be MapQuery in common/graphql/types.ts (with the query result type as MapQuery.Query and the variables as MapQuery.Variables, see below).

props: ({ data }) => ({ map: (data && data.source && data.source.map) || {} }),
props: ({ data }) => {
const nodes = get(data, 'source.map.nodes', []);
return { map: nodesToWaffleMap(nodes) };
Copy link
Member

Choose a reason for hiding this comment

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

According to the schema source.map.nodes can be null, which means the nodesToWaffleMap function fails at runtime when the query does not yield any nodes:

image

The compiler would have warned about this if instead of the hand-written Response, the generated Query.Query (or MapQuery.Query after the proposed renaming above) from common/graphql/types.ts had been used.

How about fixing that by

  1. use the generated query response type and
  2. change the schema and resolver of InfraResponse to always return an array for nodes (empty when no nodes are found)?

The same goes for the Variables. Let's use the generated Query.Variables (or MapQuery.Variables).

@simianhacker
Copy link
Member Author

@weltenwort I implemented the changes you requested. The if statements in the withMap HOC are a little meh but technically it's sound. I also had to add an ID to the nodes being returned because GraphQL seem to use that to do deduplication or something beyond my understanding the resulted all the nodes ending up in one path.

@elasticmachine
Copy link
Contributor

💔 Build Failed

Copy link
Member

@weltenwort weltenwort left a comment

Choose a reason for hiding this comment

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

When we supply an id, apollo-graphql uses it to identify the entity in its cache, so later responses containing that id will overwrite any previous one with the same key. Not sure how it will merge new data coming in when we implement the polling. It's one of the reasons why I want to put the storage logic into the redux store - it's easier to control the merging. I think for our purposes it might be most beneficial to not have ids in the hierarchy beneath maps(), but to associate a fixed key with the whole query using the @connection directive. 🤔

@@ -38,10 +33,10 @@ interface Variables {

export const withMap = graphql<
{}, // OptionProps, this will end up being the options that contain index pattern, filters, etc
Response,
MapQuery.Query,
Variables,
Copy link
Member

Choose a reason for hiding this comment

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

There is also a generated variable type in MapQuery.Variables.

const { nodes } = data.source.map;
if (!nodes) {
return emptyResponse;
}
Copy link
Member

Choose a reason for hiding this comment

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

I usually express that as

  props: ({ data }) => ({
    map:
      data && data.source && data.source.map && data.source.map.nodes
        ? nodesToWaffleMap(data.source.map.nodes)
        : [],
  }),

I find that more readable, but that's obviously a matter of taste and habit. What do you think?

Copy link
Member

@weltenwort weltenwort left a comment

Choose a reason for hiding this comment

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

When we supply an id, apollo-graphql uses it to identify the entity in its cache, so later responses containing that id will overwrite any previous one with the same key. Not sure how it will merge new data coming in when we implement the polling. I would expect to land in a weird mix of states between old and new data. It's one of the reasons why I want to put the storage logic into the redux store - it's easier to control the merging.

I think for our purposes it might be most beneficial to not have ids in the hierarchy beneath maps(), but to associate a fixed key with the whole map() query using the @connection directive. 🤔

edit: no idea why this was submitted twice, sorry

@elasticmachine
Copy link
Contributor

💔 Build Failed

Copy link
Member

@weltenwort weltenwort left a comment

Choose a reason for hiding this comment

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

Seems to work with a no-cache fetchPolicy using the newer apollo-client version 👍 And with the removal of the ids the path argument is a lot lighter too.

I think this is mostly ready to be merged to bring us forward in the feature branch. I just left a small comment about the bucket name handling below.

const secondGroup: InfraPathInput = groupBy[1];
const paths: InfraNode[] = node[firstGroup!.id].buckets.reduce(
const paths: InfraNode[] = node.path_0.buckets.reduce(
(acc: InfraNode[], bucket: InfraBucket, index: number): InfraNode[] => {
const nodeItem = createNodeItem(options, node, bucket);
const key: string = String(bucket.key || index);
if (secondGroup) {
Copy link
Member

Choose a reason for hiding this comment

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

Should this be node.path_1 for consistency?

@weltenwort
Copy link
Member

jenkins did not trigger a test run 🤔 jenkins, test this, please

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

Copy link
Contributor

@skh skh left a comment

Choose a reason for hiding this comment

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

Could we use a less generic name than Container for the outer styled component, and could we use a consistent schema?

Right now, some of them have a name indicating what they are styling, e.g. GroupOfNodesContainer, but a generic StyledContainer (or whatever) that's the same in each component would probably work as well.

);
};

export const Container = styled.div`
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we use a less generic name for this?

Copy link
Member Author

Choose a reason for hiding this comment

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

What name would have made more sense here?

Keep in mind I think that name is only visible in this file. It doesn't leak outside the file anywhere else, those styled components are isolated to the file. If you look at the page with the React dev tool it shows up under a different name. It was a mistake to export those containers, force of habit :D

Copy link
Contributor

Choose a reason for hiding this comment

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

We could follow the naming convention you used in the other components, so it would be a GroupOfGroupsContainer in this case. (See also the review comment above.)

};
}

const Container = styled.div`
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we use a less generic name for this?

Copy link
Member Author

Choose a reason for hiding this comment

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

See above

};
}

export const Container = styled.div`
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we use a less generic name for this?

Copy link
Member Author

Choose a reason for hiding this comment

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

See above

import { InfraWaffleData, InfraWaffleMapGroup, InfraWaffleOptions } from '../../lib/lib';
import { applyWaffleMapLayout } from './lib/apply_wafflemap_layout';

interface WafleMapProps {
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: WaffleMapProps

Copy link
Member Author

@simianhacker simianhacker Aug 14, 2018

Choose a reason for hiding this comment

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

Good catch

@simianhacker
Copy link
Member Author

@skh I updated the names to be more specific. I also removed all the exports since I never intended those to be used outside the context of that component.

@weltenwort We should be ready

@weltenwort
Copy link
Member

jenkins, test this

Copy link
Member

@weltenwort weltenwort left a comment

Choose a reason for hiding this comment

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

Jenkins seems unwilling to run the tests at the moment. That aside I'd say merging this would bring us forward a lot 👍 Great job!

@weltenwort
Copy link
Member

ah, it's running now 🎉

@elasticmachine
Copy link
Contributor

💔 Build Failed

@weltenwort
Copy link
Member

looks like unrelated test failures related to the region map

@simianhacker
Copy link
Member Author

Merging... since we are just merging into our own feature branch, if it something we broke we can fix it later. Moving on.

@simianhacker simianhacker merged commit 3bf9b5d into elastic:feature-infra-ui Aug 15, 2018
@weltenwort
Copy link
Member

🎉

@simianhacker simianhacker deleted the feature-infra-ui-wafflemap-2 branch April 17, 2024 14:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Metrics UI Metrics UI feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants