FE - Cycle analytics architecture improvements
## Background Recently we built out group level cycle analytics, this involved moving cycle analytics from a project level, to a group level and [refactoring existing HAML](https://gitlab.com/gitlab-org/gitlab/merge_requests/15039) functionality into Vue components. The initial approach was to simply port existing functionality as we were preparing to add new features. Since then we have been building additional features: - [Customizable cycle analytics](https://gitlab.com/gitlab-org/gitlab-ee/issues/12196) - [Group analytics over time charts](https://gitlab.com/gitlab-org/gitlab/issues/12755) - [Visualizing tasks by type](https://gitlab.com/gitlab-org/gitlab/issues/32421) - [Visualizing flow of tasks](https://gitlab.com/gitlab-org/gitlab/issues/32422) Previously we had a single endpoint for cycle analytics data, but by completion of https://gitlab.com/gitlab-org/gitlab-ee/issues/12196 we will have multiple endpoints to fetch individual sections of data. Additionally we now have multiple "top-level" components that have different data requirements. ![cycle-analytics](/uploads/89cc6e8c4a543f2e66ebd6c337230994/cycle-analytics.jpg) | Endpoint | Result | | --- | --- | | `GET` /-/analytics/cycle_analytics/summary | returns: Summary data | | `GET\|POST` /-/analytics/cycle_analytics/stages | returns: Stages, Custom stage events, post creates a custom stage | | `GET` /-/analytics/cycle_analytics/stages/:stage_id/records | returns: Stage events | | `GET` /-/analytics/cycle_analytics/stages/:stage_id/median | returns: Stage median value | | `GET` /-/analytics/cycle_analytics/stages/:stage_id/duration_chart | returns: Duration chart data | | `GET\|PUT\|DELETE` /-/analytics/cycle_analytics/stages/:stage_id | returns a stage, update / delete stage | | `GET` /groups/:group_id/-/labels | returns: Group labels | | `GET` /-/analytics/type_of_work/tasks_by_type | returns: Task by type data | | `GET` /-/analytics/type_of_work/tasks_by_stage - not implemented yet | I expect this would return the Tasks by stage data | | Section | Summary data | Stages | Group labels | Stage events | Stage medians | Tasks by type | Tasks by stage | Custom stage events | Duration chart data | | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | | A | [x] | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] | | B | [ ] | [x] | [x] | [x] | [x] | [ ] | [ ] | [x] | [ ] | | C | [ ] | [x] | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] | [x] | | D | [ ] | [ ] | [x] | [ ] | [ ] | [x] | [ ] | [ ] | [ ] | | E | [ ] | [ ] | [x] | [ ] | [ ] | [ ] | [x] | [ ] | [ ] | ## Challenges After a group is selected a series of request are sent to fetch the data required to render the stage table and charts required. * Multiple requests to different endpoints needed to fetch all the required data * Vuex store is getting quite large with some dependent requests - Stage medians requires Stages request first - Stage events requires Stages request first - Tasks by type requires group labels ## Possible improvements ### Split `/-/analytics/cycle_analytics/stages` endpoint Currently this endpoint returns the stages for cycle analytics as well as the events needed to create a custom analytics stage, changes to the stage list (adding a stage, hiding a default stage, removing a custom stage and eventually updating the order of stages) require a refetch to the endpoint to retrieve the updated list of stages, returning the custom stage events seems a bit wasteful here. #### Pros * We only fetch the custom stage events when we need them (when we display the form) * Clearer purpose for the endpoint #### Cons * Another endpoint * Possibly premature optimization / yak-shaving ### Split the major components into several modules We should be able to confidently split the `base.vue` component into smaller modules, similar to the approach taken for [productivity analytics](https://gitlab.com/gitlab-org/gitlab/tree/master/ee/app/assets/javascripts/analytics/productivity_analytics/store): - Summary data (A) - Stage table (B) - Charts (C, D, E) This should provide a clearer distinction between the data and requests needed for a specific module and the data needed across all the modules. #### Pros - Seems to be an [accepted Vuex pattern](https://vuex.vuejs.org/guide/modules.html) - Gives us smaller more maintainable apps to work with moving forward - Similar approach already taken with [productivity analytics]() so we would be adding consistency to analytics - We can better work independently on new features / enhancements with less conflicts - Easier to progressively load parts of the page as requests for data complete #### Cons - Some refactoring required - Probably additional testing needed ### Move requests to a graphql endpoint We have graphql available but have not explored this yet for analytics features, if part of our vision is to provide graphql as the [main way to interact with our APIs](https://docs.gitlab.com/ee/api/graphql/#vision), now seems like a good time to explore what this might mean for analytics. #### Pros - Single endpoint for all our current data - Easier discoverability of cycle analytics data when building FE features - Looser coupling between UI and API endpoints - Good opportunity to understand potential issues we will encounter moving analytics endpoints to graphql #### Cons - Needs a bit more investigation - Extra time needed to get up to speed + possibly more engineering burden - Adding another layer of complexity ### Continue along #### Pros * We can continue to ship features * No additional work required * We can continue to iterate on possible ways forward while gathering user feedback #### Cons * Potentially harder to bring new FE's up to speed since theres already a lot going on * More moving parts that are interrelated, more chance of bugs / regressions * Kicking the can down the road, future features will probably be more time consuming to develop than they need to be
epic