[aider assisted] MM-61888: Add ClientSideUserIds field to MetricsSettings (#30127)
We add a new config setting to allow the admin to set a fixed list of userIDs to track for all client side webapp metrics. This gives the admin to get a deeper look at how the application is behaving for a single user. A new section in the system console is also added for the user to edit this setting from the UI. https://mattermost.atlassian.net/browse/MM-61888 ```release-note A new config setting MetricsSettings.ClientSideUserIds is added where you can set the user ids you want to track for client side webapp metrics. ``` * fix lint errors ```release-note NONE ``` * fixing tests ```release-note NONE ```
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
632a60b332
Коммит
1a58f923e0
@@ -91,7 +91,11 @@ func TestSubmitMetrics(t *testing.T) {
|
||||
|
||||
t.Run("metrics enabled and valid", func(t *testing.T) {
|
||||
metricsMock := setupMetricsMock()
|
||||
metricsMock.On("IncrementClientLongTasks", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("float64")).Return()
|
||||
metricsMock.On("IncrementClientLongTasks",
|
||||
mock.AnythingOfType("string"),
|
||||
mock.AnythingOfType("string"),
|
||||
mock.AnythingOfType("string"),
|
||||
mock.AnythingOfType("float64")).Return()
|
||||
|
||||
platform.RegisterMetricsInterface(func(_ *platform.PlatformService, _, _ string) einterfaces.MetricsInterface {
|
||||
return metricsMock
|
||||
@@ -159,7 +163,11 @@ func TestSubmitMetrics(t *testing.T) {
|
||||
|
||||
t.Run("metrics recorded for API errors", func(t *testing.T) {
|
||||
metricsMock := setupMetricsMock()
|
||||
metricsMock.On("IncrementClientLongTasks", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("float64")).Return()
|
||||
metricsMock.On("IncrementClientLongTasks",
|
||||
mock.AnythingOfType("string"),
|
||||
mock.AnythingOfType("string"),
|
||||
mock.AnythingOfType("string"),
|
||||
mock.AnythingOfType("float64")).Return()
|
||||
|
||||
platform.RegisterMetricsInterface(func(_ *platform.PlatformService, _, _ string) einterfaces.MetricsInterface {
|
||||
return metricsMock
|
||||
@@ -190,7 +198,11 @@ func TestSubmitMetrics(t *testing.T) {
|
||||
|
||||
t.Run("metrics recorded for URL length limit errors", func(t *testing.T) {
|
||||
metricsMock := setupMetricsMock()
|
||||
metricsMock.On("IncrementClientLongTasks", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("float64")).Return()
|
||||
metricsMock.On("IncrementClientLongTasks",
|
||||
mock.AnythingOfType("string"),
|
||||
mock.AnythingOfType("string"),
|
||||
mock.AnythingOfType("string"),
|
||||
mock.AnythingOfType("float64")).Return()
|
||||
|
||||
platform.RegisterMetricsInterface(func(_ *platform.PlatformService, _, _ string) einterfaces.MetricsInterface {
|
||||
return metricsMock
|
||||
|
||||
@@ -19,7 +19,7 @@ func (a *App) RegisterPerformanceReport(rctx request.CTX, report *model.Performa
|
||||
for _, c := range report.Counters {
|
||||
switch c.Metric {
|
||||
case model.ClientLongTasks:
|
||||
a.Metrics().IncrementClientLongTasks(commonLabels["platform"], commonLabels["agent"], c.Value)
|
||||
a.Metrics().IncrementClientLongTasks(commonLabels["platform"], commonLabels["agent"], userID, c.Value)
|
||||
default:
|
||||
// we intentionally skip unknown metrics
|
||||
}
|
||||
@@ -50,22 +50,26 @@ func (a *App) RegisterPerformanceReport(rctx request.CTX, report *model.Performa
|
||||
case model.ClientFirstContentfulPaint:
|
||||
a.Metrics().ObserveClientFirstContentfulPaint(commonLabels["platform"],
|
||||
commonLabels["agent"],
|
||||
userID,
|
||||
h.Value/1000)
|
||||
case model.ClientLargestContentfulPaint:
|
||||
a.Metrics().ObserveClientLargestContentfulPaint(
|
||||
commonLabels["platform"],
|
||||
commonLabels["agent"],
|
||||
h.GetLabelValue("region", model.AcceptedLCPRegions, "other"),
|
||||
userID,
|
||||
h.Value/1000)
|
||||
case model.ClientInteractionToNextPaint:
|
||||
a.Metrics().ObserveClientInteractionToNextPaint(
|
||||
commonLabels["platform"],
|
||||
commonLabels["agent"],
|
||||
h.GetLabelValue("interaction", model.AcceptedInteractions, "other"),
|
||||
userID,
|
||||
h.Value/1000)
|
||||
case model.ClientCumulativeLayoutShift:
|
||||
a.Metrics().ObserveClientCumulativeLayoutShift(commonLabels["platform"],
|
||||
commonLabels["agent"],
|
||||
userID,
|
||||
h.Value)
|
||||
case model.ClientPageLoadDuration:
|
||||
a.Metrics().ObserveClientPageLoadDuration(commonLabels["platform"],
|
||||
@@ -76,20 +80,24 @@ func (a *App) RegisterPerformanceReport(rctx request.CTX, report *model.Performa
|
||||
commonLabels["platform"],
|
||||
commonLabels["agent"],
|
||||
h.GetLabelValue("fresh", model.AcceptedTrueFalseLabels, ""),
|
||||
userID,
|
||||
h.Value/1000)
|
||||
case model.ClientTeamSwitchDuration:
|
||||
a.Metrics().ObserveClientTeamSwitchDuration(
|
||||
commonLabels["platform"],
|
||||
commonLabels["agent"],
|
||||
h.GetLabelValue("fresh", model.AcceptedTrueFalseLabels, ""),
|
||||
userID,
|
||||
h.Value/1000)
|
||||
case model.ClientRHSLoadDuration:
|
||||
a.Metrics().ObserveClientRHSLoadDuration(commonLabels["platform"],
|
||||
commonLabels["agent"],
|
||||
userID,
|
||||
h.Value/1000)
|
||||
case model.ClientGlobalThreadsLoadDuration:
|
||||
a.Metrics().ObserveGlobalThreadsLoadDuration(commonLabels["platform"],
|
||||
commonLabels["agent"],
|
||||
userID,
|
||||
h.Value/1000)
|
||||
case model.MobileClientLoadDuration:
|
||||
a.Metrics().ObserveMobileClientLoadDuration(commonLabels["platform"],
|
||||
|
||||
@@ -108,16 +108,16 @@ type MetricsInterface interface {
|
||||
ObserveClientTimeToLastByte(platform, agent, userID string, elapsed float64)
|
||||
ObserveClientTimeToDomInteractive(platform, agent, userID string, elapsed float64)
|
||||
ObserveClientSplashScreenEnd(platform, agent, pageType, userID string, elapsed float64)
|
||||
ObserveClientFirstContentfulPaint(platform, agent string, elapsed float64)
|
||||
ObserveClientLargestContentfulPaint(platform, agent, region string, elapsed float64)
|
||||
ObserveClientInteractionToNextPaint(platform, agent, interaction string, elapsed float64)
|
||||
ObserveClientCumulativeLayoutShift(platform, agent string, elapsed float64)
|
||||
IncrementClientLongTasks(platform, agent string, inc float64)
|
||||
ObserveClientFirstContentfulPaint(platform, agent, userID string, elapsed float64)
|
||||
ObserveClientLargestContentfulPaint(platform, agent, region, userID string, elapsed float64)
|
||||
ObserveClientInteractionToNextPaint(platform, agent, interaction, userID string, elapsed float64)
|
||||
ObserveClientCumulativeLayoutShift(platform, agent, userID string, elapsed float64)
|
||||
IncrementClientLongTasks(platform, agent, userID string, inc float64)
|
||||
ObserveClientPageLoadDuration(platform, agent, userID string, elapsed float64)
|
||||
ObserveClientChannelSwitchDuration(platform, agent, fresh string, elapsed float64)
|
||||
ObserveClientTeamSwitchDuration(platform, agent, fresh string, elapsed float64)
|
||||
ObserveClientRHSLoadDuration(platform, agent string, elapsed float64)
|
||||
ObserveGlobalThreadsLoadDuration(platform, agent string, elapsed float64)
|
||||
ObserveClientChannelSwitchDuration(platform, agent, fresh, userID string, elapsed float64)
|
||||
ObserveClientTeamSwitchDuration(platform, agent, fresh, userID string, elapsed float64)
|
||||
ObserveClientRHSLoadDuration(platform, agent, userID string, elapsed float64)
|
||||
ObserveGlobalThreadsLoadDuration(platform, agent, userID string, elapsed float64)
|
||||
ObserveMobileClientLoadDuration(platform string, elapsed float64)
|
||||
ObserveMobileClientChannelSwitchDuration(platform string, elapsed float64)
|
||||
ObserveMobileClientTeamSwitchDuration(platform string, elapsed float64)
|
||||
|
||||
@@ -78,9 +78,9 @@ func (_m *MetricsInterface) IncrementChannelIndexCounter() {
|
||||
_m.Called()
|
||||
}
|
||||
|
||||
// IncrementClientLongTasks provides a mock function with given fields: platform, agent, inc
|
||||
func (_m *MetricsInterface) IncrementClientLongTasks(platform string, agent string, inc float64) {
|
||||
_m.Called(platform, agent, inc)
|
||||
// IncrementClientLongTasks provides a mock function with given fields: platform, agent, userID, inc
|
||||
func (_m *MetricsInterface) IncrementClientLongTasks(platform string, agent string, userID string, inc float64) {
|
||||
_m.Called(platform, agent, userID, inc)
|
||||
}
|
||||
|
||||
// IncrementClusterEventType provides a mock function with given fields: eventType
|
||||
@@ -303,29 +303,29 @@ func (_m *MetricsInterface) ObserveAPIEndpointDuration(endpoint string, method s
|
||||
_m.Called(endpoint, method, statusCode, originClient, pageLoadContext, elapsed)
|
||||
}
|
||||
|
||||
// ObserveClientChannelSwitchDuration provides a mock function with given fields: platform, agent, fresh, elapsed
|
||||
func (_m *MetricsInterface) ObserveClientChannelSwitchDuration(platform string, agent string, fresh string, elapsed float64) {
|
||||
_m.Called(platform, agent, fresh, elapsed)
|
||||
// ObserveClientChannelSwitchDuration provides a mock function with given fields: platform, agent, fresh, userID, elapsed
|
||||
func (_m *MetricsInterface) ObserveClientChannelSwitchDuration(platform string, agent string, fresh string, userID string, elapsed float64) {
|
||||
_m.Called(platform, agent, fresh, userID, elapsed)
|
||||
}
|
||||
|
||||
// ObserveClientCumulativeLayoutShift provides a mock function with given fields: platform, agent, elapsed
|
||||
func (_m *MetricsInterface) ObserveClientCumulativeLayoutShift(platform string, agent string, elapsed float64) {
|
||||
_m.Called(platform, agent, elapsed)
|
||||
// ObserveClientCumulativeLayoutShift provides a mock function with given fields: platform, agent, userID, elapsed
|
||||
func (_m *MetricsInterface) ObserveClientCumulativeLayoutShift(platform string, agent string, userID string, elapsed float64) {
|
||||
_m.Called(platform, agent, userID, elapsed)
|
||||
}
|
||||
|
||||
// ObserveClientFirstContentfulPaint provides a mock function with given fields: platform, agent, elapsed
|
||||
func (_m *MetricsInterface) ObserveClientFirstContentfulPaint(platform string, agent string, elapsed float64) {
|
||||
_m.Called(platform, agent, elapsed)
|
||||
// ObserveClientFirstContentfulPaint provides a mock function with given fields: platform, agent, userID, elapsed
|
||||
func (_m *MetricsInterface) ObserveClientFirstContentfulPaint(platform string, agent string, userID string, elapsed float64) {
|
||||
_m.Called(platform, agent, userID, elapsed)
|
||||
}
|
||||
|
||||
// ObserveClientInteractionToNextPaint provides a mock function with given fields: platform, agent, interaction, elapsed
|
||||
func (_m *MetricsInterface) ObserveClientInteractionToNextPaint(platform string, agent string, interaction string, elapsed float64) {
|
||||
_m.Called(platform, agent, interaction, elapsed)
|
||||
// ObserveClientInteractionToNextPaint provides a mock function with given fields: platform, agent, interaction, userID, elapsed
|
||||
func (_m *MetricsInterface) ObserveClientInteractionToNextPaint(platform string, agent string, interaction string, userID string, elapsed float64) {
|
||||
_m.Called(platform, agent, interaction, userID, elapsed)
|
||||
}
|
||||
|
||||
// ObserveClientLargestContentfulPaint provides a mock function with given fields: platform, agent, region, elapsed
|
||||
func (_m *MetricsInterface) ObserveClientLargestContentfulPaint(platform string, agent string, region string, elapsed float64) {
|
||||
_m.Called(platform, agent, region, elapsed)
|
||||
// ObserveClientLargestContentfulPaint provides a mock function with given fields: platform, agent, region, userID, elapsed
|
||||
func (_m *MetricsInterface) ObserveClientLargestContentfulPaint(platform string, agent string, region string, userID string, elapsed float64) {
|
||||
_m.Called(platform, agent, region, userID, elapsed)
|
||||
}
|
||||
|
||||
// ObserveClientPageLoadDuration provides a mock function with given fields: platform, agent, userID, elapsed
|
||||
@@ -333,9 +333,9 @@ func (_m *MetricsInterface) ObserveClientPageLoadDuration(platform string, agent
|
||||
_m.Called(platform, agent, userID, elapsed)
|
||||
}
|
||||
|
||||
// ObserveClientRHSLoadDuration provides a mock function with given fields: platform, agent, elapsed
|
||||
func (_m *MetricsInterface) ObserveClientRHSLoadDuration(platform string, agent string, elapsed float64) {
|
||||
_m.Called(platform, agent, elapsed)
|
||||
// ObserveClientRHSLoadDuration provides a mock function with given fields: platform, agent, userID, elapsed
|
||||
func (_m *MetricsInterface) ObserveClientRHSLoadDuration(platform string, agent string, userID string, elapsed float64) {
|
||||
_m.Called(platform, agent, userID, elapsed)
|
||||
}
|
||||
|
||||
// ObserveClientSplashScreenEnd provides a mock function with given fields: platform, agent, pageType, userID, elapsed
|
||||
@@ -343,9 +343,9 @@ func (_m *MetricsInterface) ObserveClientSplashScreenEnd(platform string, agent
|
||||
_m.Called(platform, agent, pageType, userID, elapsed)
|
||||
}
|
||||
|
||||
// ObserveClientTeamSwitchDuration provides a mock function with given fields: platform, agent, fresh, elapsed
|
||||
func (_m *MetricsInterface) ObserveClientTeamSwitchDuration(platform string, agent string, fresh string, elapsed float64) {
|
||||
_m.Called(platform, agent, fresh, elapsed)
|
||||
// ObserveClientTeamSwitchDuration provides a mock function with given fields: platform, agent, fresh, userID, elapsed
|
||||
func (_m *MetricsInterface) ObserveClientTeamSwitchDuration(platform string, agent string, fresh string, userID string, elapsed float64) {
|
||||
_m.Called(platform, agent, fresh, userID, elapsed)
|
||||
}
|
||||
|
||||
// ObserveClientTimeToDomInteractive provides a mock function with given fields: platform, agent, userID, elapsed
|
||||
@@ -388,9 +388,9 @@ func (_m *MetricsInterface) ObserveFilesSearchDuration(elapsed float64) {
|
||||
_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)
|
||||
// ObserveGlobalThreadsLoadDuration provides a mock function with given fields: platform, agent, userID, elapsed
|
||||
func (_m *MetricsInterface) ObserveGlobalThreadsLoadDuration(platform string, agent string, userID string, elapsed float64) {
|
||||
_m.Called(platform, agent, userID, elapsed)
|
||||
}
|
||||
|
||||
// ObserveMobileClientChannelSwitchDuration provides a mock function with given fields: platform, elapsed
|
||||
|
||||
@@ -55,6 +55,8 @@ type MetricsInterfaceImpl struct {
|
||||
|
||||
Registry *prometheus.Registry
|
||||
|
||||
ClientSideUserIds map[string]bool
|
||||
|
||||
DbMasterConnectionsGauge prometheus.GaugeFunc
|
||||
DbReadConnectionsGauge prometheus.GaugeFunc
|
||||
DbSearchConnectionsGauge prometheus.GaugeFunc
|
||||
@@ -240,7 +242,7 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// New creates a new MetricsInterface. The driver and datasoruce parameters are added during
|
||||
// New creates a new MetricsInterface. The driver and datasource parameters are added during
|
||||
// migrating configuration store to the new platform service. Once the store and license are migrated,
|
||||
// we will be able to remove server dependency and lean on platform service during initialization.
|
||||
func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterfaceImpl {
|
||||
@@ -248,6 +250,12 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
Platform: ps,
|
||||
}
|
||||
|
||||
// Initialize ClientSideUserIds map
|
||||
m.ClientSideUserIds = make(map[string]bool)
|
||||
for _, userId := range ps.Config().MetricsSettings.ClientSideUserIds {
|
||||
m.ClientSideUserIds[userId] = true
|
||||
}
|
||||
|
||||
m.Registry = prometheus.NewRegistry()
|
||||
options := collectors.ProcessCollectorOpts{
|
||||
Namespace: MetricsNamespace,
|
||||
@@ -1196,7 +1204,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
Help: "Duration from when a browser starts to request a page from a server until when it starts to receive data in response (seconds)",
|
||||
ConstLabels: additionalLabels,
|
||||
},
|
||||
[]string{"platform", "agent"},
|
||||
[]string{"platform", "agent", "user_id"},
|
||||
m.Platform.Log(),
|
||||
)
|
||||
m.Registry.MustRegister(m.ClientTimeToFirstByte)
|
||||
@@ -1209,7 +1217,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
Help: "Duration from when a browser starts to request a page from a server until when it receives the last byte of the resource or immediately before the transport connection is closed, whichever comes first. (seconds)",
|
||||
ConstLabels: additionalLabels,
|
||||
},
|
||||
[]string{"platform", "agent"},
|
||||
[]string{"platform", "agent", "user_id"},
|
||||
m.Platform.Log(),
|
||||
)
|
||||
m.Registry.MustRegister(m.ClientTimeToLastByte)
|
||||
@@ -1223,7 +1231,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
Buckets: []float64{.1, .25, .5, 1, 2.5, 5, 7.5, 10, 12.5, 15},
|
||||
ConstLabels: additionalLabels,
|
||||
},
|
||||
[]string{"platform", "agent"},
|
||||
[]string{"platform", "agent", "user_id"},
|
||||
m.Platform.Log(),
|
||||
)
|
||||
m.Registry.MustRegister(m.ClientTimeToDOMInteractive)
|
||||
@@ -1237,7 +1245,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
Buckets: []float64{.1, .25, .5, 1, 2.5, 5, 7.5, 10, 12.5, 15},
|
||||
ConstLabels: additionalLabels,
|
||||
},
|
||||
[]string{"platform", "agent", "page_type"},
|
||||
[]string{"platform", "agent", "page_type", "user_id"},
|
||||
m.Platform.Log(),
|
||||
)
|
||||
m.Registry.MustRegister(m.ClientSplashScreenEnd)
|
||||
@@ -1253,7 +1261,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
Buckets: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10, 15, 20},
|
||||
ConstLabels: additionalLabels,
|
||||
},
|
||||
[]string{"platform", "agent"},
|
||||
[]string{"platform", "agent", "user_id"},
|
||||
)
|
||||
m.Registry.MustRegister(m.ClientFirstContentfulPaint)
|
||||
|
||||
@@ -1268,7 +1276,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
Buckets: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10, 15, 20},
|
||||
ConstLabels: additionalLabels,
|
||||
},
|
||||
[]string{"platform", "agent", "region"},
|
||||
[]string{"platform", "agent", "region", "user_id"},
|
||||
)
|
||||
m.Registry.MustRegister(m.ClientLargestContentfulPaint)
|
||||
|
||||
@@ -1280,7 +1288,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
Help: "Measure of how long it takes for a user to see the effects of clicking with a mouse, tapping with a touchscreen, or pressing a key on the keyboard (seconds)",
|
||||
ConstLabels: additionalLabels,
|
||||
},
|
||||
[]string{"platform", "agent", "interaction"},
|
||||
[]string{"platform", "agent", "interaction", "user_id"},
|
||||
)
|
||||
m.Registry.MustRegister(m.ClientInteractionToNextPaint)
|
||||
|
||||
@@ -1292,7 +1300,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
Help: "Measure of how much a page's content shifts unexpectedly",
|
||||
ConstLabels: additionalLabels,
|
||||
},
|
||||
[]string{"platform", "agent"},
|
||||
[]string{"platform", "agent", "user_id"},
|
||||
)
|
||||
m.Registry.MustRegister(m.ClientCumulativeLayoutShift)
|
||||
|
||||
@@ -1304,7 +1312,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
Help: "Counter of the number of times that the browser's main UI thread is blocked for more than 50ms by a single task",
|
||||
ConstLabels: additionalLabels,
|
||||
},
|
||||
[]string{"platform", "agent"},
|
||||
[]string{"platform", "agent", "user_id"},
|
||||
)
|
||||
m.Registry.MustRegister(m.ClientLongTasks)
|
||||
|
||||
@@ -1317,7 +1325,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
Buckets: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10, 20, 40},
|
||||
ConstLabels: additionalLabels,
|
||||
},
|
||||
[]string{"platform", "agent"},
|
||||
[]string{"platform", "agent", "user_id"},
|
||||
m.Platform.Log(),
|
||||
)
|
||||
m.Registry.MustRegister(m.ClientPageLoadDuration)
|
||||
@@ -1330,7 +1338,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
Help: "Duration of the time taken from when a user clicks on a channel in the LHS to when posts in that channel become visible (seconds)",
|
||||
ConstLabels: additionalLabels,
|
||||
},
|
||||
[]string{"platform", "agent", "fresh"},
|
||||
[]string{"platform", "agent", "fresh", "user_id"},
|
||||
)
|
||||
m.Registry.MustRegister(m.ClientChannelSwitchDuration)
|
||||
|
||||
@@ -1342,7 +1350,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
Help: "Duration of the time taken from when a user clicks on a team in the LHS to when posts in that team become visible (seconds)",
|
||||
ConstLabels: additionalLabels,
|
||||
},
|
||||
[]string{"platform", "agent", "fresh"},
|
||||
[]string{"platform", "agent", "fresh", "user_id"},
|
||||
)
|
||||
m.Registry.MustRegister(m.ClientTeamSwitchDuration)
|
||||
|
||||
@@ -1354,7 +1362,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
Help: "Duration of the time taken from when a user clicks to open a thread in the RHS until when posts in that thread become visible (seconds)",
|
||||
ConstLabels: additionalLabels,
|
||||
},
|
||||
[]string{"platform", "agent"},
|
||||
[]string{"platform", "agent", "user_id"},
|
||||
)
|
||||
m.Registry.MustRegister(m.ClientRHSLoadDuration)
|
||||
|
||||
@@ -1366,7 +1374,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
|
||||
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)",
|
||||
ConstLabels: additionalLabels,
|
||||
},
|
||||
[]string{"platform", "agent"},
|
||||
[]string{"platform", "agent", "user_id"},
|
||||
)
|
||||
m.Registry.MustRegister(m.ClientGlobalThreadsLoadDuration)
|
||||
|
||||
@@ -2024,63 +2032,81 @@ func (mi *MetricsInterfaceImpl) DecrementHTTPWebSockets(originClient string) {
|
||||
mi.HTTPWebsocketsGauge.With(prometheus.Labels{"origin_client": originClient}).Dec()
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) getEffectiveUserID(userID string) string {
|
||||
if mi.ClientSideUserIds[userID] {
|
||||
return userID
|
||||
}
|
||||
return "<placeholder>"
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientTimeToFirstByte(platform, agent, userID string, elapsed float64) {
|
||||
mi.ClientTimeToFirstByte.With(prometheus.Labels{"platform": platform, "agent": agent}, userID).Observe(elapsed)
|
||||
effectiveUserID := mi.getEffectiveUserID(userID)
|
||||
mi.ClientTimeToFirstByte.With(prometheus.Labels{"platform": platform, "agent": agent, "user_id": effectiveUserID}, userID).Observe(elapsed)
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientTimeToLastByte(platform, agent, userID string, elapsed float64) {
|
||||
mi.ClientTimeToLastByte.With(prometheus.Labels{"platform": platform, "agent": agent}, userID).Observe(elapsed)
|
||||
effectiveUserID := mi.getEffectiveUserID(userID)
|
||||
mi.ClientTimeToLastByte.With(prometheus.Labels{"platform": platform, "agent": agent, "user_id": effectiveUserID}, userID).Observe(elapsed)
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientTimeToDomInteractive(platform, agent, userID string, elapsed float64) {
|
||||
mi.ClientTimeToDOMInteractive.With(prometheus.Labels{"platform": platform, "agent": agent}, userID).Observe(elapsed)
|
||||
effectiveUserID := mi.getEffectiveUserID(userID)
|
||||
mi.ClientTimeToDOMInteractive.With(prometheus.Labels{"platform": platform, "agent": agent, "user_id": effectiveUserID}, userID).Observe(elapsed)
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientSplashScreenEnd(platform, agent, pageType, userID string, elapsed float64) {
|
||||
mi.ClientSplashScreenEnd.With(prometheus.Labels{"platform": platform, "agent": agent, "page_type": pageType}, userID).Observe(elapsed)
|
||||
effectiveUserID := mi.getEffectiveUserID(userID)
|
||||
mi.ClientSplashScreenEnd.With(prometheus.Labels{"platform": platform, "agent": agent, "page_type": pageType, "user_id": effectiveUserID}, userID).Observe(elapsed)
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientFirstContentfulPaint(platform, agent string, elapsed float64) {
|
||||
mi.ClientFirstContentfulPaint.With(prometheus.Labels{"platform": platform, "agent": agent}).Observe(elapsed)
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientFirstContentfulPaint(platform, agent, userID string, elapsed float64) {
|
||||
effectiveUserID := mi.getEffectiveUserID(userID)
|
||||
mi.ClientFirstContentfulPaint.With(prometheus.Labels{"platform": platform, "agent": agent, "user_id": effectiveUserID}).Observe(elapsed)
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientLargestContentfulPaint(platform, agent, region string, elapsed float64) {
|
||||
mi.ClientLargestContentfulPaint.With(prometheus.Labels{"platform": platform, "agent": agent, "region": region}).Observe(elapsed)
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientLargestContentfulPaint(platform, agent, region, userID string, elapsed float64) {
|
||||
effectiveUserID := mi.getEffectiveUserID(userID)
|
||||
mi.ClientLargestContentfulPaint.With(prometheus.Labels{"platform": platform, "agent": agent, "region": region, "user_id": effectiveUserID}).Observe(elapsed)
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientInteractionToNextPaint(platform, agent, interaction string, elapsed float64) {
|
||||
mi.ClientInteractionToNextPaint.With(prometheus.Labels{"platform": platform, "agent": agent, "interaction": interaction}).Observe(elapsed)
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientInteractionToNextPaint(platform, agent, interaction, userID string, elapsed float64) {
|
||||
effectiveUserID := mi.getEffectiveUserID(userID)
|
||||
mi.ClientInteractionToNextPaint.With(prometheus.Labels{"platform": platform, "agent": agent, "interaction": interaction, "user_id": effectiveUserID}).Observe(elapsed)
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientCumulativeLayoutShift(platform, agent string, elapsed float64) {
|
||||
mi.ClientCumulativeLayoutShift.With(prometheus.Labels{"platform": platform, "agent": agent}).Observe(elapsed)
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientCumulativeLayoutShift(platform, agent, userID string, elapsed float64) {
|
||||
effectiveUserID := mi.getEffectiveUserID(userID)
|
||||
mi.ClientCumulativeLayoutShift.With(prometheus.Labels{"platform": platform, "agent": agent, "user_id": effectiveUserID}).Observe(elapsed)
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) IncrementClientLongTasks(platform, agent string, inc float64) {
|
||||
mi.ClientLongTasks.With(prometheus.Labels{"platform": platform, "agent": agent}).Add(inc)
|
||||
func (mi *MetricsInterfaceImpl) IncrementClientLongTasks(platform, agent, userID string, inc float64) {
|
||||
effectiveUserID := mi.getEffectiveUserID(userID)
|
||||
mi.ClientLongTasks.With(prometheus.Labels{"platform": platform, "agent": agent, "user_id": effectiveUserID}).Add(inc)
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientPageLoadDuration(platform, agent, userID string, elapsed float64) {
|
||||
mi.ClientPageLoadDuration.With(prometheus.Labels{
|
||||
"platform": platform,
|
||||
"agent": agent,
|
||||
}, userID).Observe(elapsed)
|
||||
effectiveUserID := mi.getEffectiveUserID(userID)
|
||||
mi.ClientPageLoadDuration.With(prometheus.Labels{"platform": platform, "agent": agent, "user_id": effectiveUserID}, userID).Observe(elapsed)
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientChannelSwitchDuration(platform, agent, fresh string, elapsed float64) {
|
||||
mi.ClientChannelSwitchDuration.With(prometheus.Labels{"platform": platform, "agent": agent, "fresh": fresh}).Observe(elapsed)
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientChannelSwitchDuration(platform, agent, fresh, userID string, elapsed float64) {
|
||||
effectiveUserID := mi.getEffectiveUserID(userID)
|
||||
mi.ClientChannelSwitchDuration.With(prometheus.Labels{"platform": platform, "agent": agent, "fresh": fresh, "user_id": effectiveUserID}).Observe(elapsed)
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientTeamSwitchDuration(platform, agent, fresh string, elapsed float64) {
|
||||
mi.ClientTeamSwitchDuration.With(prometheus.Labels{"platform": platform, "agent": agent, "fresh": fresh}).Observe(elapsed)
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientTeamSwitchDuration(platform, agent, fresh, userID string, elapsed float64) {
|
||||
effectiveUserID := mi.getEffectiveUserID(userID)
|
||||
mi.ClientTeamSwitchDuration.With(prometheus.Labels{"platform": platform, "agent": agent, "fresh": fresh, "user_id": effectiveUserID}).Observe(elapsed)
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientRHSLoadDuration(platform, agent string, elapsed float64) {
|
||||
mi.ClientRHSLoadDuration.With(prometheus.Labels{"platform": platform, "agent": agent}).Observe(elapsed)
|
||||
func (mi *MetricsInterfaceImpl) ObserveClientRHSLoadDuration(platform, agent, userID string, elapsed float64) {
|
||||
effectiveUserID := mi.getEffectiveUserID(userID)
|
||||
mi.ClientRHSLoadDuration.With(prometheus.Labels{"platform": platform, "agent": agent, "user_id": effectiveUserID}).Observe(elapsed)
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) ObserveGlobalThreadsLoadDuration(platform, agent string, elapsed float64) {
|
||||
mi.ClientGlobalThreadsLoadDuration.With(prometheus.Labels{"platform": platform, "agent": agent}).Observe(elapsed)
|
||||
func (mi *MetricsInterfaceImpl) ObserveGlobalThreadsLoadDuration(platform, agent, userID string, elapsed float64) {
|
||||
effectiveUserID := mi.getEffectiveUserID(userID)
|
||||
mi.ClientGlobalThreadsLoadDuration.With(prometheus.Labels{"platform": platform, "agent": agent, "user_id": effectiveUserID}).Observe(elapsed)
|
||||
}
|
||||
|
||||
func (mi *MetricsInterfaceImpl) ObserveDesktopCpuUsage(platform, version, process string, usage float64) {
|
||||
|
||||
@@ -9076,6 +9076,14 @@
|
||||
"id": "model.config.is_valid.message_export.global_relay.smtp_username.app_error",
|
||||
"translation": "Message export job GlobalRelaySettings.SmtpUsername must be set."
|
||||
},
|
||||
{
|
||||
"id": "model.config.is_valid.metrics_client_side_user_id.app_error",
|
||||
"translation": "Invalid client side user id: {{.Id}}"
|
||||
},
|
||||
{
|
||||
"id": "model.config.is_valid.metrics_client_side_user_ids.app_error",
|
||||
"translation": "Number of elements in ClientSideUserIds {{.CurrentLength}} is higher than maximum limit of {{.MaxLength}}."
|
||||
},
|
||||
{
|
||||
"id": "model.config.is_valid.move_thread.domain_invalid.app_error",
|
||||
"translation": "Invalid domain for move thread settings"
|
||||
@@ -9426,7 +9434,7 @@
|
||||
},
|
||||
{
|
||||
"id": "model.incoming_hook.id.app_error",
|
||||
"translation": "Invalid Id."
|
||||
"translation": "Invalid Id: {{.Id}}."
|
||||
},
|
||||
{
|
||||
"id": "model.incoming_hook.parse_data.app_error",
|
||||
|
||||
@@ -1071,11 +1071,12 @@ func (s *ClusterSettings) SetDefaults() {
|
||||
}
|
||||
|
||||
type MetricsSettings struct {
|
||||
Enable *bool `access:"environment_performance_monitoring,write_restrictable,cloud_restrictable"`
|
||||
BlockProfileRate *int `access:"environment_performance_monitoring,write_restrictable,cloud_restrictable"`
|
||||
ListenAddress *string `access:"environment_performance_monitoring,write_restrictable,cloud_restrictable"` // telemetry: none
|
||||
EnableClientMetrics *bool `access:"environment_performance_monitoring,write_restrictable,cloud_restrictable"`
|
||||
EnableNotificationMetrics *bool `access:"environment_performance_monitoring,write_restrictable,cloud_restrictable"`
|
||||
Enable *bool `access:"environment_performance_monitoring,write_restrictable,cloud_restrictable"`
|
||||
BlockProfileRate *int `access:"environment_performance_monitoring,write_restrictable,cloud_restrictable"`
|
||||
ListenAddress *string `access:"environment_performance_monitoring,write_restrictable,cloud_restrictable"` // telemetry: none
|
||||
EnableClientMetrics *bool `access:"environment_performance_monitoring,write_restrictable,cloud_restrictable"`
|
||||
EnableNotificationMetrics *bool `access:"environment_performance_monitoring,write_restrictable,cloud_restrictable"`
|
||||
ClientSideUserIds []string `access:"environment_performance_monitoring,write_restrictable,cloud_restrictable"` // telemetry: none
|
||||
}
|
||||
|
||||
func (s *MetricsSettings) SetDefaults() {
|
||||
@@ -1098,6 +1099,23 @@ func (s *MetricsSettings) SetDefaults() {
|
||||
if s.EnableNotificationMetrics == nil {
|
||||
s.EnableNotificationMetrics = NewPointer(true)
|
||||
}
|
||||
|
||||
if s.ClientSideUserIds == nil {
|
||||
s.ClientSideUserIds = []string{}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *MetricsSettings) isValid() *AppError {
|
||||
const maxLength = 5
|
||||
if len(s.ClientSideUserIds) > maxLength {
|
||||
return NewAppError("MetricsSettings.IsValid", "model.config.is_valid.metrics_client_side_user_ids.app_error", map[string]any{"MaxLength": maxLength, "CurrentLength": len(s.ClientSideUserIds)}, "", http.StatusBadRequest)
|
||||
}
|
||||
for _, id := range s.ClientSideUserIds {
|
||||
if !IsValidId(id) {
|
||||
return NewAppError("MetricsSettings.IsValid", "model.config.is_valid.metrics_client_side_user_id.app_error", map[string]any{"Id": id}, "", http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ExperimentalSettings struct {
|
||||
@@ -3806,6 +3824,10 @@ func (o *Config) IsValid() *AppError {
|
||||
return NewAppError("Config.IsValid", "model.config.is_valid.cluster_email_batching.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if appErr := o.MetricsSettings.isValid(); appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
|
||||
if appErr := o.CacheSettings.isValid(); appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ type IncomingWebhooksWithCount struct {
|
||||
|
||||
func (o *IncomingWebhook) IsValid() *AppError {
|
||||
if !IsValidId(o.Id) {
|
||||
return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.id.app_error", nil, "", http.StatusBadRequest)
|
||||
return NewAppError("IncomingWebhook.IsValid", "model.incoming_hook.id.app_error", map[string]any{"Id": o.Id}, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if o.CreateAt == 0 {
|
||||
|
||||
Ссылка в новой задаче
Block a user