[UI Telemetry] Add rudimentary logging for navbar clicks#19480
[UI Telemetry] Add rudimentary logging for navbar clicks#19480daniellok-db merged 11 commits intomlflow:masterfrom
Conversation
| import { DesignSystemObservabilityEvent } from '../types'; | ||
| import { telemetryClient } from '../TelemetryClient'; | ||
|
|
||
| export const useLogTelemetryEvent = () => { |
There was a problem hiding this comment.
this will be edge blocked upstream and replaced with something that works in non-OSS
| const { experimentId } = useParams(); | ||
| const { search } = useLocation(); | ||
| const logTelemetryEvent = useLogTelemetryEvent(); | ||
| const viewId = crypto.randomUUID(); |
There was a problem hiding this comment.
this is not strictly accurate because viewId should be tied to the component itself, while this is generated in the parent component. however practically it's not a critical field and linking to parent is still better than nothing
| const { theme } = useDesignSystemTheme(); | ||
| const invalidateExperimentList = useInvalidateExperimentList(); | ||
| const navigate = useNavigate(); | ||
| const viewId = crypto.randomUUID(); |
There was a problem hiding this comment.
|
@daniellok-db Thank you for the contribution! Could you fix the following issue(s)? ⚠ DCO checkThe DCO check failed. Please sign off your commit(s) by following the instructions here. See https://github.com/mlflow/mlflow/blob/master/CONTRIBUTING.md#sign-your-work for more details. |
There was a problem hiding this comment.
Pull request overview
This PR adds rudimentary telemetry logging for navigation clicks in the MLflow UI. As part of a broader UI telemetry effort, it implements click tracking for sidebar navigation links and experiment page side navigation tabs.
Key Changes
- Adds telemetry event logging hook (
useLogTelemetryEvent) for tracking UI interactions - Implements click tracking for main sidebar navigation items and experiment page side navigation tabs
- Introduces a new Settings page with telemetry preferences toggle
- Adds informational alert about UI telemetry on the home page
- Updates documentation with details about UI interaction metadata collection
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| mlflow/server/js/src/telemetry/utils.ts | Adds version constant for telemetry alert dismissal tracking |
| mlflow/server/js/src/telemetry/types.ts | Adds proper TypeScript types from design system for event types |
| mlflow/server/js/src/telemetry/hooks/useLogTelemetryEvent.tsx | New hook for logging telemetry events with callback wrapper |
| mlflow/server/js/src/telemetry/TelemetryInfoAlert.tsx | New component displaying informational alert about telemetry collection |
| mlflow/server/js/src/settings/SettingsPage.tsx | New settings page allowing users to toggle telemetry preferences |
| mlflow/server/js/src/lang/default/en.json | Adds localization strings for telemetry UI elements |
| mlflow/server/js/src/home/HomePage.tsx | Integrates telemetry info alert on home page |
| mlflow/server/js/src/experiment-tracking/routes.ts | Adds routing configuration for new settings page |
| mlflow/server/js/src/experiment-tracking/route-defs.ts | Registers settings page route definition |
| mlflow/server/js/src/experiment-tracking/pages/experiment-page-tabs/side-nav/constants.tsx | Adds componentId fields to side navigation items for telemetry tracking |
| mlflow/server/js/src/experiment-tracking/pages/experiment-page-tabs/side-nav/ExperimentPageSideNavSection.tsx | Implements click event logging for experiment page side navigation tabs |
| mlflow/server/js/src/experiment-tracking/pages/experiment-page-tabs/side-nav/ExperimentPageSideNav.tsx | Imports telemetry hook (unused) |
| mlflow/server/js/src/common/components/MlflowSidebar.tsx | Adds click event logging for main sidebar navigation, adds Settings link |
| docs/docs/community/usage-tracking.mdx | Documents UI interaction metadata and telemetry opt-out options |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <Link | ||
| to={ExperimentTrackingRoutes.settingsPageRoute} | ||
| aria-current={isSettingsActive(location) ? 'page' : undefined} | ||
| css={{ | ||
| display: 'flex', | ||
| alignItems: 'center', | ||
| gap: theme.spacing.sm, | ||
| color: theme.colors.textPrimary, | ||
| paddingInline: theme.spacing.md, | ||
| paddingBlock: theme.spacing.sm, | ||
| borderRadius: theme.borders.borderRadiusSm, | ||
| '&:hover': { | ||
| color: theme.colors.actionLinkHover, | ||
| backgroundColor: theme.colors.actionDefaultBackgroundHover, | ||
| }, | ||
| '&[aria-current="page"]': { | ||
| backgroundColor: theme.colors.actionDefaultBackgroundPress, | ||
| color: theme.isDarkMode ? theme.colors.blue300 : theme.colors.blue700, | ||
| fontWeight: theme.typography.typographyBoldFontWeight, | ||
| }, | ||
| }} | ||
| > | ||
| <GearIcon /> | ||
| <FormattedMessage defaultMessage="Settings" description="Sidebar link for settings page" /> | ||
| </Link> |
There was a problem hiding this comment.
The Settings link is missing telemetry event logging. All other sidebar links have onClick handlers that log telemetry events, but the Settings link (lines 219-243) does not. This creates an inconsistency in telemetry data collection.
Add an onClick handler similar to the other links to ensure consistent telemetry tracking across all navigation elements.
| const { theme } = useDesignSystemTheme(); | ||
| const invalidateExperimentList = useInvalidateExperimentList(); | ||
| const navigate = useNavigate(); | ||
| const viewId = crypto.randomUUID(); |
There was a problem hiding this comment.
The viewId is generated once when the component renders and reuses the same UUID for all click events. According to the documentation (line 315 in usage-tracking.mdx), the componentViewId should be "regenerated whenever the UI element rerenders."
Currently, crypto.randomUUID() is called directly in the component body (line 45), which means it only generates once when the component mounts. This should be wrapped in a useMemo with an empty dependency array, or better yet, generate a new UUID for each interaction if that's the intended behavior based on the documentation.
| const { experimentId } = useParams(); | ||
| const { search } = useLocation(); | ||
| const logTelemetryEvent = useLogTelemetryEvent(); | ||
| const viewId = crypto.randomUUID(); |
There was a problem hiding this comment.
The viewId is generated once when the component renders and reuses the same UUID for all click events. According to the documentation (line 315 in usage-tracking.mdx), the componentViewId should be "regenerated whenever the UI element rerenders."
Currently, crypto.randomUUID() is called directly in the component body (line 35), which means it only generates once when the component mounts. This should be wrapped in a useMemo with an empty dependency array, or better yet, generate a new UUID for each interaction if that's the intended behavior based on the documentation.
There was a problem hiding this comment.
this is relevant too actually
| @@ -1,5 +1,5 @@ | |||
| import { useState } from 'react'; | |||
| import { Header, useDesignSystemTheme } from '@databricks/design-system'; | |||
| import { Alert, Button, Header, useDesignSystemTheme } from '@databricks/design-system'; | |||
There was a problem hiding this comment.
The imports Alert and Button from @databricks/design-system are not used anywhere in this file. These should be removed to keep the code clean.
| import { Alert, Button, Header, useDesignSystemTheme } from '@databricks/design-system'; | |
| import { Header, useDesignSystemTheme } from '@databricks/design-system'; |
| import { useLogTelemetryEvent } from '@mlflow/mlflow/src/telemetry/hooks/useLogTelemetryEvent'; | ||
|
|
There was a problem hiding this comment.
The import useLogTelemetryEvent is not used anywhere in this file. It should be removed to keep the code clean.
| import { useLogTelemetryEvent } from '@mlflow/mlflow/src/telemetry/hooks/useLogTelemetryEvent'; |
There was a problem hiding this comment.
@daniellok-db This comment seems to be relevant
|
Documentation preview for e4e6f4c is available at: Changed Pages (1)
More info
|
5c3387c to
85186cb
Compare
| import { useLogTelemetryEvent } from '@mlflow/mlflow/src/telemetry/hooks/useLogTelemetryEvent'; | ||
|
|
There was a problem hiding this comment.
@daniellok-db This comment seems to be relevant
5021f8b to
af235d3
Compare
af235d3 to
e4e6f4c
Compare
hubertzub-db
left a comment
There was a problem hiding this comment.
lg with a suggestion
| const { experimentId } = useParams(); | ||
| const { search } = useLocation(); | ||
| const logTelemetryEvent = useLogTelemetryEvent(); | ||
| const viewId = useMemo(() => crypto.randomUUID(), []); |
There was a problem hiding this comment.
I wonder if we could shove this inside useLogTelemetryEvent (which will be used as default componentViewId if not provided externally). This way, it's easier to reverse-EDGE-block in the future so it won't be executed in DB
|
This change breaks HTTP deployments. On the front end users will see a blank screen with the this error message in the console "TypeError: crypto.randomUUID is not a function".
|
🥞 Stacked PR
Use this link to review incremental changes.
Related Issues/PRs
#xxxWhat changes are proposed in this pull request?
Quick PR to add some rudimentary logging for tab clicks. Currently it is not logged due to the
<Link>component not being a design system component (it's fromreact-router-dom).Eventually it would be nice to have some context provider that automatically injects the current tab into the observability logs, but that will be a larger more complex change.
How is this PR tested?
Checked that logs are indeed logged:
Screen.Recording.2025-12-18.at.1.12.50.PM.mov
Does this PR require documentation update?
Release Notes
Is this a user-facing change?
What component(s), interfaces, languages, and integrations does this PR affect?
Components
area/tracking: Tracking Service, tracking client APIs, autologgingarea/models: MLmodel format, model serialization/deserialization, flavorsarea/model-registry: Model Registry service, APIs, and the fluent client calls for Model Registryarea/scoring: MLflow Model server, model deployment tools, Spark UDFsarea/evaluation: MLflow model evaluation features, evaluation metrics, and evaluation workflowsarea/gateway: MLflow AI Gateway client APIs, server, and third-party integrationsarea/prompts: MLflow prompt engineering features, prompt templates, and prompt managementarea/tracing: MLflow Tracing features, tracing APIs, and LLM tracing functionalityarea/projects: MLproject format, project running backendsarea/uiux: Front-end, user experience, plotting, JavaScript, JavaScript dev serverarea/build: Build and test infrastructure for MLflowarea/docs: MLflow documentation pagesHow should the PR be classified in the release notes? Choose one:
rn/none- No description will be included. The PR will be mentioned only by the PR number in the "Small Bugfixes and Documentation Updates" sectionrn/breaking-change- The PR will be mentioned in the "Breaking Changes" sectionrn/feature- A new user-facing feature worth mentioning in the release notesrn/bug-fix- A user-facing bug fix worth mentioning in the release notesrn/documentation- A user-facing documentation change worth mentioning in the release notesShould this PR be included in the next patch release?
Yesshould be selected for bug fixes, documentation updates, and other small changes.Noshould be selected for new features and larger changes. If you're unsure about the release classification of this PR, leave this unchecked to let the maintainers decide.What is a minor/patch release?
Bug fixes, doc updates and new features usually go into minor releases.
Bug fixes and doc updates usually go into patch releases.