App Center (macOS) 損毀
重要
Visual Studio App Center 已排定於 2025 年 3 月 31 日淘汰。 雖然您可以繼續使用 Visual Studio App Center,直到完全淘汰為止,但有數個建議的替代方案可以考慮移轉至。
App Center 當機會在每次應用程式當機時自動產生當機記錄。 記錄會先寫入裝置的記憶體,當使用者再次啟動應用程式時,當機報告會傳送至 App Center。 收集當機適用於 Beta 和即時應用程式,也就是提交至 App Store 的應用程式。 當機記錄包含寶貴的資訊,可協助您修正當機。
如果您尚未在應用程式中設定 SDK,請遵循 使用者入門 一節。
此外,macOS 上的當機記錄需要符號,請參閱 App Center 診斷檔 ,說明如何為您的應用程式提供符號。
注意
4.0.0
在 App Center 重大變更版本中引進。 遵循 移轉至 App Center SDK 4.0.0 和更新 版本一節,從舊版移轉 App Center。
擴充功能中的當機報告
App Center 支援 macOS 擴充功能中的當機報告。 使用方式與容器應用程式中相同。
產生測試當機
App Center 當機可讓您使用 API 來產生測試損毀,以便輕鬆測試 SDK。 此 API 只能用於測試/Beta 應用程式,且不會在生產應用程式中執行任何動作。
[MSACCrashes generateTestCrash];
Crashes.generateTestCrash()
取得先前損毀的詳細資訊
App Center 當機有兩個 API,可讓您在應用程式損毀時提供詳細資訊。
應用程式是否在上一個會話中收到記憶體不足的警告?
在啟動 SDK 之後,您可以隨時檢查應用程式是否在上一個工作階段中收到記憶體警告:
[MSACCrashes hasReceivedMemoryWarningInLastSession];
Crashes.hasReceivedMemoryWarningInLastSession
注意
這個方法只能在啟動之後 Crashes
使用,它一律會傳回 NO
或 false
啟動之前。
注意
在某些情況下,記憶體不足的裝置無法傳送事件。
應用程式在上一個工作階段中是否當機?
在啟動 SDK 之後,您可以隨時檢查應用程式是否在上一次啟動時損毀:
[MSACCrashes hasCrashedInLastSession];
Crashes.hasCrashedInLastSession
如果您想要在發生當機之後調整應用程式的行為或 UI,這會很有用。
注意
這個方法只能在啟動之後 MSACCrashes
使用,它一律會傳回 NO
或 false
啟動之前。
上次當機的詳細數據
如果您的應用程式先前損毀,您可以取得最後一次當機的詳細數據。
MSACErrorReport *crashReport = [MSACCrashes lastSessionCrashReport];
var crashReport = Crashes.lastSessionCrashReport
注意
這個方法只能在啟動之後 Crashes
使用,它一律會在開始之前傳回 nil
。
此 API 有許多使用案例,最常見的是呼叫此 API 並實作其自定義 CrashesDelegate 的人員。
自訂 App Center 損毀的使用方式
App Center 當機提供回呼,讓開發人員在將當機記錄傳送至 App Center 之前和時執行其他動作。
若要新增自定義行為,您必須採用 CrashesDelegate
-protocol,其所有方法都是選擇性的。
註冊為委派
[MSACCrashes setDelegate:self];
Crashes.delegate = self
注意
您必須在呼叫 AppCenter.start
之前設定委派,因為 App Center 會在啟動後立即開始處理當機。
是否應該處理當機?
crashes:shouldProcessErrorReport:
如果您想要決定是否需要處理特定當機,請在採用 -protocol 的 類別CrashesDelegate
中實作 -method。 例如,您可能想要忽略系統層級損毀,而且您不想傳送至 App Center。
- (BOOL)crashes:(MSACCrashes *)crashes shouldProcessErrorReport:(MSACErrorReport *)errorReport {
return YES; // return YES if the crash report should be processed, otherwise NO.
}
func crashes(_ crashes: Crashes, shouldProcess errorReport: ErrorReport) -> Bool {
return true; // return true if the crash report should be processed, otherwise false.
}
已處理的錯誤
App Center 也可讓您透過方法使用已處理的例外狀況 trackError
來追蹤錯誤。 應用程式可以選擇性地將屬性或/和附件附加至已處理的錯誤報告,以提供進一步的內容。
@try {
// Throw error.
} @catch (NSError *error) {
// Init attachments.
NSArray<MSACErrorAttachmentLog *> attachments = @[ MSACErrorAttachmentLog attachmentWithText:@"Hello world!" filename:@"hello.txt"] ]
// Init properties.
NSDictionary *properties = @{ "Category" : "Music", "Wifi" : "On" };
// Track errors.
[MSACCrashes trackError:error withProperties:properties attachments:attachments];
[MSACCrashes trackError:error withProperties:properties attachments:nil];
[MSACCrashes trackError:error withProperties:nil attachments:attachments];
[MSACCrashes trackError:error withProperties:nil attachments:nil];
}
do {
// Throw error.
} catch {
// Init attachments.
let attachments = [ErrorAttachmentLog.attachment(withText: "Hello world!", filename: "hello.txt")]
// Init properties.
let properties:Dictionary<String, String> = ["Category" : "Music", "Wifi" : "On"]
// Track errors.
Crashes.trackError(error, properties: properties, attachments: attachments)
Crashes.trackError(error, properties: properties, attachments: nil)
Crashes.trackError(error, properties: nil, attachments: attachments)
Crashes.trackError(error, properties: nil, attachments: nil)
}
針對追蹤例外狀況,您可以使用 trackException
方法:
@try {
// Throw exceptions.
} @catch (NSException *exception) {
// Init exceptions.
MSACExceptionModel *customException1 = [MSACExceptionModel initWithType:@"Custom exception" exceptionMessage:"Track custom exception.", stackTrace:exception.callStackSymbols];
MSACExceptionModel *customException2 = [MSACExceptionModel initWithException:exception];
// Track exceptions.
[MSACCrashes trackException:customException1 withProperties:properties attachments:nil];
[MSACCrashes trackException:customException2 withProperties:properties attachments:nil];
}
do {
// Throw exception.
} catch {
// Init exception.
let exception = ExceptionModel(withType: "Custom exception", exceptionMessage: "Track custom exception.", stackTrace: Thread.callStackSymbols)
// Track exception.
Crashes.trackException(exception, properties: properties, attachments: nil)
}
要求使用者同意傳送當機記錄檔
如果用戶隱私權對您很重要,您可能想要先取得使用者確認,再將當機報告傳送至 App Center。 SDK 會公開回呼,告知 App Center 當機以等候使用者確認,再傳送任何當機報告。
如果您選擇這樣做,您必須負責取得使用者的確認,例如透過對話框提示字元,其中包含下列其中一個選項: 一律傳送、 傳送和 不要傳送。 根據輸入,您會告訴 App Center 當機該怎麼做,然後會據以處理當機。
注意
SDK 不會顯示此對話框,應用程式必須提供自己的 UI 以要求使用者同意。
下列方法示範如何設定使用者確認處理程式:
[MSACCrashes setUserConfirmationHandler:(^(NSArray<MSACErrorReport *> *errorReports) {
// Your code to present your UI to the user, e.g. an NSAlert.
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText:@"Sorry about that!"];
[alert setInformativeText:@"Do you want to send an anonymous crash report so we can fix the issue?"];
[alert addButtonWithTitle:@"Always send"];
[alert addButtonWithTitle:@"Send"];
[alert addButtonWithTitle:@"Don't send"];
[alert setAlertStyle:NSWarningAlertStyle];
switch ([alert runModal]) {
case NSAlertFirstButtonReturn:
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationAlways];
break;
case NSAlertSecondButtonReturn:
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationSend];
break;
case NSAlertThirdButtonReturn:
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationDontSend];
break;
default:
break;
}
return YES; // Return YES if the SDK should await user confirmation, otherwise NO.
})];
Crashes.setUserConfirmationHandler({ (errorReports: [ErrorReport]) in
// Your code to present your UI to the user, e.g. an NSAlert.
let alert: NSAlert = NSAlert()
alert.messageText = "Sorry about that!"
alert.informativeText = "Do you want to send an anonymous crash report so we can fix the issue?"
alert.addButton(withTitle: "Always send")
alert.addButton(withTitle: "Send")
alert.addButton(withTitle: "Don't send")
alert.alertStyle = NSWarningAlertStyle
switch (alert.runModal()) {
case NSAlertFirstButtonReturn:
Crashes.notify(with: .always)
break;
case NSAlertSecondButtonReturn:
Crashes.notify(with: .send)
break;
case NSAlertThirdButtonReturn:
Crashes.notify(with: .dontSend)
break;
default:
break;
}
return true // Return true if the SDK should await user confirmation, otherwise return false.
})
如果您在上述處理程式區塊中傳回 YES
/true
,您的應用程式應該取得用戶許可權,並使用下列 API 向 SDK 訊息。 如果您使用此警示,如同我們在上述範例中所做的一樣,您會根據呼叫的結果 (ModalResponse) 呼叫 runModal
。
// Depending on the user's choice, call notifyWithUserConfirmation: with the right value.
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationDontSend];
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationSend];
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationAlways];
// Depending on the user's choice, call notify(with:) with the right value.
Crashes.notify(with: .dontSend)
Crashes.notify(with: .send)
Crashes.notify(with: .always)
啟用擷取在主線程上擲回的未攔截例外狀況
AppKit 會攔截在主線程上擲回的例外狀況,防止應用程式在macOS上當機,因此SDK無法攔截這些損毀。 若要模擬 iOS 行為,請在 SDK 初始化之前設定 NSApplicationCrashOnExceptions
旗標,此旗標可讓應用程式在未攔截的例外狀況時當機,且 SDK 可以報告它們。
[[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"NSApplicationCrashOnExceptions" : @YES }];
UserDefaults.standard.register(defaults: ["NSApplicationCrashOnExceptions": true])
注意
App Center SDK 會在 1.10.0 版和以下版本中自動設定 旗標。 從 1.11.0 版開始,此旗標將不再自動設定。
停用對 App Center 損毀之應用程式主要類別方法呼叫的轉送
App Center 當機 SDK 會使用撥動來改善其整合,方法是轉送一些應用程式主要類別的方法呼叫。 方法撥動是在運行時間變更方法實作的方法。 如果基於任何原因而不想使用 (例如,因為特定原則) ,您應該自行覆寫應用程式的 reportException:
和 sendEvent:
方法,以便讓當機報告主線程上擲回的例外狀況。
建立 ReportExceptionApplication.m 檔案,並新增下列實作:
@import Cocoa; @import AppCenterCrashes; @interface ReportExceptionApplication : NSApplication @end @implementation ReportExceptionApplication - (void)reportException:(NSException *)exception { [MSACCrashes applicationDidReportException:exception]; [super reportException:exception]; } - (void)sendEvent:(NSEvent *)theEvent { @try { [super sendEvent:theEvent]; } @catch (NSException *exception) { [self reportException:exception]; } } @end
注意
try
/catch
Swift 不適用於NSException
。 這些例外狀況只能在 Objective-C 中處理。開啟 Info.plist 檔案,並將 Principal 類別欄位中的 NSApplication 取代為您的應用程式類別名稱 ReportExceptionApplication 在此範例中。
若要停用 App Center SDK 中的撥動,請將金鑰新增
AppCenterApplicationForwarderEnabled
至 Info.plist 檔案,並將值設定為0
。
取得當機記錄的傳送狀態相關信息
有時候,您想要知道應用程式當機的狀態。 常見的使用案例是您可能想要顯示UI,告知使用者您的應用程式正在提交當機報告,或者,如果您的app在啟動後快速當機,您想要調整應用程式的行為,以確保可以提交當機記錄。 CrashesDelegate
-protocol 會定義三個不同的回呼,您可以在應用程式中用來通知發生什麼情況:
SDK 傳送當機記錄檔之前,將會叫用下列回呼
- (void)crashes:(MSACCrashes *)crashes willSendErrorReport:(MSACErrorReport *)errorReport {
// Your code, e.g. to present a custom UI.
}
func crashes(_ crashes: Crashes, willSend errorReport: ErrorReport) {
// Your code, e.g. to present a custom UI.
}
如果端點發生網路問題或中斷,且您重新啟動應用程式, willSendErrorReport
則會在進程重新啟動后再次觸發。
SDK 成功傳送當機記錄檔之後,將會叫用下列回呼
- (void)crashes:(MSACCrashes *)crashes didSucceedSendingErrorReport:(MSACErrorReport *)errorReport {
// Your code, e.g. to hide the custom UI.
}
func crashes(_ crashes: Crashes, didSucceedSending errorReport: ErrorReport) {
// Your code goes here.
}
如果 SDK 無法傳送當機記錄檔,將會叫用下列回呼
- (void)crashes:(MSACCrashes *)crashes didFailSendingErrorReport:(MSACErrorReport *)errorReport withError:(NSError *)error {
// Your code goes here.
}
func crashes(_ crashes: Crashes, didFailSending errorReport: ErrorReport, withError error: Error) {
// Your code goes here.
}
didFailSendingErrorReport
接收表示發生無法復原的錯誤,例如 4xx 碼。 例如, 401 表示 appSecret
錯誤。
如果這是網路問題,則不會觸發此回呼。 在此情況下,SDK 會持續重試 (,並在網路連線關閉時暫停重試) 。
將附件新增至損毀報告
您可以將二進位和文字附件新增至當機報表。 SDK 會連同當機一起傳送它們,讓您可以在 App Center 入口網站中看到它們。 在傳送先前應用程式啟動的預存損毀之前,會立即叫用下列回呼。 噹噹機發生時,不會叫用它。 以下是如何將文字和影像附加至當機的範例:
- (NSArray<MSACErrorAttachmentLog *> *)attachmentsWithCrashes:(MSACCrashes *)crashes
forErrorReport:(MSACErrorReport *)errorReport {
MSACErrorAttachmentLog *attachment1 = [MSACErrorAttachmentLog attachmentWithText:@"Hello world!" filename:@"hello.txt"];
MSACErrorAttachmentLog *attachment2 = [MSACErrorAttachmentLog attachmentWithBinary:[@"Fake image" dataUsingEncoding:NSUTF8StringEncoding] filename:@"fake_image.jpeg" contentType:@"image/jpeg"];
return @[ attachment1, attachment2 ];
}
func attachments(with crashes: Crashes, for errorReport: ErrorReport) -> [ErrorAttachmentLog]? {
let attachment1 = ErrorAttachmentLog.attachment(withText: "Hello world!", filename: "hello.txt")
let attachment2 = ErrorAttachmentLog.attachment(withBinary: "Fake image".data(using: String.Encoding.utf8), filename: nil, contentType: "image/jpeg")
return [attachment1!, attachment2!]
}
注意
大小限制目前為 7 MB。 嘗試傳送較大的附件將會觸發錯誤。
在運行時間啟用或停用 App Center 當機
您可以在執行時間啟用和停用 App Center 當機。 如果您停用此功能,SDK 將不會對應用程式執行任何損毀報告。
[MSACCrashes setEnabled:NO];
Crashes.enabled = false
若要再次啟用App Center當機,請使用相同的API,但傳遞 YES
/true
做為參數。
[MSACCrashes setEnabled:YES];
Crashes.enabled = true
狀態會保存在應用程式啟動的裝置記憶體中。
注意
只有在啟動之後 Crashes
,才能使用這個方法。
檢查 App Center 當機是否已啟用
您也可以檢查 App Center 當機是否已啟用:
BOOL enabled = [MSACCrashes isEnabled];
var enabled = Crashes.enabled
注意
這個方法只能在啟動之後 Crashes
使用,它一律會在 start 之前傳回 false
。
停用Mach例外狀況處理
根據預設,App Center 當機會使用 Mach 例外狀況處理程式,透過 Mach 例外狀況伺服器攔截嚴重訊號,例如堆疊溢位。
disableMachExceptionHandler
-method 提供選項,可透過Mach例外狀況伺服器停用攔截嚴重訊號。 如果您想要停用 Mach 例外狀況處理程式,您應該在啟動 SDK 之前 先呼叫此方法。 您的一般設定程式代碼看起來會像這樣:
[MSACCrashes disableMachExceptionHandler];
[MSACAppCenter start:@"{Your App Secret}" withServices:@[[MSACAnalytics class], [MSACCrashes class]]];
Crashes.disableMachExceptionHandler()
AppCenter.start(withAppSecret: "{Your App Secret}", services: [Analytics.self, Crashes.self])