···11-import Foundation
22-import Sentry
33-44-/// Client-side filter for Sentry events.
55-///
66-/// Wired into `SentrySDK.start { options.beforeSend = SentryEventFilter.filterSystemHang }`.
77-///
88-/// Members are explicitly `nonisolated`: Sentry invokes `beforeSend` synchronously
99-/// from its own background threads (notably `SentryANRTrackerV1`'s detection thread).
1010-/// Under the project's `SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor` setting, any
1111-/// un-annotated member would implicitly be `@MainActor`, and Swift 6.2's executor
1212-/// check aborts the process via libdispatch when such code runs off the main thread.
1313-enum SentryEventFilter {
1414- /// Known stack frame function-name fragments that indicate a system-induced
1515- /// App Hang (wake-from-sleep, active space change, external display connect,
1616- /// menu bar redraw, etc.). These hangs are observable but have no app-level
1717- /// remedy — filter them out to avoid drowning real hangs in noise.
1818- nonisolated static let systemHangSignatures = [
1919- "_NSMenuBarDisplayManagerActiveSpaceChanged",
2020- "NSMenuBarLocalDisplayWindow",
2121- "NSMenuBarPresentationInstance",
2222- "NSMenuBarReplicantWindow",
2323- ]
2424-2525- /// Drop App Hang events whose stack contains zero in-app frames AND matches
2626- /// at least one known system signature. Conservative by design: if the hang
2727- /// involves any app code, keep it; if the stack is all-system but matches no
2828- /// known pattern, keep it too (so we still see novel system-level issues).
2929- nonisolated static func filterSystemHang(_ event: Event) -> Event? {
3030- guard let exception = event.exceptions?.first,
3131- exception.mechanism?.type == "AppHang"
3232- else {
3333- return event
3434- }
3535- let frames = exception.stacktrace?.frames ?? []
3636- let hasAppFrame = frames.contains { $0.inApp?.boolValue == true }
3737- let hasSystemSignature = frames.contains { frame in
3838- guard let function = frame.function else { return false }
3939- return systemHangSignatures.contains { function.contains($0) }
4040- }
4141- if !hasAppFrame && hasSystemSignature {
4242- return nil
4343- }
4444- return event
4545- }
4646-}