diff --git a/app/scripts/modules/amazon/src/loadBalancer/AmazonLoadBalancersTag.tsx b/app/scripts/modules/amazon/src/loadBalancer/AmazonLoadBalancersTag.tsx index 9f897f86090..74dc87e5172 100644 --- a/app/scripts/modules/amazon/src/loadBalancer/AmazonLoadBalancersTag.tsx +++ b/app/scripts/modules/amazon/src/loadBalancer/AmazonLoadBalancersTag.tsx @@ -3,7 +3,6 @@ import { sortBy } from 'lodash'; import React from 'react'; -import ReactGA from 'react-ga'; import { HealthCounts, @@ -11,6 +10,7 @@ import { ILoadBalancer, ILoadBalancersTagProps, LoadBalancerDataUtils, + logger, ReactInjector, Spinner, Tooltip, @@ -87,7 +87,7 @@ export class AmazonLoadBalancersTag extends React.Component { const { $state } = ReactInjector; const serverGroup = this.props.serverGroup; - ReactGA.event({ category: 'Cluster Pod', action: `Load Load Balancer Details (multiple menu)` }); + logger.log({ category: 'Cluster Pod', action: `Load Load Balancer Details (multiple menu)` }); const nextState = $state.current.name.endsWith('.clusters') ? '.loadBalancerDetails' : '^.loadBalancerDetails'; $state.go(nextState, { region: serverGroup.region, @@ -99,7 +99,7 @@ export class AmazonLoadBalancersTag extends React.Component { const { $state } = ReactInjector; - ReactGA.event({ category: 'Cluster Pod', action: `Load Target Group Details (multiple menu)` }); + logger.log({ category: 'Cluster Pod', action: `Load Target Group Details (multiple menu)` }); const nextState = $state.current.name.endsWith('.clusters') ? '.targetGroupDetails' : '^.targetGroupDetails'; $state.go(nextState, { region: targetGroup.region, @@ -111,7 +111,7 @@ export class AmazonLoadBalancersTag extends React.Component { - ReactGA.event({ category: 'Cluster Pod', action: `Show Load Balancers Menu` }); + logger.log({ category: 'Cluster Pod', action: `Show Load Balancers Menu` }); }; private handleClick = (e: React.MouseEvent): void => { diff --git a/app/scripts/modules/core/src/application/config/managedResources/ManagedResourceConfig.tsx b/app/scripts/modules/core/src/application/config/managedResources/ManagedResourceConfig.tsx index 7bc0d78e0a8..65ad54c5a9f 100644 --- a/app/scripts/modules/core/src/application/config/managedResources/ManagedResourceConfig.tsx +++ b/app/scripts/modules/core/src/application/config/managedResources/ManagedResourceConfig.tsx @@ -1,13 +1,13 @@ import { module } from 'angular'; import classNames from 'classnames'; import React from 'react'; -import ReactGA from 'react-ga'; import { react2angular } from 'react2angular'; import { ManagedWriter } from 'core/managed'; import { useLatestCallback, ValidationMessage } from 'core/presentation'; import { withErrorBoundary } from 'core/presentation/SpinErrorBoundary'; import { NgReact } from 'core/reactShims'; +import { logger } from 'core/utils'; import { Application } from '../../application.model'; @@ -21,10 +21,10 @@ export interface IManagedResourceConfigProps { } const logClick = (label: string, application: string) => - ReactGA.event({ + logger.log({ category: 'Managed Resource Config', action: `${label} clicked`, - label: application, + data: { label: application }, }); const getManagementStatus = (paused: boolean) => { diff --git a/app/scripts/modules/core/src/entityTag/notifications/NotificationsPopover.tsx b/app/scripts/modules/core/src/entityTag/notifications/NotificationsPopover.tsx index 3942ea4d69c..ac6193e6666 100644 --- a/app/scripts/modules/core/src/entityTag/notifications/NotificationsPopover.tsx +++ b/app/scripts/modules/core/src/entityTag/notifications/NotificationsPopover.tsx @@ -1,13 +1,12 @@ import { pick, uniq } from 'lodash'; import React from 'react'; -import ReactGA from 'react-ga'; import { Application } from 'core/application'; import { ConfirmationModalService } from 'core/confirmationModal'; import { IEntityTag, IEntityTags } from 'core/domain'; import { HoverablePopover, IHoverablePopoverContentsProps, Placement } from 'core/presentation'; import { ITaskMonitorConfig } from 'core/task'; -import { noop } from 'core/utils'; +import { logger, noop } from 'core/utils'; import { CategorizedNotifications } from './CategorizedNotifications'; import { EntityTagEditor, IEntityTagEditorProps } from '../EntityTagEditor'; @@ -154,7 +153,7 @@ export class NotificationsPopover extends React.Component { const analyticsLabel = this.props.gaLabelFn(this.props); - ReactGA.event({ action: 'SPAN', category: 'Alerts hovered', label: analyticsLabel }); + logger.log({ action: 'SPAN', category: 'Alerts hovered', data: { label: analyticsLabel } }); }; private PopoverContent = ({ hidePopover }: IHoverablePopoverContentsProps) => { diff --git a/app/scripts/modules/core/src/filterModel/FilterTags.tsx b/app/scripts/modules/core/src/filterModel/FilterTags.tsx index da336bb4d48..b1735b0d191 100644 --- a/app/scripts/modules/core/src/filterModel/FilterTags.tsx +++ b/app/scripts/modules/core/src/filterModel/FilterTags.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import ReactGA from 'react-ga'; import { CollapsibleSectionStateCache } from 'core/cache'; +import { logger } from 'core/utils'; export interface IFilter { label: string; @@ -39,13 +39,13 @@ export const FilterTags = ({ clearFilters, tags, tagCleared }: IFilterTagsProps) if (clearFilters) { clearFilters(); } - ReactGA.event({ category: 'Filter Tags', action: 'Clear All clicked' }); + logger.log({ category: 'Filter Tags', action: 'Clear All clicked' }); }; const clearIndividualFilter = (tag: IFilterTag): void => { tag.clear(); tagCleared(); - ReactGA.event({ category: 'Filter Tags', action: 'Individual tag removed' }); + logger.log({ category: 'Filter Tags', action: 'Individual tag removed' }); }; return ( diff --git a/app/scripts/modules/core/src/help/HelpField.tsx b/app/scripts/modules/core/src/help/HelpField.tsx index 62eb88d378b..4c9e6c7ad43 100644 --- a/app/scripts/modules/core/src/help/HelpField.tsx +++ b/app/scripts/modules/core/src/help/HelpField.tsx @@ -1,8 +1,8 @@ import { isUndefined } from 'lodash'; import React from 'react'; -import ReactGA from 'react-ga'; import { HoverablePopover, Markdown, Placement } from 'core/presentation'; +import { logger } from 'core/utils'; import { HelpTextExpandedContext } from './HelpTextExpandedContext'; import { HelpContentsRegistry } from './helpContents.registry'; @@ -35,7 +35,7 @@ export function HelpField(props: IHelpFieldProps) { const onShow = (): void => setPopoverShownStart(Date.now()); const onHide = (): void => { if (Date.now() - popoverShownStart > 500) { - ReactGA.event({ action: 'Help contents viewed', category: 'Help', label: props.id || props.content }); + logger.log({ action: 'Help contents viewed', category: 'Help', data: { label: props.id || props.content } }); } }; diff --git a/app/scripts/modules/core/src/instance/details/InstanceInsights.tsx b/app/scripts/modules/core/src/instance/details/InstanceInsights.tsx index 3e8e4091bdd..48c5a550093 100644 --- a/app/scripts/modules/core/src/instance/details/InstanceInsights.tsx +++ b/app/scripts/modules/core/src/instance/details/InstanceInsights.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { Dropdown } from 'react-bootstrap'; -import ReactGA from 'react-ga'; import { IInstance } from 'core/domain'; +import { logger } from 'core/utils'; export interface Insight { label: string; @@ -18,10 +18,10 @@ export interface IInstanceInsightsProps { export const InstanceInsights = ({ analytics, insights, instance, title }: IInstanceInsightsProps) => { const logClickEvent = (label: string) => { - ReactGA.event({ + logger.log({ category: 'Insight Menu (Instance)', action: `${label} clicked`, - label: `${instance.account}/${instance.region}/${instance.name}/${instance.serverGroup}`, + data: { label: `${instance.account}/${instance.region}/${instance.name}/${instance.serverGroup}` }, }); }; diff --git a/app/scripts/modules/core/src/loadBalancer/LoadBalancersTag.tsx b/app/scripts/modules/core/src/loadBalancer/LoadBalancersTag.tsx index 449db148d6e..47ba89a33ba 100644 --- a/app/scripts/modules/core/src/loadBalancer/LoadBalancersTag.tsx +++ b/app/scripts/modules/core/src/loadBalancer/LoadBalancersTag.tsx @@ -1,12 +1,12 @@ import { sortBy } from 'lodash'; import React from 'react'; -import ReactGA from 'react-ga'; import { ILoadBalancer } from 'core/domain'; import { HealthCounts } from 'core/healthCounts/HealthCounts'; import { HoverablePopover } from 'core/presentation'; import { Tooltip } from 'core/presentation/Tooltip'; import { ReactInjector } from 'core/reactShims'; +import { logger } from 'core/utils'; import { Spinner } from 'core/widgets'; import { ILoadBalancersTagProps } from './LoadBalancersTagWrapper'; @@ -72,7 +72,7 @@ export class LoadBalancersTag extends React.Component { const { $state } = ReactInjector; const serverGroup = this.props.serverGroup; - ReactGA.event({ category: 'Cluster Pod', action: `Load Load Balancer Details (multiple menu)` }); + logger.log({ category: 'Cluster Pod', action: `Load Load Balancer Details (multiple menu)` }); const nextState = $state.current.name.endsWith('.clusters') ? '.loadBalancerDetails' : '^.loadBalancerDetails'; $state.go(nextState, { region: serverGroup.region, @@ -83,7 +83,7 @@ export class LoadBalancersTag extends React.Component { - ReactGA.event({ category: 'Cluster Pod', action: `Show Load Balancers Menu` }); + logger.log({ category: 'Cluster Pod', action: `Show Load Balancers Menu` }); }; private handleClick = (e: React.MouseEvent): void => { diff --git a/app/scripts/modules/core/src/managed/ManagedResourceDetailsIndicator.tsx b/app/scripts/modules/core/src/managed/ManagedResourceDetailsIndicator.tsx index cffc397c8dd..eaea66c7b9b 100644 --- a/app/scripts/modules/core/src/managed/ManagedResourceDetailsIndicator.tsx +++ b/app/scripts/modules/core/src/managed/ManagedResourceDetailsIndicator.tsx @@ -1,6 +1,5 @@ import React from 'react'; import { Dropdown, MenuItem } from 'react-bootstrap'; -import ReactGA from 'react-ga'; import { Application } from 'core/application'; import { SETTINGS } from 'core/config/settings'; @@ -9,6 +8,7 @@ import { HelpField } from 'core/help'; import { HoverablePopover } from 'core/presentation'; import { ReactInjector } from 'core/reactShims'; +import { logger } from '..'; import managedDeliveryLogo from './icons/md-logo-color.svg'; import { showManagedResourceHistoryModal } from './resourceHistory/ManagedResourceHistoryModal'; import { toggleResourcePause } from './toggleResourceManagement'; @@ -21,10 +21,10 @@ export interface IManagedResourceDetailsIndicatorProps { } const logClick = (label: string, resourceId: string) => - ReactGA.event({ + logger.log({ category: 'Managed Resource Menu', action: `${label} clicked`, - label: resourceId, + data: { label: resourceId }, }); export const ManagedResourceDetailsIndicator = ({ diff --git a/app/scripts/modules/core/src/managed/ToggleManagedResourceForApplication.tsx b/app/scripts/modules/core/src/managed/ToggleManagedResourceForApplication.tsx index 7f92fe15348..d49c05c1fb3 100644 --- a/app/scripts/modules/core/src/managed/ToggleManagedResourceForApplication.tsx +++ b/app/scripts/modules/core/src/managed/ToggleManagedResourceForApplication.tsx @@ -1,7 +1,7 @@ import React, { memo, useState } from 'react'; -import ReactGA from 'react-ga'; import { Illustration, IllustrationName } from '@spinnaker/presentation'; +import { logger } from 'core/utils'; import { Button } from './Button'; import { ManagedWriter } from './ManagedWriter'; @@ -16,10 +16,10 @@ import { } from '../presentation'; const logClick = (label: string, application: string) => - ReactGA.event({ + logger.log({ category: 'Environments - toggle application management modal', action: `${label} clicked`, - label: application, + data: { label: application }, }); export interface IToggleManagedResourceForApplicationModalProps extends IModalComponentProps { diff --git a/app/scripts/modules/core/src/managed/artifactDetail/MarkArtifactAsBadModal.tsx b/app/scripts/modules/core/src/managed/artifactDetail/MarkArtifactAsBadModal.tsx index c1d95dd4ae2..280716fb4ac 100644 --- a/app/scripts/modules/core/src/managed/artifactDetail/MarkArtifactAsBadModal.tsx +++ b/app/scripts/modules/core/src/managed/artifactDetail/MarkArtifactAsBadModal.tsx @@ -1,8 +1,8 @@ import React, { memo, useCallback, useEffect } from 'react'; -import ReactGA from 'react-ga'; import { Option } from 'react-select'; import { Illustration } from '@spinnaker/presentation'; +import { logger } from 'core/utils'; import { Button } from '../Button'; import { EnvironmentBadge } from '../EnvironmentBadge'; @@ -28,10 +28,10 @@ import { useEnvironmentTypeFromResources } from '../useEnvironmentTypeFromResour const MARK_BAD_DOCS_URL = 'https://www.spinnaker.io/guides/user/managed-delivery/marking-as-bad/'; const logEvent = (label: string, application: string, environment?: string, reference?: string) => - ReactGA.event({ + logger.log({ category: 'Environments - mark version as bad modal', action: label, - label: environment ? `${application}:${environment}:${reference}` : application, + data: { label: environment ? `${application}:${environment}:${reference}` : application }, }); type IEnvironmentOptionProps = Required> & { diff --git a/app/scripts/modules/core/src/managed/artifactDetail/PinArtifactModal.tsx b/app/scripts/modules/core/src/managed/artifactDetail/PinArtifactModal.tsx index 6b1f0e99110..ded3699ebce 100644 --- a/app/scripts/modules/core/src/managed/artifactDetail/PinArtifactModal.tsx +++ b/app/scripts/modules/core/src/managed/artifactDetail/PinArtifactModal.tsx @@ -1,8 +1,8 @@ import React, { memo, useCallback, useEffect } from 'react'; -import ReactGA from 'react-ga'; import { Option } from 'react-select'; import { Illustration } from '@spinnaker/presentation'; +import { logger } from 'core/utils'; import { Button } from '../Button'; import { EnvironmentBadge } from '../EnvironmentBadge'; @@ -28,10 +28,10 @@ import { useEnvironmentTypeFromResources } from '../useEnvironmentTypeFromResour const PINNING_DOCS_URL = 'https://www.spinnaker.io/guides/user/managed-delivery/pinning'; const logEvent = (label: string, application: string, environment?: string, reference?: string) => - ReactGA.event({ + logger.log({ category: 'Environments - pin version modal', action: label, - label: environment ? `${application}:${environment}:${reference}` : application, + data: { label: environment ? `${application}:${environment}:${reference}` : application }, }); type IEnvironmentOptionProps = Required> & { diff --git a/app/scripts/modules/core/src/managed/artifactDetail/PreDeploymentStepCard.tsx b/app/scripts/modules/core/src/managed/artifactDetail/PreDeploymentStepCard.tsx index 1d4cceaecf1..0647ac603bd 100644 --- a/app/scripts/modules/core/src/managed/artifactDetail/PreDeploymentStepCard.tsx +++ b/app/scripts/modules/core/src/managed/artifactDetail/PreDeploymentStepCard.tsx @@ -1,12 +1,11 @@ import { DateTime } from 'luxon'; import React, { memo } from 'react'; -import ReactGA from 'react-ga'; import { Button } from '../Button'; import { StatusCard } from '../StatusCard'; import { Application } from '../../application'; import { IManagedArtifactVersionLifecycleStep } from '../../domain'; -import { timeDiffToString } from '../../utils'; +import { logger, timeDiffToString } from '../../utils'; const cardAppearanceByStatus = { NOT_STARTED: 'future', @@ -69,10 +68,10 @@ const cardConfigurationByType = { } as const; const logEvent = (label: string, application: string, reference: string, type: string, status: string) => - ReactGA.event({ + logger.log({ category: 'Environments - version details', action: label, - label: `${application}:${reference}:${type}:${status}`, + data: { label: `${application}:${reference}:${type}:${status}` }, }); const getTimestamp = (startedAt?: string, completedAt?: string) => { diff --git a/app/scripts/modules/core/src/managed/artifactDetail/UnpinArtifactModal.tsx b/app/scripts/modules/core/src/managed/artifactDetail/UnpinArtifactModal.tsx index 0368d9ec894..45dd90a7918 100644 --- a/app/scripts/modules/core/src/managed/artifactDetail/UnpinArtifactModal.tsx +++ b/app/scripts/modules/core/src/managed/artifactDetail/UnpinArtifactModal.tsx @@ -1,7 +1,7 @@ import React, { memo, useEffect, useState } from 'react'; -import ReactGA from 'react-ga'; import { Illustration } from '@spinnaker/presentation'; +import { logger } from 'core/utils'; import { Button } from '../Button'; import { ManagedWriter } from '../ManagedWriter'; @@ -21,10 +21,10 @@ import { const PINNING_DOCS_URL = 'https://www.spinnaker.io/guides/user/managed-delivery/pinning'; const logEvent = (label: string, application: string, environment?: string, reference?: string) => - ReactGA.event({ + logger.log({ category: 'Environments - unpin version modal', action: label, - label: environment ? `${application}:${environment}:${reference}` : application, + data: { label: environment ? `${application}:${environment}:${reference}` : application }, }); export const UnpinVersionIntro = ({ application, environment }: { application: string; environment: string }) => ( diff --git a/app/scripts/modules/core/src/managed/constraints/ConstraintCard.tsx b/app/scripts/modules/core/src/managed/constraints/ConstraintCard.tsx index 2439c3a77a1..78877d59ea9 100644 --- a/app/scripts/modules/core/src/managed/constraints/ConstraintCard.tsx +++ b/app/scripts/modules/core/src/managed/constraints/ConstraintCard.tsx @@ -1,6 +1,7 @@ import classNames from 'classnames'; import React, { memo, useState } from 'react'; -import ReactGA from 'react-ga'; + +import { logger } from 'core/utils'; import { Button } from '../Button'; import { IUpdateConstraintStatusRequest, ManagedWriter } from '../ManagedWriter'; @@ -40,10 +41,10 @@ const skippedConstraintCardAppearanceByStatus: { [key in ConstraintStatus]: ISta } as const; const logEvent = (label: string, application: string, environment: string, reference: string) => - ReactGA.event({ + logger.log({ category: 'Environments - version details', action: label, - label: `${application}:${environment}:${reference}`, + data: { label: `${application}:${environment}:${reference}` }, }); // TODO: improve this logic below diff --git a/app/scripts/modules/core/src/managed/managedResourceStatusConfig.tsx b/app/scripts/modules/core/src/managed/managedResourceStatusConfig.tsx index 95cb34c2c1e..3098c8f994b 100644 --- a/app/scripts/modules/core/src/managed/managedResourceStatusConfig.tsx +++ b/app/scripts/modules/core/src/managed/managedResourceStatusConfig.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import ReactGA from 'react-ga'; import { IconNames } from '@spinnaker/presentation'; import { Application } from 'core/application'; import { IManagedResourceSummary, ManagedResourceStatus } from 'core/domain'; +import { logger } from 'core/utils'; interface IViewConfiguration { appearance: 'info' | 'warning' | 'error'; @@ -12,10 +12,10 @@ interface IViewConfiguration { } const logClick = (label: string, resourceId: string, status: ManagedResourceStatus) => - ReactGA.event({ + logger.log({ category: 'Managed Resource Status Indicator', action: `${label} clicked`, - label: `${resourceId},${status}`, + data: { label: `${resourceId},${status}` }, }); const LearnMoreLink = ({ resourceSummary }: { resourceSummary: IManagedResourceSummary }) => ( diff --git a/app/scripts/modules/core/src/managed/utils/logging.ts b/app/scripts/modules/core/src/managed/utils/logging.ts index 94c544915ba..609bce5782e 100644 --- a/app/scripts/modules/core/src/managed/utils/logging.ts +++ b/app/scripts/modules/core/src/managed/utils/logging.ts @@ -1,4 +1,4 @@ -import ReactGA from 'react-ga'; +import { logger } from 'core/utils'; import { useApplicationContext } from '../../presentation/hooks/useApplicationContext.hook'; interface LogProps { @@ -9,10 +9,10 @@ interface LogProps { } export const logEvent = ({ category, action, application, label }: LogProps) => { - ReactGA.event({ + logger.log({ category, - action, - label: (application ? `${application}:` : ``) + label, + action: action, + data: { label: (application ? `${application}:` : ``) + label }, }); }; diff --git a/app/scripts/modules/core/src/pipeline/config/CreatePipeline.tsx b/app/scripts/modules/core/src/pipeline/config/CreatePipeline.tsx index 4b3af2084d8..bb5db092467 100644 --- a/app/scripts/modules/core/src/pipeline/config/CreatePipeline.tsx +++ b/app/scripts/modules/core/src/pipeline/config/CreatePipeline.tsx @@ -1,12 +1,12 @@ import { get } from 'lodash'; import React from 'react'; import { Dropdown } from 'react-bootstrap'; -import ReactGA from 'react-ga'; import { Application } from 'core/application'; import { IPipeline } from 'core/domain'; import { Tooltip } from 'core/presentation/Tooltip'; import { ReactInjector } from 'core/reactShims'; +import { logger } from 'core/utils'; import { CreatePipelineButton } from '../create/CreatePipelineButton'; @@ -16,7 +16,7 @@ export interface ICreatePipelineProps { export class CreatePipeline extends React.Component { private dropdownToggled = (): void => { - ReactGA.event({ category: 'Pipelines', action: 'Configure (top level)' }); + logger.log({ category: 'Pipelines', action: 'Configure (top level)' }); }; public render() { @@ -75,7 +75,7 @@ export class CreatePipeline extends React.Component { const Pipeline = (props: { pipeline: any; type: 'pipeline' | 'strategy' }): JSX.Element => { const clicked = () => { - ReactGA.event({ category: 'Pipelines', action: `Configure ${props.type} (via top level)` }); + logger.log({ category: 'Pipelines', action: `Configure ${props.type} (via top level)` }); const { $state } = ReactInjector; if (!$state.current.name.includes('.executions.execution')) { $state.go('^.pipelineConfig', { pipelineId: props.pipeline.id }); diff --git a/app/scripts/modules/core/src/pipeline/config/graph/PipelineGraphNode.tsx b/app/scripts/modules/core/src/pipeline/config/graph/PipelineGraphNode.tsx index 3547d31cece..b23377f5f8a 100644 --- a/app/scripts/modules/core/src/pipeline/config/graph/PipelineGraphNode.tsx +++ b/app/scripts/modules/core/src/pipeline/config/graph/PipelineGraphNode.tsx @@ -1,11 +1,11 @@ import classNames from 'classnames'; import { get } from 'lodash'; import React from 'react'; -import ReactGA from 'react-ga'; import { IExecutionStageSummary } from 'core/domain'; import { LabelComponent, Markdown } from 'core/presentation'; import { Popover } from 'core/presentation/Popover'; +import { logger } from 'core/utils'; import { IPipelineGraphNode } from './pipelineGraph.service'; import { GroupExecutionPopover } from '../stages/group/GroupExecutionPopover'; @@ -31,7 +31,7 @@ export class PipelineGraphNode extends React.Component }; private handleClick = (): void => { - ReactGA.event({ + logger.log({ category: `Pipeline Graph (${this.props.isExecution ? 'execution' : 'config'})`, action: `Node clicked`, }); @@ -39,7 +39,7 @@ export class PipelineGraphNode extends React.Component }; private subStageClicked = (groupStage: IExecutionStageSummary, stage: IExecutionStageSummary): void => { - ReactGA.event({ + logger.log({ category: `Pipeline Graph (${this.props.isExecution ? 'execution' : 'config'})`, action: `Grouped stage clicked`, }); diff --git a/app/scripts/modules/core/src/pipeline/create/CreatePipelineButton.tsx b/app/scripts/modules/core/src/pipeline/create/CreatePipelineButton.tsx index dce3de3854f..a203f47dd4b 100644 --- a/app/scripts/modules/core/src/pipeline/create/CreatePipelineButton.tsx +++ b/app/scripts/modules/core/src/pipeline/create/CreatePipelineButton.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import ReactGA from 'react-ga'; import { Application } from 'core/application'; import { Tooltip } from 'core/presentation/Tooltip'; import { ReactInjector } from 'core/reactShims'; +import { logger } from 'core/utils'; import { CreatePipelineModal } from './CreatePipelineModal'; @@ -30,7 +30,7 @@ export class CreatePipelineButton extends React.Component { - ReactGA.event({ category: 'Pipelines', action: 'Create Pipeline' }); + logger.log({ category: 'Pipelines', action: 'Create Pipeline' }); this.setState({ showCreatePipelineModal: true }); }; diff --git a/app/scripts/modules/core/src/pipeline/details/ExecutionDetailsSectionNav.tsx b/app/scripts/modules/core/src/pipeline/details/ExecutionDetailsSectionNav.tsx index 3ca2673659d..9061ac77ffe 100644 --- a/app/scripts/modules/core/src/pipeline/details/ExecutionDetailsSectionNav.tsx +++ b/app/scripts/modules/core/src/pipeline/details/ExecutionDetailsSectionNav.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import ReactGA from 'react-ga'; import { Subscription } from 'rxjs'; import { robotToHuman } from 'core/presentation/robotToHumanFilter/robotToHuman.filter'; import { ReactInjector } from 'core/reactShims'; +import { logger } from 'core/utils'; export interface IExecutionDetailsSectionNavProps { sections: string[]; @@ -57,7 +57,7 @@ export class ExecutionDetailsSectionNav extends React.Component< const Section = (props: { section: string; active: boolean }): JSX.Element => { const clicked = () => { - ReactGA.event({ category: 'Pipeline', action: 'Execution details section selected', label: props.section }); + logger.log({ category: 'Pipeline', action: 'Execution details section selected', data: { label: props.section } }); ReactInjector.$state.go('.', { details: props.section }); }; return ( diff --git a/app/scripts/modules/core/src/pipeline/details/SingleExecutionDetails.tsx b/app/scripts/modules/core/src/pipeline/details/SingleExecutionDetails.tsx index 1a3e49f3790..777cb2f4ae6 100644 --- a/app/scripts/modules/core/src/pipeline/details/SingleExecutionDetails.tsx +++ b/app/scripts/modules/core/src/pipeline/details/SingleExecutionDetails.tsx @@ -1,7 +1,6 @@ import { UISref, useCurrentStateAndParams } from '@uirouter/react'; import { set } from 'lodash'; import React, { useEffect, useState } from 'react'; -import ReactGA from 'react-ga'; import { Application } from 'core/application/application.model'; import { IExecution, IPipeline } from 'core/domain'; @@ -9,6 +8,7 @@ import { useData, useLatestPromise } from 'core/presentation'; import { IStateChange, ReactInjector } from 'core/reactShims'; import { SchedulerFactory } from 'core/scheduler'; import { ExecutionState } from 'core/state'; +import { logger } from 'core/utils'; import { Execution } from '../executions/execution/Execution'; import { ManualExecutionModal } from '../manualExecution'; @@ -125,7 +125,7 @@ export function SingleExecutionDetails(props: ISingleExecutionDetailsProps) { const checked = event.target.checked; setShowDurations(checked); ExecutionState.filterModel.asFilterModel.sortFilter.showDurations = showDurations; - ReactGA.event({ category: 'Pipelines', action: 'Toggle Durations', label: checked.toString() }); + logger.log({ category: 'Pipelines', action: 'Toggle Durations', data: { label: checked.toString() } }); }; const rerunExecution = (execution: IExecution, application: Application, pipeline: IPipeline) => { diff --git a/app/scripts/modules/core/src/pipeline/executionBuild/ExecutionBuildLink.tsx b/app/scripts/modules/core/src/pipeline/executionBuild/ExecutionBuildLink.tsx index 8e449276b68..93b09d2cfa1 100644 --- a/app/scripts/modules/core/src/pipeline/executionBuild/ExecutionBuildLink.tsx +++ b/app/scripts/modules/core/src/pipeline/executionBuild/ExecutionBuildLink.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import ReactGA from 'react-ga'; import { IExecution } from 'core/domain'; +import { logger } from 'core/utils'; import './ExecutionBuildLink.less'; @@ -15,7 +15,7 @@ export class ExecutionBuildLink extends React.Component) => { - ReactGA.event({ category: 'Pipeline', action: 'Execution build number clicked - build info' }); + logger.log({ category: 'Pipeline', action: 'Execution build number clicked - build info' }); event.stopPropagation(); }; diff --git a/app/scripts/modules/core/src/pipeline/executions/Executions.tsx b/app/scripts/modules/core/src/pipeline/executions/Executions.tsx index ea802a575da..d3a601f18f6 100644 --- a/app/scripts/modules/core/src/pipeline/executions/Executions.tsx +++ b/app/scripts/modules/core/src/pipeline/executions/Executions.tsx @@ -1,7 +1,6 @@ import { get } from 'lodash'; import { $q } from 'ngimport'; import React from 'react'; -import ReactGA from 'react-ga'; import { Subscription } from 'rxjs'; import { Application } from 'core/application'; @@ -13,6 +12,7 @@ import { ReactInjector } from 'core/reactShims'; import { SchedulerFactory } from 'core/scheduler'; import { IScheduler } from 'core/scheduler/SchedulerFactory'; import { ExecutionState } from 'core/state'; +import { logger } from 'core/utils'; import { IRetryablePromise } from 'core/utils/retryablePromise'; import { Spinner } from 'core/widgets/spinners/Spinner'; @@ -136,12 +136,12 @@ export class Executions extends React.Component { - ReactGA.event({ category: 'Pipelines', action: 'Expand All' }); + logger.log({ category: 'Pipelines', action: 'Expand All' }); ExecutionState.filterModel.expandSubject.next(true); }; private collapse = (): void => { - ReactGA.event({ category: 'Pipelines', action: 'Collapse All' }); + logger.log({ category: 'Pipelines', action: 'Collapse All' }); ExecutionState.filterModel.expandSubject.next(false); }; @@ -164,7 +164,7 @@ export class Executions extends React.Component): void => { const value = event.target.value; - ReactGA.event({ category: 'Pipelines', action: 'Group By', label: value }); + logger.log({ category: 'Pipelines', action: 'Group By', data: { label: value } }); this.state.sortFilter.groupBy = value; this.updateExecutionGroups(); }; @@ -276,7 +276,7 @@ export class Executions extends React.Component): void => { const value = event.target.value; this.state.sortFilter.count = parseInt(value, 10); - ReactGA.event({ category: 'Pipelines', action: 'Change Count', label: value }); + logger.log({ category: 'Pipelines', action: 'Change Count', data: { label: value } }); this.updateExecutionGroups(true); }; @@ -287,7 +287,7 @@ export class Executions extends React.Component { diff --git a/app/scripts/modules/core/src/pipeline/executions/execution/Execution.tsx b/app/scripts/modules/core/src/pipeline/executions/execution/Execution.tsx index 2be5003f2cd..542e423e054 100644 --- a/app/scripts/modules/core/src/pipeline/executions/execution/Execution.tsx +++ b/app/scripts/modules/core/src/pipeline/executions/execution/Execution.tsx @@ -3,7 +3,6 @@ import classNames from 'classnames'; import { isEqual } from 'lodash'; import { $location } from 'ngimport'; import React from 'react'; -import ReactGA from 'react-ga'; import { Subscription } from 'rxjs'; import { AccountTag } from 'core/account'; @@ -17,6 +16,7 @@ import { Overridable } from 'core/overrideRegistry'; import { Tooltip } from 'core/presentation/Tooltip'; import { ReactInjector } from 'core/reactShims'; import { ExecutionState } from 'core/state'; +import { logger } from 'core/utils'; import { duration, timestamp } from 'core/utils/timeFormatters'; import { ExecutionBreadcrumbs } from './ExecutionBreadcrumbs'; @@ -266,48 +266,48 @@ export class Execution extends React.PureComponent { - ReactGA.event({ category: 'Pipeline', action: 'Execution source clicked (no stages found)' }); + logger.log({ category: 'Pipeline', action: 'Execution source clicked (no stages found)' }); }; private handlePauseClick = (): void => { - ReactGA.event({ category: 'Pipeline', action: 'Execution pause clicked' }); + logger.log({ category: 'Pipeline', action: 'Execution pause clicked' }); this.pauseExecution(); }; private handleResumeClick = (): void => { - ReactGA.event({ category: 'Pipeline', action: 'Execution resume clicked' }); + logger.log({ category: 'Pipeline', action: 'Execution resume clicked' }); this.resumeExecution(); }; private handleDeleteClick = (): void => { - ReactGA.event({ category: 'Pipeline', action: 'Execution delete clicked' }); + logger.log({ category: 'Pipeline', action: 'Execution delete clicked' }); this.deleteExecution(); }; private handleCancelClick = (): void => { - ReactGA.event({ category: 'Pipeline', action: 'Execution cancel clicked' }); + logger.log({ category: 'Pipeline', action: 'Execution cancel clicked' }); this.cancelExecution(); }; private handleRerunClick = (): void => { - ReactGA.event({ category: 'Pipeline', action: 'Execution rerun clicked' }); + logger.log({ category: 'Pipeline', action: 'Execution rerun clicked' }); const { application, execution } = this.props; const pipelineConfig = application.pipelineConfigs.data.find((p: IPipeline) => p.id === execution.pipelineConfigId); this.props.onRerun(execution, pipelineConfig); }; private handleSourceClick = (): void => { - ReactGA.event({ category: 'Pipeline', action: 'Execution source clicked' }); + logger.log({ category: 'Pipeline', action: 'Execution source clicked' }); }; private handleToggleDetails = (showingDetails: boolean): void => { - ReactGA.event({ category: 'Pipeline', action: 'Execution details toggled (Details link)' }); + logger.log({ category: 'Pipeline', action: 'Execution details toggled (Details link)' }); showingDetails ? this.toggleDetails() : this.toggleDetails(0, 0); }; private handleConfigureClicked = (e: React.MouseEvent): void => { const { application, execution } = this.props; - ReactGA.event({ category: 'Execution', action: 'Configuration' }); + logger.log({ category: 'Execution', action: 'Configuration' }); ReactInjector.$state.go('^.pipelineConfig', { application: application.name, pipelineId: execution.pipelineConfigId, diff --git a/app/scripts/modules/core/src/pipeline/executions/execution/ExecutionBreadcrumbs.tsx b/app/scripts/modules/core/src/pipeline/executions/execution/ExecutionBreadcrumbs.tsx index e9d96f801fd..620a15feead 100644 --- a/app/scripts/modules/core/src/pipeline/executions/execution/ExecutionBreadcrumbs.tsx +++ b/app/scripts/modules/core/src/pipeline/executions/execution/ExecutionBreadcrumbs.tsx @@ -1,8 +1,8 @@ import { useCurrentStateAndParams, useSref } from '@uirouter/react'; import React, { MouseEventHandler } from 'react'; -import ReactGA from 'react-ga'; import { IExecution } from 'core/domain'; +import { logger } from 'core/utils'; import { ExecutionInformationService } from './executionInformation.service'; @@ -45,7 +45,7 @@ function ExecutionPermaLink({ execution }: IExecutionBreadcrumbsProps) { const sref = useSref(toState, srefParams, srefOptions); const handleClick: MouseEventHandler = (e) => { - ReactGA.event({ category: 'Pipeline', action: 'Execution build number clicked - parent pipeline' }); + logger.log({ category: 'Pipeline', action: 'Execution build number clicked - parent pipeline' }); sref.onClick(e); }; diff --git a/app/scripts/modules/core/src/pipeline/executions/execution/ExecutionMarker.tsx b/app/scripts/modules/core/src/pipeline/executions/execution/ExecutionMarker.tsx index 9c665c9abd6..6478d19e5ea 100644 --- a/app/scripts/modules/core/src/pipeline/executions/execution/ExecutionMarker.tsx +++ b/app/scripts/modules/core/src/pipeline/executions/execution/ExecutionMarker.tsx @@ -1,11 +1,11 @@ import { UISref } from '@uirouter/react'; import { isEmpty } from 'lodash'; import React from 'react'; -import ReactGA from 'react-ga'; import { Application } from 'core/application/application.model'; import { SETTINGS } from 'core/config/settings'; import { IExecution, IExecutionStageSummary } from 'core/domain'; +import { logger } from 'core/utils'; import { duration } from 'core/utils/timeFormatters'; import { ExecutionMarkerInformationModal } from './ExecutionMarkerInformationModal'; @@ -60,12 +60,12 @@ export class ExecutionMarker extends React.Component { - ReactGA.event({ category: 'Pipeline', action: 'Stage clicked (bar)' }); + logger.log({ category: 'Pipeline', action: 'Stage clicked (bar)' }); this.props.onClick(this.props.stage.index); }; private handleStageInformationClick = (event: any): void => { - ReactGA.event({ category: 'Pipeline', action: 'Stage show context menu (bar)' }); + logger.log({ category: 'Pipeline', action: 'Stage show context menu (bar)' }); event.preventDefault(); event.stopPropagation(); this.showExecutionMarkerInformationModal(); diff --git a/app/scripts/modules/core/src/pipeline/executions/execution/ExecutionPermalink.tsx b/app/scripts/modules/core/src/pipeline/executions/execution/ExecutionPermalink.tsx index 8a7b2b79192..e6fee0e8b34 100644 --- a/app/scripts/modules/core/src/pipeline/executions/execution/ExecutionPermalink.tsx +++ b/app/scripts/modules/core/src/pipeline/executions/execution/ExecutionPermalink.tsx @@ -1,8 +1,7 @@ import React from 'react'; -import ReactGA from 'react-ga'; import { ReactInjector } from 'core/reactShims'; -import { CopyToClipboard } from 'core/utils'; +import { CopyToClipboard, logger } from 'core/utils'; export interface IExecutionPermalinkProps { standalone: boolean; @@ -23,7 +22,7 @@ export const ExecutionPermalink = ({ standalone }: IExecutionPermalinkProps) => }, []); const handlePermalinkClick = (): void => { - ReactGA.event({ category: 'Pipeline', action: 'Permalink clicked' }); + logger.log({ category: 'Pipeline', action: 'Permalink clicked' }); }; return ( diff --git a/app/scripts/modules/core/src/pipeline/executions/executionGroup/ExecutionGroup.tsx b/app/scripts/modules/core/src/pipeline/executions/executionGroup/ExecutionGroup.tsx index 653502ddc5c..8056b0ca861 100644 --- a/app/scripts/modules/core/src/pipeline/executions/executionGroup/ExecutionGroup.tsx +++ b/app/scripts/modules/core/src/pipeline/executions/executionGroup/ExecutionGroup.tsx @@ -1,7 +1,6 @@ import classnames from 'classnames'; import { flatten, uniq, without } from 'lodash'; import React from 'react'; -import ReactGA from 'react-ga'; import { from as observableFrom, Subject, Subscription } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @@ -22,6 +21,7 @@ import { Placement } from 'core/presentation/Placement'; import { Popover } from 'core/presentation/Popover'; import { ReactInjector } from 'core/reactShims'; import { ExecutionState } from 'core/state'; +import { logger } from 'core/utils'; import { RenderWhenVisible } from 'core/utils/RenderWhenVisible'; import { IRetryablePromise } from 'core/utils/retryablePromise'; import { Spinner } from 'core/widgets/spinners/Spinner'; @@ -203,32 +203,36 @@ export class ExecutionGroup extends React.PureComponent { - ReactGA.event({ + logger.log({ category: 'Pipeline', action: `Group ${this.state.open ? 'collapsed' : 'expanded'}`, - label: this.props.group.heading, + data: { label: this.props.group.heading }, }); this.toggle(); }; private handleConfigureClicked = (e: React.MouseEvent): void => { - ReactGA.event({ + logger.log({ category: 'Pipeline', action: 'Configure pipeline button clicked', - label: this.props.group.heading, + data: { label: this.props.group.heading }, }); this.configure(this.props.group.config.id); e.stopPropagation(); }; private handleTriggerClicked = (e: React.MouseEvent): void => { - ReactGA.event({ category: 'Pipeline', action: 'Trigger pipeline button clicked', label: this.props.group.heading }); + logger.log({ + category: 'Pipeline', + action: 'Trigger pipeline button clicked', + data: { label: this.props.group.heading }, + }); this.triggerPipeline(); e.stopPropagation(); }; private rerunExecutionClicked = (execution: IExecution, config: IPipeline): void => { - ReactGA.event({ category: 'Pipeline', action: 'Rerun pipeline button clicked', label: config.name }); + logger.log({ category: 'Pipeline', action: 'Rerun pipeline button clicked', data: { label: config.name } }); this.triggerPipeline(execution.trigger, config); }; diff --git a/app/scripts/modules/core/src/pipeline/filter/ExecutionFilters.tsx b/app/scripts/modules/core/src/pipeline/filter/ExecutionFilters.tsx index a7ec925a6a4..9ab7888dd77 100644 --- a/app/scripts/modules/core/src/pipeline/filter/ExecutionFilters.tsx +++ b/app/scripts/modules/core/src/pipeline/filter/ExecutionFilters.tsx @@ -2,7 +2,6 @@ import classNames from 'classnames'; import { flatten, get, isEmpty, isEqual, orderBy, uniq } from 'lodash'; import { Debounce } from 'lodash-decorators'; import React from 'react'; -import ReactGA from 'react-ga'; import { arrayMove, SortableContainer, SortableElement, SortableHandle, SortEnd } from 'react-sortable-hoc'; import { Subscription } from 'rxjs'; @@ -13,6 +12,7 @@ import { IExecution, IPipeline, IPipelineTag } from 'core/domain'; import { IFilterTag } from 'core/filterModel'; import { ReactInjector } from 'core/reactShims'; import { ExecutionState } from 'core/state'; +import { logger } from 'core/utils'; import { PipelineConfigService } from '../config/services/PipelineConfigService'; import { ExecutionFilterService } from './executionFilter.service'; @@ -86,12 +86,12 @@ export class ExecutionFilters extends React.Component { this.setState({ pipelineReorderEnabled: true }); - ReactGA.event({ category: 'Pipelines', action: 'Filter: reorder' }); + logger.log({ category: 'Pipelines', action: 'Filter: reorder' }); }; private disablePipelineReorder = (): void => { this.setState({ pipelineReorderEnabled: false }); - ReactGA.event({ category: 'Pipelines', action: 'Filter: stop reorder' }); + logger.log({ category: 'Pipelines', action: 'Filter: stop reorder' }); }; private updateExecutionGroups(): void { @@ -192,7 +192,7 @@ export class ExecutionFilters extends React.Component { const { application } = this.props; - ReactGA.event({ category: 'Pipelines', action: 'Reordered pipeline' }); + logger.log({ category: 'Pipelines', action: 'Reordered pipeline' }); const idsToUpdatedIndices: { [key: string]: number } = {}; application.pipelineConfigs.data.forEach((pipeline: IPipeline) => { const newIndex = pipelineNames.indexOf(pipeline.name); @@ -331,7 +331,7 @@ const FilterCheckbox = (props: { const { pipeline, tag, update, visible } = props; const sortFilter = ExecutionState.filterModel.asFilterModel.sortFilter; const changeHandler = () => { - ReactGA.event({ category: 'Pipelines', action: 'Filter: pipeline', label: pipeline }); + logger.log({ category: 'Pipelines', action: 'Filter: pipeline', data: { label: pipeline } }); if (tag) { tag.clear(); } else { @@ -429,7 +429,7 @@ const FilterStatus = (props: { }): JSX.Element => { const sortFilter = ExecutionState.filterModel.asFilterModel.sortFilter; const changed = () => { - ReactGA.event({ category: 'Pipelines', action: 'Filter: status', label: props.label.toUpperCase() }); + logger.log({ category: 'Pipelines', action: 'Filter: status', data: { label: props.label.toUpperCase() } }); sortFilter.status[props.status] = !sortFilter.status[props.status]; props.refresh(); }; @@ -452,7 +452,7 @@ const FilterAwaitingJudgement = (props: { refresh: () => void }): JSX.Element => const { sortFilter } = ExecutionState.filterModel.asFilterModel; const label = 'Awaiting Judgement'; const changed = () => { - ReactGA.event({ category: 'Pipelines', action: 'Filter: status', label }); + logger.log({ category: 'Pipelines', action: 'Filter: status', data: { label } }); sortFilter.awaitingJudgement = !sortFilter.awaitingJudgement; if (sortFilter.awaitingJudgement) { sortFilter.status['RUNNING'] = true; diff --git a/app/scripts/modules/core/src/presentation/SpinErrorBoundary.tsx b/app/scripts/modules/core/src/presentation/SpinErrorBoundary.tsx index 751499a19b5..5aeab76ca35 100644 --- a/app/scripts/modules/core/src/presentation/SpinErrorBoundary.tsx +++ b/app/scripts/modules/core/src/presentation/SpinErrorBoundary.tsx @@ -2,7 +2,6 @@ import { StateObject, UIRouter } from '@uirouter/core'; import { ReactViewDeclaration } from '@uirouter/react'; import { module } from 'angular'; import React, { ErrorInfo } from 'react'; -import ReactGA from 'react-ga'; import { logger } from 'core/utils/Logger'; @@ -39,12 +38,13 @@ export class SpinErrorBoundary extends React.Component { + ReactGA.event({ category: event.category, action: event.action, label: event.data?.label }); + }, + }); } diff --git a/app/scripts/modules/core/src/search/global/GlobalSearch.tsx b/app/scripts/modules/core/src/search/global/GlobalSearch.tsx index 4ca4412cab3..1ceebe8f670 100644 --- a/app/scripts/modules/core/src/search/global/GlobalSearch.tsx +++ b/app/scripts/modules/core/src/search/global/GlobalSearch.tsx @@ -2,13 +2,13 @@ import { UIRouterContext } from '@uirouter/react-hybrid'; import { flatten } from 'lodash'; import { Debounce } from 'lodash-decorators'; import React from 'react'; -import ReactGA from 'react-ga'; import { from as observableFrom, Subject } from 'rxjs'; import { debounceTime, map, switchMap, takeUntil, tap } from 'rxjs/operators'; import { Tooltip } from 'core/presentation/Tooltip'; import { ReactInjector } from 'core/reactShims'; import { ClusterState } from 'core/state'; +import { logger } from 'core/utils'; import { Spinner } from 'core/widgets/spinners/Spinner'; import { GlobalSearchRecentItems } from './GlobalSearchRecentItems'; @@ -63,7 +63,7 @@ export class GlobalSearch extends React.Component<{}, IGlobalSearchState> { .pipe( debounceTime(300), tap((query) => { - ReactGA.event({ category: 'Global Search', action: 'Query', label: query }); + logger.log({ category: 'Global Search', action: 'Query', data: { label: query } }); this.setState({ querying: true }); }), switchMap((query: string) => observableFrom(search.query(query))), @@ -126,19 +126,19 @@ export class GlobalSearch extends React.Component<{}, IGlobalSearchState> { const { key, shiftKey } = event; if (key === 'Escape') { - ReactGA.event({ category: 'Global Search', action: 'Keyboard Nav', label: 'escape (from input)' }); + logger.log({ category: 'Global Search', action: 'Keyboard Nav', data: { label: 'escape (from input)' } }); this.searchField.blur(); } else if (key === 'ArrowDown') { - ReactGA.event({ category: 'Global Search', action: 'Keyboard Nav', label: 'arrow down (from input)' }); + logger.log({ category: 'Global Search', action: 'Keyboard Nav', data: { label: 'arrow down (from input)' } }); event.preventDefault(); this.focusFirstSearchResult(); } else if (key === 'ArrowUp') { - ReactGA.event({ category: 'Global Search', action: 'Keyboard Nav', label: 'arrow up (from input)' }); + logger.log({ category: 'Global Search', action: 'Keyboard Nav', data: { label: 'arrow up (from input)' } }); event.preventDefault(); this.focusLastSearchResult(); } else if (key === 'Tab') { if (!shiftKey) { - ReactGA.event({ category: 'Global Search', action: 'Keyboard Nav', label: 'tab (from input)' }); + logger.log({ category: 'Global Search', action: 'Keyboard Nav', data: { label: 'tab (from input)' } }); event.preventDefault(); this.focusFirstSearchResult(); } @@ -174,7 +174,7 @@ export class GlobalSearch extends React.Component<{}, IGlobalSearchState> { private navigateResult = (event: React.KeyboardEvent) => { const { key, target } = event; if (key === 'Escape') { - ReactGA.event({ category: 'Global Search', action: 'Keyboard Nav', label: 'escape (from result)' }); + logger.log({ category: 'Global Search', action: 'Keyboard Nav', data: { label: 'escape (from result)' } }); this.setState({ showDropdown: false, showMinLengthWarning: false, @@ -187,12 +187,12 @@ export class GlobalSearch extends React.Component<{}, IGlobalSearchState> { const flattenedRefs = flatten(this.resultRefs); const lastResultRef = flattenedRefs[flattenedRefs.length - 1]; if (target === lastResultRef) { - ReactGA.event({ category: 'Global Search', action: 'Keyboard Nav', label: 'tab (from result)' }); + logger.log({ category: 'Global Search', action: 'Keyboard Nav', data: { label: 'tab (from result)' } }); this.hideDropdown(); return; } } else if (key === 'ArrowDown') { - ReactGA.event({ category: 'Global Search', action: 'Keyboard Nav', label: 'down (from result)' }); + logger.log({ category: 'Global Search', action: 'Keyboard Nav', data: { label: 'down (from result)' } }); const flattenedRefs = flatten(this.resultRefs); const currentRefIndex = flattenedRefs.indexOf(target as HTMLElement); const nextResultRef = flattenedRefs[currentRefIndex + 1]; @@ -200,7 +200,7 @@ export class GlobalSearch extends React.Component<{}, IGlobalSearchState> { nextResultRef && nextResultRef.focus(); event.preventDefault(); } else if (key === 'ArrowUp') { - ReactGA.event({ category: 'Global Search', action: 'Keyboard Nav', label: 'up (from result)' }); + logger.log({ category: 'Global Search', action: 'Keyboard Nav', data: { label: 'up (from result)' } }); const flattenedRefs = flatten(this.resultRefs); const currentRefIndex = flattenedRefs.indexOf(target as HTMLElement); const prevResultRef = flattenedRefs[currentRefIndex - 1]; @@ -208,7 +208,7 @@ export class GlobalSearch extends React.Component<{}, IGlobalSearchState> { prevResultRef && prevResultRef.focus(); event.preventDefault(); } else if (key === 'Enter') { - ReactGA.event({ category: 'Global Search', action: 'Keyboard Nav', label: 'enter (from result)' }); + logger.log({ category: 'Global Search', action: 'Keyboard Nav', data: { label: 'enter (from result)' } }); // Allow keyboard event to activate the href, then hide the drop down setTimeout(() => this.hideDropdown(), 100); } @@ -345,7 +345,7 @@ export class GlobalSearch extends React.Component<{}, IGlobalSearchState> { onItemKeyDown={this.navigateResult} onResultClick={(category: string) => { this.hideDropdown(); - ReactGA.event({ category: 'Global Search', action: `Recent item selected from ${category}` }); + logger.log({ category: 'Global Search', action: `Recent item selected from ${category}` }); }} resultRef={(categoryIndex, resultIndex, ref) => { if (this.resultRefs[categoryIndex]) { @@ -367,12 +367,12 @@ export class GlobalSearch extends React.Component<{}, IGlobalSearchState> { query={query} onItemKeyDown={this.navigateResult} onResultClick={(result: ISearchResult) => { - ReactGA.event({ category: 'Global Search', action: 'Result Selected' }); + logger.log({ category: 'Global Search', action: 'Result Selected' }); this.hideDropdown(); this.clearFilters(result); }} onSeeMoreClick={() => { - ReactGA.event({ category: 'Global Search', action: 'See all results selected' }); + logger.log({ category: 'Global Search', action: 'See all results selected' }); this.hideDropdown(); }} resultRef={(categoryIndex, resultIndex, ref) => { diff --git a/app/scripts/modules/core/src/search/infrastructure/RecentlyViewedItems.tsx b/app/scripts/modules/core/src/search/infrastructure/RecentlyViewedItems.tsx index e1ec5ae0c5c..61231f0f6c7 100644 --- a/app/scripts/modules/core/src/search/infrastructure/RecentlyViewedItems.tsx +++ b/app/scripts/modules/core/src/search/infrastructure/RecentlyViewedItems.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import ReactGA from 'react-ga'; import { IRecentHistoryEntry, RecentHistoryService } from 'core/history'; import { useData } from 'core/presentation/hooks'; import { ReactInjector } from 'core/reactShims'; +import { logger } from 'core/utils'; import { ISearchResult, ISearchResultPodData, SearchResultPods } from './SearchResultPods'; @@ -53,7 +53,7 @@ export function RecentlyViewedItems(props: IRecentlyViewedItemsProps) { }; const handleResultClick = (categoryName: string): void => { - ReactGA.event({ category: 'Primary Search', action: `Recent item selected from ${categoryName}` }); + logger.log({ category: 'Primary Search', action: `Recent item selected from ${categoryName}` }); }; return Component ? ( diff --git a/app/scripts/modules/core/src/serverGroup/ServerGroup.tsx b/app/scripts/modules/core/src/serverGroup/ServerGroup.tsx index 7355688e119..3ee96d5aebc 100644 --- a/app/scripts/modules/core/src/serverGroup/ServerGroup.tsx +++ b/app/scripts/modules/core/src/serverGroup/ServerGroup.tsx @@ -2,7 +2,6 @@ import classNames from 'classnames'; import { has } from 'lodash'; import { $interpolate } from 'ngimport'; import React from 'react'; -import ReactGA from 'react-ga'; import { Subscription } from 'rxjs'; import { merge } from 'rxjs/operators'; @@ -14,7 +13,7 @@ import { InstanceList } from 'core/instance/InstanceList'; import { Instances } from 'core/instance/Instances'; import { ReactInjector } from 'core/reactShims'; import { ClusterState } from 'core/state'; -import { ScrollToService } from 'core/utils'; +import { logger, ScrollToService } from 'core/utils'; import { ServerGroupHeader } from './ServerGroupHeader'; @@ -176,7 +175,7 @@ export class ServerGroup extends React.Component) => { - ReactGA.event({ category: 'Cluster Pod', action: 'Load Server Group Details' }); + logger.log({ category: 'Cluster Pod', action: 'Load Server Group Details' }); this.loadDetails(event); }; diff --git a/app/scripts/modules/core/src/serverGroup/details/ServerGroupInsightActions.tsx b/app/scripts/modules/core/src/serverGroup/details/ServerGroupInsightActions.tsx index da07f21941d..4ec262f89cf 100644 --- a/app/scripts/modules/core/src/serverGroup/details/ServerGroupInsightActions.tsx +++ b/app/scripts/modules/core/src/serverGroup/details/ServerGroupInsightActions.tsx @@ -1,16 +1,16 @@ import React from 'react'; import { Dropdown } from 'react-bootstrap'; -import ReactGA from 'react-ga'; import { IServerGroup } from 'core/domain'; +import { logger } from 'core/utils'; export class ServerGroupInsightActions extends React.Component<{ serverGroup: IServerGroup }> { private onClick(label: string): void { const { serverGroup } = this.props; - ReactGA.event({ + logger.log({ category: 'Insight Menu (Server Group)', action: `${label} clicked`, - label: `${serverGroup.account}/${serverGroup.region}/${serverGroup.name}`, + data: { label: `${serverGroup.account}/${serverGroup.region}/${serverGroup.name}` }, }); } diff --git a/app/scripts/modules/core/src/utils/Logger.ts b/app/scripts/modules/core/src/utils/Logger.ts index 743acdc5a4a..14fc6d1c414 100644 --- a/app/scripts/modules/core/src/utils/Logger.ts +++ b/app/scripts/modules/core/src/utils/Logger.ts @@ -13,9 +13,10 @@ type Level = keyof typeof LEVELS; interface Event { level?: Level; - message: string; + action: string; + category?: string; error?: Error; - data?: object; + data?: Record; } export interface LoggerSubscriber { diff --git a/app/scripts/modules/core/src/utils/clipboard/CopyToClipboard.spec.tsx b/app/scripts/modules/core/src/utils/clipboard/CopyToClipboard.spec.tsx index 2915cc66ca6..f2e7dee3953 100644 --- a/app/scripts/modules/core/src/utils/clipboard/CopyToClipboard.spec.tsx +++ b/app/scripts/modules/core/src/utils/clipboard/CopyToClipboard.spec.tsx @@ -1,11 +1,10 @@ -import React from 'react'; -import ReactGA from 'react-ga'; import { mount } from 'enzyme'; - +import React from 'react'; +import { logger } from '../Logger'; import { CopyToClipboard } from './CopyToClipboard'; describe('', () => { - beforeEach(() => spyOn(ReactGA, 'event')); + beforeEach(() => spyOn(logger, 'log')); it('renders an input with the text value', () => { const wrapper = mount(); @@ -41,6 +40,6 @@ describe('', () => { const wrapper = mount(); const button = wrapper.find('button'); button.simulate('click'); - expect(ReactGA.event).toHaveBeenCalled(); + expect(logger.log).toHaveBeenCalled(); }); }); diff --git a/app/scripts/modules/core/src/utils/clipboard/CopyToClipboard.tsx b/app/scripts/modules/core/src/utils/clipboard/CopyToClipboard.tsx index caa9b8da672..9244dcae93d 100644 --- a/app/scripts/modules/core/src/utils/clipboard/CopyToClipboard.tsx +++ b/app/scripts/modules/core/src/utils/clipboard/CopyToClipboard.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { OverlayTrigger, Tooltip } from 'react-bootstrap'; -import ReactGA from 'react-ga'; - +import { logger } from '../Logger'; import './CopyToClipboard.less'; export interface ICopyToClipboardProps { @@ -65,10 +64,10 @@ export class CopyToClipboard extends React.Component { break; } - ReactGA.event({ category: 'Infrastructure Search Tags', action: 'Individual tag removed' }); + logger.log({ category: 'Infrastructure Search Tags', action: 'Individual tag removed' }); }; private handleFocus = (): void => { diff --git a/app/scripts/modules/kubernetes/src/rawResource/component/group/RawResourceDetails.tsx b/app/scripts/modules/kubernetes/src/rawResource/component/group/RawResourceDetails.tsx index 956977e71cb..0207b316f30 100644 --- a/app/scripts/modules/kubernetes/src/rawResource/component/group/RawResourceDetails.tsx +++ b/app/scripts/modules/kubernetes/src/rawResource/component/group/RawResourceDetails.tsx @@ -3,7 +3,6 @@ import { get } from 'lodash'; import { DateTime } from 'luxon'; import React from 'react'; import { Dropdown } from 'react-bootstrap'; -import ReactGA from 'react-ga'; import { Subject } from 'rxjs'; import { @@ -12,6 +11,7 @@ import { CollapsibleSection, ConfirmationModalService, IManifest, + logger, ManifestWriter, Overridable, Spinner, @@ -118,7 +118,7 @@ export class RawResourceDetails extends React.Component { - ReactGA.event({ category: 'RawResource', action: 'Delete clicked' }); + logger.log({ category: 'RawResource', action: 'Delete clicked' }); const command = { manifestName: this.state.name, location: this.state.region, @@ -142,7 +142,7 @@ export class RawResourceDetails extends React.Component { - ReactGA.event({ category: 'RawResource', action: 'Edit clicked' }); + logger.log({ category: 'RawResource', action: 'Edit clicked' }); this.editRawResource(); };