From 022e94c722d711e691ee2cec6b9d98f2a1c14ef9 Mon Sep 17 00:00:00 2001 From: Davide Valleri <146823822+dvalleri@users.noreply.github.com> Date: Tue, 13 Aug 2024 11:15:35 +0200 Subject: [PATCH] feat(ui): grafana improvement (#164) * grafana improvement * feat(ui) : manage uuid generation about grafana session * feat(ui): remove console.debug --- ui/package.json | 1 + ui/src/api/utils.js | 2 ++ .../add-new-model/step-four/form-fields.jsx | 5 +++ .../step-two/use-handle-on-next.js | 2 ++ ui/src/helpers/queryParams.js | 3 ++ ui/src/main.jsx | 35 ++++++++++++------- .../state/context-configuration/thunks.js | 2 ++ ui/yarn.lock | 5 +++ 8 files changed, 42 insertions(+), 13 deletions(-) diff --git a/ui/package.json b/ui/package.json index 63c72b65..0b56407d 100644 --- a/ui/package.json +++ b/ui/package.json @@ -37,6 +37,7 @@ "react-router": "^6.23.0", "react-router-dom": "^6.23.0", "react-virtuoso": "^4.7.11", + "uuid": "^10.0.0", "vite": "^5.2.0", "vite-plugin-svgr": "^4.2.0", "yup": "^1.4.0" diff --git a/ui/src/api/utils.js b/ui/src/api/utils.js index d6707a7a..a1420b61 100644 --- a/ui/src/api/utils.js +++ b/ui/src/api/utils.js @@ -1,3 +1,4 @@ +import { grafanaTracking } from '@Src/main'; import axios from 'axios'; export const customBaseQuery = () => async ({ @@ -23,6 +24,7 @@ export const customBaseQuery = () => async ({ return { data: result.data }; } catch (axiosError) { const err = axiosError; + grafanaTracking?.api.pushError(axiosError); return { error: { status: err.response?.status, data: err.response?.data }, diff --git a/ui/src/components/modals/add-new-model/step-four/form-fields.jsx b/ui/src/components/modals/add-new-model/step-four/form-fields.jsx index 3df7ed37..facc5909 100644 --- a/ui/src/components/modals/add-new-model/step-four/form-fields.jsx +++ b/ui/src/components/modals/add-new-model/step-four/form-fields.jsx @@ -4,6 +4,7 @@ import { Select, Tooltip, } from '@radicalbit/radicalbit-design-system'; +import { grafanaTracking } from '@Src/main'; import { useModalContext } from '../modal-context-provider'; function Target() { @@ -28,6 +29,7 @@ function Target() { write('target', JSON.parse(val)); } catch (e) { console.error('Error in parsing Select.Option value: ', e); + grafanaTracking?.api.pushError(e); } }; @@ -124,6 +126,7 @@ function Timestamp() { write('timestamp', JSON.parse(val)); } catch (e) { console.error('Error in parsing Select.Option value: ', e); + grafanaTracking?.api.pushError(e); } }; @@ -220,6 +223,7 @@ function Prediction() { write('prediction', JSON.parse(val)); } catch (e) { console.error('Error in parsing Select.Option value: ', e); + grafanaTracking?.api.pushError(e); } }; @@ -319,6 +323,7 @@ function Probability() { write('predictionProba', JSON.parse(val)); } catch (e) { console.error('Error in parsing Select.Option value: ', e); + grafanaTracking?.api.pushError(e); } }; diff --git a/ui/src/components/modals/add-new-model/step-two/use-handle-on-next.js b/ui/src/components/modals/add-new-model/step-two/use-handle-on-next.js index 1f4d8587..42527863 100644 --- a/ui/src/components/modals/add-new-model/step-two/use-handle-on-next.js +++ b/ui/src/components/modals/add-new-model/step-two/use-handle-on-next.js @@ -1,5 +1,6 @@ import { modelsApiSlice } from '@State/models/api'; import { useCallback } from 'react'; +import { grafanaTracking } from '@Src/main'; import { useModalContext } from '../modal-context-provider'; const { useInferSchemaMutation } = modelsApiSlice; @@ -66,6 +67,7 @@ export default () => { } catch (e) { const parsedErrorMessage = parseErrorMessage(e); console.error(e); + grafanaTracking?.api.pushError(e); setError('silent.backend', parsedErrorMessage); write('file', { ...form.file, status: 'error', response: parsedErrorMessage }); diff --git a/ui/src/helpers/queryParams.js b/ui/src/helpers/queryParams.js index b11719db..c0796a80 100644 --- a/ui/src/helpers/queryParams.js +++ b/ui/src/helpers/queryParams.js @@ -1,3 +1,5 @@ +import { grafanaTracking } from '@Src/main'; + const qs = (param) => new URLSearchParams(window.location.search).get(param); const qsContextConfiguration = () => { @@ -26,6 +28,7 @@ const qsEncode64JSON = (search, param) => { return JSON.parse(qsAtob); } catch (e) { console.warn('Error in parsing qsEncode64JSON: ', e); + grafanaTracking?.api.pushError(e); return {}; } }; diff --git a/ui/src/main.jsx b/ui/src/main.jsx index c5ce6269..76b900cc 100644 --- a/ui/src/main.jsx +++ b/ui/src/main.jsx @@ -4,12 +4,34 @@ import ReactDOM from 'react-dom/client'; import { Provider } from 'react-redux'; import { RouterProvider, createBrowserRouter } from 'react-router-dom'; import { getCookieConsentValue } from 'react-cookie-consent'; +import { v4 as uuidv4 } from 'uuid'; import { notFoundRoute } from './components/ErrorPage'; import App from './container/app'; import { modelsRoutes } from './container/models/routes'; import { store } from './store/configureStore'; +const getGrafanaTracking = (enableGrafanaTracking) => { + let tracking; + + if (enableGrafanaTracking === 'true') { + if (tracking === undefined) { + const userUUID = localStorage.getItem('radicalbit_user_uuid') === null ? uuidv4() : localStorage.getItem('radicalbit_user_uuid'); + localStorage.setItem('radicalbit_user_uuid', userUUID); + + tracking = initializeFaro({ + url: 'https://telemetry.oss.radicalbit.ai', + apiKey: 'rbitoss-JpIYMVC677edETUbJN9Me3iLS7ngGaE2RYLzQWCOYVljUJh5JJk5o2FE', + app: { name: 'radicalbit-ai-monitoring' }, + sessionTracking: { enabled: true }, + }); + tracking.api.setSession({ id: userUUID }); + } + } + return tracking; +}; + const enableGrafanaTracking = getCookieConsentValue('rbit-tracking'); +export const grafanaTracking = getGrafanaTracking(enableGrafanaTracking); const router = createBrowserRouter([ { @@ -22,19 +44,6 @@ const router = createBrowserRouter([ }, ]); -if (enableGrafanaTracking === 'true') { - initializeFaro({ - // required: the URL of the Grafana collector - url: 'https://telemetry.oss.radicalbit.ai', - apiKey: 'rbitoss-JpIYMVC677edETUbJN9Me3iLS7ngGaE2RYLzQWCOYVljUJh5JJk5o2FE', - - // required: the identification label of your application - app: { - name: 'radicalbit-ai-monitoring', - }, - }); -} - const browserRouter = (enableGrafanaTracking === 'true') ? withFaroRouterInstrumentation(router) : router; ReactDOM.createRoot(document.getElementById('root')).render( diff --git a/ui/src/store/state/context-configuration/thunks.js b/ui/src/store/state/context-configuration/thunks.js index bdabbb72..104c07a7 100644 --- a/ui/src/store/state/context-configuration/thunks.js +++ b/ui/src/store/state/context-configuration/thunks.js @@ -3,6 +3,7 @@ import { qsSetEncode64JSON } from '@Helpers/queryParams'; import { actions as notificationActions } from '@State/notification'; import { createAsyncThunk } from '@reduxjs/toolkit'; import { isEqual } from 'lodash'; +import { grafanaTracking } from '@Src/main'; import contextConfigurationSelectors from './selectors'; const { selectContextConfiguration } = contextConfigurationSelectors; @@ -42,6 +43,7 @@ const changeContextConfiguration = createAsyncThunk( return fulfillWithValue(newConfiguration); } catch (e) { console.error(e); + grafanaTracking?.api.pushError(e); const notificationMessage = notificationErrorJson(e); dispatch(setNotificationMessage(notificationMessage)); diff --git a/ui/yarn.lock b/ui/yarn.lock index 538f310c..8c814ed0 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -5981,6 +5981,11 @@ util-deprecate@^1.0.2: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +uuid@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-10.0.0.tgz#5a95aa454e6e002725c79055fd42aaba30ca6294" + integrity sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ== + vfile-message@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-4.0.2.tgz#c883c9f677c72c166362fd635f21fc165a7d1181"