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

Fetch ddg action and reducer #398

Merged

Conversation

everett980
Copy link
Collaborator

Which problem is this PR solving?

  • Implement DDG actions & reducers

Short description of the changes

  • Adds entry to actions/jaeger-api to fetch ddg data (endpoint subject to change, of course)
  • Adds actions/deep-dependency-graph for adding and clearing styles
  • Adds reducer/deep-dependency-graph for processing ddg request, and updating styles

Updated destination, previous PR

everett980 added 21 commits June 6, 2019 17:17
Signed-off-by: Everett Ross <[email protected]>
Signed-off-by: Everett Ross <[email protected]>
Signed-off-by: Everett Ross <[email protected]>
Signed-off-by: Everett Ross <[email protected]>
@codecov
Copy link

codecov bot commented Jun 24, 2019

Codecov Report

Merging #398 into master will increase coverage by 0.51%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #398      +/-   ##
==========================================
+ Coverage   89.26%   89.77%   +0.51%     
==========================================
  Files         164      170       +6     
  Lines        3734     3842     +108     
  Branches      846      869      +23     
==========================================
+ Hits         3333     3449     +116     
+ Misses        365      357       -8     
  Partials       36       36
Impacted Files Coverage Δ
packages/jaeger-ui/src/utils/tracking/fixtures.js 100% <ø> (ø) ⬆️
packages/jaeger-ui/src/components/App/index.js 100% <ø> (ø) ⬆️
packages/jaeger-ui/src/api/jaeger.js 100% <100%> (+5%) ⬆️
...er-ui/src/components/DeepDependencyGraph/Graph.tsx 100% <100%> (ø)
...es/jaeger-ui/src/actions/deep-dependency-graph.tsx 100% <100%> (ø)
packages/jaeger-ui/src/model/ddg/Graph.tsx 100% <100%> (ø) ⬆️
packages/jaeger-ui/src/model/ddg/types.tsx 100% <100%> (ø)
...eger-ui/src/components/DeepDependencyGraph/url.tsx 100% <100%> (ø)
...er-ui/src/components/DeepDependencyGraph/index.tsx 100% <100%> (ø)
packages/jaeger-ui/src/utils/guardReducer.tsx 100% <100%> (+25%) ⬆️
... and 10 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d507832...ef15710. Read the comment docs.

Copy link
Member

@tiffon tiffon left a comment

Choose a reason for hiding this comment

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

Quite a few comments, but this looks great. Great tests, too.

LMK if any of these comments look awry.

query: TDdgRequiredUrlState;
};

export type TDdgAddStylePayload = TDdgRequiredUrlState & { visibilityIndices: number[]; style: number };
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 change the nomenclature around these styling related actions and state to refer to view modifiers. Also, why not use the EViewModifier enum?

E.g.

export type TDdgAddViewModifierPayload = TDdgRequiredUrlState & { visibilityIndices: number[]; viewModifier: EViewModifier };

Also, I think this should take in the key instead of the visibilityIndices?

Same comment for the following payload type.

Copy link
Member

Choose a reason for hiding this comment

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

Or maybe it should take in key or visibility indices? For find, it makes sense to use visibility indices. For mouse-over, where it's coming from the graph node, key is more natural.

export type TDdgAddViewModifierPayload = TDdgRequiredUrlState &
  ({ visibilityIndices: number[] } | { key: string }) & {
    viewModifier: EViewModifier
  };

Copy link
Member

Choose a reason for hiding this comment

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

Same for the following payload.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The reason to prefer visIndices is that if we want to modify the view of edges (such as all edges on all paths that go through a specific vertex), it will be easiest to do so through knowing with pathElems have had view modifications. Even if both the to and the from of an edge are styled, that doesn't mean the edge should be styled.

Copy link
Member

Choose a reason for hiding this comment

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

I agree that edge {from: a, to: b} should not necessarily be highlighted even if both a and b are highlighted.

OTOH, if I mouseover a node, the node should trigger an action to have a view modifier added to it. But, the node only knows the vertexKey:

type TProps = {
  vertexKey: string;
  service: string;
  operation: string | null;
  focalNodeUrl: string | null;
  isFocalNode: boolean;
  viewModifiers: number;
  setViewModifier: (vertexKey: string, viewModifier: EViewModifier, isEnabled: boolean) => void;
};

So, either the reducer or some parent component needs to translate from vertexKey to visIndices. I would argue it's fine for this to happen in the reducer.

This brings up another point, though, we currently do not have a way to identify edges. visIndices suffers from your same point: edge {from: a, to: b} should not necessarily be highlighted even if both a and b are highlighted.

packages/jaeger-ui/src/actions/deep-dependency-graph.tsx Outdated Show resolved Hide resolved
packages/jaeger-ui/src/actions/deep-dependency-graph.tsx Outdated Show resolved Hide resolved
mock.expects('fetchTrace').withExactArgs(id);
jaegerApiActions.fetchTrace(id);
expect(() => mock.verify()).not.toThrow();
});
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 these can be driven by an array of params?

const tests = [
  {
    msg: '@JAEGER_API/SEARCH_TRACES should fetch the trace by id',
    fn: 'searchTraces',
    arg: query,  // or null
  },
  // etc ... 
];
tests.forEach(test => {
  const { msg, fn, args } = test;
  it(msg, () => {
    mock.expects(fn).withExactArgs(arg);
    jaegerApiActions[fn](arg);
    expect(() => mock.verify()).not.toThrow();
  });
});

Seems like the same with the promise tests.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

that's true for most, but not @JAEGER_API/FETCH_MULTIPLE_TRACES which calls an action with one name and an API fn with another. I know that's not hard to handle (optional extra key on tests), but perhaps best to leave jaeger-api.test and api/jaeger.test clean up for its own targeted PR?

Copy link
Member

Choose a reason for hiding this comment

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

The reason I mentioned it is because you re-wrote the tests in this PR.

packages/jaeger-ui/src/api/jaeger.test.js Show resolved Hide resolved
};
}

export function clearStyleState(state: TDdgState, { payload }: { payload: TDdgClearStylePayload }) {
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 this action is too overloaded:

  • remove one view modifier for a path element
  • clear all view modifiers for a path element
  • clear all view modifiers for all path elements

The downside of this is you pretty much need to read the implementation of the reducer to know the action has these capabilities.

Currently, we don't need the clear all for a path element or clear all for all path elements. And, one I have about the "added powers" of this action / reducer is one component is it becomes more likely for one component to clobber the view modifiers of another component.

I suggest pairing this down to the first scenario and adding other actions and reducers if we need to expand the capabilities.

Copy link
Member

@tiffon tiffon Jun 26, 2019

Choose a reason for hiding this comment

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

As an aside, it might be handy to use a util class for dealing with view modifers:

class ViewModifiers extends Map<number, number> {
  clone() {
    return new ViewModifiers(this);
  }

  rmModifier(modifier: EViewModifier | null, index: number) {
    if (modifier == null) {
      this.delete(index);
      return this;
    }
    const value = (this.get(index) || 0) & ~modifier;
    if (value === EViewModifier.None) {
      this.delete(index);
    } else {
      this.set(index, value);
    }
    return this;
  }

  addModifier(modifier: EViewModifier, index: number) {
    const value = (this.get(index) || 0) | modifier;
    this.set(index, value);
    return this;
  }
}

Copy link
Collaborator Author

@everett980 everett980 Jun 26, 2019

Choose a reason for hiding this comment

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

Things like emphasizing all paths through a vertex will mean that many pathElems need to be added/removed at once. It may be easier to clear emphasized from all elems rather than calculate which need to be unemphasized
Clearing all view modifications for one or more pathElems could be part of a vertice's componentWillUnmount clean up.

return state;
}
const styleStates = new Map(stateEntry.styleStates);
(visibilityIndices || Array.from(styleStates.keys())).forEach(idx => {
Copy link
Member

Choose a reason for hiding this comment

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

Looks like this should use forEach on visibilityIndices not styleStates.keys()?

Copy link
Member

Choose a reason for hiding this comment

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

My first take on this was to think this is a bug. Something like the following would be more clear:

const styleStates = visibilityIndices ? new Map(stateEntry.styleStates) : new Map();

Copy link
Member

Choose a reason for hiding this comment

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

Or, are there actually four scenarios, with the fourth being

  • Remove a particular view modifier from all path elements

packages/jaeger-ui/src/reducers/index.js Show resolved Hide resolved
Copy link
Member

@tiffon tiffon left a comment

Choose a reason for hiding this comment

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

Looks good. A couple of comments.

viewModifier: number;
};

export type TDdgClearViewModifiersFromIndicesPayload = TDdgAddViewModifierPayload & { viewModifier?: void };
Copy link
Member

Choose a reason for hiding this comment

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

I don't see much benefit in basing these types off of TDdgAddViewModifierPayload.

Copy link
Collaborator Author

@everett980 everett980 Jul 2, 2019

Choose a reason for hiding this comment

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

The reason I defined the types as:
export type TDdgClearViewModifiersFromIndicesPayload = TDdgAddViewModifierPayload & { viewModifier?: void };
not export type TDdgClearViewModifiersFromIndicesPayload = TDdgModelParams & { visibilityIndices: number [] };
is because this line in the reducer const { visibilityIndices, viewModifier } = payload; would have the this type error: Property 'viewModifier' does not exist on type 'TDdgViewModifierRemovalPayload'.

I agree that the second type is a clearer, but TypeScript doesn't seem to like the implicit number | undefined when destructuring from the union type.
Playground


export type TDdgAddViewModifierPayload = TDdgModelParams & {
visibilityIndices: number[];
viewModifier: number;
Copy link
Member

Choose a reason for hiding this comment

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

Why not use EViewModifier, instead of number, as the type, here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added a comment for this:

+  // Number instead of EViewModifier so that multiple views can be changed at once.

everett980 and others added 3 commits July 2, 2019 10:47
Add DDG Index with Loading, Error, and temporary header and done views
@everett980 everett980 merged commit fdea0f7 into jaegertracing:master Jul 2, 2019
@everett980 everett980 deleted the fetch-ddg-action-and-reducer branch July 2, 2019 15:30
vvvprabhakar pushed a commit to vvvprabhakar/jaeger-ui that referenced this pull request Jul 5, 2021
…-and-reducer

Fetch ddg action and reducer
Signed-off-by: vvvprabhakar <[email protected]>
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.

2 participants