diff --git a/pkg/ui/workspaces/cluster-ui/src/sessions/sessionDetailsConnected.tsx b/pkg/ui/workspaces/cluster-ui/src/sessions/sessionDetailsConnected.tsx index 9ac90780b1d..6f4d2c7b77c 100644 --- a/pkg/ui/workspaces/cluster-ui/src/sessions/sessionDetailsConnected.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/sessions/sessionDetailsConnected.tsx @@ -10,7 +10,7 @@ import { connect } from "react-redux"; import { RouteComponentProps, withRouter } from "react-router-dom"; -import { analyticsActions, AppState } from "src/store"; +import { AppState } from "src/store"; import { SessionDetails } from "."; import { actions as sessionsActions, @@ -39,28 +39,6 @@ export const SessionDetailsPageConnected = withRouter( cancelQuery: terminateQueryActions.terminateQuery, refreshNodes: nodesActions.refresh, refreshNodesLiveness: nodesLivenessActions.refresh, - onTerminateSessionClick: () => - analyticsActions.track({ - name: "Session Actions Clicked", - page: "Sessions Details", - action: "Cancel Session", - }), - onTerminateStatementClick: () => - analyticsActions.track({ - name: "Session Actions Clicked", - page: "Sessions Details", - action: "Cancel Statement", - }), - onBackButtonClick: () => - analyticsActions.track({ - name: "Back Clicked", - page: "Sessions Details", - }), - onStatementClick: () => - analyticsActions.track({ - name: "Statement Clicked", - page: "Sessions Details", - }), }, )(SessionDetails), ); diff --git a/pkg/ui/workspaces/cluster-ui/src/sessions/sessionsPageConnected.tsx b/pkg/ui/workspaces/cluster-ui/src/sessions/sessionsPageConnected.tsx index 5cdcca2d824..8a9bc3b847f 100644 --- a/pkg/ui/workspaces/cluster-ui/src/sessions/sessionsPageConnected.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/sessions/sessionsPageConnected.tsx @@ -10,7 +10,7 @@ import { RouteComponentProps, withRouter } from "react-router-dom"; import { connect } from "react-redux"; -import { analyticsActions, AppState } from "src/store"; +import { AppState } from "src/store"; import { SessionsState } from "src/store/sessions"; import { createSelector } from "reselect"; @@ -103,14 +103,6 @@ export const SessionsPageConnected = withRouter( columnName: string, ascending: boolean, ) => { - dispatch( - analyticsActions.track({ - name: "Column Sorted", - page: "Sessions", - tableName, - columnName, - }), - ); dispatch( localStorageActions.update({ key: "sortSetting/SessionsPage", @@ -118,35 +110,7 @@ export const SessionsPageConnected = withRouter( }), ); }, - onSessionClick: () => { - dispatch( - analyticsActions.track({ - name: "Session Clicked", - page: "Sessions", - }), - ); - }, - onTerminateSessionClick: () => - analyticsActions.track({ - name: "Session Actions Clicked", - page: "Sessions", - action: "Cancel Session", - }), - onTerminateStatementClick: () => - analyticsActions.track({ - name: "Session Actions Clicked", - page: "Sessions", - action: "Cancel Statement", - }), onFilterChange: (value: Filters) => { - dispatch( - analyticsActions.track({ - name: "Filter Clicked", - page: "Sessions", - filterName: "app", - value: value.toString(), - }), - ); dispatch( localStorageActions.update({ key: "filters/SessionsPage", diff --git a/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetailsConnected.ts b/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetailsConnected.ts index a8b2b3a904e..f8a4fc9a848 100644 --- a/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetailsConnected.ts +++ b/pkg/ui/workspaces/cluster-ui/src/statementDetails/statementDetailsConnected.ts @@ -35,7 +35,6 @@ import { actions as statementDiagnosticsActions, selectDiagnosticsReportsByStatementFingerprint, } from "src/store/statementDiagnostics"; -import { actions as analyticsActions } from "src/store/analytics"; import { actions as localStorageActions } from "src/store/localStorage"; import { actions as nodesActions } from "../store/nodes"; import { actions as nodeLivenessActions } from "../store/liveness"; @@ -121,30 +120,7 @@ const mapDispatchToProps = ( }), ), ); - dispatch( - analyticsActions.track({ - name: "Statement Diagnostics Clicked", - page: "Statement Details", - action: "Activated", - }), - ); }, - onTabChanged: tabName => - dispatch( - analyticsActions.track({ - name: "Tab Changed", - page: "Statement Details", - tabName, - }), - ), - onDiagnosticBundleDownload: () => - dispatch( - analyticsActions.track({ - name: "Statement Diagnostics Clicked", - page: "Statement Details", - action: "Downloaded", - }), - ), onDiagnosticCancelRequest: (report: IStatementDiagnosticsReport) => { dispatch( statementDiagnosticsActions.cancelReport( @@ -153,13 +129,6 @@ const mapDispatchToProps = ( }), ), ); - dispatch( - analyticsActions.track({ - name: "Statement Diagnostics Clicked", - page: "Statement Details", - action: "Cancelled", - }), - ); }, onStatementDetailsQueryChange: (latestQuery: string) => { dispatch(sqlDetailsStatsActions.setLatestQuery(latestQuery)); @@ -169,22 +138,6 @@ const mapDispatchToProps = ( sqlDetailsStatsActions.setLatestFormattedQuery(latestFormattedQuery), ); }, - onSortingChange: (tableName, columnName) => - dispatch( - analyticsActions.track({ - name: "Column Sorted", - page: "Statement Details", - columnName, - tableName, - }), - ), - onBackToStatementsClick: () => - dispatch( - analyticsActions.track({ - name: "Back Clicked", - page: "Statement Details", - }), - ), }); export const ConnectedStatementDetailsPage = withRouter( diff --git a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPageConnected.tsx b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPageConnected.tsx index b4e84900f60..f41d8c5db2a 100644 --- a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPageConnected.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPageConnected.tsx @@ -14,7 +14,6 @@ import { Dispatch } from "redux"; import { AppState, uiConfigActions } from "src/store"; import { actions as statementDiagnosticsActions } from "src/store/statementDiagnostics"; -import { actions as analyticsActions } from "src/store/analytics"; import { actions as localStorageActions, updateStmtsPageLimitAction, @@ -134,26 +133,11 @@ export const ConnectedStatementsPage = withRouter( }), ), ); - dispatch( - analyticsActions.track({ - name: "Statement Diagnostics Clicked", - page: "Statements", - action: "Activated", - }), - ); }, onSelectDiagnosticsReportDropdownOption: ( report: IStatementDiagnosticsReport, ) => { - if (report.completed) { - dispatch( - analyticsActions.track({ - name: "Statement Diagnostics Clicked", - page: "Statements", - action: "Downloaded", - }), - ); - } else { + if (!report.completed) { dispatch( statementDiagnosticsActions.cancelReport( new CancelStatementDiagnosticsReportRequest({ @@ -161,22 +145,9 @@ export const ConnectedStatementsPage = withRouter( }), ), ); - dispatch( - analyticsActions.track({ - name: "Statement Diagnostics Clicked", - page: "Statements", - action: "Cancelled", - }), - ); } }, onSearchComplete: (query: string) => { - dispatch( - analyticsActions.track({ - name: "Keyword Searched", - page: "Statements", - }), - ); dispatch( localStorageActions.update({ key: "search/StatementsPage", @@ -185,14 +156,6 @@ export const ConnectedStatementsPage = withRouter( ); }, onFilterChange: value => { - dispatch( - analyticsActions.track({ - name: "Filter Clicked", - page: "Statements", - filterName: "app", - value: value.toString(), - }), - ); dispatch( localStorageActions.update({ key: "filters/StatementsPage", @@ -205,14 +168,6 @@ export const ConnectedStatementsPage = withRouter( columnName: string, ascending: boolean, ) => { - dispatch( - analyticsActions.track({ - name: "Column Sorted", - page: "Statements", - tableName, - columnName, - }), - ); dispatch( localStorageActions.update({ key: "sortSetting/StatementsPage", @@ -220,13 +175,6 @@ export const ConnectedStatementsPage = withRouter( }), ); }, - onStatementClick: () => - dispatch( - analyticsActions.track({ - name: "Statement Clicked", - page: "Statements", - }), - ), // We use `null` when the value was never set and it will show all columns. // If the user modifies the selection and no columns are selected, // the function will save the value as a blank space, otherwise diff --git a/pkg/ui/workspaces/cluster-ui/src/store/analytics/analytics.reducer.ts b/pkg/ui/workspaces/cluster-ui/src/store/analytics/analytics.reducer.ts deleted file mode 100644 index 4f9b4b995ba..00000000000 --- a/pkg/ui/workspaces/cluster-ui/src/store/analytics/analytics.reducer.ts +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2021 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { createAction } from "@reduxjs/toolkit"; -import { DOMAIN_NAME } from "../utils"; - -type Page = - | "Statements" - | "Statement Details" - | "Sessions" - | "Sessions Details" - | "Transactions" - | "Transaction Details"; - -type SearchEvent = { - name: "Keyword Searched"; - page: Page; -}; - -type SortingEvent = { - name: "Column Sorted"; - page: Page; - tableName: string; - columnName: string; -}; - -type StatementDiagnosticEvent = { - name: "Statement Diagnostics Clicked"; - page: Page; - action: "Activated" | "Downloaded" | "Cancelled"; -}; - -type TabChangedEvent = { - name: "Tab Changed"; - tabName: string; - page: Page; -}; - -type BackButtonClick = { - name: "Back Clicked"; - page: Page; -}; - -type StatementClicked = { - name: "Statement Clicked"; - page: Page; -}; - -type SessionClicked = { - name: "Session Clicked"; - page: Page; -}; - -type SessionActionsClicked = { - name: "Session Actions Clicked"; - page: Page; - action: "Cancel Statement" | "Cancel Session"; -}; - -type FilterEvent = { - name: "Filter Clicked"; - page: Page; - filterName: string; - value: string; -}; - -type AnalyticsEvent = - | SortingEvent - | StatementDiagnosticEvent - | SearchEvent - | TabChangedEvent - | BackButtonClick - | FilterEvent - | StatementClicked - | SessionClicked - | SessionActionsClicked; - -const PREFIX = `${DOMAIN_NAME}/analytics`; - -/** - * actions accept payload with "page" field which specifies the page where - * action occurs and a value expected expected by specific action. - */ -export const actions = { - track: createAction(`${PREFIX}/track`, (event: AnalyticsEvent) => ({ - payload: event, - })), -}; diff --git a/pkg/ui/workspaces/cluster-ui/src/store/analytics/index.ts b/pkg/ui/workspaces/cluster-ui/src/store/analytics/index.ts deleted file mode 100644 index f71353c36dd..00000000000 --- a/pkg/ui/workspaces/cluster-ui/src/store/analytics/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2021 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -export * from "./analytics.reducer"; diff --git a/pkg/ui/workspaces/cluster-ui/src/store/index.ts b/pkg/ui/workspaces/cluster-ui/src/store/index.ts index cf18010eaf9..7eb6bacca51 100644 --- a/pkg/ui/workspaces/cluster-ui/src/store/index.ts +++ b/pkg/ui/workspaces/cluster-ui/src/store/index.ts @@ -10,6 +10,5 @@ export { sagas } from "./sagas"; export { notificationAction } from "./notifications"; -export { actions as analyticsActions } from "./analytics"; export { actions as uiConfigActions, UIConfigState } from "./uiConfig"; export { rootReducer, AppState, rootActions } from "./reducers"; diff --git a/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPageConnected.tsx b/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPageConnected.tsx index ab94b5b22f1..2adb3478024 100644 --- a/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPageConnected.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/transactionsPage/transactionsPageConnected.tsx @@ -46,7 +46,6 @@ import { updateTxnsPageReqSortAction, } from "../store/localStorage"; import { Filters } from "../queryFilter"; -import { actions as analyticsActions } from "../store/analytics"; import { TimeScale } from "../timeScaleDropdown"; export const TransactionsPageConnected = withRouter( @@ -111,14 +110,6 @@ export const TransactionsPageConnected = withRouter( ); }, onFilterChange: (value: Filters) => { - dispatch( - analyticsActions.track({ - name: "Filter Clicked", - page: "Transactions", - filterName: "app", - value: value.toString(), - }), - ); dispatch( localStorageActions.update({ key: "filters/TransactionsPage", @@ -127,12 +118,6 @@ export const TransactionsPageConnected = withRouter( ); }, onSearchComplete: (query: string) => { - dispatch( - analyticsActions.track({ - name: "Keyword Searched", - page: "Transactions", - }), - ); dispatch( localStorageActions.update({ key: "search/TransactionsPage", diff --git a/pkg/ui/workspaces/db-console/package.json b/pkg/ui/workspaces/db-console/package.json index 8b0695622cb..980d4a3638f 100644 --- a/pkg/ui/workspaces/db-console/package.json +++ b/pkg/ui/workspaces/db-console/package.json @@ -21,7 +21,6 @@ "@cockroachlabs/crdb-protobuf-client": "link:./src/js", "@cockroachlabs/design-tokens": "0.4.5", "@cockroachlabs/icons": "0.3.0", - "analytics-node": "^3.5.0", "antd": "^3.25.2", "babel-polyfill": "^6.26.0", "classnames": "^2.2.5", @@ -64,7 +63,6 @@ "@testing-library/dom": "^8.11.1", "@testing-library/react": "^12.1.0", "@testing-library/user-event": "^13.5.0", - "@types/analytics-node": "^0.0.32", "@types/assert": "^1.4.0", "@types/bytebuffer": "^5.0.33", "@types/chai": "^4.1.0", diff --git a/pkg/ui/workspaces/db-console/src/index.tsx b/pkg/ui/workspaces/db-console/src/index.tsx index a08369a648f..3405922728f 100644 --- a/pkg/ui/workspaces/db-console/src/index.tsx +++ b/pkg/ui/workspaces/db-console/src/index.tsx @@ -15,7 +15,6 @@ import "src/protobufInit"; import { alertDataSync } from "src/redux/alerts"; import { App } from "src/app"; import { store, history } from "src/redux/state"; -import "src/redux/analytics"; ReactDOM.render( , diff --git a/pkg/ui/workspaces/db-console/src/redux/alerts.spec.ts b/pkg/ui/workspaces/db-console/src/redux/alerts.spec.ts index 085299b7fb5..6f93e359e4e 100644 --- a/pkg/ui/workspaces/db-console/src/redux/alerts.spec.ts +++ b/pkg/ui/workspaces/db-console/src/redux/alerts.spec.ts @@ -16,7 +16,6 @@ import { createHashHistory } from "history"; import * as protos from "src/js/protos"; import { cockroach } from "src/js/protos"; -import { API_PREFIX } from "src/util/api"; import fetchMock from "src/util/fetch-mock"; import { AdminUIState, createAdminUIStore } from "./state"; @@ -25,23 +24,15 @@ import { alertDataSync, staggeredVersionWarningSelector, staggeredVersionDismissedSetting, - newVersionNotificationSelector, - newVersionDismissedLocalSetting, disconnectedAlertSelector, disconnectedDismissedLocalSetting, emailSubscriptionAlertLocalSetting, emailSubscriptionAlertSelector, } from "./alerts"; import { versionsSelector } from "src/redux/nodes"; -import { - VERSION_DISMISSED_KEY, - INSTRUCTIONS_BOX_COLLAPSED_KEY, - setUIDataKey, - isInFlight, -} from "./uiData"; +import { INSTRUCTIONS_BOX_COLLAPSED_KEY, setUIDataKey } from "./uiData"; import { livenessReducerObj, - versionReducerObj, nodesReducerObj, clusterReducerObj, healthReducerObj, @@ -260,154 +251,6 @@ describe("alerts", function() { }); }); - describe("new version available notification", function() { - it("displays nothing when versions have not yet been loaded", function() { - dispatch(setUIDataKey(VERSION_DISMISSED_KEY, null)); - const alert = newVersionNotificationSelector(state()); - assert.isUndefined(alert); - }); - - it("displays nothing when persistent dismissal has not been checked", function() { - dispatch( - versionReducerObj.receiveData({ - details: [ - { - version: "0.1", - detail: "alpha", - }, - ], - }), - ); - const alert = newVersionNotificationSelector(state()); - assert.isUndefined(alert); - }); - - it("displays nothing when no new version is available", function() { - dispatch(setUIDataKey(VERSION_DISMISSED_KEY, null)); - dispatch( - versionReducerObj.receiveData({ - details: [], - }), - ); - const alert = newVersionNotificationSelector(state()); - assert.isUndefined(alert); - }); - - it("displays when new version available and not dismissed", function() { - dispatch(setUIDataKey(VERSION_DISMISSED_KEY, null)); - dispatch( - versionReducerObj.receiveData({ - details: [ - { - version: "0.1", - detail: "alpha", - }, - ], - }), - ); - const alert = newVersionNotificationSelector(state()); - assert.isObject(alert); - assert.equal(alert.level, AlertLevel.NOTIFICATION); - assert.equal(alert.title, "New Version Available"); - }); - - it("respects local dismissal setting", function() { - dispatch(setUIDataKey(VERSION_DISMISSED_KEY, null)); - dispatch( - versionReducerObj.receiveData({ - details: [ - { - version: "0.1", - detail: "alpha", - }, - ], - }), - ); - dispatch(newVersionDismissedLocalSetting.set(moment())); - let alert = newVersionNotificationSelector(state()); - assert.isUndefined(alert); - - // Local dismissal only lasts one day. - dispatch( - newVersionDismissedLocalSetting.set(moment().subtract(2, "days")), - ); - alert = newVersionNotificationSelector(state()); - assert.isDefined(alert); - }); - - it("respects persistent dismissal setting", function() { - dispatch(setUIDataKey(VERSION_DISMISSED_KEY, moment().valueOf())); - dispatch( - versionReducerObj.receiveData({ - details: [ - { - version: "0.1", - detail: "alpha", - }, - ], - }), - ); - let alert = newVersionNotificationSelector(state()); - assert.isUndefined(alert); - - // Dismissal only lasts one day. - dispatch( - setUIDataKey( - VERSION_DISMISSED_KEY, - moment() - .subtract(2, "days") - .valueOf(), - ), - ); - alert = newVersionNotificationSelector(state()); - assert.isDefined(alert); - }); - - it("dismisses by setting local and persistent dismissal", function(done) { - fetchMock.mock({ - matcher: `${API_PREFIX}/uidata`, - method: "POST", - response: (_url: string) => { - const encodedResponse = protos.cockroach.server.serverpb.SetUIDataResponse.encode( - {}, - ).finish(); - return { - body: encodedResponse, - }; - }, - }); - - dispatch(setUIDataKey(VERSION_DISMISSED_KEY, null)); - dispatch( - versionReducerObj.receiveData({ - details: [ - { - version: "0.1", - detail: "alpha", - }, - ], - }), - ); - const alert = newVersionNotificationSelector(state()); - const beforeDismiss = moment(); - - alert.dismiss(dispatch, state).then(() => { - assert.isTrue( - newVersionDismissedLocalSetting - .selector(state()) - .isSameOrAfter(beforeDismiss), - ); - assert.isNotNull(state().uiData[VERSION_DISMISSED_KEY]); - assert.isNotNull(state().uiData[VERSION_DISMISSED_KEY].data); - const dismissedMoment = moment( - state().uiData[VERSION_DISMISSED_KEY].data as number, - ); - assert.isTrue(dismissedMoment.isSameOrAfter(beforeDismiss)); - done(); - }); - }); - }); - describe("disconnected alert", function() { it("requires health to be available before displaying", function() { const alert = disconnectedAlertSelector(state()); @@ -497,62 +340,11 @@ describe("alerts", function() { it("dispatches requests for expected data on empty store", function() { sync(); - assert.isTrue(isInFlight(state(), VERSION_DISMISSED_KEY)); assert.isTrue(state().cachedData.cluster.inFlight); assert.isTrue(state().cachedData.nodes.inFlight); - assert.isFalse(state().cachedData.version.inFlight); assert.isTrue(state().cachedData.health.inFlight); }); - it("dispatches request for version data when cluster ID and nodes are available", function() { - dispatch( - nodesReducerObj.receiveData([ - { - build_info: { - tag: "0.1", - }, - }, - ]), - ); - dispatch( - clusterReducerObj.receiveData( - new protos.cockroach.server.serverpb.ClusterResponse({ - cluster_id: "my-cluster", - }), - ), - ); - - sync(); - assert.isTrue(state().cachedData.version.inFlight); - }); - - it("does not request version data when version is staggered", function() { - dispatch( - nodesReducerObj.receiveData([ - { - build_info: { - tag: "0.1", - }, - }, - { - build_info: { - tag: "0.2", - }, - }, - ]), - ); - dispatch( - clusterReducerObj.receiveData( - new protos.cockroach.server.serverpb.ClusterResponse({ - cluster_id: "my-cluster", - }), - ), - ); - - sync(); - assert.isFalse(state().cachedData.version.inFlight); - }); - it("refreshes health function whenever the last health response is no longer valid.", function() { dispatch( healthReducerObj.receiveData( @@ -581,13 +373,7 @@ describe("alerts", function() { }), ), ); - dispatch(setUIDataKey(VERSION_DISMISSED_KEY, "blank")); dispatch(setUIDataKey(INSTRUCTIONS_BOX_COLLAPSED_KEY, false)); - dispatch( - versionReducerObj.receiveData({ - details: [], - }), - ); dispatch( healthReducerObj.receiveData( new protos.cockroach.server.serverpb.ClusterResponse({}), diff --git a/pkg/ui/workspaces/db-console/src/redux/alerts.ts b/pkg/ui/workspaces/db-console/src/redux/alerts.ts index f2f1063959f..b6425977962 100644 --- a/pkg/ui/workspaces/db-console/src/redux/alerts.ts +++ b/pkg/ui/workspaces/db-console/src/redux/alerts.ts @@ -21,7 +21,6 @@ import { ThunkAction } from "redux-thunk"; import { LocalSetting } from "./localsettings"; import { - VERSION_DISMISSED_KEY, INSTRUCTIONS_BOX_COLLAPSED_KEY, saveUIData, loadUIData, @@ -29,18 +28,9 @@ import { UIDataState, UIDataStatus, } from "./uiData"; -import { - refreshCluster, - refreshNodes, - refreshVersion, - refreshHealth, -} from "./apiReducers"; -import { - singleVersionSelector, - numNodesByVersionsSelector, -} from "src/redux/nodes"; +import { refreshCluster, refreshNodes, refreshHealth } from "./apiReducers"; +import { numNodesByVersionsSelector } from "src/redux/nodes"; import { AdminUIState, AppDispatch } from "./state"; -import * as docsURL from "src/util/docs"; export enum AlertLevel { NOTIFICATION, @@ -166,99 +156,6 @@ export const staggeredVersionWarningSelector = createSelector( }, ); -// A boolean that indicates whether the server has yet been checked for a -// persistent dismissal of this notification. -// TODO(mrtracy): Refactor so that we can distinguish "never loaded" from -// "loaded, doesn't exist on server" without a separate selector. -const newVersionDismissedPersistentLoadedSelector = createSelector( - (state: AdminUIState) => state.uiData, - uiData => uiData && _.has(uiData, VERSION_DISMISSED_KEY), -); - -const newVersionDismissedPersistentSelector = createSelector( - (state: AdminUIState) => state.uiData, - uiData => { - return ( - (uiData && - uiData[VERSION_DISMISSED_KEY] && - uiData[VERSION_DISMISSED_KEY].data && - moment(uiData[VERSION_DISMISSED_KEY].data)) || - moment(0) - ); - }, -); - -export const newVersionDismissedLocalSetting = new LocalSetting( - "new_version_dismissed", - localSettingsSelector, - moment(0), -); - -export const newerVersionsSelector = (state: AdminUIState) => - state.cachedData.version.valid ? state.cachedData.version.data : null; - -/** - * Notification when a new version of CockroachDB is available. - */ -export const newVersionNotificationSelector = createSelector( - newerVersionsSelector, - newVersionDismissedPersistentLoadedSelector, - newVersionDismissedPersistentSelector, - newVersionDismissedLocalSetting.selector, - ( - newerVersions, - newVersionDismissedPersistentLoaded, - newVersionDismissedPersistent, - newVersionDismissedLocal, - ): Alert => { - // Check if there are new versions available. - if ( - !newerVersions || - !newerVersions.details || - newerVersions.details.length === 0 - ) { - return undefined; - } - - // Check local dismissal. Local dismissal is valid for one day. - const yesterday = moment().subtract(1, "day"); - if ( - newVersionDismissedLocal.isAfter && - newVersionDismissedLocal.isAfter(yesterday) - ) { - return undefined; - } - - // Check persistent dismissal, also valid for one day. - if ( - !newVersionDismissedPersistentLoaded || - !newVersionDismissedPersistent || - newVersionDismissedPersistent.isAfter(yesterday) - ) { - return undefined; - } - - return { - level: AlertLevel.NOTIFICATION, - title: "New Version Available", - text: "A new version of CockroachDB is available.", - link: docsURL.upgradeCockroachVersion, - dismiss: (dispatch: any) => { - const dismissedAt = moment(); - // Dismiss locally. - dispatch(newVersionDismissedLocalSetting.set(dismissedAt)); - // Dismiss persistently. - return dispatch( - saveUIData({ - key: VERSION_DISMISSED_KEY, - value: dismissedAt.valueOf(), - }), - ); - }, - }; - }, -); - export const disconnectedDismissedLocalSetting = new LocalSetting( "disconnected_dismissed", localSettingsSelector, @@ -532,7 +429,6 @@ export const overviewListAlertsSelector = createSelector( * page; currently, this includes all non-critical alerts. */ export const panelAlertsSelector = createSelector( - newVersionNotificationSelector, staggeredVersionWarningSelector, (...alerts: Alert[]): Alert[] => { return _.without(alerts, null, undefined); @@ -580,10 +476,7 @@ export function alertDataSync(store: Store) { const uiData = state.uiData; if (uiData !== lastUIData) { lastUIData = uiData; - const keysToMaybeLoad = [ - VERSION_DISMISSED_KEY, - INSTRUCTIONS_BOX_COLLAPSED_KEY, - ]; + const keysToMaybeLoad = [INSTRUCTIONS_BOX_COLLAPSED_KEY]; const keysToLoad = _.filter(keysToMaybeLoad, key => { return !(_.has(uiData, key) || isInFlight(state, key)); }); @@ -603,21 +496,5 @@ export function alertDataSync(store: Store) { if (nodes && !nodes.data && !nodes.inFlight) { dispatch(refreshNodes()); } - - // Load potential new versions from CockroachDB cluster. This is the - // complicating factor of this function, since the call requires the cluster - // ID and node statuses being loaded first and thus cannot simply run at - // startup. - const currentVersion = singleVersionSelector(state); - if (_.isNil(newerVersionsSelector(state))) { - if (cluster.data && cluster.data.cluster_id && currentVersion) { - dispatch( - refreshVersion({ - clusterID: cluster.data.cluster_id, - buildtag: currentVersion, - }), - ); - } - } }; } diff --git a/pkg/ui/workspaces/db-console/src/redux/analytics.spec.ts b/pkg/ui/workspaces/db-console/src/redux/analytics.spec.ts deleted file mode 100644 index 9d231950897..00000000000 --- a/pkg/ui/workspaces/db-console/src/redux/analytics.spec.ts +++ /dev/null @@ -1,422 +0,0 @@ -// Copyright 2018 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { assert } from "chai"; -import * as sinon from "sinon"; - -import Analytics from "analytics-node"; -import { Location, createLocation, createHashHistory } from "history"; -import _ from "lodash"; -import { Store } from "redux"; - -import { history } from "src/redux/state"; -import { AnalyticsSync, defaultRedactions } from "./analytics"; -import { clusterReducerObj, nodesReducerObj } from "./apiReducers"; -import { AdminUIState, createAdminUIStore } from "./state"; - -import * as protos from "src/js/protos"; - -const sandbox = sinon.createSandbox(); - -describe("analytics listener", function() { - const clusterID = "a49f0ced-7ada-4135-af37-8acf6b548df0"; - const setClusterData = ( - store: Store, - enabled = true, - enterprise = true, - ) => { - store.dispatch( - clusterReducerObj.receiveData( - new protos.cockroach.server.serverpb.ClusterResponse({ - cluster_id: clusterID, - reporting_enabled: enabled, - enterprise_enabled: enterprise, - }), - ), - ); - }; - - describe("page method", function() { - let store: Store; - let analytics: Analytics; - let pageSpy: sinon.SinonSpy; - - beforeEach(function() { - store = createAdminUIStore(createHashHistory()); - pageSpy = sandbox.spy(); - - // Analytics is a completely fake object, we don't want to call - // segment if an unexpected method is called. - analytics = { - page: pageSpy, - } as any; - }); - - afterEach(() => { - sandbox.reset(); - }); - - it("does nothing if cluster info is not available", function() { - const sync = new AnalyticsSync(analytics, store, []); - - sync.page({ - pathname: "/test/path", - } as Location); - - assert.isTrue(pageSpy.notCalled); - }); - - it("does nothing if reporting is not explicitly enabled", function() { - const sync = new AnalyticsSync(analytics, store, []); - setClusterData(store, false); - - sync.page({ - pathname: "/test/path", - } as Location); - - assert.isTrue(pageSpy.notCalled); - }); - - it("correctly calls segment on a page call", function() { - const sync = new AnalyticsSync(analytics, store, []); - setClusterData(store); - - sync.page({ - pathname: "/test/path", - } as Location); - - assert.isTrue(pageSpy.calledOnce); - assert.deepEqual(pageSpy.args[0][0], { - userId: clusterID, - name: "/test/path", - properties: { - path: "/test/path", - search: "", - }, - }); - }); - - it("correctly queues calls before cluster ID is available", function() { - const sync = new AnalyticsSync(analytics, store, []); - - sync.page({ - pathname: "/test/path", - } as Location); - - setClusterData(store); - assert.isTrue(pageSpy.notCalled); - - sync.page({ - pathname: "/test/path/2", - } as Location); - - assert.equal(pageSpy.callCount, 2); - assert.deepEqual(pageSpy.args[0][0], { - userId: clusterID, - name: "/test/path", - properties: { - path: "/test/path", - search: "", - }, - }); - assert.deepEqual(pageSpy.args[1][0], { - userId: clusterID, - name: "/test/path/2", - properties: { - path: "/test/path/2", - search: "", - }, - }); - }); - - it("correctly applies redaction to matched paths", function() { - setClusterData(store); - const sync = new AnalyticsSync(analytics, store, [ - { - match: RegExp("/test/.*/path"), - replace: "/test/[redacted]/path", - }, - ]); - - sync.page({ - pathname: "/test/username/path", - } as Location); - - assert.isTrue(pageSpy.calledOnce); - assert.deepEqual(pageSpy.args[0][0], { - userId: clusterID, - name: "/test/[redacted]/path", - properties: { - path: "/test/[redacted]/path", - search: "", - }, - }); - }); - - function testRedaction(title: string, input: string, expected: string) { - return { title, input, expected }; - } - - [ - testRedaction( - "old database URL (redirect)", - "/databases/database/foobar/table/baz", - "/databases/database/[db]/table/[tbl]", - ), - testRedaction( - "database URL (redirect)", - "/database/foobar", - "/database/[db]", - ), - testRedaction( - "database tables URL", - "/database/foobar/tables", - "/database/[db]/tables", - ), - testRedaction( - "database grants URL", - "/database/foobar/grants", - "/database/[db]/grants", - ), - testRedaction( - "database table URL (redirect)", - "/database/foobar/table", - "/database/[db]/table", - ), - testRedaction( - "database table URL", - "/database/foobar/table/baz", - "/database/[db]/table/[tbl]", - ), - testRedaction("clusterviz map root", "/overview/map/", "/overview/map/"), - testRedaction( - "clusterviz map single locality", - "/overview/map/datacenter=us-west-1", - "/overview/map/[locality]", - ), - testRedaction( - "clusterviz map multiple localities", - "/overview/map/datacenter=us-west-1/rack=1234", - "/overview/map/[locality]/[locality]", - ), - testRedaction( - "login redirect URL parameters", - "/login?redirectTo=%2Fdatabase%2Ffoobar%2Ftable%2Fbaz", - "/login?redirectTo=%2Fdatabase%2F%5Bdb%5D%2Ftable%2F%5Btbl%5D", - ), - testRedaction( - "statement details page", - "/statement/SELECT * FROM database.table", - "/statement/[statement]", - ), - ].map(function({ title, input, expected }) { - it(`applies a redaction for ${title}`, function() { - setClusterData(store); - const sync = new AnalyticsSync(analytics, store, defaultRedactions); - const expectedLocation = createLocation(expected); - - sync.page(createLocation(input)); - - assert.isTrue(pageSpy.calledOnce); - - const actualArgs = pageSpy.args[0][0]; - const expectedArgs = { - userId: clusterID, - name: expectedLocation.pathname, - properties: { - path: expectedLocation.pathname, - search: expectedLocation.search, - }, - }; - assert.deepEqual( - actualArgs, - expectedArgs, - `Expected:\n${JSON.stringify( - expectedArgs, - null, - 2, - )}\nActual:\n${JSON.stringify(actualArgs, null, 2)}\n`, - ); - }); - }); - }); - - describe("identify method", function() { - let store: Store; - let analytics: Analytics; - let identifySpy: sinon.SinonSpy; - - beforeEach(function() { - store = createAdminUIStore(createHashHistory()); - identifySpy = sandbox.spy(); - - // Analytics is a completely fake object, we don't want to call - // segment if an unexpected method is called. - analytics = { - identify: identifySpy, - } as any; - }); - - afterEach(() => { - sandbox.reset(); - }); - - const setVersionData = function() { - store.dispatch( - nodesReducerObj.receiveData([ - { - build_info: { - tag: "0.1", - }, - }, - ]), - ); - }; - - it("does nothing if cluster info is not available", function() { - const sync = new AnalyticsSync(analytics, store, []); - setVersionData(); - - sync.identify(); - - assert.isTrue(identifySpy.notCalled); - }); - - it("does nothing if version info is not available", function() { - const sync = new AnalyticsSync(analytics, store, []); - setClusterData(store, true, true); - - sync.identify(); - - assert.isTrue(identifySpy.notCalled); - }); - - it("does nothing if reporting is not explicitly enabled", function() { - const sync = new AnalyticsSync(analytics, store, []); - setClusterData(store, false, true); - setVersionData(); - - sync.identify(); - - assert.isTrue(identifySpy.notCalled); - }); - - it("sends the correct value of clusterID, version and enterprise", function() { - setVersionData(); - - _.each([false, true], enterpriseSetting => { - sandbox.reset(); - setClusterData(store, true, enterpriseSetting); - const sync = new AnalyticsSync(analytics, store, []); - sync.identify(); - - assert.isTrue(identifySpy.calledOnce); - assert.deepEqual(identifySpy.args[0][0], { - userId: clusterID, - traits: { - version: "0.1", - userAgent: window.navigator.userAgent, - enterprise: enterpriseSetting, - }, - }); - }); - }); - - it("only reports once", function() { - const sync = new AnalyticsSync(analytics, store, []); - setClusterData(store, true, true); - setVersionData(); - - sync.identify(); - sync.identify(); - - assert.isTrue(identifySpy.calledOnce); - }); - }); - - describe("track method", function() { - const store: Store = createAdminUIStore(createHashHistory()); - let analytics: Analytics; - let trackSpy: sinon.SinonSpy; - - beforeEach(() => { - trackSpy = sandbox.spy(); - - // Analytics is a completely fake object, we don't want to call - // segment if an unexpected method is called. - analytics = { - track: trackSpy, - } as any; - }); - - afterEach(() => { - sandbox.reset(); - }); - - it("does nothing if cluster info is not available", () => { - const sync = new AnalyticsSync(analytics, store, []); - - sync.track({ - event: "test", - }); - - assert.isTrue(trackSpy.notCalled); - }); - - it("add userId to track calls using the cluster_id", () => { - setClusterData(store); - const sync = new AnalyticsSync(analytics, store, []); - - sync.track({ - event: "test", - }); - - const expected = { - userId: clusterID, - properties: { - pagePath: "/", - }, - event: "test", - }; - const message = trackSpy.args[0][0]; - - assert.isTrue(trackSpy.calledOnce); - assert.deepEqual(message, expected); - }); - - it("add the page path to properties", () => { - setClusterData(store); - const sync = new AnalyticsSync(analytics, store, []); - const testPagePath = "/test/page/path"; - - history.push(testPagePath); - - sync.track({ - event: "test", - properties: { - testProp: "test", - }, - }); - - const expected = { - userId: clusterID, - properties: { - pagePath: testPagePath, - testProp: "test", - }, - event: "test", - }; - const message = trackSpy.args[0][0]; - - assert.isTrue(trackSpy.calledOnce); - assert.deepEqual(message, expected); - }); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/redux/analytics.ts b/pkg/ui/workspaces/db-console/src/redux/analytics.ts deleted file mode 100644 index a220cca2a70..00000000000 --- a/pkg/ui/workspaces/db-console/src/redux/analytics.ts +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright 2018 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import Analytics from "analytics-node"; -import { Location } from "history"; -import _ from "lodash"; -import { Store } from "redux"; - -import * as protos from "src/js/protos"; -import { versionsSelector } from "src/redux/nodes"; -import { store, history, AdminUIState } from "src/redux/state"; -import { COCKROACHLABS_ADDR } from "src/util/cockroachlabsAPI"; - -type ClusterResponse = protos.cockroach.server.serverpb.IClusterResponse; - -interface TrackMessage { - event: string; - properties?: Object; - timestamp?: Date; - context?: Object; -} -/** - * List of current redactions needed for pages tracked by the Admin UI. - * TODO(mrtracy): It this list becomes more extensive, it might benefit from a - * set of tests as a double-check. - */ -export const defaultRedactions = [ - // When viewing a specific database, the database name and table are part of - // the URL path. - { - match: new RegExp("/databases/database/.+/table/.+"), - replace: "/databases/database/[db]/table/[tbl]", - }, - { - match: new RegExp("/database/.+/table/.+"), - replace: "/database/[db]/table/[tbl]", - }, - { - match: new RegExp("/database/.+/tables"), - replace: "/database/[db]/tables", - }, - { - match: new RegExp("/database/.+/table"), - replace: "/database/[db]/table", - }, - { - match: new RegExp("/database/.+/grants"), - replace: "/database/[db]/grants", - }, - { - match: new RegExp("/database/.+"), - replace: "/database/[db]", - }, - // The clusterviz map page, which puts localities in the URL. - { - match: new RegExp("/overview/map((/.+)+)"), - useFunction: true, // I hate TypeScript. - replace: function countTiers(original: string, localities: string) { - const tierCount = localities.match(new RegExp("/", "g")).length; - let redactedLocalities = ""; - for (let i = 0; i < tierCount; i++) { - redactedLocalities += "/[locality]"; - } - return original.replace(localities, redactedLocalities); - }, - }, - // The statement details page, with a full SQL statement in the URL. - { - match: new RegExp("/statement/.*"), - replace: "/statement/[statement]", - }, -]; - -type PageTrackReplacementFunction = (match: string, ...args: any[]) => string; -type PageTrackReplacement = string | PageTrackReplacementFunction; - -/** - * A PageTrackRedaction describes a regular expression used to identify PII - * in strings that are being sent to analytics. If a string matches the given - * "match" RegExp, it will be replaced with the "replace" string before being - * sent to analytics. - */ -interface PageTrackRedaction { - match: RegExp; - replace: PageTrackReplacement; - useFunction?: boolean; // I hate Typescript. -} - -/** - * AnalyticsSync is used to dispatch analytics event from the Admin UI to an - * analytics service (currently Segment). It combines information on individual - * events with user information from the redux state in order to properly - * identify events. - */ -export class AnalyticsSync { - /** - * queuedPages are used to store pages visited before the cluster ID - * is available. Once the cluster ID is available, the next call to page() - * will dispatch all queued locations to the underlying analytics API. - */ - private queuedPages: Location[] = []; - - /** - * sentIdentifyEvent tracks whether the identification event has already - * been sent for this session. This event is not sent until all necessary - * information has been retrieved (current version of cockroachDB, - * cluster settings). - */ - private identifyEventSent = false; - - /** - * Construct a new AnalyticsSync object. - * @param analyticsService Underlying interface to push to the analytics service. - * @param deprecatedStore The redux store for the Admin UI. [DEPRECATED] - * @param redactions A list of redaction regular expressions, used to - * scrub any potential personally-identifying information from the data - * being tracked. - */ - constructor( - private analyticsService: Analytics, - private deprecatedStore: Store, - private redactions: PageTrackRedaction[], - ) {} - - /** - * page should be called whenever the user moves to a new page in the - * application. - * @param location The location (URL information) of the page. - */ - page(location: Location) { - // If the cluster ID is not yet available, queue the location to be - // pushed later. - const cluster = this.getCluster(); - if (cluster === null) { - this.queuedPages.push(location); - return; - } - - const { cluster_id, reporting_enabled } = cluster; - - // A cluster setting determines if diagnostic reporting is enabled. If - // it is not explicitly enabled, do nothing. - if (!reporting_enabled) { - if (this.queuedPages.length > 0) { - this.queuedPages = []; - } - return; - } - - // If there are any queued pages, push them. - _.each(this.queuedPages, l => this.pushPage(cluster_id, l)); - this.queuedPages = []; - - // Push the page that was just accessed. - this.pushPage(cluster_id, location); - } - - /** - * identify attempts to send an "identify" event to the analytics service. - * The identify event will only be sent once per session; if it has already - * been sent, it will be a no-op whenever called afterwards. - */ - identify() { - if (this.identifyEventSent) { - return; - } - - // Do nothing if Cluster information is not yet available. - const cluster = this.getCluster(); - if (cluster === null) { - return; - } - - const { cluster_id, reporting_enabled, enterprise_enabled } = cluster; - if (!reporting_enabled) { - return; - } - - // Do nothing if version information is not yet available. - const state = this.deprecatedStore.getState(); - const versions = versionsSelector(state); - if (_.isEmpty(versions)) { - return; - } - - this.analyticsService.identify({ - userId: cluster_id, - traits: { - version: versions[0], - userAgent: window.navigator.userAgent, - enterprise: enterprise_enabled, - }, - }); - this.identifyEventSent = true; - } - - /** Analytics Track for Segment: https://segment.com/docs/connections/spec/track/ */ - track(msg: TrackMessage) { - const cluster = this.getCluster(); - if (cluster === null) { - return; - } - - // get cluster_id to id the event - const { cluster_id } = cluster; - const pagePath = this.redact(history.location.pathname); - - // break down properties from message - const { properties, ...rest } = msg; - const props = { - pagePath, - ...properties, - }; - - const message = { - userId: cluster_id, - properties: { ...props }, - ...rest, - }; - - this.analyticsService.track(message); - } - - /** - * Return the ClusterID from the store, returning null if the clusterID - * has not yet been fetched. We can depend on the alertdatasync component - * to eventually retrieve this without having to request it ourselves. - */ - private getCluster(): ClusterResponse | null { - const state = this.deprecatedStore.getState(); - - // Do nothing if cluster ID has not been loaded. - const cluster = state.cachedData.cluster; - if (!cluster || !cluster.data) { - return null; - } - - return cluster.data; - } - - /** - * pushPage pushes a single "page" event to the analytics service. - */ - private pushPage = (userID: string, location: Location) => { - // Loop through redactions, if any matches return the appropriate - // redacted string. - const path = this.redact(location.pathname); - let search = ""; - - if (location.search && location.search.length > 1) { - const query = location.search.slice(1); - const params = new URLSearchParams(query); - - params.forEach((value, key) => { - params.set(key, this.redact(value)); - }); - search = "?" + params.toString(); - } - - this.analyticsService.page({ - userId: userID, - name: path, - properties: { - path, - search, - }, - }); - }; - - private redact(path: string): string { - _.each(this.redactions, r => { - if (r.match.test(path)) { - // Apparently TypeScript doesn't know how to dispatch functions. - // If there are two function overloads defined (as with - // String.prototype.replace), it is unable to recognize that - // a union of the two types can be successfully passed in as a - // parameter of that function. We have to explicitly - // disambiguate the types for it. - // See https://github.com/Microsoft/TypeScript/issues/14107 - if (r.useFunction) { - path = path.replace( - r.match, - r.replace as PageTrackReplacementFunction, - ); - } else { - path = path.replace(r.match, r.replace as string); - } - return false; - } - }); - return path; - } -} - -// Create a global instance of AnalyticsSync which can be used from various -// packages. If enabled, this instance will push to segment using the following -// analytics key. -const analyticsOpts = { - host: COCKROACHLABS_ADDR + "/api/segment", -}; -const analyticsInstance = new Analytics( - "5Vbp8WMYDmZTfCwE0uiUqEdAcTiZWFDb", - analyticsOpts, -); -export const analytics = new AnalyticsSync( - analyticsInstance, - store, - defaultRedactions, -); - -// Attach a listener to the history object which will track a 'page' event -// whenever the user navigates to a new path. -let lastPageLocation: Location; -history.listen((location: Location) => { - // Do not log if the pathname is the same as the previous. - // Needed because history.listen() fires twice when using hash history, this - // bug is "won't fix" in the version of history we are using, and upgrading - // would imply a difficult upgrade to react-router v4. - // (https://github.com/ReactTraining/history/issues/427). - if (lastPageLocation && lastPageLocation.pathname === location.pathname) { - return; - } - lastPageLocation = location; - analytics.page(location); - // Identify the cluster. - analytics.identify(); -}); - -// Record the initial page that was accessed; listen won't fire for the first -// page loaded. -analytics.page(history.location); -// Identify the cluster. -analytics.identify(); diff --git a/pkg/ui/workspaces/db-console/src/redux/analyticsActions.ts b/pkg/ui/workspaces/db-console/src/redux/analyticsActions.ts deleted file mode 100644 index 39c8e380e77..00000000000 --- a/pkg/ui/workspaces/db-console/src/redux/analyticsActions.ts +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { PayloadAction } from "src/interfaces/action"; - -export const TRACK_STATEMENTS_SEARCH = - "cockroachui/analytics/TRACK_STATEMENTS_SEARCH"; -export const TRACK_STATEMENTS_PAGINATION = - "cockroachui/analytics/TRACK_STATEMENTS_PAGINATION"; -export const TRACK_TABLE_SORT = "cockroachui/analytics/TRACK_TABLE_SORT"; -export const TRACK_DOWNLOAD_DIAGNOSTIC_BUNDLE = - "cockroachui/analytics/TRACK_DOWNLOAD_DIAGNOSTIC_BUNDLE"; -export const TRACK_CANCEL_DIAGNOSTIC_BUNDLE = - "cockroachui/analytics/TRACK_CANCEL_DIAGNOSTIC_BUNDLE"; -export const TRACK_STATEMENT_DETAILS_SUBNAV_SELECTION = - "cockroachui/analytics/TRACK_STATEMENT_DETAILS_SUBNAV_SELECTION"; - -export interface TableSortActionPayload { - tableName: string; - columnName: string; - ascending?: boolean; -} - -export function trackStatementsSearchAction( - searchResults: number, -): PayloadAction { - return { - type: TRACK_STATEMENTS_SEARCH, - payload: searchResults, - }; -} - -export function trackStatementsPaginationAction( - pageNum: number, -): PayloadAction { - return { - type: TRACK_STATEMENTS_PAGINATION, - payload: pageNum, - }; -} - -export function trackTableSortAction( - tableName: string, - columnName: string, - ascending?: boolean, -): PayloadAction { - return { - type: TRACK_TABLE_SORT, - payload: { - tableName, - columnName, - ascending, - }, - }; -} - -export function trackDownloadDiagnosticsBundleAction( - statementFingerprint: string, -): PayloadAction { - return { - type: TRACK_DOWNLOAD_DIAGNOSTIC_BUNDLE, - payload: statementFingerprint, - }; -} - -export function trackCancelDiagnosticsBundleAction( - statementFingerprint: string, -): PayloadAction { - return { - type: TRACK_CANCEL_DIAGNOSTIC_BUNDLE, - payload: statementFingerprint, - }; -} - -export function trackStatementDetailsSubnavSelectionAction( - tabName: string, -): PayloadAction { - return { - type: TRACK_STATEMENT_DETAILS_SUBNAV_SELECTION, - payload: tabName, - }; -} diff --git a/pkg/ui/workspaces/db-console/src/redux/analyticsSagas.ts b/pkg/ui/workspaces/db-console/src/redux/analyticsSagas.ts deleted file mode 100644 index fad9f06c176..00000000000 --- a/pkg/ui/workspaces/db-console/src/redux/analyticsSagas.ts +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { all, call, takeEvery } from "redux-saga/effects"; -import { PayloadAction } from "src/interfaces/action"; -import { - CREATE_STATEMENT_DIAGNOSTICS_REPORT, - DiagnosticsReportPayload, - OPEN_STATEMENT_DIAGNOSTICS_MODAL, -} from "src/redux/statements"; -import { - trackActivateDiagnostics, - trackDiagnosticsModalOpen, - trackPaginate, - trackSearch, - trackTableSort, - trackDownloadDiagnosticsBundle, - trackSubnavSelection, -} from "src/util/analytics"; -import { - TRACK_STATEMENTS_SEARCH, - TRACK_STATEMENTS_PAGINATION, - TRACK_TABLE_SORT, - TableSortActionPayload, - TRACK_DOWNLOAD_DIAGNOSTIC_BUNDLE, - TRACK_STATEMENT_DETAILS_SUBNAV_SELECTION, - TRACK_CANCEL_DIAGNOSTIC_BUNDLE, -} from "./analyticsActions"; -import trackCancelDiagnosticsBundle from "src/util/analytics/trackCancelDiagnosticsBundle"; - -export function* trackActivateStatementsDiagnostics( - action: PayloadAction, -) { - const { statementFingerprint } = action.payload; - yield call(trackActivateDiagnostics, statementFingerprint); -} - -export function* trackOpenStatementsDiagnostics( - action: PayloadAction, -) { - const { statementFingerprint } = action.payload; - yield call(trackDiagnosticsModalOpen, statementFingerprint); -} - -export function* trackStatementsSearch(action: PayloadAction) { - yield call(trackSearch, action.payload); -} - -export function* trackStatementsPagination(action: PayloadAction) { - yield call(trackPaginate, action.payload); -} - -export function* trackTableSortChange( - action: PayloadAction, -) { - const { tableName, columnName, ascending } = action.payload; - yield call(trackTableSort, tableName, columnName, ascending); -} - -export function* trackDownloadDiagnosticBundleSaga( - action: PayloadAction, -) { - yield call(trackDownloadDiagnosticsBundle, action.payload); -} - -export function* trackCancelDiagnosticBundleSaga( - action: PayloadAction, -) { - yield call(trackCancelDiagnosticsBundle, action.payload); -} - -export function* trackStatementDetailsSubnavSelectionSaga( - action: PayloadAction, -) { - yield call(trackSubnavSelection, action.payload); -} - -export function* analyticsSaga() { - yield all([ - takeEvery( - CREATE_STATEMENT_DIAGNOSTICS_REPORT, - trackActivateStatementsDiagnostics, - ), - takeEvery(OPEN_STATEMENT_DIAGNOSTICS_MODAL, trackOpenStatementsDiagnostics), - takeEvery(TRACK_STATEMENTS_SEARCH, trackStatementsSearch), - takeEvery(TRACK_STATEMENTS_PAGINATION, trackStatementsPagination), - takeEvery(TRACK_TABLE_SORT, trackTableSortChange), - takeEvery( - TRACK_DOWNLOAD_DIAGNOSTIC_BUNDLE, - trackDownloadDiagnosticBundleSaga, - ), - takeEvery(TRACK_CANCEL_DIAGNOSTIC_BUNDLE, trackCancelDiagnosticBundleSaga), - takeEvery( - TRACK_STATEMENT_DETAILS_SUBNAV_SELECTION, - trackStatementDetailsSubnavSelectionSaga, - ), - ]); -} diff --git a/pkg/ui/workspaces/db-console/src/redux/apiReducers.ts b/pkg/ui/workspaces/db-console/src/redux/apiReducers.ts index 6107a4816e0..d1fae907219 100644 --- a/pkg/ui/workspaces/db-console/src/redux/apiReducers.ts +++ b/pkg/ui/workspaces/db-console/src/redux/apiReducers.ts @@ -23,8 +23,6 @@ import { PaginatedCachedDataReducerState, } from "./cachedDataReducer"; import * as api from "src/util/api"; -import { VersionList } from "src/interfaces/cockroachlabs"; -import { versionCheck } from "src/util/cockroachlabsAPI"; import { INodeStatus, RollupStoreMetrics } from "src/util/proto"; import { api as clusterUiApi } from "@cockroachlabs/cluster-ui"; import * as protos from "src/js/protos"; @@ -79,9 +77,6 @@ const raftReducerObj = new CachedDataReducer( ); export const refreshRaft = raftReducerObj.refresh; -export const versionReducerObj = new CachedDataReducer(versionCheck, "version"); -export const refreshVersion = versionReducerObj.refresh; - export const locationsReducerObj = new CachedDataReducer( api.getLocations, "locations", @@ -401,7 +396,6 @@ export interface APIReducersState { health: HealthState; nodes: CachedDataReducerState; raft: CachedDataReducerState; - version: CachedDataReducerState; locations: CachedDataReducerState; databases: CachedDataReducerState; databaseDetails: KeyedCachedDataReducerState< @@ -446,7 +440,6 @@ export const apiReducersReducer = combineReducers({ [healthReducerObj.actionNamespace]: healthReducerObj.reducer, [nodesReducerObj.actionNamespace]: nodesReducerObj.reducer, [raftReducerObj.actionNamespace]: raftReducerObj.reducer, - [versionReducerObj.actionNamespace]: versionReducerObj.reducer, [locationsReducerObj.actionNamespace]: locationsReducerObj.reducer, [databasesReducerObj.actionNamespace]: databasesReducerObj.reducer, [databaseDetailsReducerObj.actionNamespace]: diff --git a/pkg/ui/workspaces/db-console/src/redux/customAnalytics/customAnalyticsSagas.spec.ts b/pkg/ui/workspaces/db-console/src/redux/customAnalytics/customAnalyticsSagas.spec.ts deleted file mode 100644 index f411fa7b14f..00000000000 --- a/pkg/ui/workspaces/db-console/src/redux/customAnalytics/customAnalyticsSagas.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { expectSaga } from "redux-saga-test-plan"; -import sinon from "sinon"; -import Analytics from "analytics-node"; - -import { signUpEmailSubscription } from "./customAnalyticsSagas"; -import { signUpForEmailSubscription } from "./customAnanlyticsActions"; - -const sandbox = sinon.createSandbox(); - -describe("customAnalyticsSagas", () => { - describe("signUpEmailSubscription generator", () => { - afterEach(() => { - sandbox.reset(); - }); - - it("calls analytics#identify with user email in args ", () => { - const analyticsIdentifyFn = sandbox.stub(Analytics.prototype, "identify"); - const clusterId = "cluster-1"; - const email = "foo@bar.com"; - const action = signUpForEmailSubscription(clusterId, email); - - return expectSaga(signUpEmailSubscription, action) - .dispatch(action) - .run() - .then(() => { - const expectedAnalyticsMessage = { - userId: clusterId, - traits: { - email, - }, - }; - analyticsIdentifyFn.calledOnceWith(expectedAnalyticsMessage); - }); - }); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/redux/customAnalytics/customAnalyticsSagas.ts b/pkg/ui/workspaces/db-console/src/redux/customAnalytics/customAnalyticsSagas.ts deleted file mode 100644 index 76bf98ed545..00000000000 --- a/pkg/ui/workspaces/db-console/src/redux/customAnalytics/customAnalyticsSagas.ts +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { call, put, takeEvery } from "redux-saga/effects"; -import Analytics from "analytics-node"; - -import { PayloadAction } from "src/interfaces/action"; -import { COCKROACHLABS_ADDR } from "src/util/cockroachlabsAPI"; -import { emailSubscriptionAlertLocalSetting } from "src/redux/alerts"; - -import { - EMAIL_SUBSCRIPTION_SIGN_UP, - EmailSubscriptionSignUpPayload, -} from "./customAnanlyticsActions"; - -export type AnalyticsClientTarget = "email_sign_up"; - -// TODO (koorosh): has to be moved out from code base -const EMAIL_SIGN_UP_CLIENT_KEY = "72EEC0nqQKfoLWq0ZcGoTkJFIG9G9SII"; - -const analyticsOpts = { - host: COCKROACHLABS_ADDR + "/api/segment", -}; - -export function getAnalyticsClientFor( - target: AnalyticsClientTarget, -): Analytics { - switch (target) { - case "email_sign_up": - return new Analytics(EMAIL_SIGN_UP_CLIENT_KEY, analyticsOpts); - default: - throw new Error("Unrecognized Analytics Client target."); - } -} - -export function* signUpEmailSubscription( - action: PayloadAction, -) { - const client = getAnalyticsClientFor("email_sign_up"); - const { clusterId, email } = action.payload; - yield call([client, client.identify], { - userId: clusterId, - traits: { - email, - release_notes_sign_up_from_admin_ui: "true", - product_updates: "true", - }, - }); - yield put(emailSubscriptionAlertLocalSetting.set(true)); -} - -export function* customAnalyticsSaga() { - yield takeEvery(EMAIL_SUBSCRIPTION_SIGN_UP, signUpEmailSubscription); -} diff --git a/pkg/ui/workspaces/db-console/src/redux/customAnalytics/customAnanlyticsActions.ts b/pkg/ui/workspaces/db-console/src/redux/customAnalytics/customAnanlyticsActions.ts deleted file mode 100644 index 31b43cef312..00000000000 --- a/pkg/ui/workspaces/db-console/src/redux/customAnalytics/customAnanlyticsActions.ts +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { PayloadAction } from "src/interfaces/action"; - -export const EMAIL_SUBSCRIPTION_SIGN_UP = - "cockroachui/customanalytics/EMAIL_SUBSCRIPTION_SIGN_UP"; - -export type EmailSubscriptionSignUpPayload = { - email: string; - clusterId: string; -}; - -export function signUpForEmailSubscription( - clusterId: string, - email: string, -): PayloadAction { - return { - type: EMAIL_SUBSCRIPTION_SIGN_UP, - payload: { - email, - clusterId, - }, - }; -} diff --git a/pkg/ui/workspaces/db-console/src/redux/customAnalytics/index.ts b/pkg/ui/workspaces/db-console/src/redux/customAnalytics/index.ts deleted file mode 100644 index a6ad48640fd..00000000000 --- a/pkg/ui/workspaces/db-console/src/redux/customAnalytics/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -export * from "./customAnalyticsSagas"; -export * from "./customAnanlyticsActions"; diff --git a/pkg/ui/workspaces/db-console/src/redux/sagas.ts b/pkg/ui/workspaces/db-console/src/redux/sagas.ts index 6451ffbd884..e7241942d61 100644 --- a/pkg/ui/workspaces/db-console/src/redux/sagas.ts +++ b/pkg/ui/workspaces/db-console/src/redux/sagas.ts @@ -12,9 +12,7 @@ import { all, fork } from "redux-saga/effects"; import { queryMetricsSaga } from "./metrics"; import { localSettingsSaga } from "./localsettings"; -import { customAnalyticsSaga } from "./customAnalytics"; import { statementsSaga } from "./statements"; -import { analyticsSaga } from "./analyticsSagas"; import { sessionsSaga } from "./sessions"; import { sqlStatsSaga } from "./sqlStats"; import { indexUsageStatsSaga } from "./indexUsageStats"; @@ -24,9 +22,7 @@ export default function* rootSaga() { yield all([ fork(queryMetricsSaga), fork(localSettingsSaga), - fork(customAnalyticsSaga), fork(statementsSaga), - fork(analyticsSaga), fork(sessionsSaga), fork(sqlStatsSaga), fork(indexUsageStatsSaga), diff --git a/pkg/ui/workspaces/db-console/src/redux/uiData.ts b/pkg/ui/workspaces/db-console/src/redux/uiData.ts index b28da1c473b..3e81938aeb2 100644 --- a/pkg/ui/workspaces/db-console/src/redux/uiData.ts +++ b/pkg/ui/workspaces/db-console/src/redux/uiData.ts @@ -52,10 +52,6 @@ export class OptInAttributes { updates: boolean = null; // Did the user sign up for product/feature updates } -// VERSION_DISMISSED_KEY is the uiData key on the server that tracks when the outdated banner -// was last dismissed. -export const VERSION_DISMISSED_KEY = "version_dismissed"; - // INSTRUCTIONS_BOX_COLLAPSED_KEY is the uiData key on the server that tracks whether the // instructions box on the cluster viz has been collapsed or not. export const INSTRUCTIONS_BOX_COLLAPSED_KEY = diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/index.ts b/pkg/ui/workspaces/db-console/src/util/analytics/index.ts deleted file mode 100644 index c6b61149927..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -export { default as trackActivateDiagnostics } from "./trackActivateDiagnostics"; -export { default as trackDiagnosticsModalOpen } from "./trackDiagnosticsModalOpen"; -export { default as trackSubnavSelection } from "./trackStatementDetailsSubnavSelection"; -export { default as trackTableSort } from "./trackTableSort"; -export { default as trackPaginate } from "./trackPaginate"; -export { default as trackSearch } from "./trackSearch"; -export { default as trackDownloadDiagnosticsBundle } from "./trackDownloadDiagnosticsBundle"; -export { default as trackDocsLink } from "./trackDocsLink"; -export { default as trackFilter } from "./trackFilter"; -export { default as trackNetworkSort } from "./trackNetworkSort"; -export { default as trackCollapseNodes } from "./trackCollapseNodes"; -export { default as trackTimeScaleSelected } from "./trackTimeScaleSelected"; -export { default as trackTimeFrameChange } from "./trackTimeFrameChange"; diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackActivateDiagnostics.spec.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackActivateDiagnostics.spec.ts deleted file mode 100644 index 1bc550f6835..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackActivateDiagnostics.spec.ts +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { get, isString } from "lodash"; -import { assert } from "chai"; -import { createSandbox } from "sinon"; -import { track } from "./trackActivateDiagnostics"; - -const sandbox = createSandbox(); - -describe("trackActivateDiagnostics", () => { - afterEach(() => { - sandbox.reset(); - }); - - it("should only call track once", () => { - const spy = sandbox.spy(); - track(spy)("some statement"); - assert.isTrue(spy.calledOnce); - }); - - it("should send the right event", () => { - const spy = sandbox.spy(); - const expected = "Diagnostics Activation"; - - track(spy)("whatever"); - - const sent = spy.getCall(0).args[0]; - const event = get(sent, "event"); - - assert.isTrue(isString(event)); - assert.isTrue(event === expected); - }); - - it("should send the correct payload", () => { - const spy = sandbox.spy(); - const statement = "SELECT blah from blah-blah"; - - track(spy)(statement); - - const sent = spy.getCall(0).args[0]; - const fingerprint = get(sent, "properties.fingerprint"); - - assert.isTrue(isString(fingerprint)); - assert.isTrue(fingerprint === statement); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackActivateDiagnostics.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackActivateDiagnostics.ts deleted file mode 100644 index a32e0801f0b..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackActivateDiagnostics.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { analytics } from "src/redux/analytics"; - -export const track = (fn: Function) => (statement: string) => { - fn({ - event: "Diagnostics Activation", - properties: { - fingerprint: statement, - }, - }); -}; - -export default function trackActivateDiagnostics(statement: string) { - const boundTrack = analytics.track.bind(analytics); - track(boundTrack)(statement); -} diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackCancelDiagnosticsBundle.spec.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackCancelDiagnosticsBundle.spec.ts deleted file mode 100644 index 08c91e4c3f8..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackCancelDiagnosticsBundle.spec.ts +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2022 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { get, isString } from "lodash"; -import { assert } from "chai"; -import { createSandbox } from "sinon"; -import { track } from "./trackCancelDiagnosticsBundle"; - -const sandbox = createSandbox(); - -describe("trackCancelDiagnosticsBundle", () => { - afterEach(() => { - sandbox.reset(); - }); - - it("should only call track once", () => { - const spy = sandbox.spy(); - track(spy)("some statement"); - assert.isTrue(spy.calledOnce); - }); - - it("should send the right event", () => { - const spy = sandbox.spy(); - const expected = "Diagnostics Bundle Cancellation"; - - track(spy)("whatever"); - - const sent = spy.getCall(0).args[0]; - const event = get(sent, "event"); - - assert.isTrue(isString(event)); - assert.isTrue(event === expected); - }); - - it("should send the correct payload", () => { - const spy = sandbox.spy(); - const statement = "SELECT blah from blah-blah"; - - track(spy)(statement); - - const sent = spy.getCall(0).args[0]; - const fingerprint = get(sent, "properties.fingerprint"); - - assert.isTrue(isString(fingerprint)); - assert.isTrue(fingerprint === statement); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackCancelDiagnosticsBundle.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackCancelDiagnosticsBundle.ts deleted file mode 100644 index 49ed6448ebf..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackCancelDiagnosticsBundle.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2022 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { analytics } from "src/redux/analytics"; - -export const track = (fn: Function) => (statement: string) => { - fn({ - event: "Diagnostics Bundle Cancellation", - properties: { - fingerprint: statement, - }, - }); -}; - -export default function trackCancelDiagnosticsBundle(statement: string) { - const boundTrack = analytics.track.bind(analytics); - track(boundTrack)(statement); -} diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackCollapseNodes.spec.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackCollapseNodes.spec.ts deleted file mode 100644 index b07019d5b51..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackCollapseNodes.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { get } from "lodash"; -import { assert } from "chai"; -import { createSandbox } from "sinon"; -import { track } from "./trackCollapseNodes"; - -const sandbox = createSandbox(); - -describe("trackCollapseNodes", () => { - const testCollapsed = true; - - afterEach(() => { - sandbox.reset(); - }); - - it("should only call track once", () => { - const spy = sandbox.spy(); - track(spy)(testCollapsed); - assert.isTrue(spy.calledOnce); - }); - - it("should send the right event", () => { - const spy = sandbox.spy(); - const expected = "Collapse Nodes"; - - track(spy)(testCollapsed); - - const sent = spy.getCall(0).args[0]; - const event = get(sent, "event"); - - assert.isTrue(event === expected); - }); - - it("should send the correct payload", () => { - const spy = sandbox.spy(); - - track(spy)(testCollapsed); - - const sent = spy.getCall(0).args[0]; - const collapsed = get(sent, "properties.collapsed"); - - assert.isTrue(collapsed === testCollapsed); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackCollapseNodes.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackCollapseNodes.ts deleted file mode 100644 index 9b6310375a5..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackCollapseNodes.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. -import { analytics } from "src/redux/analytics"; - -export const track = (fn: Function) => (collapsed: boolean) => { - fn({ - event: "Collapse Nodes", - properties: { - collapsed: collapsed, - }, - }); -}; - -export default function trackCollapseNode(collapsed: boolean) { - const boundTrack = analytics.track.bind(analytics); - track(boundTrack)(collapsed); -} diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackDiagnosticsModalOpen.spec.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackDiagnosticsModalOpen.spec.ts deleted file mode 100644 index 0dc2e2cde52..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackDiagnosticsModalOpen.spec.ts +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { get, isString } from "lodash"; -import { assert } from "chai"; -import { createSandbox } from "sinon"; -import { track } from "./trackDiagnosticsModalOpen"; - -const sandbox = createSandbox(); - -describe("trackDiagnosticsModalOpen", () => { - afterEach(() => { - sandbox.reset(); - }); - - it("should only call track once", () => { - const spy = sandbox.spy(); - track(spy)("some statement"); - assert.isTrue(spy.calledOnce); - }); - - it("should send a track call with the correct event", () => { - const spy = sandbox.spy(); - const expected = "Diagnostics Modal Open"; - - track(spy)("some statement"); - - const sent = spy.getCall(0).args[0]; - const event = get(sent, "event"); - - assert.isTrue(isString(event)); - assert.isTrue(event === expected); - }); - - it("send the correct payload", () => { - const spy = sandbox.spy(); - const statement = "SELECT blah from blah-blah"; - - track(spy)(statement); - - const sent = spy.getCall(0).args[0]; - const fingerprint = get(sent, "properties.fingerprint"); - - assert.isTrue(isString(fingerprint)); - assert.isTrue(fingerprint === statement); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackDiagnosticsModalOpen.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackDiagnosticsModalOpen.ts deleted file mode 100644 index dc263ff0c69..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackDiagnosticsModalOpen.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { analytics } from "src/redux/analytics"; - -export const track = (fn: Function) => (statement: string) => { - fn({ - event: "Diagnostics Modal Open", - properties: { - fingerprint: statement, - }, - }); -}; - -export default function trackDiagnosticsModalOpen(statement: string) { - const boundTrack = analytics.track.bind(analytics); - track(boundTrack)(statement); -} diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackDocsLink.spec.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackDocsLink.spec.ts deleted file mode 100644 index be82f61fd86..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackDocsLink.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { get } from "lodash"; -import { assert } from "chai"; -import { createSandbox } from "sinon"; -import { track } from "./trackDocsLink"; - -const sandbox = createSandbox(); - -describe("trackDocsLink", () => { - const targetText = "Test target"; - - afterEach(() => { - sandbox.reset(); - }); - - it("should only call track once", () => { - const spy = sandbox.spy(); - track(spy)(targetText); - assert.isTrue(spy.calledOnce); - }); - - it("should send the right event", () => { - const spy = sandbox.spy(); - const expected = "Link to Docs"; - - track(spy)(targetText); - - const sent = spy.getCall(0).args[0]; - const event = get(sent, "event"); - - assert.isTrue(event === expected); - }); - - it("should send the correct payload", () => { - const spy = sandbox.spy(); - - track(spy)(targetText); - - const sent = spy.getCall(0).args[0]; - const linkText = get(sent, "properties.linkText"); - - assert.isTrue(linkText === targetText); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackDocsLink.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackDocsLink.ts deleted file mode 100644 index 05847938db3..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackDocsLink.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. -import { analytics } from "src/redux/analytics"; - -export const track = (fn: Function) => (targetText: string) => { - fn({ - event: "Link to Docs", - properties: { - linkText: targetText, - }, - }); -}; - -export default function trackDocsLink(targetText: string) { - const boundTrack = analytics.track.bind(analytics); - track(boundTrack)(targetText); -} diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackDownloadDiagnosticsBundle.spec.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackDownloadDiagnosticsBundle.spec.ts deleted file mode 100644 index cc419fc3af2..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackDownloadDiagnosticsBundle.spec.ts +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { get, isString } from "lodash"; -import { assert } from "chai"; -import { createSandbox } from "sinon"; -import { track } from "./trackDownloadDiagnosticsBundle"; - -const sandbox = createSandbox(); - -describe("trackDownloadDiagnosticsBundle", () => { - afterEach(() => { - sandbox.reset(); - }); - - it("should only call track once", () => { - const spy = sandbox.spy(); - track(spy)("some statement"); - assert.isTrue(spy.calledOnce); - }); - - it("should send the right event", () => { - const spy = sandbox.spy(); - const expected = "Diagnostics Bundle Download"; - - track(spy)("whatever"); - - const sent = spy.getCall(0).args[0]; - const event = get(sent, "event"); - - assert.isTrue(isString(event)); - assert.isTrue(event === expected); - }); - - it("should send the correct payload", () => { - const spy = sandbox.spy(); - const statement = "SELECT blah from blah-blah"; - - track(spy)(statement); - - const sent = spy.getCall(0).args[0]; - const fingerprint = get(sent, "properties.fingerprint"); - - assert.isTrue(isString(fingerprint)); - assert.isTrue(fingerprint === statement); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackDownloadDiagnosticsBundle.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackDownloadDiagnosticsBundle.ts deleted file mode 100644 index e8ae4889e58..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackDownloadDiagnosticsBundle.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { analytics } from "src/redux/analytics"; - -export const track = (fn: Function) => (statement: string) => { - fn({ - event: "Diagnostics Bundle Download", - properties: { - fingerprint: statement, - }, - }); -}; - -export default function trackDownloadDiagnosticsBundle(statement: string) { - const boundTrack = analytics.track.bind(analytics); - track(boundTrack)(statement); -} diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackFilter.spec.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackFilter.spec.ts deleted file mode 100644 index ec7869fbd06..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackFilter.spec.ts +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { get } from "lodash"; -import { assert } from "chai"; -import { createSandbox } from "sinon"; -import { track } from "./trackFilter"; - -const sandbox = createSandbox(); - -describe("trackFilter", () => { - const filter = "Test"; - const filterValue = "test-value"; - - afterEach(() => { - sandbox.reset(); - }); - - it("should only call track once", () => { - const spy = sandbox.spy(); - track(spy)(filter, filterValue); - assert.isTrue(spy.calledOnce); - }); - - it("should send a track call with the correct event", () => { - const spy = sandbox.spy(); - const expected = "Test Filter"; - - track(spy)(filter, filterValue); - - const sent = spy.getCall(0).args[0]; - const event = get(sent, "event"); - - assert.isTrue(event === expected); - }); - - it("send the correct payload", () => { - const spy = sandbox.spy(); - - track(spy)(filter, filterValue); - - const sent = spy.getCall(0).args[0]; - const selectedFilter = get(sent, "properties.selectedFilter"); - - assert.isTrue(selectedFilter === filterValue); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackFilter.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackFilter.ts deleted file mode 100644 index f5c12621332..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackFilter.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. -import { analytics } from "src/redux/analytics"; - -export const track = (fn: Function) => (filter: string, value: string) => { - fn({ - event: `${filter} Filter`, - properties: { - selectedFilter: value, - }, - }); -}; - -export default function trackFilter(filter: string, value: string) { - const boundTrack = analytics.track.bind(analytics); - track(boundTrack)(filter, value); -} diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackNetworkSort.spec.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackNetworkSort.spec.ts deleted file mode 100644 index 096c9e08704..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackNetworkSort.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { get } from "lodash"; -import { assert } from "chai"; -import { createSandbox } from "sinon"; -import { track } from "./trackNetworkSort"; - -const sandbox = createSandbox(); - -describe("trackNetworkSort", () => { - const sortBy = "Test"; - - afterEach(() => { - sandbox.reset(); - }); - - it("should only call track once", () => { - const spy = sandbox.spy(); - track(spy)(sortBy); - assert.isTrue(spy.calledOnce); - }); - - it("should send the right event", () => { - const spy = sandbox.spy(); - const expected = "Sort Network Diagnostics"; - - track(spy)(sortBy); - - const sent = spy.getCall(0).args[0]; - const event = get(sent, "event"); - - assert.isTrue(event === expected); - }); - - it("should send the correct payload", () => { - const spy = sandbox.spy(); - - track(spy)(sortBy); - - const sent = spy.getCall(0).args[0]; - const sortedBy = get(sent, "properties.sortBy"); - - assert.isTrue(sortedBy === sortBy); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackNetworkSort.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackNetworkSort.ts deleted file mode 100644 index f29a83b4469..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackNetworkSort.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. -import { analytics } from "src/redux/analytics"; - -export const track = (fn: Function) => (sortBy: string) => { - fn({ - event: "Sort Network Diagnostics", - properties: { - sortBy, - }, - }); -}; - -export default function trackNetworkSort(sortBy: string) { - const boundTrack = analytics.track.bind(analytics); - track(boundTrack)(sortBy); -} diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackPaginate.spec.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackPaginate.spec.ts deleted file mode 100644 index 2654f8a72ad..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackPaginate.spec.ts +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { get, isString, isNumber } from "lodash"; -import { assert } from "chai"; -import { createSandbox } from "sinon"; -import { track } from "./trackPaginate"; - -const sandbox = createSandbox(); - -describe("trackPaginate", () => { - const testPage = 5; - - afterEach(() => { - sandbox.reset(); - }); - - it("should only call track once", () => { - const spy = sandbox.spy(); - track(spy)(testPage); - assert.isTrue(spy.calledOnce); - }); - - it("should send the right event", () => { - const spy = sandbox.spy(); - const expected = "Paginate"; - - track(spy)(testPage); - - const sent = spy.getCall(0).args[0]; - const event = get(sent, "event"); - - assert.isTrue(isString(event)); - assert.isTrue(event === expected); - }); - - it("should send the correct payload", () => { - const spy = sandbox.spy(); - - track(spy)(testPage); - - const sent = spy.getCall(0).args[0]; - const selectedPage = get(sent, "properties.selectedPage"); - - assert.isTrue(isNumber(selectedPage)); - assert.isTrue(selectedPage === testPage); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackPaginate.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackPaginate.ts deleted file mode 100644 index 202dd71642d..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackPaginate.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. -import { analytics } from "src/redux/analytics"; - -export const track = (fn: Function) => (page: number) => { - fn({ - event: "Paginate", - properties: { - selectedPage: page, - }, - }); -}; - -export default function trackPaginate(pageNumber: number) { - const boundTrack = analytics.track.bind(analytics); - track(boundTrack)(pageNumber); -} diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackSearch.spec.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackSearch.spec.ts deleted file mode 100644 index 040a82fa18f..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackSearch.spec.ts +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { get, isString, isNumber } from "lodash"; -import { assert } from "chai"; -import { createSandbox } from "sinon"; -import { track } from "./trackSearch"; - -const sandbox = createSandbox(); - -describe("trackSearch", () => { - const testSearchResults = 3; - - afterEach(() => { - sandbox.reset(); - }); - - it("should only call track once", () => { - const spy = sandbox.spy(); - track(spy)(testSearchResults); - assert.isTrue(spy.calledOnce); - }); - - it("should send the right event", () => { - const spy = sandbox.spy(); - const expected = "Search"; - - track(spy)(testSearchResults); - - const sent = spy.getCall(0).args[0]; - const event = get(sent, "event"); - - assert.isTrue(isString(event)); - assert.isTrue(event === expected); - }); - - it("should send the correct payload", () => { - const spy = sandbox.spy(); - - track(spy)(testSearchResults); - - const sent = spy.getCall(0).args[0]; - const numberOfResults = get(sent, "properties.numberOfResults"); - - assert.isTrue(isNumber(numberOfResults)); - assert.isTrue(numberOfResults === testSearchResults); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackSearch.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackSearch.ts deleted file mode 100644 index 9c7d3832baf..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackSearch.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { analytics } from "src/redux/analytics"; - -export const track = (fn: Function) => (numberOfResults: number) => { - fn({ - event: "Search", - properties: { - numberOfResults, - }, - }); -}; - -export default function trackSearch(numberOfResults: number) { - const boundTrack = analytics.track.bind(analytics); - track(boundTrack)(numberOfResults); -} diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackStatementDetailsSubnavSelection.spec.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackStatementDetailsSubnavSelection.spec.ts deleted file mode 100644 index a74c21667bf..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackStatementDetailsSubnavSelection.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { get } from "lodash"; -import { assert } from "chai"; -import { createSandbox } from "sinon"; -import { track } from "./trackStatementDetailsSubnavSelection"; - -const sandbox = createSandbox(); - -describe("trackSubnavSelection", () => { - const subNavKey = "subnav-test"; - - afterEach(() => { - sandbox.reset(); - }); - - it("should only call track once", () => { - const spy = sandbox.spy(); - track(spy)(subNavKey); - assert.isTrue(spy.calledOnce); - }); - - it("should send a track call with the correct event", () => { - const spy = sandbox.spy(); - const expected = "SubNavigation Selection"; - - track(spy)(subNavKey); - - const sent = spy.getCall(0).args[0]; - const event = get(sent, "event"); - - assert.isTrue(event === expected); - }); - - it("send the correct payload", () => { - const spy = sandbox.spy(); - - track(spy)(subNavKey); - - const sent = spy.getCall(0).args[0]; - const selection = get(sent, "properties.selection"); - - assert.isTrue(selection === subNavKey); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackStatementDetailsSubnavSelection.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackStatementDetailsSubnavSelection.ts deleted file mode 100644 index e3eb61e1d88..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackStatementDetailsSubnavSelection.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { analytics } from "src/redux/analytics"; - -export const track = (fn: Function) => (selection: string) => { - fn({ - event: "SubNavigation Selection", - properties: { - selection, - }, - }); -}; - -export default function trackSubnavSelection(selection: string) { - const boundTrack = analytics.track.bind(analytics); - track(boundTrack)(selection); -} diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackTableSort.spec.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackTableSort.spec.ts deleted file mode 100644 index 23b3d4a430e..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackTableSort.spec.ts +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { get, isString } from "lodash"; -import { assert } from "chai"; -import { createSandbox } from "sinon"; -import { track } from "./trackTableSort"; - -const sandbox = createSandbox(); - -describe("trackTableSort", () => { - afterEach(() => { - sandbox.reset(); - }); - - it("should only call track once", () => { - const spy = sandbox.spy(); - track(spy)(); - assert.isTrue(spy.calledOnce); - }); - - it("should send the right event", () => { - const spy = sandbox.spy(); - const expected = "Table Sort"; - - track(spy)(); - - const sent = spy.getCall(0).args[0]; - const event = get(sent, "event"); - - assert.isTrue(isString(event)); - assert.isTrue(event === expected); - }); - - it("should send the correct payload", () => { - const spy = sandbox.spy(); - const tableName = "Test table"; - const title = "test"; - - track(spy)(tableName, title, "asc"); - - const sent = spy.getCall(0).args[0]; - const table = get(sent, "properties.tableName"); - const columnName = get(sent, "properties.columnName"); - const direction = get(sent, "properties.sortDirection"); - - assert.isTrue(isString(table), "Table name is a string"); - assert.isTrue(table === tableName, "Table name matches given table name"); - - assert.isTrue(isString(columnName), "Column name is a string"); - assert.isTrue( - title === columnName, - "Column name matches given column name", - ); - - assert.isTrue(isString(direction), "Sort direction is a string"); - assert.isTrue( - direction === "asc", - "Sort direction matches the sort setting ascending property", - ); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackTableSort.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackTableSort.ts deleted file mode 100644 index 08544c26137..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackTableSort.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. -import { analytics } from "src/redux/analytics"; - -export const track = (fn: Function) => ( - tableName = "", - columnName = "", - sortDirection: "asc" | "desc" = undefined, -) => { - fn({ - event: "Table Sort", - properties: { - tableName, - columnName, - sortDirection, - }, - }); -}; - -export default function trackTableSort( - tableName?: string, - columnTitle?: string, - ascending?: boolean, -) { - const boundTrack = analytics.track.bind(analytics); - const sortDirection = ascending && ascending ? "asc" : "desc"; - track(boundTrack)(tableName, columnTitle, sortDirection); -} diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackTerminate.tsx b/pkg/ui/workspaces/db-console/src/util/analytics/trackTerminate.tsx deleted file mode 100644 index 6fd213a3c9d..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackTerminate.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { analytics } from "src/redux/analytics"; - -export function trackTerminateSession() { - const boundTrack = analytics.track.bind(analytics); - (() => { - boundTrack({ - event: "Terminate Session", - }); - })(); -} - -export function trackTerminateQuery() { - const boundTrack = analytics.track.bind(analytics); - (() => { - boundTrack({ - event: "Terminate Query", - }); - })(); -} diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackTimeFrameChange.spec.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackTimeFrameChange.spec.ts deleted file mode 100644 index 9904aa4d548..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackTimeFrameChange.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { get } from "lodash"; -import { assert } from "chai"; -import { createSandbox } from "sinon"; -import { track } from "./trackTimeFrameChange"; - -const sandbox = createSandbox(); - -describe("trackPaginate", () => { - const direction = "test"; - - afterEach(() => { - sandbox.reset(); - }); - - it("should only call track once", () => { - const spy = sandbox.spy(); - track(spy)(direction); - assert.isTrue(spy.calledOnce); - }); - - it("should send the right event", () => { - const spy = sandbox.spy(); - const expected = "Time Frame Change"; - - track(spy)(direction); - - const sent = spy.getCall(0).args[0]; - const event = get(sent, "event"); - - assert.isTrue(event === expected); - }); - - it("should send the correct payload", () => { - const spy = sandbox.spy(); - - track(spy)(direction); - - const sent = spy.getCall(0).args[0]; - const changeDirection = get(sent, "properties.direction"); - - assert.isTrue(changeDirection === direction); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackTimeFrameChange.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackTimeFrameChange.ts deleted file mode 100644 index 102ff70309b..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackTimeFrameChange.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. -import { analytics } from "src/redux/analytics"; - -export const track = (fn: Function) => (direction: string) => { - fn({ - event: "Time Frame Change", - properties: { - direction, - }, - }); -}; - -export default function trackTimeFrameChange(direction: string) { - const boundTrack = analytics.track.bind(analytics); - track(boundTrack)(direction); -} diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackTimeScaleOption.spec.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackTimeScaleOption.spec.ts deleted file mode 100644 index 9097c0cbd63..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackTimeScaleOption.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import { get } from "lodash"; -import { assert } from "chai"; -import { createSandbox } from "sinon"; -import { track } from "./trackTimeScaleSelected"; - -const sandbox = createSandbox(); - -describe("trackTimeScaleSelected", () => { - const scale = "Last 2 weeks"; - - afterEach(() => { - sandbox.reset(); - }); - - it("should only call track once", () => { - const spy = sandbox.spy(); - track(spy)(scale); - assert.isTrue(spy.calledOnce); - }); - - it("should send the right event", () => { - const spy = sandbox.spy(); - const expected = "Time Scale Selected"; - - track(spy)(scale); - - const sent = spy.getCall(0).args[0]; - const event = get(sent, "event"); - - assert.isTrue(event === expected); - }); - - it("should send the correct payload", () => { - const spy = sandbox.spy(); - - track(spy)(scale); - - const sent = spy.getCall(0).args[0]; - const timeScale = get(sent, "properties.timeScale"); - - assert.isTrue(timeScale === scale); - }); -}); diff --git a/pkg/ui/workspaces/db-console/src/util/analytics/trackTimeScaleSelected.ts b/pkg/ui/workspaces/db-console/src/util/analytics/trackTimeScaleSelected.ts deleted file mode 100644 index 745960afbde..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/analytics/trackTimeScaleSelected.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. -import { analytics } from "src/redux/analytics"; - -export const track = (fn: Function) => (scale: string) => { - fn({ - event: "Time Scale Selected", - properties: { - timeScale: scale, - }, - }); -}; - -export default function trackTimeScaleSelected(scale: string) { - const boundTrack = analytics.track.bind(analytics); - track(boundTrack)(scale); -} diff --git a/pkg/ui/workspaces/db-console/src/util/cockroachlabsAPI.ts b/pkg/ui/workspaces/db-console/src/util/cockroachlabsAPI.ts deleted file mode 100644 index 2967359b75e..00000000000 --- a/pkg/ui/workspaces/db-console/src/util/cockroachlabsAPI.ts +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2018 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -/** - * This module contains all the REST endpoints for communicating with the admin UI. - */ - -import moment from "moment"; - -import { VersionList, VersionCheckRequest } from "src/interfaces/cockroachlabs"; -import { withTimeout } from "./api"; - -export const COCKROACHLABS_ADDR = "https://register.cockroachdb.com"; - -interface FetchConfig { - method?: string; - timeout?: moment.Duration; -} - -// TODO(maxlang): might be possible to consolidate with Fetch in api.ts -function timeoutFetch( - url: string, - req?: T, - config: FetchConfig = {}, -): Promise { - return withTimeout( - fetch(url, { - method: config.method || (req ? "POST" : "GET"), - headers: { - Accept: "application/json", - "Content-Type": "application/json", - }, - body: req, - }), - config.timeout, - ).then(res => { - if (!res.ok) { - throw Error(res.statusText); - } - return res.json() as Promise; - }); -} - -/** - * COCKROACH LABS ENDPOINTS - */ - -export function versionCheck( - request: VersionCheckRequest, - timeout?: moment.Duration, -): Promise { - return timeoutFetch( - `${COCKROACHLABS_ADDR}/api/clusters/updates?uuid=${request.clusterID}&version=${request.buildtag}`, - null, - { timeout }, - ); -} diff --git a/pkg/ui/workspaces/db-console/src/views/cluster/containers/clusterOverview/index.tsx b/pkg/ui/workspaces/db-console/src/views/cluster/containers/clusterOverview/index.tsx index c325ceab6a1..081f91954d2 100644 --- a/pkg/ui/workspaces/db-console/src/views/cluster/containers/clusterOverview/index.tsx +++ b/pkg/ui/workspaces/db-console/src/views/cluster/containers/clusterOverview/index.tsx @@ -23,7 +23,6 @@ import capacityChart from "./capacity"; import spinner from "assets/spinner.gif"; import { refreshNodes, refreshLiveness } from "src/redux/apiReducers"; import OverviewListAlerts from "src/views/shared/containers/alerts/overviewListAlerts"; -import EmailSubscription from "src/views/dashboard/emailSubscription"; import "./cluster.styl"; import { CapacityUsageTooltip, @@ -308,7 +307,6 @@ export default class ClusterOverview extends React.Component { return (
-
diff --git a/pkg/ui/workspaces/db-console/src/views/dashboard/emailSubscription.tsx b/pkg/ui/workspaces/db-console/src/views/dashboard/emailSubscription.tsx deleted file mode 100644 index 6e583606fbe..00000000000 --- a/pkg/ui/workspaces/db-console/src/views/dashboard/emailSubscription.tsx +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2020 The Cockroach Authors. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -import React from "react"; -import { connect } from "react-redux"; - -import { EmailSubscriptionForm } from "src/views/shared/components/emailSubscriptionForm"; -import { signUpForEmailSubscription } from "src/redux/customAnalytics"; -import { AdminUIState } from "src/redux/state"; -import { clusterIdSelector } from "src/redux/nodes"; - -import "./emailSubscription.styl"; -import { - loadUIData, - RELEASE_NOTES_SIGNUP_DISMISSED_KEY, - saveUIData, -} from "src/redux/uiData"; -import { dismissReleaseNotesSignupForm } from "src/redux/uiDataSelectors"; -import { emailSubscriptionAlertLocalSetting } from "src/redux/alerts"; - -type EmailSubscriptionProps = MapDispatchToProps & MapStateToProps; - -class EmailSubscription extends React.Component { - componentDidMount() { - this.props.refresh(); - } - - handleEmailSubscriptionSubmit = (email: string) => { - this.props.signUpForEmailSubscription(this.props.clusterId, email); - }; - - handlePanelHide = () => { - this.props.dismissAlertMessage(); - this.props.hidePanel(); - }; - - componentWillUnmount() { - this.props.dismissAlertMessage(); - } - - render() { - const { isHiddenPanel } = this.props; - - if (isHiddenPanel) { - return null; - } - - return ( -
-
-
-
- Keep up-to-date with CockroachDB software releases and best - practices. -
-
-
- -
-
- × -
-
-
- ); - } -} - -interface MapDispatchToProps { - signUpForEmailSubscription: (clusterId: string, email: string) => void; - hidePanel: () => void; - refresh: () => void; - dismissAlertMessage: () => void; -} - -const mapDispatchToProps = { - signUpForEmailSubscription, - refresh: () => loadUIData(RELEASE_NOTES_SIGNUP_DISMISSED_KEY), - hidePanel: () => { - return saveUIData({ - key: RELEASE_NOTES_SIGNUP_DISMISSED_KEY, - value: true, - }); - }, - dismissAlertMessage: () => emailSubscriptionAlertLocalSetting.set(false), -}; - -interface MapStateToProps { - isHiddenPanel: boolean; - clusterId: string; -} -const mapStateToProps = (state: AdminUIState) => ({ - isHiddenPanel: dismissReleaseNotesSignupForm(state), - clusterId: clusterIdSelector(state), -}); - -export default connect(mapStateToProps, mapDispatchToProps)(EmailSubscription); diff --git a/pkg/ui/workspaces/db-console/src/views/jobs/index.tsx b/pkg/ui/workspaces/db-console/src/views/jobs/index.tsx index ff12ca3603b..5fa43133a76 100644 --- a/pkg/ui/workspaces/db-console/src/views/jobs/index.tsx +++ b/pkg/ui/workspaces/db-console/src/views/jobs/index.tsx @@ -29,7 +29,6 @@ import { import "./index.styl"; import { statusOptions } from "./jobStatusOptions"; import { JobTable } from "src/views/jobs/jobTable"; -import { trackFilter } from "src/util/analytics"; import JobType = cockroach.sql.jobs.jobspb.Type; import JobsRequest = cockroach.server.serverpb.JobsRequest; import JobsResponse = cockroach.server.serverpb.JobsResponse; @@ -183,8 +182,6 @@ export class JobsTable extends React.Component { } onStatusSelected = (selected: DropdownOption) => { - const filter = selected.value === "" ? "all" : selected.value; - trackFilter("Status", filter); this.props.setStatus(selected.value); util.syncHistory( @@ -197,8 +194,6 @@ export class JobsTable extends React.Component { onTypeSelected = (selected: DropdownOption) => { const type = parseInt(selected.value, 10); - const typeLabel = typeOptions[type].label; - trackFilter("Type", typeLabel); this.props.setType(type); util.syncHistory( diff --git a/pkg/ui/workspaces/db-console/src/views/jobs/jobTable.tsx b/pkg/ui/workspaces/db-console/src/views/jobs/jobTable.tsx index 353b6b66a6e..92dd1684f7b 100644 --- a/pkg/ui/workspaces/db-console/src/views/jobs/jobTable.tsx +++ b/pkg/ui/workspaces/db-console/src/views/jobs/jobTable.tsx @@ -8,7 +8,7 @@ // by the Apache License, Version 2.0, included in the file // licenses/APL.txt. -import React, { MouseEvent } from "react"; +import React from "react"; import { cockroach } from "src/js/protos"; import { DATE_FORMAT_24_UTC } from "src/util/format"; import { JobStatusCell } from "src/views/jobs/jobStatusCell"; @@ -31,7 +31,6 @@ import { jobStatus, jobTable, } from "src/util/docs"; -import { trackDocsLink } from "src/util/analytics"; import { EmptyTable, SortedTable } from "@cockroachlabs/cluster-ui"; import { Anchor } from "src/components"; import emptyTableResultsIcon from "assets/emptyState/empty-table-results.svg"; @@ -263,11 +262,7 @@ export class JobTable extends React.Component { title="No jobs match your search" icon={magnifyingGlassIcon} footer={ - + Learn more about jobs } @@ -280,11 +275,7 @@ export class JobTable extends React.Component { icon={emptyTableResultsIcon} message="The jobs page provides details about backup/restore jobs, schema changes, user-created table statistics, automatic table statistics jobs and changefeeds." footer={ - + Learn more about jobs } @@ -293,10 +284,6 @@ export class JobTable extends React.Component { } }; - redirectToLearnMore = (e: MouseEvent) => { - trackDocsLink(e.currentTarget.text); - }; - render() { const jobs = this.props.jobs.data.jobs; const { pagination } = this.state; diff --git a/pkg/ui/workspaces/db-console/src/views/reports/containers/network/index.tsx b/pkg/ui/workspaces/db-console/src/views/reports/containers/network/index.tsx index 6307c072922..b366c2c8de6 100644 --- a/pkg/ui/workspaces/db-console/src/views/reports/containers/network/index.tsx +++ b/pkg/ui/workspaces/db-console/src/views/reports/containers/network/index.tsx @@ -9,7 +9,7 @@ // licenses/APL.txt. import { deviation as d3Deviation, mean as d3Mean } from "d3"; -import _, { capitalize } from "lodash"; +import _ from "lodash"; import moment from "moment"; import React, { Fragment } from "react"; import { Helmet } from "react-helmet"; @@ -28,7 +28,6 @@ import { import { AdminUIState } from "src/redux/state"; import { util } from "@cockroachlabs/cluster-ui"; import { FixLong } from "src/util/fixLong"; -import { trackFilter, trackCollapseNodes } from "src/util/analytics"; import { getFilters, localityToString, @@ -127,7 +126,6 @@ export class Network extends React.Component { } onChangeCollapse = (collapsed: boolean) => { - trackCollapseNodes(collapsed); this.setState({ collapsed }); }; @@ -141,7 +139,6 @@ export class Network extends React.Component { : data.length === 1 ? null : data.filter((m: string | number) => m !== value); - trackFilter(capitalize(key), value); this.setState({ filter: { ...newFilter, @@ -153,7 +150,6 @@ export class Network extends React.Component { deselectFilterByKey = (key: string) => { const { filter } = this.state; const newFilter = filter ? filter : {}; - trackFilter(capitalize(key), "deselect all"); this.setState({ filter: { ...newFilter, diff --git a/pkg/ui/workspaces/db-console/src/views/reports/containers/network/sort/index.tsx b/pkg/ui/workspaces/db-console/src/views/reports/containers/network/sort/index.tsx index 46a999e4bd0..8bd537ffc89 100644 --- a/pkg/ui/workspaces/db-console/src/views/reports/containers/network/sort/index.tsx +++ b/pkg/ui/workspaces/db-console/src/views/reports/containers/network/sort/index.tsx @@ -13,7 +13,6 @@ import Dropdown, { DropdownOption } from "src/views/shared/components/dropdown"; import React from "react"; import { RouteComponentProps, withRouter } from "react-router-dom"; -import { trackNetworkSort } from "src/util/analytics"; import { getMatchParamByName } from "src/util/query"; import { NetworkFilter, NetworkSort } from ".."; import { Filter } from "../filter"; @@ -38,7 +37,6 @@ class Sort extends React.Component { }; navigateTo = (selected: DropdownOption) => { - trackNetworkSort(selected.label); this.props.onChangeCollapse(false); this.props.history.push(`/reports/network/${selected.value}`); }; diff --git a/pkg/ui/workspaces/db-console/src/views/reports/containers/statementDiagnosticsHistory/index.tsx b/pkg/ui/workspaces/db-console/src/views/reports/containers/statementDiagnosticsHistory/index.tsx index f47275566f6..54ed484b502 100644 --- a/pkg/ui/workspaces/db-console/src/views/reports/containers/statementDiagnosticsHistory/index.tsx +++ b/pkg/ui/workspaces/db-console/src/views/reports/containers/statementDiagnosticsHistory/index.tsx @@ -34,7 +34,6 @@ import { cockroach } from "src/js/protos"; import IStatementDiagnosticsReport = cockroach.server.serverpb.IStatementDiagnosticsReport; import { statementDiagnostics } from "src/util/docs"; import { summarize } from "src/util/sql/summarize"; -import { trackDownloadDiagnosticsBundle } from "src/util/analytics"; import EmptyTableIcon from "!!url-loader!assets/emptyState/empty-table-results.svg"; import { DownloadFile, @@ -49,7 +48,6 @@ import { util, } from "@cockroachlabs/cluster-ui"; import { cancelStatementDiagnosticsReportAction } from "src/redux/statements"; -import { trackCancelDiagnosticsBundleAction } from "src/redux/analyticsActions"; type StatementDiagnosticsHistoryViewProps = MapStateToProps & MapDispatchToProps; @@ -150,9 +148,6 @@ class StatementDiagnosticsHistoryView extends React.Component<
- trackDownloadDiagnosticsBundle(record.statement_fingerprint) - } >