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
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
45e3b54b60
Коммит
441f5657c8
@@ -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',
|
||||||
}
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user