From 11582dacc2b77bcce3121ad90dbdefd6802c5023 Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Thu, 16 Sep 2021 15:31:34 +0200 Subject: [PATCH] Stabilize the tracker reference to avoid duplicate events. Signed-off-by: Eric Peterson --- .../core-app-api/src/routing/RouteTracker.tsx | 3 +- .../core-plugin-api/src/analytics/Tracker.ts | 51 +++++++++++++++++++ .../src/analytics/useAnalytics.tsx | 27 +++------- 3 files changed, 58 insertions(+), 23 deletions(-) create mode 100644 packages/core-plugin-api/src/analytics/Tracker.ts diff --git a/packages/core-app-api/src/routing/RouteTracker.tsx b/packages/core-app-api/src/routing/RouteTracker.tsx index 8ca76be78e..5c0cd56862 100644 --- a/packages/core-app-api/src/routing/RouteTracker.tsx +++ b/packages/core-app-api/src/routing/RouteTracker.tsx @@ -99,8 +99,7 @@ const TrackNavigation = ({ useEffect(() => { analytics.captureEvent('navigate', `${pathname}${search}${hash}`); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [pathname, search, hash]); + }, [analytics, pathname, search, hash]); return null; }; diff --git a/packages/core-plugin-api/src/analytics/Tracker.ts b/packages/core-plugin-api/src/analytics/Tracker.ts new file mode 100644 index 0000000000..d1ddf5d342 --- /dev/null +++ b/packages/core-plugin-api/src/analytics/Tracker.ts @@ -0,0 +1,51 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AnalyticsApi, AnalyticsEventAttributes } from '../apis'; +import { AnalyticsContextValue } from './'; + +export class Tracker { + constructor( + private readonly analyticsApi: AnalyticsApi, + private context: AnalyticsContextValue = {}, + ) {} + + setContext(context: AnalyticsContextValue) { + this.context = context; + } + + captureEvent( + action: string, + subject: string, + { + value, + attributes, + }: { value?: number; attributes?: AnalyticsEventAttributes } = {}, + ) { + try { + this.analyticsApi.captureEvent({ + action, + subject, + value, + attributes, + context: this.context, + }); + } catch (e) { + // eslint-disable-next-line no-console + console.warn('Error during analytics event capture. %o', e); + } + } +} diff --git a/packages/core-plugin-api/src/analytics/useAnalytics.tsx b/packages/core-plugin-api/src/analytics/useAnalytics.tsx index 8b104e347c..dd1176fff0 100644 --- a/packages/core-plugin-api/src/analytics/useAnalytics.tsx +++ b/packages/core-plugin-api/src/analytics/useAnalytics.tsx @@ -15,31 +15,16 @@ */ import { useAnalyticsContext } from './AnalyticsContext'; -import { - analyticsApiRef, - AnalyticsTracker, -} from '../apis/definitions/AnalyticsApi'; -import { useApi } from '../apis'; +import { analyticsApiRef, AnalyticsTracker, useApi } from '../apis'; +import { useRef } from 'react'; +import { Tracker } from './Tracker'; function useTracker(): AnalyticsTracker { const analyticsApi = useApi(analyticsApiRef); + const tracker = useRef(new Tracker(analyticsApi)); const context = useAnalyticsContext(); - return { - captureEvent: (action, subject, { value, attributes } = {}) => { - try { - analyticsApi.captureEvent({ - action, - subject, - value, - attributes, - context, - }); - } catch (e) { - // eslint-disable-next-line no-console - console.warn('Error during analytics event capture. %o', e); - } - }, - }; + tracker.current.setContext(context); + return tracker.current; } /**