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

fix: reset perf logger timer for soft navigation for SPA pages #16668

Merged

Conversation

graceguo-supercat
Copy link

@graceguo-supercat graceguo-supercat commented Sep 10, 2021

SUMMARY

We used some features from HTML5 Performance API to track dashboard page load performance. After we started to use SPA to generate and soft navigate between pages, "navigation" is any subsequent route change. Performance API's start point is based on onload event, so if user switch between chart list, dash list and dashboard (these pages are built from SPA structure), the old measurement for dashboard page load time is not accurate anymore.

This PR uses location to detect soft navigation and reset logging time start point.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

BEFORE SPA
Screen Shot 2021-09-10 at 11 05 50 AM

AFTER FIX
Screen Shot 2021-09-11 at 3 53 43 PM

TESTING INSTRUCTIONS

CI and manual test

ADDITIONAL INFORMATION

cc @etr2460 @ktmud

@codecov
Copy link

codecov bot commented Sep 10, 2021

Codecov Report

Merging #16668 (4d065f3) into master (4dc859f) will decrease coverage by 0.01%.
The diff coverage is 7.14%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #16668      +/-   ##
==========================================
- Coverage   76.90%   76.89%   -0.02%     
==========================================
  Files        1005     1005              
  Lines       54007    54016       +9     
  Branches     7337     7338       +1     
==========================================
  Hits        41536    41536              
- Misses      12231    12240       +9     
  Partials      240      240              
Flag Coverage Δ
javascript 71.25% <7.14%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
...et-frontend/src/dashboard/components/Dashboard.jsx 78.84% <ø> (ø)
superset-frontend/src/views/App.tsx 0.00% <0.00%> (ø)
superset-frontend/src/logger/LogUtils.ts 84.00% <33.33%> (-7.31%) ⬇️

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 4dc859f...4d065f3. Read the comment docs.

Copy link
Member

@etr2460 etr2460 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 comments

resetStartTime() {
this.softNavigationStart = window.performance.now();
},

// note that this returns ms since page load, NOT ms since epoch
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// note that this returns ms since page load, NOT ms since epoch
// note that this returns ms since last navigation, NOT ms since epoch

@@ -43,26 +49,39 @@ const bootstrap = JSON.parse(container?.getAttribute('data-bootstrap') ?? '{}');
const user = { ...bootstrap.user };
const menu = { ...bootstrap.common.menu_data };
const common = { ...bootstrap.common };
let lastLocation: string;
Copy link
Member

Choose a reason for hiding this comment

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

can we call this lastLocationPathname or lastPathname to make it more clear?

useEffect(() => {
// reset performance logger timer start point to avoid soft navigation
// cause dashboard perf measurement problem
if (lastLocation && lastLocation !== location.pathname) {
Copy link
Member

Choose a reason for hiding this comment

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

Maybe a problem for future us, but will this break with slice navigation since viewing slices in explore all have the same pathnames (and instead use url params for switching which slice you're on)?

Copy link
Author

Choose a reason for hiding this comment

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

switch between slices is not a big concern for me, because in the explore view page, there is no link out to other slice(s). Like dashboard, most use cases are switching between list page and dashboard. Right now click on + button to create new slice/dashboard, are all hard navigation.

@ktmud
Copy link
Member

ktmud commented Sep 10, 2021

Thanks for the fix! +1 on making perf tracking more accurate.

Is there a way in current tracking setup to distinguish between "hard landing" and "soft navigation"s? If possible, some example SQL queries on the superset.logs table would be nice.

Copy link
Member

@ktmud ktmud left a comment

Choose a reason for hiding this comment

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

This looks like a valid stop-gap solution, but in the future, it might be more useful to utilize browser API like Performance.mark and Performance.measure to get even more accurate perf logging.

@@ -34,6 +39,7 @@ import { theme } from 'src/preamble';
import ToastPresenter from 'src/messageToasts/containers/ToastPresenter';
import setupApp from 'src/setup/setupApp';
import { routes, isFrontendRoute } from 'src/views/routes';
import { Logger } from '../logger/LogUtils';
Copy link
Member

Choose a reason for hiding this comment

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

Please use absolute imports.

useEffect(() => {
// reset performance logger timer start point to avoid soft navigation
// cause dashboard perf measurement problem
if (lastLocation && lastLocation !== location.pathname) {
Copy link
Member

Choose a reason for hiding this comment

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

lastLocation is a Location object so lastLocation !== location.pathname will always be true. Plus comparing with last location is not needed because useEffect already only triggers when the dependency [location.pathname] updates.

Copy link
Member

@etr2460 etr2460 Sep 10, 2021

Choose a reason for hiding this comment

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

lastLocation is actually the pathname (see line 63) :P that's why i made a comment about variable naming

</ReduxProvider>
</ThemeProvider>
);
const RootContextProviders: React.FC = ({ children }) => {
Copy link
Member

Choose a reason for hiding this comment

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

Instead of putting this in RootContextProviders, it might be more appropriate to put the logic into App itself----the logger is not exactly a provider.

Copy link
Author

@graceguo-supercat graceguo-supercat Sep 10, 2021

Choose a reason for hiding this comment

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

This logic needs to stay with global route change. Do you mean to move this logic to root dashboard / list / welcome etc, each component?

Copy link
Member

Choose a reason for hiding this comment

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

I mean move it to the App component in L86.

Copy link
Author

Choose a reason for hiding this comment

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

we chatted a little bit offline. Based on current way we use <Router> and <RootContextProviders>, keep this logic inside is probably the best solution.

@@ -43,26 +49,39 @@ const bootstrap = JSON.parse(container?.getAttribute('data-bootstrap') ?? '{}');
const user = { ...bootstrap.user };
const menu = { ...bootstrap.common.menu_data };
const common = { ...bootstrap.common };
let lastLocation: string;
Copy link
Author

Choose a reason for hiding this comment

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

@ktmud lastLocation is string type. I think the name is really misleading, i fixed as Erik suggested.

@@ -101,6 +101,7 @@ class Dashboard extends React.PureComponent {
const bootstrapData = appContainer?.getAttribute('data-bootstrap') || '';
const { dashboardState, layout } = this.props;
const eventData = {
is_soft_navigation: Logger.softNavigationStart > 0,
Copy link
Author

Choose a reason for hiding this comment

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

@ktmud i added flag here to track soft navigation or not.

@graceguo-supercat
Copy link
Author

Thanks for the fix! +1 on making perf tracking more accurate.

Is there a way in current tracking setup to distinguish between "hard landing" and "soft navigation"s? If possible, some example SQL queries on the superset.logs table would be nice.

Screen Shot 2021-09-10 at 12 23 19 PM


resetStartTime() {
this.softNavigationStart = window.performance.now();
},
Copy link
Member

@ktmud ktmud Sep 10, 2021

Choose a reason for hiding this comment

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

The window.performance API refers the start time as "time origin", so how about renaming the variables like:

  markTimeOrigin() {
    this.timeOriginOffset = window.performance.now();
  }

  getTimestamp() {
    return Math.round(window.performance.now() - this.timeOriginOffset);
  },

@graceguo-supercat graceguo-supercat merged commit b0b9965 into apache:master Sep 13, 2021
opus-42 pushed a commit to opus-42/incubator-superset that referenced this pull request Nov 14, 2021
…e#16668)

* fix: reset perf logger timer for soft navigation for SPA pages

* fix comments

* fix extra comments

Co-authored-by: grace_guo <grace_guo@grace-guos-MacBook-Pro.local>
QAlexBall pushed a commit to QAlexBall/superset that referenced this pull request Dec 28, 2021
…e#16668)

* fix: reset perf logger timer for soft navigation for SPA pages

* fix comments

* fix extra comments

Co-authored-by: grace_guo <grace_guo@grace-guos-MacBook-Pro.local>
@mistercrunch mistercrunch added 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 1.4.0 labels Mar 13, 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 size/M 🚢 1.4.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants