Commit f89cb044 authored by Scott Hampton's avatar Scott Hampton

Add metrics for group coverage link

Add usage metric event for when a user clicks
on a project link on the group code coverage
table.
parent 0969b729
---
name: usage_data_i_testing_group_code_coverage_project_click_total
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51411
rollout_issue_url:
milestone: '13.8'
type: development
group: group::testing
default_enabled: true
<script> <script>
import Vue from 'vue'; import Vue from 'vue';
import { GlCard, GlEmptyState, GlLink, GlSkeletonLoader, GlTable } from '@gitlab/ui'; import { GlCard, GlEmptyState, GlLink, GlSkeletonLoader, GlTable } from '@gitlab/ui';
import { once } from 'lodash';
import api from '~/api';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { __, s__ } from '~/locale'; import { __, s__ } from '~/locale';
import { joinPaths } from '~/lib/utils/url_utility'; import { joinPaths } from '~/lib/utils/url_utility';
import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format'; import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format';
...@@ -19,6 +22,7 @@ export default { ...@@ -19,6 +22,7 @@ export default {
SelectProjectsDropdown, SelectProjectsDropdown,
TimeAgoTooltip, TimeAgoTooltip,
}, },
mixins: [glFeatureFlagsMixin()],
apollo: { apollo: {
projects: { projects: {
query: getProjectsTestCoverage, query: getProjectsTestCoverage,
...@@ -66,6 +70,13 @@ export default { ...@@ -66,6 +70,13 @@ export default {
}; };
}, },
computed: { computed: {
handleProjectUsageData() {
return once(() => {
if (this.glFeatures.usageDataITestingGroupCodeCoverageProjectClickTotal) {
api.trackRedisHllUserEvent(this.$options.usagePingProjectEvent);
}
});
},
hasCoverageData() { hasCoverageData() {
return Boolean(this.selectedCoverageData.length); return Boolean(this.selectedCoverageData.length);
}, },
...@@ -154,6 +165,7 @@ export default { ...@@ -154,6 +165,7 @@ export default {
totalHeight: 15, totalHeight: 15,
}, },
averageCoverageFormatter: getFormatter(SUPPORTED_FORMATS.percentHundred), averageCoverageFormatter: getFormatter(SUPPORTED_FORMATS.percentHundred),
usagePingProjectEvent: 'i_testing_group_code_coverage_project_click_total',
}; };
</script> </script>
<template> <template>
...@@ -211,7 +223,12 @@ export default { ...@@ -211,7 +223,12 @@ export default {
</template> </template>
<template #cell(project)="{ item }"> <template #cell(project)="{ item }">
<gl-link target="_blank" :href="item.codeCoveragePath" :data-testid="`${item.id}-name`"> <gl-link
target="_blank"
:href="item.codeCoveragePath"
:data-testid="`${item.id}-name`"
@click="handleProjectUsageData"
>
{{ item.name }} {{ item.name }}
</gl-link> </gl-link>
</template> </template>
......
...@@ -7,6 +7,9 @@ class Groups::Analytics::RepositoryAnalyticsController < Groups::Analytics::Appl ...@@ -7,6 +7,9 @@ class Groups::Analytics::RepositoryAnalyticsController < Groups::Analytics::Appl
before_action :load_group before_action :load_group
before_action -> { check_feature_availability!(:group_repository_analytics) } before_action -> { check_feature_availability!(:group_repository_analytics) }
before_action -> { authorize_view_by_action!(:read_group_repository_analytics) } before_action -> { authorize_view_by_action!(:read_group_repository_analytics) }
before_action only: [:show] do
push_frontend_feature_flag(:usage_data_i_testing_group_code_coverage_project_click_total, @group, default_enabled: true)
end
track_redis_hll_event :show, name: 'i_testing_group_code_coverage_visit_total', feature: :usage_data_i_testing_group_code_coverage_visit_total, feature_default_enabled: true track_redis_hll_event :show, name: 'i_testing_group_code_coverage_visit_total', feature: :usage_data_i_testing_group_code_coverage_visit_total, feature_default_enabled: true
def show def show
......
---
title: Capture metrics for group coverage project links
merge_request: 51411
author:
type: added
...@@ -6,6 +6,9 @@ import getProjectsTestCoverage from 'ee/analytics/repository_analytics/graphql/q ...@@ -6,6 +6,9 @@ import getProjectsTestCoverage from 'ee/analytics/repository_analytics/graphql/q
import { useFakeDate } from 'helpers/fake_date'; import { useFakeDate } from 'helpers/fake_date';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
jest.mock('~/api.js');
const localVue = createLocalVue(); const localVue = createLocalVue();
...@@ -52,6 +55,7 @@ describe('Test coverage table component', () => { ...@@ -52,6 +55,7 @@ describe('Test coverage table component', () => {
data = {}, data = {},
mountFn = shallowMount, mountFn = shallowMount,
queryData = {}, queryData = {},
glFeatures = {},
} = {}) => { } = {}) => {
localVue.use(VueApollo); localVue.use(VueApollo);
fakeApollo = createMockApollo([ fakeApollo = createMockApollo([
...@@ -72,6 +76,9 @@ describe('Test coverage table component', () => { ...@@ -72,6 +76,9 @@ describe('Test coverage table component', () => {
}; };
}, },
apolloProvider: fakeApollo, apolloProvider: fakeApollo,
provide: {
glFeatures,
},
}); });
}; };
...@@ -222,6 +229,89 @@ describe('Test coverage table component', () => { ...@@ -222,6 +229,89 @@ describe('Test coverage table component', () => {
expect(findTable().exists()).toBe(true); expect(findTable().exists()).toBe(true);
expect(findProjectNameById(id).attributes('href')).toBe(expectedPath); expect(findProjectNameById(id).attributes('href')).toBe(expectedPath);
}); });
describe('with usage metrics', () => {
describe('with :usageDataITestingGroupCodeCoverageProjectClickTotal enabled', () => {
it('tracks i_testing_group_code_coverage_project_click_total metric', async () => {
const id = 1;
createComponentWithApollo({
data: {
projectIds: { [id]: true },
},
queryData: {
data: {
projects: {
nodes: [
{
fullPath: 'test/test',
name: 'test',
id,
repository: {
rootRef: 'master',
},
codeCoverageSummary: {
averageCoverage: '1.45',
coverageCount: '1',
lastUpdatedOn: new Date().toISOString(),
},
},
],
},
},
},
mountFn: mount,
glFeatures: { usageDataITestingGroupCodeCoverageProjectClickTotal: true },
});
jest.runOnlyPendingTimers();
await waitForPromises();
findProjectNameById(id).trigger('click');
expect(Api.trackRedisHllUserEvent).toHaveBeenCalledTimes(1);
expect(Api.trackRedisHllUserEvent).toHaveBeenCalledWith(
wrapper.vm.$options.usagePingProjectEvent,
);
});
});
describe('with :usageDataITestingGroupCodeCoverageProjectClickTotal disabled', () => {
it('does not track i_testing_group_code_coverage_project_click_total metric', async () => {
const id = 1;
createComponentWithApollo({
data: {
projectIds: { [id]: true },
},
queryData: {
data: {
projects: {
nodes: [
{
fullPath: 'test/test',
name: 'test',
id,
repository: {
rootRef: 'master',
},
codeCoverageSummary: {
averageCoverage: '1.45',
coverageCount: '1',
lastUpdatedOn: new Date().toISOString(),
},
},
],
},
},
},
mountFn: mount,
glFeatures: { usageDataITestingGroupCodeCoverageProjectClickTotal: false },
});
jest.runOnlyPendingTimers();
await waitForPromises();
findProjectNameById(id).trigger('click');
expect(Api.trackRedisHllUserEvent).not.toHaveBeenCalled();
});
});
});
}); });
describe('when selected project has no coverage', () => { describe('when selected project has no coverage', () => {
......
...@@ -268,6 +268,11 @@ ...@@ -268,6 +268,11 @@
redis_slot: testing redis_slot: testing
aggregation: weekly aggregation: weekly
feature_flag: usage_data_i_testing_web_performance_widget_total feature_flag: usage_data_i_testing_web_performance_widget_total
- name: i_testing_group_code_coverage_project_click_total
category: testing
redis_slot: testing
aggregation: weekly
feature_flag: usage_data_i_testing_group_code_coverage_project_click_total
# Project Management group # Project Management group
- name: g_project_management_issue_title_changed - name: g_project_management_issue_title_changed
category: issues_edit category: issues_edit
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment