Selhání App Center (macOS)

Důležité

Visual Studio App Center je naplánované k vyřazení na 31. března 2025. I když můžete Visual Studio App Center dál používat, dokud ho úplně nevyřadíte, existuje několik doporučených alternativ, na které můžete migraci zvážit.

Přečtěte si další informace o časových osách a alternativách podpory.

Chybové ukončení app center automaticky vygeneruje protokol chybových ukončení pokaždé, když dojde k chybě aplikace. Protokol se nejprve zapíše do úložiště zařízení, a když uživatel aplikaci znovu spustí, zpráva o chybách se odešle do App Center. Shromažďování chyb funguje pro beta i živé aplikace, tj. ty, které byly odeslány do App Store. Protokoly chyb obsahují cenné informace, které vám pomůžou chybu opravit.

Pokud jste v aplikaci ještě nenastavili sadu SDK, postupujte podle Začínáme části.

Protokoly chyb v systému macOS také vyžadují symboliku. Přečtěte si dokumentaci k diagnostice app center , která vysvětluje, jak poskytnout symboly pro vaši aplikaci.

Poznámka

4.0.0 Ve verzi App Center byly zavedeny zásadní změny. Pokud chcete migrovat App Center z předchozích verzí, postupujte podle části Migrace na sadu App Center SDK 4.0.0 a vyšší .

Hlášení chyb v rozšířeních

App Center podporuje hlášení chybových ukončení v rozšířeních pro macOS. Využití je stejné jako v kontejnerové aplikaci.

Vygenerování chybového ukončení testu

Chybové ukončení app center poskytuje rozhraní API pro vygenerování testovací chyby pro snadné testování sady SDK. Toto rozhraní API se dá použít jenom v testovacích nebo beta aplikacích a v produkčních aplikacích nic nedělá.

[MSACCrashes generateTestCrash];
Crashes.generateTestCrash()

Získání dalších informací o předchozím chybovém ukončení

Aplikace App Center crashes má dvě rozhraní API, která poskytují další informace pro případ, že dojde k chybě aplikace.

Obdržela aplikace v předchozí relaci upozornění na nedostatek paměti?

Kdykoli po spuštění sady SDK můžete zkontrolovat, jestli aplikace obdržela upozornění paměti v předchozí relaci:

[MSACCrashes hasReceivedMemoryWarningInLastSession];
Crashes.hasReceivedMemoryWarningInLastSession

Poznámka

Tato metoda musí být použita pouze po Crashes spuštění, bude vždy vrácena NO nebo false před spuštěním.

Poznámka

V některých případech zařízení s nedostatkem paměti nemůže odesílat události.

Došlo k chybě aplikace v předchozí relaci?

Kdykoli po spuštění sady SDK můžete zkontrolovat, jestli se aplikace při předchozím spuštění chybově ukončila:

[MSACCrashes hasCrashedInLastSession];
Crashes.hasCrashedInLastSession

To se hodí v případě, že chcete upravit chování nebo uživatelské rozhraní aplikace po chybovém ukončení.

Poznámka

Tato metoda musí být použita pouze po MSACCrashes spuštění, bude vždy vrácena NO nebo false před spuštěním.

Podrobnosti o posledním chybovém ukončení

Pokud dříve došlo k chybovému ukončení vaší aplikace, můžete získat podrobnosti o posledním chybovém ukončení.

MSACErrorReport *crashReport = [MSACCrashes lastSessionCrashReport];
var crashReport = Crashes.lastSessionCrashReport

Poznámka

Tato metoda musí být použita pouze po Crashes spuštění, bude vždy vrácena nil před spuštěním.

Pro toto rozhraní API existuje mnoho případů použití. Nejběžnějším z nich jsou lidé, kteří toto rozhraní API volají a implementují vlastní CrashesDelegate.

Přizpůsobení používání chyb app center

Chybové ukončení App Center poskytuje vývojářům zpětná volání, aby mohli provádět další akce před a při odesílání protokolů chyb do App Center.

Chcete-li přidat vlastní chování, musíte přijmout CrashesDelegate-protocol, všechny jeho metody jsou volitelné.

Registrace jako delegát

[MSACCrashes setDelegate:self];
Crashes.delegate = self

Poznámka

Delegáta musíte nastavit před voláním AppCenter.start, protože App Center začne zpracovávat chyby hned po spuštění.

Mělo by se chybové ukončení zpracovat?

Implementujte ve třídě metodu crashes:shouldProcessErrorReport:-, která přijímá CrashesDelegate-protocol, pokud chcete rozhodnout, jestli je potřeba zpracovat konkrétní chybu nebo ne. Může například dojít k chybovému ukončení na úrovni systému, které byste chtěli ignorovat a které nechcete odesílat do 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.
}

Zpracovávané chyby

App Center také umožňuje sledovat chyby pomocí zpracovaných výjimek pomocí trackError metody. Aplikace může volitelně připojit vlastnosti nebo/a přílohy ke zpracovávané zprávě o chybách, aby poskytla další kontext.

@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)
}

Pro sledování výjimek můžete použít trackException metodu :

@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)
}

Pokud je pro vás ochrana osobních údajů uživatelů důležitá, můžete před odesláním zprávy o chybách do App Center získat potvrzení uživatele. Sada SDK zveřejňuje zpětné volání, které informuje o chybovém ukončení app center, aby před odesláním případných zpráv o chybách čekalo na potvrzení uživatele.

Pokud jste to zvolili, zodpovídáte za získání potvrzení uživatele, například prostřednictvím dialogového okna s některou z následujících možností: Vždy odesílat, Odeslat a Neodesílat. Na základě zadání řeknete, co dělat, když dojde k chybám App Center, a chyba se pak zpracuje odpovídajícím způsobem.

Poznámka

V sadě SDK se nezobrazuje dialogové okno, aplikace musí poskytnout vlastní uživatelské rozhraní, které může požádat o souhlas uživatele.

Následující metoda ukazuje, jak nastavit obslužnou rutinu potvrzení uživatele:

[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.
})

Pokud se vrátíte YES/true v bloku obslužné rutiny výše, měla by vaše aplikace získat oprávnění uživatele a odeslat sadě SDK zprávu s výsledkem pomocí následujícího rozhraní API. Pokud k tomu používáte upozornění, jak to děláme v ukázce výše, volali byste ho na základě výsledku volání (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)

Povolení zachytávání nezachycených výjimek vyvolaných v hlavním vlákně

AppKit zachycuje výjimky vyvolané v hlavním vlákně, což brání chybovému ukončení aplikace v systému macOS, takže sada SDK nemůže tato selhání zachytit. Pokud chcete napodobit chování iOSu, nastavte NSApplicationCrashOnExceptions příznak před inicializací sady SDK. Tento příznak umožňuje aplikaci chybově dojít při nezachycených výjimkách a sada SDK je může nahlásit.

[[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"NSApplicationCrashOnExceptions" : @YES }];
UserDefaults.standard.register(defaults: ["NSApplicationCrashOnExceptions": true])

Poznámka

Sada App Center SDK nastaví příznak automaticky ve verzích 1.10.0 a nižších. Od verze 1.11.0 se tento příznak už nenastavuje automaticky.

Zakázání přesměrování volání metod hlavní třídy aplikace na chyby app center

Sada App Center Crashes SDK používá k vylepšení své integrace potáčení, a to přesměrováním některých volání metod hlavní třídy aplikace. Potáčení metod je způsob, jak změnit implementaci metod za běhu. Pokud z nějakého důvodu nechcete používat potáčení (např. kvůli určité zásadě), měli byste přepsat aplikace reportException: a sendEvent: metody sami, aby chybové ukončení hlásila výjimky vyvolané na hlavním vlákně správně.

  1. Vytvořte soubor ReportExceptionApplication.m a přidejte následující implementaci:

    @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
    

    Poznámka

    try/catch Swift nefunguje s NSException. Tyto výjimky lze zpracovat pouze v Objective-C.

  2. Otevřete soubor Info.plist a nahraďte NSApplication v poli Třída Principal názvem třídy aplikace ReportExceptionApplication v tomto příkladu.

  3. Pokud chcete zakázat potáčení v sadě App Center SDK, přidejte AppCenterApplicationForwarderEnabled klíč do souboru Info.plist a nastavte hodnotu na 0.

Získání informací o stavu odesílání pro protokol chybových ukončení

Někdy chcete zjistit stav chybového ukončení aplikace. Běžným případem použití je, že můžete chtít zobrazit uživatelské rozhraní s oznámením uživatelům, že vaše aplikace odesílá zprávu o chybách, nebo v případě rychlého chybového ukončení aplikace po spuštění upravit chování aplikace, aby bylo možné odesílat protokoly chybových ukončení. Parametr CrashesDelegate-protocol definuje tři různá zpětná volání, která můžete v aplikaci použít k oznámení o tom, co se děje:

Před odesláním protokolu chyb sdk se vyvolá následující zpětné volání.

- (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.
}

V případě problémů se sítí nebo výpadkem koncového bodu a vy restartujete aplikaci, willSendErrorReport se po restartování procesu aktivuje znovu.

Následující zpětné volání se vyvolá poté, co sada SDK úspěšně odeslala protokol chybových ukončení.

- (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.
}

Pokud se sadě SDK nepodařilo odeslat protokol chyb, vyvolá se následující zpětné volání.

- (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.
}

Příjem didFailSendingErrorReport znamená, že došlo k neopravitelné chybě, například k kódu 4xx . Například 401 znamená, že je špatně appSecret .

Toto zpětné volání se neaktivuje, pokud se jedná o problém se sítí. V tomto případě sada SDK pokračuje v opakování (a také pozastavuje opakování, když je síťové připojení mimo provoz).

Přidání příloh ke zprávě o chybách

Do zprávy o chybách můžete přidat binární a textové přílohy. Sada SDK je odešle spolu s chybovým ukončením, abyste je viděli na portálu App Center. Následující zpětné volání se vyvolá těsně před odesláním uloženého chybového ukončení z předchozích spuštění aplikace. Nebude vyvolána, když dojde k chybě. Tady je příklad připojení textu a obrázku k chybovému ukončení:

- (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!]
}

Poznámka

Limit velikosti je aktuálně 7 MB. Pokus o odeslání větší přílohy způsobí chybu.

Povolení nebo zakázání chyb app center za běhu

Za běhu můžete povolit a zakázat chybové ukončení App Center. Pokud ho zakážete, sada SDK nebude pro aplikaci hlásit žádné chybové ukončení.

[MSACCrashes setEnabled:NO];
Crashes.enabled = false

Pokud chcete znovu povolit chybové ukončení app center, použijte stejné rozhraní API, ale předejte YES/true ho jako parametr.

[MSACCrashes setEnabled:YES];
Crashes.enabled = true

Stav se během spouštění aplikací zachová v úložišti zařízení.

Poznámka

Tuto metodu je možné použít až po Crashes spuštění.

Kontrola, jestli je povolená chyba app center

Můžete také zkontrolovat, jestli je povolená chyba App Center:

BOOL enabled = [MSACCrashes isEnabled];
var enabled = Crashes.enabled

Poznámka

Tato metoda musí být použita pouze po Crashes spuštění, bude vždy vrácena false před spuštěním.

Zakázání zpracování výjimek Mach

Chybové ukončení app center ve výchozím nastavení využívá obslužnou rutinu výjimky Mach k zachycení závažných signálů, například přetečení zásobníku, prostřednictvím serveru výjimek Mach.

Parametr disableMachExceptionHandler-method poskytuje možnost zakázat zachytávání závažných signálů prostřednictvím serveru výjimek Mach. Pokud chcete zakázat obslužnou rutinu výjimky Mach, měli byste tuto metodu volat PŘED spuštěním sady SDK. Váš typický instalační kód by vypadal takto:

[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])