MM-57882 Add metric for the time it takes to open the Threads list (#26983)

* MM-57882 Add metric for the time it takes to open the Threads list

* Clean up mark because the starting mark may be missing

* Pass global threads load duration to Prometheus

* Update mocks
Этот коммит содержится в:
Harrison Healey
2024-05-21 18:04:12 -04:00
коммит произвёл GitHub
родитель 45e3b54b60
Коммит 441f5657c8
8 изменённых файлов: 59 добавлений и 18 удалений

Просмотреть файл

@@ -42,6 +42,8 @@ func (a *App) RegisterPerformanceReport(rctx request.CTX, report *model.Performa
a.Metrics().ObserveClientTeamSwitchDuration(commonLabels["platform"], commonLabels["agent"], h.Value/1000) a.Metrics().ObserveClientTeamSwitchDuration(commonLabels["platform"], commonLabels["agent"], h.Value/1000)
case model.ClientRHSLoadDuration: case model.ClientRHSLoadDuration:
a.Metrics().ObserveClientRHSLoadDuration(commonLabels["platform"], commonLabels["agent"], h.Value/1000) a.Metrics().ObserveClientRHSLoadDuration(commonLabels["platform"], commonLabels["agent"], h.Value/1000)
case model.ClientGlobalThreadsLoadDuration:
a.Metrics().ObserveGlobalThreadsLoadDuration(commonLabels["platform"], commonLabels["agent"], h.Value/1000)
default: default:
// we intentionally skip unknown metrics // we intentionally skip unknown metrics
} }

Просмотреть файл

@@ -112,4 +112,5 @@ type MetricsInterface interface {
ObserveClientChannelSwitchDuration(platform, agent string, elapsed float64) ObserveClientChannelSwitchDuration(platform, agent string, elapsed float64)
ObserveClientTeamSwitchDuration(platform, agent string, elapsed float64) ObserveClientTeamSwitchDuration(platform, agent string, elapsed float64)
ObserveClientRHSLoadDuration(platform, agent string, elapsed float64) ObserveClientRHSLoadDuration(platform, agent string, elapsed float64)
ObserveGlobalThreadsLoadDuration(platform, agent string, elapsed float64)
} }

Просмотреть файл

@@ -353,6 +353,11 @@ func (_m *MetricsInterface) ObserveFilesSearchDuration(elapsed float64) {
_m.Called(elapsed) _m.Called(elapsed)
} }
// ObserveGlobalThreadsLoadDuration provides a mock function with given fields: platform, agent, elapsed
func (_m *MetricsInterface) ObserveGlobalThreadsLoadDuration(platform string, agent string, elapsed float64) {
_m.Called(platform, agent, elapsed)
}
// ObservePluginAPIDuration provides a mock function with given fields: pluginID, apiName, success, elapsed // ObservePluginAPIDuration provides a mock function with given fields: pluginID, apiName, success, elapsed
func (_m *MetricsInterface) ObservePluginAPIDuration(pluginID string, apiName string, success bool, elapsed float64) { func (_m *MetricsInterface) ObservePluginAPIDuration(pluginID string, apiName string, success bool, elapsed float64) {
_m.Called(pluginID, apiName, success, elapsed) _m.Called(pluginID, apiName, success, elapsed)

Просмотреть файл

@@ -211,15 +211,16 @@ type MetricsInterfaceImpl struct {
NotificationNotSentCounters *prometheus.CounterVec NotificationNotSentCounters *prometheus.CounterVec
NotificationUnsupportedCounters *prometheus.CounterVec NotificationUnsupportedCounters *prometheus.CounterVec
ClientTimeToFirstByte *prometheus.HistogramVec ClientTimeToFirstByte *prometheus.HistogramVec
ClientFirstContentfulPaint *prometheus.HistogramVec ClientFirstContentfulPaint *prometheus.HistogramVec
ClientLargestContentfulPaint *prometheus.HistogramVec ClientLargestContentfulPaint *prometheus.HistogramVec
ClientInteractionToNextPaint *prometheus.HistogramVec ClientInteractionToNextPaint *prometheus.HistogramVec
ClientCumulativeLayoutShift *prometheus.HistogramVec ClientCumulativeLayoutShift *prometheus.HistogramVec
ClientLongTasks *prometheus.CounterVec ClientLongTasks *prometheus.CounterVec
ClientChannelSwitchDuration *prometheus.HistogramVec ClientChannelSwitchDuration *prometheus.HistogramVec
ClientTeamSwitchDuration *prometheus.HistogramVec ClientTeamSwitchDuration *prometheus.HistogramVec
ClientRHSLoadDuration *prometheus.HistogramVec ClientRHSLoadDuration *prometheus.HistogramVec
ClientGlobalThreadsLoadDuration *prometheus.HistogramVec
} }
func init() { func init() {
@@ -1232,6 +1233,17 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
) )
m.Registry.MustRegister(m.ClientRHSLoadDuration) m.Registry.MustRegister(m.ClientRHSLoadDuration)
m.ClientGlobalThreadsLoadDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: MetricsNamespace,
Subsystem: MetricsSubsystemClientsWeb,
Name: "global_threads_load",
Help: "Duration of the time taken from when a user clicks to open Threads in the LHS until when the global threads view becomes visible (milliseconds)",
},
[]string{"platform", "agent"},
)
m.Registry.MustRegister(m.ClientGlobalThreadsLoadDuration)
return m return m
} }
@@ -1726,6 +1738,10 @@ func (mi *MetricsInterfaceImpl) ObserveClientRHSLoadDuration(platform, agent str
mi.ClientRHSLoadDuration.With(prometheus.Labels{"platform": platform, "agent": agent}).Observe(elapsed) mi.ClientRHSLoadDuration.With(prometheus.Labels{"platform": platform, "agent": agent}).Observe(elapsed)
} }
func (mi *MetricsInterfaceImpl) ObserveGlobalThreadsLoadDuration(platform, agent string, elapsed float64) {
mi.ClientGlobalThreadsLoadDuration.With(prometheus.Labels{"platform": platform, "agent": agent}).Observe(elapsed)
}
func extractDBCluster(driver, connectionString string) (string, error) { func extractDBCluster(driver, connectionString string) (string, error) {
host, err := extractHost(driver, connectionString) host, err := extractHost(driver, connectionString)
if err != nil { if err != nil {

Просмотреть файл

@@ -14,15 +14,16 @@ import (
type MetricType string type MetricType string
const ( const (
ClientTimeToFirstByte MetricType = "TTFB" ClientTimeToFirstByte MetricType = "TTFB"
ClientFirstContentfulPaint MetricType = "FCP" ClientFirstContentfulPaint MetricType = "FCP"
ClientLargestContentfulPaint MetricType = "LCP" ClientLargestContentfulPaint MetricType = "LCP"
ClientInteractionToNextPaint MetricType = "INP" ClientInteractionToNextPaint MetricType = "INP"
ClientCumulativeLayoutShift MetricType = "CLS" ClientCumulativeLayoutShift MetricType = "CLS"
ClientLongTasks MetricType = "long_tasks" ClientLongTasks MetricType = "long_tasks"
ClientChannelSwitchDuration MetricType = "channel_switch" ClientChannelSwitchDuration MetricType = "channel_switch"
ClientTeamSwitchDuration MetricType = "team_switch" ClientTeamSwitchDuration MetricType = "team_switch"
ClientRHSLoadDuration MetricType = "rhs_load" ClientRHSLoadDuration MetricType = "rhs_load"
ClientGlobalThreadsLoadDuration MetricType = "global_threads_load"
performanceReportTTLMilliseconds = 300 * 1000 // 300 seconds/5 minutes performanceReportTTLMilliseconds = 300 * 1000 // 300 seconds/5 minutes
) )

Просмотреть файл

@@ -31,6 +31,7 @@ import LoadingScreen from 'components/loading_screen';
import NoResultsIndicator from 'components/no_results_indicator'; import NoResultsIndicator from 'components/no_results_indicator';
import {PreviousViewedTypes} from 'utils/constants'; import {PreviousViewedTypes} from 'utils/constants';
import {Mark, Measure, measureAndReport} from 'utils/performance_telemetry';
import type {GlobalState} from 'types/store/index'; import type {GlobalState} from 'types/store/index';
import {LhsItemType, LhsPage} from 'types/store/lhs'; import {LhsItemType, LhsPage} from 'types/store/lhs';
@@ -117,6 +118,13 @@ const GlobalThreads = () => {
}); });
}, [filter, threadIds, unreadThreadIds]); }, [filter, threadIds, unreadThreadIds]);
useEffect(() => {
if (!isLoading) {
measureAndReport(Measure.GlobalThreadsLoad, Mark.GlobalThreadsLinkClicked, undefined, true);
performance.clearMarks(Mark.GlobalThreadsLinkClicked);
}
}, [isLoading]);
useEffect(() => { useEffect(() => {
if (!selectedThread && !selectedPost && !isLoading) { if (!selectedThread && !selectedPost && !isLoading) {
clear(); clear();

Просмотреть файл

@@ -35,6 +35,7 @@ import Constants, {
RHSStates, RHSStates,
} from 'utils/constants'; } from 'utils/constants';
import {t} from 'utils/i18n'; import {t} from 'utils/i18n';
import {Mark} from 'utils/performance_telemetry';
import type {GlobalState} from 'types/store'; import type {GlobalState} from 'types/store';
@@ -67,10 +68,15 @@ const GlobalThreadsLink = () => {
const showTutorialTrigger = isFeatureEnabled && crtTutorialTrigger === Constants.CrtTutorialTriggerSteps.START && !appHaveOpenModal && Boolean(threadsCount) && threadsCount.total >= 1; const showTutorialTrigger = isFeatureEnabled && crtTutorialTrigger === Constants.CrtTutorialTriggerSteps.START && !appHaveOpenModal && Boolean(threadsCount) && threadsCount.total >= 1;
const openThreads = useCallback((e) => { const openThreads = useCallback((e) => {
e.stopPropagation(); e.stopPropagation();
trackEvent('crt', 'go_to_global_threads'); trackEvent('crt', 'go_to_global_threads');
performance.mark(Mark.GlobalThreadsLinkClicked);
if (showTutorialTrigger) { if (showTutorialTrigger) {
dispatch(openModal({modalId: ModalIdentifiers.COLLAPSED_REPLY_THREADS_MODAL, dialogType: CollapsedReplyThreadsModal, dialogProps: {}})); dispatch(openModal({modalId: ModalIdentifiers.COLLAPSED_REPLY_THREADS_MODAL, dialogType: CollapsedReplyThreadsModal, dialogProps: {}}));
} }
if (rhsOpen && rhsState === RHSStates.EDIT_HISTORY) { if (rhsOpen && rhsState === RHSStates.EDIT_HISTORY) {
dispatch(closeRightHandSide()); dispatch(closeRightHandSide());
} }

Просмотреть файл

@@ -3,6 +3,7 @@
export const enum Mark { export const enum Mark {
ChannelLinkClicked = 'SidebarChannelLink#click', ChannelLinkClicked = 'SidebarChannelLink#click',
GlobalThreadsLinkClicked = 'GlobalThreadsLink#click',
PostListLoaded = 'PostList#component', PostListLoaded = 'PostList#component',
PostSelected = 'PostList#postSelected', PostSelected = 'PostList#postSelected',
TeamLinkClicked = 'TeamLink#click', TeamLinkClicked = 'TeamLink#click',
@@ -10,6 +11,7 @@ export const enum Mark {
export const enum Measure { export const enum Measure {
ChannelSwitch = 'channel_switch', ChannelSwitch = 'channel_switch',
GlobalThreadsLoad = 'global_threads_load',
RhsLoad = 'rhs_load', RhsLoad = 'rhs_load',
TeamSwitch = 'team_switch', TeamSwitch = 'team_switch',
} }