diff --git a/packages/bruno-app/next.config.js b/packages/bruno-app/next.config.js index eb8ca162..639ae300 100644 --- a/packages/bruno-app/next.config.js +++ b/packages/bruno-app/next.config.js @@ -1,5 +1,8 @@ module.exports = { reactStrictMode: true, + publicRuntimeConfig: { + CI: process.env.CI + }, webpack: (config, { isServer }) => { // Fixes npm packages that depend on `fs` module if (!isServer) { diff --git a/packages/bruno-app/package.json b/packages/bruno-app/package.json index 01f7c8c9..74fe4ab5 100644 --- a/packages/bruno-app/package.json +++ b/packages/bruno-app/package.json @@ -34,6 +34,8 @@ "nanoid": "3.3.4", "next": "12.3.1", "path": "^0.12.7", + "platform": "^1.3.6", + "posthog-node": "^2.1.0", "qs": "^6.11.0", "react": "^17.0.2", "react-dom": "^17.0.2", diff --git a/packages/bruno-app/src/providers/App/index.js b/packages/bruno-app/src/providers/App/index.js index f0653b05..e7cf91a5 100644 --- a/packages/bruno-app/src/providers/App/index.js +++ b/packages/bruno-app/src/providers/App/index.js @@ -1,5 +1,6 @@ import React, { useEffect } from 'react'; import useIdb from './useIdb'; +import useTelemetry from './useTelemetry'; import useLocalCollectionTreeSync from './useLocalCollectionTreeSync'; import { useDispatch } from 'react-redux'; import { refreshScreenWidth } from 'providers/ReduxStore/slices/app'; @@ -9,6 +10,7 @@ export const AppContext = React.createContext(); export const AppProvider = (props) => { useIdb(); + useTelemetry(); useLocalCollectionTreeSync(); const dispatch = useDispatch(); diff --git a/packages/bruno-app/src/providers/App/useTelemetry.js b/packages/bruno-app/src/providers/App/useTelemetry.js new file mode 100644 index 00000000..7ed558b6 --- /dev/null +++ b/packages/bruno-app/src/providers/App/useTelemetry.js @@ -0,0 +1,66 @@ +import { useEffect } from 'react'; +import getConfig from 'next/config'; +import { PostHog } from 'posthog-node'; +import platformLib from 'platform'; +import { uuid } from 'utils/common'; +import { isElectron } from 'utils/common/platform'; + +const { publicRuntimeConfig } = getConfig(); +const posthogApiKey = 'phc_7gtqSrrdZRohiozPMLIacjzgHbUlhalW1Bu16uYijMR'; +let posthogClient = null; + +const isCI = () => { + return publicRuntimeConfig.CI ? true : false; +}; + +// Todo support chrome and firefox extension +const getPlatform = () => { + return isElectron() ? 'electron' : 'web'; +}; + +const getPosthogClient = () => { + if(posthogClient) { + return posthogClient; + } + + posthogClient = new PostHog(posthogApiKey); + return posthogClient; +}; + +const getAnonymousTrackingId = () => { + let id = localStorage.getItem('bruno.anonymousTrackingId'); + + if(!id || !id.length || id.length !== 21) { + id = uuid(); + localStorage.setItem('bruno.anonymousTrackingId', id); + } + + return id; +}; + +const trackStart = () => { + if(isCI()) { + return; + } + + const trackingId = getAnonymousTrackingId(); + const platform = getPlatform(); + const client = getPosthogClient(); + client.capture({ + distinctId: trackingId, + event: 'start', + properties: { + platform: platform, + os: platformLib.os.family + } + }); +}; + +const useTelemetry = () => { + useEffect(() => { + trackStart(); + setInterval(trackStart , 24 * 60 * 60 * 1000); + }, []); +}; + +export default useTelemetry;