[MM-61193] Create trackFeatureEvent telemetry handler for paid features in web (#28834)
* frontend paid feature usage tracking * fixes on the tooling * fix lint errors * fix types * fix ci * move from paid to SKU * fix linter * move categories and skus to depend on event instead of feature * move to constants
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
aa450f2432
Коммит
4cd73fc2d5
@@ -38,6 +38,10 @@ export function trackEvent(category, event, props) {
|
||||
}
|
||||
}
|
||||
|
||||
export function trackFeatureEvent(featureName, event, props) {
|
||||
Client4.trackFeatureEvent(featureName, event, props);
|
||||
}
|
||||
|
||||
export function pageVisited(category, name) {
|
||||
Client4.pageVisited(category, name);
|
||||
}
|
||||
|
||||
@@ -10,8 +10,11 @@ import type {Group} from '@mattermost/types/groups';
|
||||
import type {GlobalState} from '@mattermost/types/store';
|
||||
import type {UserProfile} from '@mattermost/types/users';
|
||||
|
||||
import {TrackGroupsFeature, TrackInviteGroupEvent} from 'mattermost-redux/constants/telemetry';
|
||||
import {getUser, makeDisplayNameGetter, makeGetProfilesByIdsAndUsernames} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {trackFeatureEvent} from 'actions/telemetry_actions';
|
||||
|
||||
import type {Value} from 'components/multiselect/multiselect';
|
||||
import WithTooltip from 'components/with_tooltip';
|
||||
|
||||
@@ -55,6 +58,7 @@ const GroupOption = (props: Props) => {
|
||||
for (const profile of profiles) {
|
||||
addUserProfile(profile);
|
||||
}
|
||||
trackFeatureEvent(TrackGroupsFeature, TrackInviteGroupEvent, {});
|
||||
}, [addUserProfile, profiles]);
|
||||
|
||||
const onKeyDown = useCallback((e: KeyboardEvent) => {
|
||||
|
||||
@@ -7,10 +7,19 @@ import * as rudderAnalytics from 'rudder-sdk-js';
|
||||
|
||||
import type {TelemetryHandler} from '@mattermost/client';
|
||||
|
||||
import {TrackMiscCategory, TrackActionCategory, TrackEnterpriseSKU, TrackProfessionalSKU, TrackInviteGroupEvent} from 'mattermost-redux/constants/telemetry';
|
||||
import {isSystemAdmin} from 'mattermost-redux/utils/user_utils';
|
||||
|
||||
export {rudderAnalytics};
|
||||
|
||||
const eventSKUs: {[event: string]: string[]} = {
|
||||
[TrackInviteGroupEvent]: [TrackProfessionalSKU, TrackEnterpriseSKU],
|
||||
};
|
||||
|
||||
const eventCategory: {[event: string]: string} = {
|
||||
[TrackInviteGroupEvent]: TrackActionCategory,
|
||||
};
|
||||
|
||||
export class RudderTelemetryHandler implements TelemetryHandler {
|
||||
trackEvent(userId: string, userRoles: string, category: string, event: string, props?: any) {
|
||||
const properties = Object.assign({
|
||||
@@ -36,6 +45,25 @@ export class RudderTelemetryHandler implements TelemetryHandler {
|
||||
rudderAnalytics.track('event', properties, options);
|
||||
}
|
||||
|
||||
trackFeatureEvent(userId: string, userRoles: string, featureName: string, event: string, props?: any) {
|
||||
const properties = Object.assign({
|
||||
category: getEventCategory(event),
|
||||
type: event,
|
||||
user_actual_id: userId,
|
||||
user_actual_role: getActualRoles(userRoles),
|
||||
}, props);
|
||||
const options = {
|
||||
context: {
|
||||
feature: {
|
||||
name: featureName,
|
||||
skus: getSKUs(event),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
rudderAnalytics.track(event, properties, options);
|
||||
}
|
||||
|
||||
pageVisited(userId: string, userRoles: string, category: string, name: string) {
|
||||
rudderAnalytics.page(
|
||||
category,
|
||||
@@ -62,3 +90,22 @@ export class RudderTelemetryHandler implements TelemetryHandler {
|
||||
function getActualRoles(userRoles: string) {
|
||||
return userRoles && isSystemAdmin(userRoles) ? 'system_admin, system_user' : 'system_user';
|
||||
}
|
||||
|
||||
function getSKUs(eventName: string) {
|
||||
const skus: string[] | undefined = eventSKUs[eventName];
|
||||
if (skus === undefined) {
|
||||
// Next line is to be aware if you've forgotten to add a SKU, add an empty array for Team edition
|
||||
// eslint-disable-next-line
|
||||
console.warn(`Event ${eventName} has no SKUs attached`);
|
||||
}
|
||||
return skus ?? [];
|
||||
}
|
||||
|
||||
function getEventCategory(eventName: string) {
|
||||
const category: string | undefined = eventCategory[eventName];
|
||||
if (category === undefined) {
|
||||
// eslint-disable-next-line
|
||||
console.warn(`Event ${eventName} doesn't have a category`);
|
||||
}
|
||||
return category ?? TrackMiscCategory;
|
||||
}
|
||||
|
||||
@@ -12,8 +12,9 @@ import RequestStatus from './request_status';
|
||||
import Roles from './roles';
|
||||
import Stats from './stats';
|
||||
import Teams from './teams';
|
||||
import Telemetry from './telemetry';
|
||||
import Threads from './threads';
|
||||
import Users from './users';
|
||||
import WebsocketEvents from './websocket';
|
||||
|
||||
export {General, Preferences, Posts, Files, RequestStatus, WebsocketEvents, Teams, Stats, Permissions, Emoji, Plugins, Users, Roles, Threads};
|
||||
export {General, Preferences, Posts, Files, RequestStatus, WebsocketEvents, Teams, Stats, Permissions, Emoji, Plugins, Users, Roles, Threads, Telemetry};
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// SKUs
|
||||
export const TrackProfessionalSKU = 'professional';
|
||||
export const TrackEnterpriseSKU = 'enterprise';
|
||||
|
||||
// Features
|
||||
export const TrackGroupsFeature: string = 'custom_groups';
|
||||
|
||||
// Events
|
||||
export const TrackInviteGroupEvent: string = 'invite_group_to_channel';
|
||||
|
||||
// Categories
|
||||
export const TrackActionCategory: string = 'action';
|
||||
export const TrackMiscCategory: string = 'miscellaneous';
|
||||
|
||||
export default {TrackActionCategory, TrackMiscCategory, TrackInviteGroupEvent, TrackGroupsFeature, TrackEnterpriseSKU, TrackProfessionalSKU};
|
||||
@@ -82,6 +82,7 @@ describe('ClientError', () => {
|
||||
describe('trackEvent', () => {
|
||||
class TestTelemetryHandler implements TelemetryHandler {
|
||||
trackEvent = jest.fn();
|
||||
trackFeatureEvent = jest.fn();
|
||||
pageVisited = jest.fn();
|
||||
}
|
||||
|
||||
|
||||
@@ -4327,6 +4327,11 @@ export default class Client4 {
|
||||
this.telemetryHandler.trackEvent(this.userId, this.userRoles, category, event, props);
|
||||
}
|
||||
}
|
||||
trackFeatureEvent(featureName: string, event: string, props?: any) {
|
||||
if (this.telemetryHandler) {
|
||||
this.telemetryHandler.trackFeatureEvent(this.userId, this.userRoles, featureName, event, props);
|
||||
}
|
||||
}
|
||||
|
||||
pageVisited(category: string, name: string) {
|
||||
if (this.telemetryHandler) {
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
|
||||
export interface TelemetryHandler {
|
||||
trackEvent: (userId: string, userRoles: string, category: string, event: string, props?: any) => void;
|
||||
trackFeatureEvent: (userId: string, userRoles: string, featureName: string, event: string, props?: any) => void;
|
||||
pageVisited: (userId: string, userRoles: string, category: string, name: string) => void;
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user