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>
import Vue from 'vue';
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 { joinPaths } from '~/lib/utils/url_utility';
import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format';
......@@ -19,6 +22,7 @@ export default {
SelectProjectsDropdown,
TimeAgoTooltip,
},
mixins: [glFeatureFlagsMixin()],
apollo: {
projects: {
query: getProjectsTestCoverage,
......@@ -66,6 +70,13 @@ export default {
};
},
computed: {
handleProjectUsageData() {
return once(() => {
if (this.glFeatures.usageDataITestingGroupCodeCoverageProjectClickTotal) {
api.trackRedisHllUserEvent(this.$options.usagePingProjectEvent);
}
});
},
hasCoverageData() {
return Boolean(this.selectedCoverageData.length);
},
......@@ -154,6 +165,7 @@ export default {
totalHeight: 15,
},
averageCoverageFormatter: getFormatter(SUPPORTED_FORMATS.percentHundred),
usagePingProjectEvent: 'i_testing_group_code_coverage_project_click_total',
};
</script>
<template>
......@@ -211,7 +223,12 @@ export default {
</template>
<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 }}
</gl-link>
</template>
......
......@@ -7,6 +7,9 @@ class Groups::Analytics::RepositoryAnalyticsController < Groups::Analytics::Appl
before_action :load_group
before_action -> { check_feature_availability!(: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
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
import { useFakeDate } from 'helpers/fake_date';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import Api from '~/api';
jest.mock('~/api.js');
const localVue = createLocalVue();
......@@ -52,6 +55,7 @@ describe('Test coverage table component', () => {
data = {},
mountFn = shallowMount,
queryData = {},
glFeatures = {},
} = {}) => {
localVue.use(VueApollo);
fakeApollo = createMockApollo([
......@@ -72,6 +76,9 @@ describe('Test coverage table component', () => {
};
},
apolloProvider: fakeApollo,
provide: {
glFeatures,
},
});
};
......@@ -222,6 +229,89 @@ describe('Test coverage table component', () => {
expect(findTable().exists()).toBe(true);
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', () => {
......
......@@ -268,6 +268,11 @@
redis_slot: testing
aggregation: weekly
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
- name: g_project_management_issue_title_changed
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