Firebase Crashlytics 오류 보고서 맞춤설정

iOS
Android
Unity[베타]

Firebase Crashlytics는 최소한의 설정만으로 작동합니다. SDK를 추가하는 즉시 Crashlytics에서 Firebase 콘솔로 오류 보고서를 보내기 시작합니다.

Firebase Crashlytics는 로깅 메커니즘 4가지(맞춤 키, 맞춤 로그, 사용자 식별자, 포착된 예외)를 즉시 제공하여 오류 보고서에 대한 자세한 정보를 제공합니다.

맞춤 키 추가

맞춤 키를 사용하면 비정상 종료로 이어지는 앱의 구체적인 상태를 확인할 수 있습니다. 임의의 키-값 쌍을 오류 보고서에 연결하고 Firebase 콘솔에서 볼 수 있습니다.

iOS

[CrashlyticsKit setObjectValue:forKey:] 또는 관련 메소드 중 하나를 사용하여 시작합니다.

- (void)setObjectValue:(id)value forKey:(NSString *)key;

// calls -description on value, perfect for NSStrings!
- (void)setIntValue:(int)value forKey:(NSString *)key;

- (void)setBoolValue:(BOOL)value forKey:(NSString *)key;

- (void)setFloatValue:(float)value forKey:(NSString *)key;

경우에 따라 기존 키 값을 변경해야 합니다. 동일한 키를 호출하되 예를 들어 다음과 같이 값을 교체합니다.

Objective-C
[CrashlyticsKit setIntValue:3 forKey:@"current_level"];
[CrashlyticsKit setObjectValue:@"logged_in" forKey:@"last_UI_action"];
Swift
Crashlytics.sharedInstance().setIntValue(42, forKey: "MeaningOfLife")
Crashlytics.sharedInstance().setObjectValue("Test value", forKey: "last_UI_action")
Android

키를 설정하는 메소드는 다음과 같이 5가지입니다. 각 메소드마다 다른 데이터 유형을 처리합니다.

자바
Android

Crashlytics.setString(key, "foo" /* string value */);

Crashlytics.setBool(key, true /* boolean value */);

Crashlytics.setDouble(key, 1.0 /* double value */);

Crashlytics.setFloat(key, 1.0f /* float value */);

Crashlytics.setInt(key, 1 /* int value */);

Kotlin
Android

Crashlytics.setString(key, "foo" /* string value */)

Crashlytics.setBool(key, true /* boolean value */)

Crashlytics.setDouble(key, 1.0 /* double value */)

Crashlytics.setFloat(key, 1.0f /* float value */)

Crashlytics.setInt(key, 1 /* int value */)

키를 재설정하면 값이 업데이트됩니다. 예를 들면 다음과 같습니다.

자바
Android

Crashlytics.setInt("current_level", 3);
Crashlytics.setString("last_UI_action", "logged_in");

Kotlin
Android

Crashlytics.setInt("current_level", 3)
Crashlytics.setString("last_UI_action", "logged_in")
Unity[베타]

여러 번 호출하면 기존 키의 값이 새로 업데이트되고 비정상 종료가 기록될 때 최신 값만 캡처됩니다.

Crashlytics.SetCustomKey(string key, string value);

맞춤 로그 메시지 추가

비정상 종료로 이어지는 이벤트에 대한 배경 정보를 자세히 파악하기 위해 앱에 맞춤 Crashlytics 로그를 추가할 수 있습니다. Crashlytics가 로그를 비정상 종료 데이터에 연결하고 Firebase 콘솔에 표시합니다.

iOS
Objective-C

Objective-C에서 CLS_LOG를 사용하여 문제를 정확하게 파악할 수 있습니다. 로그에 연결된 Objective-C 클래스, 메소드, 줄 번호에 대한 정보가 자동으로 포함됩니다.

디버그 빌드와 출시 빌드 중 로깅 대상이 무엇인지에 따라 CLS_LOG 동작이 달라집니다.

  • 디버그 빌드: CLS_LOGNSLog로 전달되므로 Xcode, 기기 또는 시뮬레이터에서 출력을 볼 수 있습니다.
  • 출시 빌드: 성능 개선을 위해 CLS_LOG가 다른 모든 출력을 제외하며 NSLog로 전달되지 않습니다.

CLS_LOG(format, ...)를 사용하여 CLS_LOG로 로그를 기록합니다. 예를 들어 다음과 같습니다.

CLS_LOG(@"Higgs-Boson detected! Bailing out... %@", attributesDict);

자세한 CLS_LOG 사용 방법은 Crashlytics/Crashlytics.h 헤더 파일을 살펴보세요.

Swift

Swift에서 CLSLogv 또는 CLSNSLogv를 사용하여 문제를 정확하게 파악할 수 있습니다.

CLSLogvCLSNSLogv로 로그를 기록할 때 유의해야 할 두 가지 사항은 다음과 같습니다.

  • 형식 인수가 컴파일 시간 상수 문자열이어야 합니다. Objective-C의 컴파일러가 적용하는 작업이지만 현재 Swift 브리징에는 이 작업이 적용되지 않습니다.
  • 로그 값을 배열에 저장하고 해당 배열에서 getVaList를 호출하여 가져옵니다.

예를 들면 다음과 같습니다.

func write(string: String) {
    CLSLogv("%@", getVaList([string]))
}
Swift 문자열 보간은 컴파일 시간 상수 문자열을 생성하지 않습니다. printf 및 NSLog와 마찬가지로 CLSLog와 함께 상수가 아닌 문자열을 사용하면 비정상 종료가 발생할 수 있습니다.

고급

더 세밀한 관리를 위해 CLSLog(format, ...)CLSNSLog(format, ...)를 직접 활용할 수 있습니다. CLSNSLog가 NSLog로 전달되므로 Xcode, 기기 또는 시뮬레이터에서 출력을 볼 수 있습니다. CLSLog(format, ...)CLSNSLog(format, ...)는 스레드 안전 특성을 가집니다. CLSLog는 비정상 종료를 해결하는 데 중요한 정보를 로깅하는 용도이며 인앱 이벤트를 추적하는 데 사용해서는 안 됩니다.

Android

Android에서 Crashlytics.log를 사용하여 문제를 정확하게 파악할 수 있습니다.

Crashlytics.log는 오류 보고서와 Log.println()에 로그를 작성하거나, 다음 오류 보고서에만 로그를 작성할 수 있습니다.

  • 오류 보고서 및 Log.println:

    자바
    Android

    Crashlytics.log(Log.DEBUG, "tag", "message");

    Kotlin
    Android

    Crashlytics.log(Log.DEBUG, "tag", "message")
  • 오류 보고서에만 작성:

    자바
    Android

    Crashlytics.log("message");

    Kotlin
    Android

    Crashlytics.log("message")
Unity[베타]

로깅된 메시지는 비정상 종료 데이터와 연결되어 있으며 특정 비정상 종료를 볼 때 Firebase Crashlytics 대시보드에 표시됩니다.

Crashlytics.Log(string message);

사용자 식별자 설정

어떤 사용자에게 특정 비정상 종료가 발생했는지 파악하면 문제를 진단하는 데 도움이 될 수 있습니다. Crashlytics는 오류 보고서에서 사용자를 익명으로 식별할 수 있는 방법을 제공합니다.

iOS

보고서에 사용자 ID를 추가하려면 각 사용자에게 ID 번호, 토큰 또는 해시 값 형식으로 고유 식별자를 할당합니다.

Objective-C
[CrashlyticsKit setUserIdentifier:@"123456789"];
Swift
Crashlytics.sharedInstance().setUserIdentifier("123456789")

사용자 식별자를 설정한 후 삭제해야 하는 경우 값을 빈 문자열로 재설정합니다. 사용자 식별자를 지워도 기존 Crashlytics 레코드는 제거되지 않습니다. 사용자 ID와 연결된 레코드를 삭제하려면 Firebase 지원팀에 문의하세요.

Android

보고서에 사용자 ID를 추가하려면 각 사용자에게 ID 번호, 토큰 또는 해시 값 형식으로 고유 식별자를 할당합니다.

자바
Android

Crashlytics.setUserIdentifier("user123456789");

Kotlin
Android

Crashlytics.setUserIdentifier("user123456789")

사용자 식별자를 설정한 후 삭제해야 하는 경우 값을 빈 문자열로 재설정합니다. 사용자 식별자를 지워도 기존 Crashlytics 레코드는 제거되지 않습니다. 사용자 ID와 연결된 레코드를 삭제하려면 Firebase 지원팀에 문의하세요.

Unity[베타]

개인 정보를 공개하거나 전송하지 않고 ID 번호, 토큰 또는 해시 값을 사용하여 애플리케이션 최종 사용자를 고유하게 식별할 수 있습니다. 값을 빈 문자열로 설정하여 지울 수도 있습니다. 이 값은 특정 비정상 종료를 볼 때 Firebase Crashlytics 대시보드에 표시됩니다.

Crashlytics.SetUserId(string identifier);

심각하지 않은 예외 로깅

앱의 비정상 종료를 자동으로 보고하는 것 외에도 Crashlytics를 사용하면 심각하지 않은 예외를 로깅할 수 있습니다.

iOS

iOS에서 NSError 객체를 기록하면 되며 Crashlytics가 비정상 종료와 마찬가지로 보고하고 그룹화합니다.

Objective-C
[CrashlyticsKit recordError:error];
Swift
Crashlytics.sharedInstance().recordError(error)

recordError 메소드를 사용할 경우 NSError 구조 및 Crashlytics가 데이터를 사용하여 비정상 종료를 그룹화하는 방식을 이해해야 합니다. recordError 메소드를 잘못 사용하면 예측할 수 없는 동작이 발생할 수 있으며 Crashlytics에서 앱에서 로깅된 오류의 보고를 제한해야 할 수도 있습니다.

NSError 객체에는 다음 3가지 인수가 있습니다. domain: String, code: Int, userInfo: [AnyHashable : Any]? = nil

스택 추적 분석을 통해 그룹화되는 치명적인 비정상 종료와는 달리 로깅된 오류는 NSError domaincode로 그룹화됩니다. 이 점이 치명적인 비정상 종료와 로깅된 오류의 중요한 차이점입니다. 다음과 같이 오류가 로깅되는 예를 들어 보겠습니다.

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";
    UserID: @"Jane Smith"
};

NSError *error = [NSError domain:NSSomeErrorDomain
                          code:-1001
                          userInfo:userInfo];

NSSomeErrorDomain-1001로 그룹화되는 새 문제가 생성됩니다. 동일한 도메인과 코드 값을 사용하는 오류가 또 로깅되면 이 문제로 그룹화됩니다.

도메인 및 코드 필드에 사용자 ID, 제품 ID, 타임스탬프와 같은 고유한 값을 사용하지 마시기 바랍니다. 이러한 필드에 고유한 값을 사용하면 문제의 집합 크기가 커지고 Crashlytics에서 앱에서 로깅된 오류의 보고를 제한해야 할 수도 있습니다. 고유한 값은 userInfo 사전 객체에 추가해야 합니다.

userInfo 객체 내에 포함된 데이터는 키-값 쌍으로 전환되며 개별 문제 내의 키/로그 섹션에 표시됩니다.

Crashlytics는 특정 앱 세션의 최근 예외를 8개까지만 저장합니다. 앱에서 한 세션에 8개를 초과하는 예외가 발생하면 이전 예외가 삭제됩니다.

로그 및 맞춤 키

오류 보고서와 마찬가지로 로그 및 맞춤 키를 삽입하여 NSError에 배경 정보를 추가할 수 있습니다. 하지만 비정상 종료에 연결되는 로그 및 로깅된 오류에는 차이점이 있습니다. 비정상 종료가 발생하고 앱이 다시 실행될 때 Crashlytics가 디스크에서 가져오는 로그가 바로 비정상 종료 당시에 기록된 로그입니다. NSError를 로깅하면 앱이 즉시 종료되지 않습니다. Crashlytics는 다음에 앱을 실행할 때만 로깅된 오류 보고서를 전송하며 디스크에서 로그에 할당되는 공간을 제한해야 합니다. 이 때문에 Crashlytics가 기기에서 보고서를 전송한 시점에 모든 관련 로그가 순환되도록 NSError가 기록되고 충분히 시간이 지난 후에 로깅할 수도 있습니다. 앱에서 NSError를 기록하고 CLSLog 및 맞춤 키를 사용할 때 이 점에 유의하세요.

성능에 대한 고려사항

NSError 로깅은 리소스가 꽤 많이 들 수 있습니다. 호출을 하는 시점에서 Crashlytics가 스택 풀기라는 프로세스를 사용하여 현재 스레드의 호출 스택을 캡처합니다. 이 프로세스는 특히 DWARF 풀기(arm64 및 x86)를 지원하는 아키텍처에서 CPU와 I/O를 많이 사용할 수 있습니다. 풀기가 완료된 후 정보가 동기 방식으로 디스크에 작성됩니다. 이렇게 하면 다음 줄이 비정상 종료될 경우 데이터가 손실되지 않습니다.

백그라운드 스레드에서 이 API를 호출해도 괜찮지만 이 호출을 다른 대기열에 전달하면 현재 스택 추적의 배경 정보가 사라집니다.

NSException은 어떤가요?

Crashlytics는 NSException 인스턴스를 직접 기록하는 기능을 제공하지 않습니다. 일반적으로 Cocoa 및 Cocoa Touch API는 예외 안전성이 적용되지 않습니다. 즉, @catch를 사용할 때 극도로 주의해도 프로세스에 의도하지 않은 매우 심각한 부작용이 발생할 수 있습니다. 그러므로 코드에 @catch 문을 사용해서는 안 됩니다. 이 주제에 대한 Apple 문서를 참조하세요.

Android

Android에서 앱의 catch 블록에 포착된 예외를 로깅할 수 있습니다.

자바
Android

try {
    methodThatThrows();
} catch (Exception e) {
    Crashlytics.logException(e);
    // handle your exception here
}

Kotlin
Android

try {
    methodThatThrows()
} catch (e: Exception) {
    Crashlytics.logException(e)
    // handle your exception here
}

로깅된 모든 예외는 Firebase 콘솔에 심각하지 않은 문제로 표시됩니다. 문제 요약에는 비정상 종료에서 일반적으로 확인 가능한 모든 상태 정보가 Android 버전 및 하드웨어 기기별 분류와 함께 포함됩니다.

Crashlytics는 전용 백그라운드 스레드에서 예외를 처리하므로 앱에 미치는 성능 영향이 미미합니다. 사용자의 네트워크 트래픽을 줄이기 위해 Crashlytics는 로깅된 예외를 함께 일괄 처리하고 다음에 앱이 실행될 때 전송합니다.

Crashlytics는 특정 앱 세션의 최근 예외를 8개까지만 저장합니다. 앱에서 한 세션에 8개를 초과하는 예외가 발생하면 이전 예외가 삭제됩니다.
Unity[베타]

다음 메소드를 사용하여 C#으로 맞춤 예외를 로깅할 수 있습니다.

Crashlytics.LogException(Exception ex);

맞춤 예외는 앱의 try/catch 블록에 포함될 수 있습니다.

try {
    myMethodThatThrows();
} catch (Exception e) {
   Crashlytics.LogException(e);
   // handle your exception here!
}

보고 선택 옵션 사용 설정

기본적으로 Firebase Crashlytics는 모든 앱 사용자의 오류 보고서를 자동으로 수집하지만 사용자가 자신이 전송하는 데이터를 더 잘 관리할 수 있도록 보고 선택 옵션을 사용 설정할 수 있습니다.

이를 위해 자동 수집을 사용 중지하고 옵션을 선택한 사용자에 한해 수집하도록 Crashlytics를 초기화해야 합니다.

iOS
  1. Info.plist 파일에 대한 새 키로 자동 수집을 사용 중지합니다.
    • 키: firebase_crashlytics_collection_enabled
    • 값: false
  2. 런타임에서 Crashlytics를 초기화하여 선택한 사용자에 대해 수집을 사용 설정합니다.
    Objective-C
    [Fabric with:@[[Crashlytics class]]];
    Swift
    Fabric.with([Crashlytics.self])
Android
  1. AndroidManifest.xml 파일에서 meta-data 태그로 자동 수집을 사용 중지합니다.
    <meta-data
        android:name="firebase_crashlytics_collection_enabled"
        android:value="false" />
    
  2. 앱의 활동 중 하나에서 Crashlytics를 초기화하여 선택한 사용자에 대한 수집을 사용 설정합니다.

    자바
    Android

    Fabric.with(this, new Crashlytics());

    Kotlin
    Android

    Fabric.with(this, Crashlytics())
참고: 앱 세션에서 Crashlytics 보고를 초기화한 후에는 중지할 수 없습니다. Crashlytics를 초기화한 후에 보고를 선택 해제하려면 사용자가 앱을 다시 시작해야 합니다.
Unity[베타]
Crashlytics.IsCrashlyticsCollectionEnabled = false;

다음 예는 위 코드를 UI 요소에 연결하는 방법을 보여줍니다.

public class DataCollectionToggleScript : MonoBehaviour {

  public Toggle DataCollectionToggle;

  void Start () {
    Toggle toggle = DataCollectionToggle.GetComponent<Toggle>();
    toggle.isOn = Crashlytics.IsCrashlyticsCollectionEnabled;
    toggle.onValueChanged.AddListener(delegate {
      ToggleValueChanged(toggle);
    });
  }

  void ToggleValueChanged(Toggle toggle){
    Crashlytics.IsCrashlyticsCollectionEnabled = toggle.isOn;
  }
}

Fabric Crashlytics에서 이와 같은 항목이 표시되지 않나요? Unity API 변경사항 페이지에서 Crashlytics가 Fabric Crashlytics에서 Firebase Crashlytics로 어떻게 개선되었는지 알아보세요.

비정상 종료 통계 데이터 관리

비정상 종료 통계는 익명화된 스택 추적을 다른 Firebase 앱의 추적과 비교하여 문제가 더 큰 트렌드에 속하는지 여부를 파악함으로써 문제를 해결하는 데 도움을 줍니다. 비정상 종료 통계가 디버깅에 도움이 되는 경우도 많습니다.

비정상 종료 통계에서는 비정상 종료 집계 데이터를 사용하여 공통적인 안정성 트렌드를 파악합니다. 앱의 데이터를 공유하지 않으려는 경우 Firebase 콘솔에 있는 Crashlytics 문제 목록 상단의 비정상 종료 통계 메뉴에서 비정상 종료 통계를 선택 해제할 수 있습니다.

다음에 대한 의견 보내기...

도움이 필요하시나요? 지원 페이지를 방문하세요.