Skip to content

Troubleshooting

Ronnie Dutta edited this page Nov 23, 2022 · 11 revisions

Where to start?

If you have not figured out where an issue could be in the source code, the following check list might be helpful in starting the troubleshooting process.

  • Does it work on different browsers? Firefox, Chrome, Safari? Check Can I Use for browser specific support to features.
  • Does it work if you disable browser extensions? Some extensions like NoScript, uBlock, etc, may disable parts of the UI.
  • Does it work on a different machine? The user could have company policies that are restricting resources in the browser like WebSockets, or other settings like user language, locale, timezone, etc.
  • Anything useful in the browser console? Check the logging levels for INFO/WARN/DEBUG/etc.
  • Anything useful in the network tab? Check if you can see the WebSocket messages to/from the GraphQL backend.
  • Is the version shown in the UI correct? It should appear next to the GScan component, underneath. Confirm it is compatible with the backend version.
  • Any chance there is something wrong with how the UI was installed in the UIS? Maybe a conda issue?
  • Does it make any difference if you try pip or conda? The packaging in these two is different.
  • Can you start the UI in development mode? That should give you Vue Dev Utils and also the global window.app object (our Vue App object, good for tests).
  • Have you tried looking at the performance tab or at the debugger? You can inspect and control how the UI looks or behaves, and step through the execution if necessary.

Performance issues

Most browsers nowadays ship with good tools to help with performance issues in applications. Chrome and Firefox both contain tools to inspect memory and profile execution. There are extra extensions that may be helpful too, such as Lighthouse.

Browser extensions

Some browser extensions can impact performance. The vue-devtools development extension for Vue, for instance, may cause memory leaks, as it holds reference for some objects to show Vuex transactions and components properties.

Check for other extensions, and try a browser in incognito, or in a profile without any extensions.

DOM Reflows

DOM reflows are common source of performance issues. It may require re-designing HTML elements, CSS styles, or changing how JavaScript code changes objects and styles. Things like grouping changes in batches are helpful too.

Most browser extensions are able to display when elements are re-rendered. You want to minimize the number of times that happens, as the event loop of the browser may stay too busy doing that, instead of rendering the elements or reacting to user interactions.

Memory

There are many things that may impact the application performance, including memory use. Use the browser development tools to look at how well the application performs.

image

  1. test without a running workflow
  2. does the memory issue happens in specific views, or in only certain views?
  3. does it happen with old versions of the UI?

You can also use other tools such as taking snapshots and profiling to accompany the memory use.

image

You should be able to plot the memory pattern too. It is normal that the memory use goes up a little. But after a while the garbage collector must have collected some objects, and the memory must go down.

There are other things you can look for too when you suspect of memory leaks. Event listeners are common source of memory problems. Detached elements too.

JSPerf

JSPerf can be used to create test cases for benchmarking performance problems. You just need to find the minimal way to reproduce the issue. Which can be handy for writing a unit test later, to prevent regression :-)

Other performance issues

You can have a code problem. Something that prevents objects of being collected.

Or you could have a component that is being updated too frequently. Take a look at extensions to monitor when components are being rendered.

Vue is great for reactivity. But if you have reactivity where it is not necessary, you may be putting extra load on the browser to monitor things that are not necessary. Each data or computed value used produces an observer/proxy, that keeps looking after objects for changes, and notifying its listeners.

Things like creating frozen objects can be helpful.

For the why-did-you-render extension, you want to copy the WhyDidYouRender.js file to somewhere like src/utils/. Then import and load it in App.vue.

import WhyDidYouRender from '@/utils/WhyDidYouRender'

// install it as a global mixin
Vue.mixin(WhyDidYouRender)

Finally, to inspect the component you are inspecting, just add debug: true to the object.

export default {
  debug: true,
  name: 'GScan',
  ...
}

image

You want to minimize when components are updated. They must be updated only when necessary, as otherwise it may cause unnecessary reflows or simply decrease the application performance.

Finally, try using a debugger with the profiler. Either the old debugger change in source code, or an IDE debugger (probably better to look at the variables in the stack too).

There are several things that may impact performance. For example, JavaScript may optimize the array access grouping elements of an array together in memory. When you sort the array, you may lose that advantage, and the code can get several times slower. See this series of articles, for a good example of lower level optimization for JavaScript.

NB: it may get trickier with ES6, TypeScript, Babel, transpilation, etc., to see what is going on in the browser.

e2e tests

Please, start by referring to the Cypress docs for troubleshooting.

In #, the e2e test written passed fine on Firefox. But failed on CI GH actions. GH actions were running with --headless, which defaults to electron browser, if no other was specified. By following the Cypress docs for troubleshooting, and setting the browser to chrome, it was easy to reproduce the issue locally. It printed the following in the logs.

  1) GraphiQL
       should execute a GraphQL query and get a valid response:
     AssertionError: expected 'Syntax Error: Unexpected <EOF>.' to include 'user|one'
      at Context.eval (http://localhost:8080/__cypress/tests?p=tests/e2e/specs/graphiql.js:1743:51)

Running a single test

Start the JupyterHub fake server.

yarn run serve:jupyterhub
yarn run v1.22.5
$ nodemon src/services/mock/json-server.js
[nodemon] 2.0.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node src/services/mock/json-server.js`
JSON Server is running

Now start the Vue dev server using the proxy that forwards requests to the JupyterHub fake server.

yarn run serve:vue --mode=offline
yarn run v1.22.5
$ vue-cli-service serve --mode offline --mode=offline
 INFO  Starting development server...
98% after emitting CopyPlugin

 DONE  Compiled successfully in 30912ms                                                                                                                               4:13:29 PM


  App running at:
  - Local:   http://localhost:8080 
  - Network: http://192.168.20.3:8080

  Note that the development build is not optimized.
  To create a production build, run yarn build.

Now you should be able to run a single e2e spec file.

npx cross-env CYPRESS_baseUrl=http://localhost:8080/ cypress run --browser chrome --headless --spec "./tests/e2e/specs/graphiql.js" --config-file cypress.json --browser chrome

Cypress does not provide a way to execute a single test of that spec via the command line. If your spec has too many tests, you can modify the test that you want to run using the .only modifier:

 describe('GraphiQL', () => {
   it('tests something 1', () => {})
-   it('tests something 2', () => {})
+   it.only('tests something 2', () => {})
   it('tests something 3', () => {})
   it('tests something 4', () => {})
...
})

Remember to remove it before you commit your code.

You can use it multiple times to select several tests to run. And you can use it on a describe block too.

Enable video

If you are not able to see what's wrong with your test from the command line logs, you can change the setting in cypress.json for video to true. Then check the videos folder and see what's displayed in the Cylc UI during the test execution, or if any warning or message is displayed.

Unit tests

TypeError: Cannot read properties of undefined (reading 'components')

This is a bogus error. Try running yarn test:unit again.