Commit c9faf2ba authored by Brandon Labuschagne's avatar Brandon Labuschagne

Merge branch 'add-web-ide-preview-success-metrics' into 'master'

Add Web IDE preview success metrics

See merge request gitlab-org/gitlab!78952
parents 0da8c72d e11d4a7c
......@@ -4,7 +4,12 @@ import { listen } from 'codesandbox-api';
import { isEmpty, debounce } from 'lodash';
import { Manager } from 'smooshpack';
import { mapActions, mapGetters, mapState } from 'vuex';
import { packageJsonPath, LIVE_PREVIEW_DEBOUNCE } from '../../constants';
import {
packageJsonPath,
LIVE_PREVIEW_DEBOUNCE,
PING_USAGE_PREVIEW_KEY,
PING_USAGE_PREVIEW_SUCCESS_KEY,
} from '../../constants';
import eventHub from '../../eventhub';
import { createPathWithExt } from '../../utils';
import Navigator from './navigator.vue';
......@@ -62,6 +67,15 @@ export default {
};
},
},
watch: {
sandpackReady: {
handler(val) {
if (val) {
this.pingUsage(PING_USAGE_PREVIEW_SUCCESS_KEY);
}
},
},
},
mounted() {
this.onFilesChangeCallback = debounce(() => this.update(), LIVE_PREVIEW_DEBOUNCE);
eventHub.$on('ide.files.change', this.onFilesChangeCallback);
......@@ -101,7 +115,7 @@ export default {
initPreview() {
if (!this.mainEntry) return null;
this.pingUsage();
this.pingUsage(PING_USAGE_PREVIEW_KEY);
return this.loadFileContent(this.mainEntry)
.then(() => this.$nextTick())
......
......@@ -114,3 +114,7 @@ export const LIVE_PREVIEW_DEBOUNCE = 2000;
export const MAX_MR_FILES_AUTO_OPEN = 10;
export const DEFAULT_BRANCH = 'main';
// Ping Usage Metrics Keys
export const PING_USAGE_PREVIEW_KEY = 'web_ide_clientside_preview';
export const PING_USAGE_PREVIEW_SUCCESS_KEY = 'web_ide_clientside_preview_success';
import axios from '~/lib/utils/axios_utils';
export const pingUsage = ({ rootGetters }) => {
export const pingUsage = ({ rootGetters }, metricName) => {
const { web_url: projectUrl } = rootGetters.currentProject;
const url = `${projectUrl}/service_ping/web_ide_clientside_preview`;
const url = `${projectUrl}/service_ping/${metricName}`;
return axios.post(url);
};
......
......@@ -13,6 +13,14 @@ class Projects::ServicePingController < Projects::ApplicationController
head(200)
end
def web_ide_clientside_preview_success
return render_404 unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?
Gitlab::UsageDataCounters::WebIdeCounter.increment_previews_success_count
head(200)
end
def web_ide_pipelines_count
Gitlab::UsageDataCounters::WebIdeCounter.increment_pipelines_count
......
---
data_category: optional
key_path: counts.web_ide_previews_success
description: Count of Live Preview tab successful initializations in the Web IDE
product_section: dev
product_stage: create
product_group: group::editor
product_category: web_ide
value_type: number
status: active
time_frame: all
data_source: redis
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate
performance_indicator_type: []
milestone: "14.8"
......@@ -581,6 +581,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
scope :service_ping, controller: :service_ping do
post :web_ide_clientside_preview # rubocop:todo Cop/PutProjectRoutesUnderScope
post :web_ide_clientside_preview_success # rubocop:todo Cop/PutProjectRoutesUnderScope
post :web_ide_pipelines_count # rubocop:todo Cop/PutProjectRoutesUnderScope
end
......
......@@ -3,7 +3,7 @@
module Gitlab
module UsageDataCounters
class WebIdeCounter < BaseCounter
KNOWN_EVENTS = %w[commits views merge_requests previews terminals pipelines].freeze
KNOWN_EVENTS = %w[commits views merge_requests previews previews_success terminals pipelines].freeze
PREFIX = 'web_ide'
class << self
......@@ -33,6 +33,12 @@ module Gitlab
count('previews')
end
def increment_previews_success_count
return unless Gitlab::CurrentSettings.web_ide_clientside_preview_enabled?
count('previews_success')
end
private
def redis_key(event)
......
......@@ -69,6 +69,33 @@ RSpec.describe Projects::ServicePingController do
end
end
describe 'POST #web_ide_clientside_preview_success' do
subject { post :web_ide_clientside_preview_success, params: { namespace_id: project.namespace, project_id: project } }
context 'when web ide clientside preview is enabled' do
before do
stub_application_setting(web_ide_clientside_preview_enabled: true)
end
it_behaves_like 'counter is not increased'
it_behaves_like 'counter is increased', 'WEB_IDE_PREVIEWS_SUCCESS_COUNT'
end
context 'when web ide clientside preview is not enabled' do
let(:user) { project.owner }
before do
stub_application_setting(web_ide_clientside_preview_enabled: false)
end
it 'returns 404' do
subject
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
describe 'POST #web_ide_pipelines_count' do
subject { post :web_ide_pipelines_count, params: { namespace_id: project.namespace, project_id: project } }
......
import { GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import { dispatch } from 'codesandbox-api';
import smooshpack from 'smooshpack';
import Vuex from 'vuex';
import Clientside from '~/ide/components/preview/clientside.vue';
import { PING_USAGE_PREVIEW_KEY, PING_USAGE_PREVIEW_SUCCESS_KEY } from '~/ide/constants';
import eventHub from '~/ide/eventhub';
jest.mock('smooshpack', () => ({
......@@ -39,6 +41,7 @@ describe('IDE clientside preview', () => {
const storeClientsideActions = {
pingUsage: jest.fn().mockReturnValue(Promise.resolve({})),
};
const dispatchCodesandboxReady = () => dispatch({ type: 'done' });
const waitForCalls = () => new Promise(setImmediate);
......@@ -110,6 +113,20 @@ describe('IDE clientside preview', () => {
it('pings usage', () => {
expect(storeClientsideActions.pingUsage).toHaveBeenCalledTimes(1);
expect(storeClientsideActions.pingUsage).toHaveBeenCalledWith(
expect.anything(),
PING_USAGE_PREVIEW_KEY,
);
});
it('pings usage success', async () => {
dispatchCodesandboxReady();
await wrapper.vm.$nextTick();
expect(storeClientsideActions.pingUsage).toHaveBeenCalledTimes(2);
expect(storeClientsideActions.pingUsage).toHaveBeenCalledWith(
expect.anything(),
PING_USAGE_PREVIEW_SUCCESS_KEY,
);
});
});
......
import MockAdapter from 'axios-mock-adapter';
import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper';
import { PING_USAGE_PREVIEW_KEY } from '~/ide/constants';
import * as actions from '~/ide/stores/modules/clientside/actions';
import axios from '~/lib/utils/axios_utils';
const TEST_PROJECT_URL = `${TEST_HOST}/lorem/ipsum`;
const TEST_USAGE_URL = `${TEST_PROJECT_URL}/service_ping/web_ide_clientside_preview`;
const TEST_USAGE_URL = `${TEST_PROJECT_URL}/service_ping/${PING_USAGE_PREVIEW_KEY}`;
describe('IDE store module clientside actions', () => {
let rootGetters;
......@@ -30,7 +31,7 @@ describe('IDE store module clientside actions', () => {
mock.onPost(TEST_USAGE_URL).reply(() => usageSpy());
testAction(actions.pingUsage, null, rootGetters, [], [], () => {
testAction(actions.pingUsage, PING_USAGE_PREVIEW_KEY, rootGetters, [], [], () => {
expect(usageSpy).toHaveBeenCalled();
done();
});
......
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