Files
Doug ac2fdba3f1 Fix a potential crash caused by using old Sentry transactions. (#5459)
* Fix a deprecation warning.

* Remove unused method.

* Fix a crash caused by using old Sentry transactions.
2026-04-21 17:14:17 +01:00

116 lines
3.1 KiB
Swift

//
// Copyright 2025 Element Creations Ltd.
// Copyright 2023-2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
// Please see LICENSE files in the repository root for full details.
//
import CryptoKit
import Sentry
/// A simple wrapper around Sentry for easy instrumentation
class Signposter {
private var transactions = [TransactionName: any Sentry.Span]()
private var globalTags = [TagName: String]()
enum TransactionName: Hashable {
case cachedRoomList
case upToDateRoomList
case notificationToMessage
case openRoom
case sendMessage(uuid: String)
var id: String {
switch self {
case .cachedRoomList:
"Cached room list"
case .upToDateRoomList:
"Up-to-date room list"
case .notificationToMessage:
"Notification to message"
case .openRoom:
"Open a room"
case .sendMessage:
"Send a message"
}
}
}
enum SpanName: String {
case timelineLoad = "Timeline load"
}
struct Span {
fileprivate let innerSpan: Sentry.Span
func finish() {
innerSpan.finish()
}
}
enum TagName: String {
case homeserver
}
// MARK: - Transactions
func startTransaction(_ transactionName: TransactionName, operation: String = "ux", tags: [TagName: String] = [:]) {
let span = SentrySDK.startTransaction(name: transactionName.id, operation: operation)
tags
.merging(globalTags) { tagValue, _ in
tagValue
}
.forEach { (key: TagName, value: String) in
span.setTag(value: value, key: key.rawValue)
}
transactions[transactionName] = span
}
func finishTransaction(_ transactionName: TransactionName) {
transactions[transactionName]?.finish()
transactions[transactionName] = nil
}
func resetTransactions() {
transactions.removeAll()
}
// MARK: - Spans
func addSpan(_ spanName: SpanName, toTransaction transactionName: TransactionName) -> Span? {
guard let transaction = transactions[transactionName] else {
MXLog.error("Transaction not started or already finished")
return nil
}
return Span(innerSpan: transaction.startChild(operation: spanName.rawValue))
}
// MARK: - Tags
func addGlobalTag(_ tagName: TagName, value: String) {
let value = switch tagName {
case .homeserver:
sha512(value)
}
globalTags[tagName] = value
}
func removeGlobalTag(_ tagName: TagName) {
globalTags[tagName] = nil
}
// MARK: - Private
func sha512(_ string: String) -> String {
let data = Data(string.utf8)
let hash = SHA512.hash(data: data)
return hash.map { String(format: "%02x", $0) }.joined()
}
}