TF-4269 Apply PR review: breadcrumbs, log error details, and code cleanup for NSE Sentry integration
- Replace capture(message:) with addBreadcrumb(level: .warning) in NotificationService for non-error diagnostic checkpoints - Add addBreadcrumb method to SentryManager with category/level support - Include error details in KeychainController SentryConfig decode failure log - Split combined guard into two separate guards to distinguish nil state vs unchanged state - Remove dead do-catch block in onComplete closure; use errors.forEach to capture real errors - Translate Vietnamese doc comment to English in SentryManager
This commit is contained in:
@@ -178,8 +178,10 @@ jobs:
|
||||
# 4. Upload dSYMs (Native code: Swift, Objective-C, C++)
|
||||
DSYM_DIR="$XCARCHIVE/dSYMs"
|
||||
if [ -d "$DSYM_DIR" ]; then
|
||||
echo "dSYM contents:"
|
||||
ls -la "$DSYM_DIR"
|
||||
echo "Uploading dSYMs from $DSYM_DIR..."
|
||||
sentry-cli debug-files upload --include-sources "$DSYM_DIR"
|
||||
sentry-cli debug-files upload --include-sources --log-level info "$DSYM_DIR"
|
||||
else
|
||||
echo "::error::dSYMs directory not found inside xcarchive at $DSYM_DIR."
|
||||
exit 1
|
||||
|
||||
@@ -71,7 +71,7 @@ extension KeychainController {
|
||||
}
|
||||
return try JSONDecoder().decode(SentryConfig.self, from: configData)
|
||||
} catch {
|
||||
TwakeLogger.shared.log(message: "SentryConfig could not be decoded from Keychain")
|
||||
TwakeLogger.shared.log(message: "SentryConfig could not be decoded from Keychain: \(error)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ class NotificationService: UNNotificationServiceExtension {
|
||||
|
||||
guard let payloadData = request.content.userInfo as? [String: Any],
|
||||
!keychainController.retrieveSharingSessions().isEmpty else {
|
||||
SentryManager.shared.capture(message: "NSE: Payload invalid or No Session found in Keychain")
|
||||
SentryManager.shared.addBreadcrumb(message: "NSE: Payload invalid or No Session found in Keychain", level: .warning)
|
||||
self.showDefaultNotification(message: NSLocalizedString(self.newNotificationDefaultMessageKey, comment: "Localizable"))
|
||||
return self.notify()
|
||||
}
|
||||
@@ -63,29 +63,34 @@ class NotificationService: UNNotificationServiceExtension {
|
||||
let mapStateChanges: [String: [TypeName: String]] = PayloadParser.shared.parsingPayloadNotification(payloadData: payloadData)
|
||||
|
||||
if (mapStateChanges.isEmpty) {
|
||||
SentryManager.shared.capture(message: "NSE: Payload parsing returned empty state changes")
|
||||
SentryManager.shared.addBreadcrumb(message: "NSE: Payload parsing returned empty state changes", level: .warning)
|
||||
self.showDefaultNotification(message: NSLocalizedString(self.newNotificationDefaultMessageKey, comment: "Localizable"))
|
||||
return self.notify()
|
||||
} else {
|
||||
guard let currentAccountId = mapStateChanges.keys.first,
|
||||
let keychainSharingSession = keychainController.retrieveSharingSessionFromKeychain(accountId: currentAccountId),
|
||||
keychainSharingSession.tokenOIDC != nil || keychainSharingSession.basicAuth != nil else {
|
||||
SentryManager.shared.capture(message: "NSE: Session missing or invalid credential for account: \(mapStateChanges.keys.first ?? "unknown")")
|
||||
SentryManager.shared.addBreadcrumb(message: "NSE: Session missing or invalid credential for account: \(mapStateChanges.keys.first ?? "unknown")", level: .warning)
|
||||
self.showDefaultNotification(message: NSLocalizedString(self.newNotificationDefaultMessageKey, comment: "Localizable"))
|
||||
return self.notify()
|
||||
}
|
||||
|
||||
SentryManager.shared.setSentryUser(keychainSharingSession.sentryUser)
|
||||
|
||||
|
||||
guard let listStateOfAccount = mapStateChanges[currentAccountId],
|
||||
let newEmailDeliveryState = listStateOfAccount[TypeName.emailDelivery] else {
|
||||
SentryManager.shared.capture(message: "NSE: Missing emailDelivery state in payload")
|
||||
SentryManager.shared.addBreadcrumb(message: "NSE: Missing emailDelivery state in payload", level: .warning)
|
||||
self.showDefaultNotification(message: NSLocalizedString(self.newNotificationDefaultMessageKey, comment: "Localizable"))
|
||||
return self.notify()
|
||||
}
|
||||
|
||||
guard let oldEmailDeliveryState = keychainSharingSession.emailDeliveryState ?? keychainSharingSession.emailState,
|
||||
newEmailDeliveryState != oldEmailDeliveryState else {
|
||||
|
||||
guard let oldEmailDeliveryState = keychainSharingSession.emailDeliveryState ?? keychainSharingSession.emailState else {
|
||||
SentryManager.shared.addBreadcrumb(message: "NSE: No stored email state for account: \(currentAccountId)", level: .warning)
|
||||
self.showDefaultNotification(message: NSLocalizedString(self.newEmailDefaultMessageKey, comment: "Localizable"))
|
||||
return self.notify()
|
||||
}
|
||||
|
||||
guard newEmailDeliveryState != oldEmailDeliveryState else {
|
||||
self.showDefaultNotification(message: NSLocalizedString(self.newEmailDefaultMessageKey, comment: "Localizable"))
|
||||
return self.notify()
|
||||
}
|
||||
@@ -101,33 +106,28 @@ class NotificationService: UNNotificationServiceExtension {
|
||||
oidcScopes: keychainSharingSession.oidcScopes,
|
||||
isTWP: keychainSharingSession.isTWP,
|
||||
onComplete: { (emails, errors) in
|
||||
do {
|
||||
if emails.isEmpty {
|
||||
self.showDefaultNotification(message: NSLocalizedString(self.newEmailDefaultMessageKey, comment: "Localizable"))
|
||||
return self.notify()
|
||||
} else {
|
||||
self.keychainController.updateEmailDeliveryStateToKeychain(
|
||||
accountId: keychainSharingSession.accountId,
|
||||
newEmailDeliveryState: newEmailDeliveryState
|
||||
)
|
||||
errors.forEach { SentryManager.shared.capture(error: $0) }
|
||||
|
||||
let mailboxIdsBlockNotification = keychainSharingSession.mailboxIdsBlockNotification ?? []
|
||||
|
||||
if (mailboxIdsBlockNotification.isEmpty) {
|
||||
return self.showListNotification(emails: emails)
|
||||
} else {
|
||||
let emailFiltered = self.filterEmailsToPushNotification(
|
||||
emails: emails,
|
||||
mailboxIdsBlockNotification: mailboxIdsBlockNotification)
|
||||
return self.showListNotification(emails: emailFiltered)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
TwakeLogger.shared.log(message: "Error processing emails: \(error)")
|
||||
SentryManager.shared.capture(error: error)
|
||||
if emails.isEmpty {
|
||||
self.showDefaultNotification(message: NSLocalizedString(self.newEmailDefaultMessageKey, comment: "Localizable"))
|
||||
return self.notify()
|
||||
}
|
||||
|
||||
self.keychainController.updateEmailDeliveryStateToKeychain(
|
||||
accountId: keychainSharingSession.accountId,
|
||||
newEmailDeliveryState: newEmailDeliveryState
|
||||
)
|
||||
|
||||
let mailboxIdsBlockNotification = keychainSharingSession.mailboxIdsBlockNotification ?? []
|
||||
|
||||
if mailboxIdsBlockNotification.isEmpty {
|
||||
return self.showListNotification(emails: emails)
|
||||
} else {
|
||||
let emailFiltered = self.filterEmailsToPushNotification(
|
||||
emails: emails,
|
||||
mailboxIdsBlockNotification: mailboxIdsBlockNotification)
|
||||
return self.showListNotification(emails: emailFiltered)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -75,7 +75,20 @@ class SentryManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set user context cho Sentry
|
||||
/// Adds a breadcrumb to the current Sentry scope.
|
||||
/// Breadcrumbs are accumulated in-memory and automatically attached to the next
|
||||
/// captured error event. Use this for diagnostic checkpoints that provide context
|
||||
/// for real errors — they are NOT sent as standalone events.
|
||||
func addBreadcrumb(message: String, category: String = "nse", level: SentryLevel = .info) {
|
||||
guard isInitialized else { return }
|
||||
let crumb = Breadcrumb()
|
||||
crumb.message = message
|
||||
crumb.category = category
|
||||
crumb.level = level
|
||||
SentrySDK.addBreadcrumb(crumb)
|
||||
}
|
||||
|
||||
/// Set user context for Sentry
|
||||
func setSentryUser(_ user: User) {
|
||||
guard isInitialized else { return }
|
||||
SentrySDK.setUser(user)
|
||||
|
||||
Reference in New Issue
Block a user