2023-07-11 10:32:24 +01:00
|
|
|
//
|
2024-09-06 16:34:30 +03:00
|
|
|
// Copyright 2023, 2024 New Vector Ltd.
|
2023-07-11 10:32:24 +01:00
|
|
|
//
|
2025-01-06 11:27:37 +01:00
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
|
|
// Please see LICENSE files in the repository root for full details.
|
2023-07-11 10:32:24 +01:00
|
|
|
//
|
|
|
|
|
|
|
|
import OSLog
|
2024-06-28 18:15:57 +03:00
|
|
|
import Sentry
|
2023-07-11 10:32:24 +01:00
|
|
|
|
|
|
|
/// A simple wrapper around OSSignposter for easy performance testing.
|
|
|
|
class Signposter {
|
|
|
|
/// The underlying signposter.
|
|
|
|
private let signposter = OSSignposter(subsystem: subsystem, category: category)
|
|
|
|
/// A logger instance to capture any errors.
|
|
|
|
private let logger = Logger(subsystem: subsystem, category: category)
|
|
|
|
|
|
|
|
/// Signpost name constants.
|
2024-07-11 17:38:32 +01:00
|
|
|
enum Name {
|
2023-07-11 10:32:24 +01:00
|
|
|
static let login: StaticString = "Login"
|
2023-08-24 13:26:37 +03:00
|
|
|
static let firstSync: StaticString = "FirstSync"
|
|
|
|
static let firstRooms: StaticString = "FirstRooms"
|
2023-07-11 10:32:24 +01:00
|
|
|
static let roomFlow: StaticString = "RoomFlow"
|
2024-06-28 18:15:57 +03:00
|
|
|
|
|
|
|
static let appStartup = "AppStartup"
|
|
|
|
static let appStarted = "AppStarted"
|
|
|
|
|
|
|
|
static let homeserver = "homeserver"
|
2023-07-11 10:32:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static let subsystem = "ElementX"
|
|
|
|
static let category = "PerformanceTests"
|
|
|
|
|
2024-07-25 15:56:45 +01:00
|
|
|
// MARK: - App Startup
|
2024-06-28 18:15:57 +03:00
|
|
|
|
2024-07-25 15:56:45 +01:00
|
|
|
private var appStartupTransaction: Span?
|
|
|
|
|
|
|
|
// We have a manual start method because we need to configure the ServiceLocator *before* we configure
|
|
|
|
// Sentry but this class is created in the AnalyticsService and so spans and transactions are dropped
|
|
|
|
// until Sentry has been configured. Therefore doing this in the init doesn't work.
|
|
|
|
func start() {
|
2024-07-19 10:35:09 +03:00
|
|
|
appStartupTransaction = SentrySDK.startTransaction(name: Name.appStartup, operation: Name.appStarted)
|
2024-06-28 18:15:57 +03:00
|
|
|
}
|
|
|
|
|
2023-07-11 10:32:24 +01:00
|
|
|
// MARK: - Login
|
|
|
|
|
|
|
|
private var loginState: OSSignpostIntervalState?
|
2024-07-19 10:35:09 +03:00
|
|
|
private var loginTransaction: Span?
|
2024-06-28 18:15:57 +03:00
|
|
|
private var loginSpan: Span?
|
2023-07-11 10:32:24 +01:00
|
|
|
|
|
|
|
func beginLogin() {
|
|
|
|
loginState = signposter.beginInterval(Name.login)
|
2024-07-19 10:35:09 +03:00
|
|
|
loginTransaction = SentrySDK.startTransaction(name: "\(Name.login)", operation: "\(Name.login)")
|
2024-07-25 15:56:45 +01:00
|
|
|
loginSpan = appStartupTransaction?.startChild(operation: "\(Name.login)", description: "\(Name.login)")
|
2023-07-11 10:32:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func endLogin() {
|
|
|
|
guard let loginState else {
|
|
|
|
logger.error("Missing login state.")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
signposter.endInterval(Name.login, loginState)
|
2024-07-19 10:35:09 +03:00
|
|
|
loginTransaction?.finish()
|
2024-06-28 18:15:57 +03:00
|
|
|
loginSpan?.finish()
|
|
|
|
|
2023-07-11 10:32:24 +01:00
|
|
|
self.loginState = nil
|
2024-07-19 10:35:09 +03:00
|
|
|
loginTransaction = nil
|
2024-06-28 18:15:57 +03:00
|
|
|
loginSpan = nil
|
2023-07-11 10:32:24 +01:00
|
|
|
}
|
|
|
|
|
2023-08-24 13:26:37 +03:00
|
|
|
// MARK: - FirstSync
|
2023-07-11 10:32:24 +01:00
|
|
|
|
2023-08-24 13:26:37 +03:00
|
|
|
private var firstSyncState: OSSignpostIntervalState?
|
2024-07-19 10:35:09 +03:00
|
|
|
private var firstSyncTransaction: Span?
|
2024-06-28 18:15:57 +03:00
|
|
|
private var firstSyncSpan: Span?
|
2023-07-11 10:32:24 +01:00
|
|
|
|
2024-06-28 18:15:57 +03:00
|
|
|
func beginFirstSync(serverName: String) {
|
2024-07-25 15:56:45 +01:00
|
|
|
appStartupTransaction?.setTag(value: serverName, key: Name.homeserver)
|
2024-06-28 18:15:57 +03:00
|
|
|
|
2023-08-24 13:26:37 +03:00
|
|
|
firstSyncState = signposter.beginInterval(Name.firstSync)
|
2024-07-19 10:35:09 +03:00
|
|
|
|
|
|
|
firstSyncTransaction = SentrySDK.startTransaction(name: "\(Name.firstSync)", operation: "\(Name.firstSync)")
|
|
|
|
firstSyncTransaction?.setTag(value: serverName, key: Name.homeserver)
|
|
|
|
|
2024-07-25 15:56:45 +01:00
|
|
|
firstSyncSpan = appStartupTransaction?.startChild(operation: "\(Name.firstSync)", description: "\(Name.firstSync)")
|
2023-07-11 10:32:24 +01:00
|
|
|
}
|
|
|
|
|
2023-08-24 13:26:37 +03:00
|
|
|
func endFirstSync() {
|
|
|
|
guard let firstSyncState else { return }
|
2023-07-11 10:32:24 +01:00
|
|
|
|
2023-08-24 13:26:37 +03:00
|
|
|
signposter.endInterval(Name.firstSync, firstSyncState)
|
2024-07-19 10:35:09 +03:00
|
|
|
firstSyncTransaction?.finish()
|
2024-06-28 18:15:57 +03:00
|
|
|
firstSyncSpan?.finish()
|
|
|
|
|
2023-08-24 13:26:37 +03:00
|
|
|
self.firstSyncState = nil
|
2024-07-19 10:35:09 +03:00
|
|
|
firstSyncTransaction = nil
|
2024-06-28 18:15:57 +03:00
|
|
|
firstSyncSpan = nil
|
2023-08-24 13:26:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - FirstRooms
|
|
|
|
|
|
|
|
private var firstRoomsState: OSSignpostIntervalState?
|
2024-07-19 10:35:09 +03:00
|
|
|
private var firstRoomsTransaction: Span?
|
2024-06-28 18:15:57 +03:00
|
|
|
private var firstRoomsSpan: Span?
|
2023-08-24 13:26:37 +03:00
|
|
|
|
|
|
|
func beginFirstRooms() {
|
|
|
|
firstRoomsState = signposter.beginInterval(Name.firstRooms)
|
2024-07-19 10:35:09 +03:00
|
|
|
firstRoomsTransaction = SentrySDK.startTransaction(name: "\(Name.firstRooms)", operation: "\(Name.firstRooms)")
|
2024-07-25 15:56:45 +01:00
|
|
|
firstRoomsSpan = appStartupTransaction?.startChild(operation: "\(Name.firstRooms)", description: "\(Name.firstRooms)")
|
2023-08-24 13:26:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func endFirstRooms() {
|
2024-06-28 18:15:57 +03:00
|
|
|
defer {
|
2024-07-25 15:56:45 +01:00
|
|
|
appStartupTransaction?.finish()
|
2024-06-28 18:15:57 +03:00
|
|
|
}
|
|
|
|
|
2023-08-24 13:26:37 +03:00
|
|
|
guard let firstRoomsState else { return }
|
|
|
|
|
|
|
|
signposter.endInterval(Name.firstRooms, firstRoomsState)
|
2024-07-19 10:35:09 +03:00
|
|
|
firstRoomsTransaction?.finish()
|
2024-06-28 18:15:57 +03:00
|
|
|
firstRoomsSpan?.finish()
|
|
|
|
|
2023-08-24 13:26:37 +03:00
|
|
|
self.firstRoomsState = nil
|
2024-07-19 10:35:09 +03:00
|
|
|
firstRoomsTransaction = nil
|
2024-06-28 18:15:57 +03:00
|
|
|
firstRoomsSpan = nil
|
2023-07-11 10:32:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Room Flow
|
|
|
|
|
|
|
|
private var roomFlowState: OSSignpostIntervalState?
|
|
|
|
|
|
|
|
func beginRoomFlow(_ name: String) {
|
|
|
|
roomFlowState = signposter.beginInterval(Name.roomFlow)
|
|
|
|
signposter.emitEvent("RoomName", "\(name, privacy: .auto(mask: .hash))")
|
|
|
|
}
|
|
|
|
|
|
|
|
func endRoomFlow() {
|
|
|
|
guard let roomFlowState else { return }
|
|
|
|
|
|
|
|
signposter.endInterval(Name.roomFlow, roomFlowState)
|
|
|
|
self.roomFlowState = nil
|
|
|
|
}
|
|
|
|
}
|