Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

Personalize seus relatórios de falhas do Firebase Crashlytics

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Este guia descreve como personalizar seus relatórios de falhas usando o Firebase Crashlytics SDK. Por padrão, o Crashlytics coleta automaticamente relatórios de falhas para todos os usuários do seu aplicativo (você pode desativar os relatórios automáticos de falhas e habilitar relatórios opcionais para seus usuários). O Crashlytics fornece quatro mecanismos de log prontos para uso: chaves personalizadas , logs personalizados , identificadores de usuário e exceções capturadas .

Adicionar chaves personalizadas

As chaves personalizadas ajudam você a obter o estado específico do seu aplicativo que leva a uma falha. Você pode associar pares de chave/valor arbitrários a seus relatórios de travamento e, em seguida, usar as chaves personalizadas para pesquisar e filtrar relatórios de travamento no console do Firebase.

  • No painel do Crashlytics , você pode pesquisar problemas que correspondam a uma chave personalizada.
  • Ao revisar um problema específico no console, você pode visualizar as chaves personalizadas associadas a cada evento (subguia Chaves ) e até mesmo filtrar os eventos por chaves personalizadas (menu Filtro na parte superior da página).

Use o método setCustomValue para definir pares chave/valor. Por exemplo:

Rápido

// Set int_key to 100.
Crashlytics.crashlytics().setCustomValue(100, forKey: "int_key")

// Set str_key to "hello".
Crashlytics.crashlytics().setCustomValue("hello", forKey: "str_key")

Objective-C

Ao definir números inteiros, booleanos ou flutuantes, coloque o valor como @( value ) .

// Set int_key to 100.
[[FIRCrashlytics crashlytics] setCustomValue:@(100) forKey:@"int_key"];

// Set str_key to "hello".
[[FIRCrashlytics crashlytics] setCustomValue:@"hello" forKey:@"str_key"];

Você também pode modificar o valor de uma chave existente chamando a chave e definindo-a com um valor diferente. Por exemplo:

Rápido

Crashlytics.crashlytics().setCustomValue(100, forKey: "int_key")

// Set int_key to 50 from 100.
Crashlytics.crashlytics().setCustomValue(50, forKey: "int_key")

Objective-C

[[FIRCrashlytics crashlytics] setCustomValue:@(100) forKey:@"int_key"];

// Set int_key to 50 from 100.
[[FIRCrashlytics crashlytics] setCustomValue:@(50) forKey:@"int_key"];

Adicione pares chave/valor em massa usando o método setCustomKeysAndValues ​​com um NSDictionary como o único parâmetro:

Rápido

let keysAndValues = [
                 "string key" : "string value",
                 "string key 2" : "string value 2",
                 "boolean key" : true,
                 "boolean key 2" : false,
                 "float key" : 1.01,
                 "float key 2" : 2.02
                ] as [String : Any]

Crashlytics.crashlytics().setCustomKeysAndValues(keysAndValues)

Objective-C

NSDictionary *keysAndValues =
    @{@"string key" : @"string value",
      @"string key 2" : @"string value 2",
      @"boolean key" : @(YES),
      @"boolean key 2" : @(NO),
      @"float key" : @(1.01),
      @"float key 2" : @(2.02)};

[[FIRCrashlytics crashlytics] setCustomKeysAndValues: keysAndValues];

Adicionar mensagens de registro personalizadas

Para obter mais contexto para os eventos que levaram a uma falha, você pode adicionar logs personalizados do Crashlytics ao seu aplicativo. O Crashlytics associa os logs aos seus dados de travamento e os exibe na página Crashlytics do console do Firebase , na guia Logs .

Rápido

Use log() ou log(format:, arguments:) para ajudar a identificar problemas. Se você deseja obter uma saída de log útil com mensagens, o objeto que você passa para log() deve estar em conformidade com a propriedade CustomStringConvertible . log() retorna a propriedade de descrição que você define para o objeto. Por exemplo:

Crashlytics.crashlytics().log("Higgs-Boson detected! Bailing out…, \(attributesDict)")

.log(format:, arguments:) formata os valores retornados da chamada de getVaList() . Por exemplo:

Crashlytics.crashlytics().log(format: "%@, %@", arguments: getVaList(["Higgs-Boson detected! Bailing out…", attributesDict]))

Para obter mais detalhes sobre como usar log() ou log(format:, arguments:) , consulte a documentação de referência do Crashlytics .

Objective-C

Use log ou logWithFormat para ajudar a identificar problemas. Observe que, se você deseja obter uma saída de log útil com mensagens, o objeto que você passa para qualquer um dos métodos deve substituir a propriedade da instância de description . Por exemplo:

[[FIRCrashlytics crashlytics] log:@"Simple string message"];

[[FIRCrashlytics crashlytics] logWithFormat:@"Higgs-Boson detected! Bailing out... %@", attributesDict];

[[FIRCrashlytics crashlytics] logWithFormat:@"Logging a variable argument list %@" arguments:va_list_arg];

Para obter mais detalhes sobre como usar log e logWithFormat , consulte a documentação de referência do Crashlytics.

Definir identificadores de usuário

Para diagnosticar um problema, muitas vezes é útil saber quais usuários tiveram uma determinada falha. O Crashlytics inclui uma maneira de identificar usuários anonimamente em seus relatórios de travamento.

Para adicionar IDs de usuário a seus relatórios, atribua a cada usuário um identificador exclusivo na forma de um número de ID, token ou valor de hash:

Rápido

Crashlytics.crashlytics().setUserID("123456789")

Objective-C

[[FIRCrashlytics crashlytics] setUserID:@"123456789"];

Se você precisar limpar um identificador de usuário depois de defini-lo, redefina o valor para uma string em branco. A limpeza de um identificador de usuário não remove os registros existentes do Crashlytics. Se você precisar excluir registros associados a um ID de usuário, entre em contato com o suporte do Firebase .

Relatar exceções não fatais

Além de relatar automaticamente as falhas do seu aplicativo, o Crashlytics permite que você registre exceções não fatais e as envie para você na próxima vez que o aplicativo for iniciado.

Você pode registrar exceções não fatais gravando objetos NSError com o método recordError . recordError captura a pilha de chamadas do thread chamando [NSThread callStackReturnAddresses] .

Rápido

Crashlytics.crashlytics().record(error: error)

Objective-C

[[FIRCrashlytics crashlytics] recordError:error];

Ao usar o método recordError , é importante entender a estrutura NSError e como o Crashlytics usa os dados para agrupar falhas. O uso incorreto do método recordError pode causar um comportamento imprevisível e fazer com que o Crashlytics limite o relatório de erros registrados para seu aplicativo.

Um objeto NSError tem três argumentos:

  • domain: String
  • code: Int
  • userInfo: [AnyHashable : Any]? = nil

Ao contrário das falhas fatais, que são agrupadas por meio da análise de rastreamento de pilha, os erros registrados são agrupados por domain e code . Esta é uma distinção importante entre falhas fatais e erros registrados. Por exemplo:

Rápido

let userInfo = [
  NSLocalizedDescriptionKey: NSLocalizedString("The request failed.", comment: ""),
  NSLocalizedFailureReasonErrorKey: NSLocalizedString("The response returned a 404.", comment: ""),
  NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Does this page exist?", comment: ""),
  "ProductID": "123456",
  "View": "MainView"
]

let error = NSError.init(domain: NSCocoaErrorDomain,
                         code: -1001,
                         userInfo: userInfo)

Objective-C

NSDictionary *userInfo = @{
  NSLocalizedDescriptionKey: NSLocalizedString(@"The request failed.", nil),
  NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"The response returned a 404.", nil),
  NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Does this page exist?", nil),
  @"ProductID": @"123456",
  @"View": @"MainView",
};

NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain
                                     code:-1001
                                 userInfo:userInfo];

Quando você registra o erro acima, ele cria um novo problema que é agrupado por NSSomeErrorDomain e -1001 . Erros registrados adicionais que usam o mesmo domínio e valores de código são agrupados sob o mesmo problema. Os dados contidos no objeto userInfo são convertidos em pares chave-valor e exibidos na seção chaves/logs dentro de um problema individual.

Logs e chaves personalizadas

Assim como os relatórios de falhas, você pode incorporar logs e chaves personalizadas para adicionar contexto ao NSError . No entanto, há uma diferença em quais logs são anexados a travamentos versus erros registrados. Quando ocorre uma falha e o aplicativo é reiniciado, os logs que o Crashlytics recupera do disco são aqueles que foram gravados até o momento da falha. Quando você registra um NSError , o aplicativo não é encerrado imediatamente. Como o Crashlytics só envia o relatório de erro registrado na próxima inicialização do aplicativo e deve limitar a quantidade de espaço alocado para logs no disco, é possível registrar o suficiente depois que um NSError é registrado para que todos os logs relevantes sejam alternados no momento em que o Crashlytics envia o relatório do dispositivo. Lembre-se desse equilíbrio ao registrar NSErrors e usar logs e chaves personalizadas em seu aplicativo.

Considerações de desempenho

Lembre-se de que registrar um NSError pode ser bastante caro. No momento em que você faz a chamada, o Crashlytics captura a pilha de chamadas do thread atual usando um processo chamado de desenrolamento de pilha. Este processo pode ser intensivo em CPU e E/S, particularmente em arquiteturas que suportam o desenrolamento DWARF (arm64 e x86). Após a conclusão do desenrolamento, as informações são gravadas no disco de forma síncrona. Isso evita a perda de dados se a próxima linha falhar.

Embora seja seguro chamar essa API em um thread em segundo plano, lembre-se de que despachar essa chamada para outra fila perde o contexto do rastreamento de pilha atual.

E as NSExceptions?

O Crashlytics não oferece um recurso para registrar e registrar instâncias NSException diretamente. De um modo geral, as APIs Cocoa e Cocoa Touch não são seguras contra exceções. Isso significa que o uso de @catch pode ter efeitos colaterais indesejados muito sérios em seu processo, mesmo quando usado com extremo cuidado. Você nunca deve usar instruções @catch em seu código. Consulte a documentação da Apple sobre o assunto.

Personalizar rastreamentos de pilha

Se seu aplicativo for executado em um ambiente não nativo (como C++ ou Unity), você poderá usar a API Exception Model para relatar metadados de travamento no formato de exceção nativo de seu aplicativo. As exceções relatadas são marcadas como não fatais.

Rápido

var  ex = ExceptionModel(name:"FooException", reason:"There was a foo.")
ex.stackTrace = [
  StackFrame(symbol:"makeError", file:"handler.js", line:495),
  StackFrame(symbol:"then", file:"routes.js", line:102),
  StackFrame(symbol:"main", file:"app.js", line:12),
]

crashlytics.record(exceptionModel:ex)

Objective-C

FIRExceptionModel *model =
    [FIRExceptionModel exceptionModelWithName:@"FooException" reason:@"There was a foo."];
model.stackTrace = @[
  [FIRStackFrame stackFrameWithSymbol:@"makeError" file:@"handler.js" line:495],
  [FIRStackFrame stackFrameWithSymbol:@"then" file:@"routes.js" line:102],
  [FIRStackFrame stackFrameWithSymbol:@"main" file:@"app.js" line:12],
];

[[FIRCrashlytics crashlytics] recordExceptionModel:model];

Os quadros de pilha personalizados também podem ser inicializados apenas com endereços:

Rápido

var  ex = ExceptionModel.init(name:"FooException", reason:"There was a foo.")
ex.stackTrace = [
  StackFrame(address:0xfa12123),
  StackFrame(address:12412412),
  StackFrame(address:194129124),
]

crashlytics.record(exceptionModel:ex)

Objective-C

FIRExceptionModel *model =
    [FIRExceptionModel exceptionModelWithName:@"FooException" reason:@"There was a foo."];
model.stackTrace = @[
  [FIRStackFrame stackFrameWithAddress:0xfa12123],
  [FIRStackFrame stackFrameWithAddress:12412412],
  [FIRStackFrame stackFrameWithAddress:194129124],
];


[[FIRCrashlytics crashlytics] recordExceptionModel:model];

Ativar relatório de ativação

Por padrão, o Crashlytics coleta automaticamente relatórios de falhas para todos os usuários do seu aplicativo. Para dar aos usuários mais controle sobre os dados que eles enviam, você pode habilitar relatórios opcionais desativando os relatórios automáticos e enviando dados apenas para o Crashlytics quando você escolher em seu código:

  1. Desative a coleta automática adicionando uma nova chave ao seu arquivo Info.plist :

    • Chave: FirebaseCrashlyticsCollectionEnabled
    • Valor: false
  2. Ative a coleta para usuários selecionados chamando a substituição da coleta de dados do Crashlytics no tempo de execução. O valor de substituição persiste nas inicializações do seu aplicativo para que o Crashlytics possa coletar relatórios automaticamente.

    Para desativar o relatório de travamento automático, passe false como o valor de substituição. Quando definido como false , o novo valor não se aplica até a próxima execução do aplicativo.

    Rápido

    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)

    Objective-C

    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

Gerenciar dados do Crash Insights

O Crash Insights ajuda você a resolver problemas comparando seus rastreamentos de pilha anônimos com os rastreamentos de outros aplicativos do Firebase e informando se o problema faz parte de uma tendência maior. Para muitos problemas, o Crash Insights ainda fornece recursos para ajudá-lo a depurar o travamento.

O Crash Insights usa dados de falhas agregados para identificar tendências comuns de estabilidade. Se preferir não compartilhar os dados do seu aplicativo, você pode desativar o Crash Insights no menu Crash Insights na parte superior da lista de problemas do Crashlytics no console do Firebase .