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

Added view for showing detailed trace statistics #506

Merged
merged 8 commits into from
Jul 28, 2020

Conversation

fylip97
Copy link
Contributor

@fylip97 fylip97 commented Jan 8, 2020

Signed-off-by: Philip Dengler [email protected]

Which problem is this PR solving?

Trace-Overview

Short description of the changes

  • A new view called Trace Overview was created. The folder for the view, all dependencies and methods who are needed are located in a subfolder called “TracePageOverview” of “TracePage”

@codecov
Copy link

codecov bot commented Jan 8, 2020

Codecov Report

Merging #506 into master will decrease coverage by 0.86%.
The diff coverage is 85.53%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #506      +/-   ##
==========================================
- Coverage   93.56%   92.69%   -0.87%     
==========================================
  Files         217      227      +10     
  Lines        5296     5911     +615     
  Branches     1362     1491     +129     
==========================================
+ Hits         4955     5479     +524     
- Misses        300      391      +91     
  Partials       41       41              
Impacted Files Coverage Δ
...i/src/components/DeepDependencies/Header/index.tsx 100.00% <ø> (ø)
...jaeger-ui/src/components/QualityMetrics/Header.tsx 100.00% <ø> (ø)
...ents/TracePage/TracePageHeader/TracePageHeader.tsx 96.42% <ø> (ø)
...s/jaeger-ui/src/components/common/NameSelector.tsx 100.00% <ø> (ø)
...racePage/TraceStatistics/TraceStatisticsHeader.tsx 30.76% <30.76%> (ø)
.../components/TracePage/TraceStatistics/PopupSql.tsx 66.66% <66.66%> (ø)
...onents/TracePage/TraceStatistics/MainTableData.tsx 70.96% <70.96%> (ø)
...mponents/TracePage/TraceStatistics/HeaderTable.tsx 75.00% <75.00%> (ø)
...src/components/TracePage/TraceStatistics/index.tsx 76.61% <76.61%> (ø)
...ents/TracePage/TraceStatistics/DetailTableData.tsx 82.60% <82.60%> (ø)
... and 19 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 89f0050...d6710ac. Read the comment docs.

@everett980
Copy link
Collaborator

everett980 commented Jan 8, 2020

Hi Philip, this view looks pretty good but I have a few questions:

  1. What are the Service Name and Operation Name drop downs for?
  2. What is the color button for?
  3. It seems as though ST in Duration is span max self time / span max time, I'm wondering if span max self time / trace duration might be more useful for time-based RCA? Or in the case of identifying n+1 anti-patterns, non-overlapping total self time / trace duration might be what we want? Though that would require calculating the non-overlapping total self time for a collection of spans.
  4. Also the new folder is called TraceTagOverview, is there a form of tag analysis? Such as determining which tags have the highest (self) time?

@fylip97
Copy link
Contributor Author

fylip97 commented Jan 9, 2020

Hi Everett,

thanks for your feedback and questions!

  1. The first drop down box specifies the attribute (Service Name, Operation Name or a tag) by which the spans are grouped/splitted. With the second drop down box, it is possible to extend the grouping and split the resulting groups again. For example, if "Service Name" and "Operation Name" are selected, the table splits the spans by the "Service Name" and after that by "Operation Name".

  2. The color button colors the table according to the value of the "ST in Duration" with different shades of red. This is done according to the "ST Button" in the "Trace Graph" view.

  3. Until now "ST in Duration" is calculated total self time / total duration, like it is done in the "Trace Graph" view.

  4. Yes, as mentioned in 1, you can group/split the spans not only by Service and Operation Name, but also use all existing tags here. See also the following example screenshot where I've splitted the spans according to their "database" tag and the "service name". This results in a table which database (if the tag specifies the used database) is used by which service. The "Others" element on the bottom represents the spans which do not contain the splitting attribute, in this case the "database" tag.

Trace-Overview2

@yurishkuro
Copy link
Member

Add a caption "Group by:" in front of the drop-downs.

Is the first screenshot an example of Colored table?

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.

This is a really fantastic feature and it's great to see this PR. Thank you!

I don't have time for a full review, but I left a few comments. Let me know if any of them don't make sense or there is some other issue with them.

hideSummary: Boolean(embedded && embedded.timeline.hideSummary),
linkToStandalone: getUrl(id),
nextResult: this.nextResult,
onArchiveClicked: this.archiveTrace,
onSlimViewClicked: this.toggleSlimView,
onTraceGraphViewClicked: this.toggleTraceGraphView,
onTraceGraphViewClicked: this.toogleTraceView,
Copy link
Member

Choose a reason for hiding this comment

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

I suggest renaming the prop to onTraceViewChange since it is no longer specific to the trace graph view.

))}
(() => {
switch (selectedTraceView) {
case 0:
Copy link
Member

Choose a reason for hiding this comment

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

This code doesn't indicate selectedTraceView is actually referring to the index of the current selection from the menuItems in AltViewOptions.tsx. The ordering of values in menuItems must match this switch statement, and this isn't particular evident. This might be hard to follow for someone looking at it without the context of this PR.

I think it would be easier to follow if you create an enum for the trace view types in packages/jaeger-ui/src/components/TracePage/types.tsx. These can then be the value passed through the callback. Also, the array of values in AltViewOptions.tsx can refer to the enum and define the label.

enum ETraceViewType {
  TraceGraph = 'TraceGraph',
  // etc.
}

const menuItems = [
  {
    viewType: ETraceViewType.TraceGraph,
    label: 'Trace Graph',
  },
  // etc.
}

const { onTraceGraphViewClicked, traceGraphView, traceID } = props;
const { onTraceGraphViewClicked, traceID, selectedTraceView } = props;

const menuItems = ['Trace Timeline', 'Trace Graph', 'Trace Overview'];
Copy link
Member

Choose a reason for hiding this comment

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

This can be a top-level value because it doesn't change / is not based on the arguments to the function.

<Button
className="ub-mr2"
htmlType="button"
onClick={() => onTraceGraphViewClicked(selectedTraceView + 1)}
Copy link
Member

Choose a reason for hiding this comment

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

This + 1 is kind of odd. At first I thought repeatedly clicking the button would go from the timeline view to the graph and then get stuck on the trace overview. Then I checked toggleTraceView and saw that it cycles back to the front if index > 2.

Originally, when there were only the Trace Timeline and Trace Graph views, this button was intended to show the label for the current view and clicking it would toggle to the other view (reference to the PR).

Now with the three trace views and the two JSON views (and potentially more trace views later), I think there is a really a diminishing return on value of the button cycling through the three trace views, especially considering it ignores the JSON views when cycling, which makes it less intuitive (IMO).

I suggest having this button should show the label of the current view and do nothing when the button itself is clicked. Currently, the dropdown options are shown when the user hovers on the button. It seems fine for the user to select an item from the list. IMO, that's not much work and is not likely to be confusing.

@everett980, @yurishkuro what do you think?

Copy link
Collaborator

@everett980 everett980 Jan 13, 2020

Choose a reason for hiding this comment

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

I suggest having this button should show the label of the current view and do nothing when the button itself is clicked.

+1
We had discussed doing this even before this PR. So rather than complicating the button I agree it should only be a dropdown and not a button.

@@ -187,14 +188,14 @@ export function TracePageHeaderFn(props: TracePageHeaderEmbedProps & { forwarded
ref={forwardedRef}
resultCount={resultCount}
textFilter={textFilter}
navigable={!traceGraphView}
navigable={!(selectedTraceView !== 0)}
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 selectedTraceView === 0?

@@ -0,0 +1,67 @@
/*
Copy link
Member

Choose a reason for hiding this comment

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

For consistency (e.g. with UiFindInput.*), the file should be named PopupSql.css

@@ -0,0 +1,40 @@
// Copyright (c) 2018 The Jaeger Authors.
Copy link
Member

Choose a reason for hiding this comment

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

For consistency (e.g. with UiFindInput.*), the file should be named PopupSql.css

limitations under the License.
*/

#title {
Copy link
Member

Choose a reason for hiding this comment

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

Using IDs in CSS selectors is an anti-pattern. What's the advantage of using an ID here instead of a CSS class?

@tiffon
Copy link
Member

tiffon commented Jan 13, 2020

Also, can you add a few screenshots showing the various states of the UI?

Also, I meant to add, in your second screenshot (img), the indentation in the first column looks a like it is not working right.

Lastly, what do you think of also indenting the values in the second column, the count column? I'm wondering if that will make the roll-up / grouping more obvious.

@fylip97
Copy link
Contributor Author

fylip97 commented Jan 13, 2020

The first screenshot shows the view grouped by only one value.

1

The next screenshot shows the possibilities to group them further. Tags are marked with "Tag:".

2

The view is grouped by two values.

8

This should show the interaction with the search. The search is for "api-gateway". The found hits are marked yellow.

3

By clicking on a column, the detailed view below is hidden. In this screen the column with “api-gateway” was clicked and the "Operation Names" for this “Service Name” were hidden.

4

This shows the coloring of the detail view according to the value of the ST in Duration.

5

At sql tags it is possible to display the complete sql in a popup by clicking on the column.

7

@everett980
Copy link
Collaborator

I finally got a chance to play around with this branch and I have to say it's very clear how this will be useful!

Now that I've tried it, some follow up questions/feedback:

  1. As Yuri mentioned:

Add a caption "Group by:" in front of the drop-downs.

A caption would be helpful. If you change the Dropdowns to NameSelectors you can give the first selector the label prop "Group By" and still initialize it to "Service Name". The second selector can be given the following props: placeholder: "Optional Sub-Group..." and label: "Sub-Group", as well as the required prop false to make this field clearable.
If you choose to use this component it would be great to move it to src/components/common.

  1. I would change the "color" button to a Checkbox next to a NameSelector with the label "Color by" and the options would be the different numerical columns. This selector should also be required (otherwise a checked Checkbox doesn't make much sense) and can default to its current column.

  2. Regarding:

Until now "ST in Duration" is calculated total self time / total duration, like it is done in the "Trace Graph" view.

I'm still not sure how useful % ST in span duration is. A 10s span with 40% ST is a better opportunity for optimization than a 0.2s span with 100% ST but the latter will be much redder.
The "Trace Graph" view is considered experimental and can be tweaked / diverged from as we see fit.
If this is looking to help fix n+1 anti-patterns, then a metric that works out to be "non-concurrent-within-same-parent ST" as well as % of that in total Trace time seems like the silver bullet IMO.
That said, my changes proposed in 2. would at least address my net ST use case.

  1. I'd like to +1 Joe's suggestion:

Lastly, what do you think of also indenting the values in the second column, the count column? I'm wondering if that will make the roll-up / grouping more obvious.

Indenting sub-group numerical metrics would be nice, especially on large traces where a single group may have many sub-groups.

  1. I'd prefer if the label "Others" were replaced by another term that conveyed the sub-group dimension was missing. As of yet tags are the only dimension that could be missing, so a label like 'Without tag: "SQL"' should work. This is mostly for the case where there are many sub-groups so "Others" could be misinterpreted as "less prevalent values grouped together", as one would see on a pie chart.

  2. This should be considered as a future feature and need not be included yet, but what do you think of the ability to add more than one level of sub-grouping? E.g.: Group by service name & operation name & tag SQL?

  3. I don't think the name "Trace Overview" really communicates what this is used for, something like "Trace Statistics" would be more descriptive.

  4. Lastly, because I think this feature is great and I would want to promote it if it does not gain traction organically, can you add a GA metric to TracePageHeader.track.tsx to trackStatisticsView?

@fylip97
Copy link
Contributor Author

fylip97 commented Jan 27, 2020

This change is Reviewable

@fylip97 fylip97 force-pushed the master branch 2 times, most recently from 28bebc9 to 7e0e25b Compare January 27, 2020 13:23
@fylip97
Copy link
Contributor Author

fylip97 commented Feb 7, 2020

@everett980 do you have any idea why the test "fetchTrace: encountered a declaration exception" is failing?
Locally on my computer all tests run through without problems.

@everett980
Copy link
Collaborator

everett980 commented Feb 7, 2020

@everett980 do you have any idea why the test "fetchTrace: encountered a declaration exception" is failing?
Locally on my computer all tests run through without problems.

@fylip97 Looking at the failing test, it seems to use random numbers. It seems to have a 1e-5 chance of failing. Maybe you got unlucky (and maybe I'm misreading the probability, but definitely see chance), so I'd recommend running travis again.

@yurishkuro
Copy link
Member

could we not mock random for the tests?

@everett980
Copy link
Collaborator

could we not mock random for the tests?

I looks like the code deliberately tries to avoid this issue but has a 1/100000 chance of not avoiding it enough. It should be easy to simply add a small number to one of the two random numbers and it wouldn't happen.

@everett980
Copy link
Collaborator

@fylip97 I know I wrote a bit of a saga, but can you let me know your thoughts on these questions?

Also, if the UI has changed in your commits since 1/13, can you please add updated screenshots?

Lastly, many of the comments left by tiffon are now labeled as Outdated by Github. This indicates the line was changed, but Github itself doesn't know if the requested changes were implemented. Can you mark completed comments as resolved?

Signed-off-by: Philip Dengler <[email protected]>
@fylip97
Copy link
Contributor Author

fylip97 commented Feb 26, 2020

Hi @everett980,
I'd like to respond briefly to your little saga:

  1. I have change the Dropdowns to NameSelectors. I have also added lables before them. The components were moved to src/components/common.

30

31

  1. I removed the "color" button and replaced it with a Checkbox. A selector was added next to the Checkbox.

32

33

  1. I change the calculation. The ST in Duration is now the percentage of ST of the total trace duration.

  2. All values from the Sub Group are now indented.

  3. I have change the Other label to Without Tag.

  4. I like the idea to add more than one level of sub-grouping.

  5. The view is now called Trace Statistics.

  6. GA metrics are added for this view.

Copy link
Collaborator

@everett980 everett980 left a comment

Choose a reason for hiding this comment

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

Sorry it took me so long to get through this all. I really like the changes made with the checkbox and drop downs.

I've left a fair bit of feedback, but most of it should be pretty quickly actionable.

Please double check the copyright years for new files throughout. Any new file should be 2020.

Lastly, I think the CSS for widths needs to be reworked. I noticed in the CSS that the widths specified are very precise. Then, with a selected subgroup, the widths seem slightly broken.
Not selected:
image
Selected:
image
I mentioned how to stop using float. With that change, it should be much easier to style the column widths without exact percentages. The first column can simply flex grow and the rest can be default table styling widths that should accommodate their largest item. If necessary, a maximum width can be added to the other columns, with text overflow ellipsis and a tool tip.

Related: I have noticed that text in the first column can be truncated. For SQL tags, it is possible to view the entire tag in a modal. For everything else, the approach I mentioned for long durations should be used (an ellipsis (already implemented) and a tooltip).


type Props = {
onTraceGraphViewClicked: () => void;
traceGraphView: boolean;
onTraceViewChange: (actualViewType: ETraceViewType) => void;
Copy link
Collaborator

Choose a reason for hiding this comment

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

what does "actual" mean here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

};

const menuItems = [
Copy link
Collaborator

Choose a reason for hiding this comment

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

const MENU_ITEMS

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

return (
<Dropdown overlay={menu}>
<Button className="ub-mr2" htmlType="button" onClick={handleToggleView}>
Alternate Views <Icon type="down" />
<Button className="ub-mr2" htmlType="button">
Copy link
Collaborator

Choose a reason for hiding this comment

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

This shouldn't be an action-less button, instead it should be a span.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@@ -49,7 +49,7 @@ type TracePageHeaderEmbedProps = {
nextResult: () => void;
onArchiveClicked: () => void;
onSlimViewClicked: () => void;
onTraceGraphViewClicked: () => void;
onTraceViewChange: (actualViewType: ETraceViewType) => void;
Copy link
Collaborator

Choose a reason for hiding this comment

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

again, why actual?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@@ -0,0 +1,54 @@
/*
Copyright (c) 2018 The Jaeger Authors.
Copy link
Collaborator

Choose a reason for hiding this comment

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

please update to 2020

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

<Button className="ub-mr2" htmlType="button" onClick={handleToggleView}>
Alternate Views <Icon type="down" />
<Button className="ub-mr2" htmlType="button">
{menuItems.find(test => test.viewType === viewType) !== undefined
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd calculate the dropdownText outside of the return value. and I think this:

const currentItem = menuItems.find(item => item.viewType === viewType);
const dropdownText = currentItem ? currentItem.label : 'Alternate Views';

is clearer and better handles the (presumably impossible) case of an invalid current viewType.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

{traceGraphView ? 'Trace Timeline' : 'Trace Graph'}
</a>
</Menu.Item>
{menuItems.map(item =>
Copy link
Collaborator

Choose a reason for hiding this comment

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

This would be clearer as:

{menuItems.filter(item => item.viewType !== viewType).map(item => (
  <Menu.Item key={item.viewType}>
    {/* ... */}
  </Menu.Item>
))}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

expect(props.onTraceGraphViewClicked).toHaveBeenCalledTimes(1);

wrapper.setProps({ traceGraphView: false });
it('track dropdown menu', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

due to the increase in views, this test is getting slightly out of hand. I would rework it as follows:

const viewInteractions = [{
  link: 'Trace Graph',
  trackFn: trackGraphView,
  onTraceViewChangeArg: ETraceViewType.TraceGraph,
}, {
  link: 'Trace Statistics',
  trackFn: trackStatisticsView,
  onTraceViewChangeArg: ETraceViewType.TraceStatisticsView,
  propViewType: ETraceViewType.TraceGraph,
}, {
  link: 'Trace Timeline',
  trackFn: trackGanttView,
  onTraceViewChangeArg: ETraceViewType.TraceTimelineViewer,
  propViewType: ETraceViewType.TraceStatisticsView
}];

viewInteractions.forEach(({ link, trackFn, onTraceViewChangeArg, propViewType }, i) => {
  if (propViewType) {
    wrapper.setProps({ viewType: propViewType });
  }
  expect(props.onTraceViewChange).toHaveBeenCalledTimes(i);
  expect(trackFn).not.toHaveBeenCalled();

  getLink(link).simulate('click');
  expect(props.onTraceViewChange).toHaveBeenCalledTimes(i + 1);
  expect(props.onTraceViewChange).toHaveBeenLastCalledWith(onTraceViewChangeArg);
  viewInteractions.forEach(({ trackFn: fn, j }) => {
    expect(fn).toHaveBeenCalledTimes(j <= i ? 1 : 0);
  });
});

['Avg', 'avg'],
['Min', 'min'],
['Max', 'max'],
['Total ST', 'self'],
Copy link
Collaborator

Choose a reason for hiding this comment

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

please update this to ['ST Total', 'selfTotal'],, for consistency.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Likewise, please update the corresponding column header of the table.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

['ST Avg', 'selfAvg'],
['ST Min', 'selfMin'],
['ST Max', 'selfMax'],
['ST Duration', 'percent'],
Copy link
Collaborator

Choose a reason for hiding this comment

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

please update this to 'ST in Duration'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@everett980
Copy link
Collaborator

Hi @fylip97, just wanted to check in on this PR. About a month ago you replied to nearly all of my feedback saying they've been addressed. If you'd like help with the last two items or don't have time to complete that yourself, you can push the changes you have done and I can review the changes and tackle the last two items.

Signed-off-by: Philip Dengler <[email protected]>
@fylip97
Copy link
Contributor Author

fylip97 commented Apr 21, 2020

Hi @everett980
I just pushed my changes.
At the moment I have very little time and would like to accept your offer.

@idohalevi
Copy link

@fylip97 @everett980 Thank you for this great feature. Is there any way I can assist in pushing this PR?

Copy link
Collaborator

@everett980 everett980 left a comment

Choose a reason for hiding this comment

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

Apologies it took me so long to get to this. I got pulled in another direction.

This feature looks great and I'm super excited to get it out in front of people.

@everett980 everett980 merged commit 8279218 into jaegertracing:master Jul 28, 2020
@yurishkuro
Copy link
Member

🎉 🎉 🎉

@AlexanderWert
Copy link

Great! Happy to see this feature being approved!

vvvprabhakar pushed a commit to vvvprabhakar/jaeger-ui that referenced this pull request Jul 4, 2021
* Added view for showing detailed trace statistics
* Reworked trace statistics ui
* review included
* feedback added
Signed-off-by: Philip Dengler <[email protected]>

* Handle merge conflict, clean up AltViewOptions style
Signed-off-by: Everett Ross <[email protected]>

Co-authored-by: Philip <[email protected]>
Co-authored-by: Everett Ross <[email protected]>
Signed-off-by: vvvprabhakar <[email protected]>
vvvprabhakar pushed a commit to vvvprabhakar/jaeger-ui that referenced this pull request Jul 4, 2021
* Added view for showing detailed trace statistics
* Reworked trace statistics ui
* review included
* feedback added
Signed-off-by: Philip Dengler <[email protected]>

* Handle merge conflict, clean up AltViewOptions style
Signed-off-by: Everett Ross <[email protected]>

Co-authored-by: Philip <[email protected]>
Co-authored-by: Everett Ross <[email protected]>
Signed-off-by: vvvprabhakar <[email protected]>
vvvprabhakar pushed a commit to vvvprabhakar/jaeger-ui that referenced this pull request Jul 5, 2021
* Added view for showing detailed trace statistics
* Reworked trace statistics ui
* review included
* feedback added
Signed-off-by: Philip Dengler <[email protected]>

* Handle merge conflict, clean up AltViewOptions style
Signed-off-by: Everett Ross <[email protected]>

Co-authored-by: Philip <[email protected]>
Co-authored-by: Everett Ross <[email protected]>
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.

6 participants