/bugsnag-android-core/src/main/java/com/bugsnag/android/InternalReportDelegate.java
https://github.com/bugsnag/bugsnag-android · Java · 136 lines · 107 code · 21 blank · 8 comment · 4 complexity · 97690b55a87b16be2ec269bbbe9c5cf4 MD5 · raw file
- package com.bugsnag.android;
- import static com.bugsnag.android.DeliveryHeadersKt.HEADER_INTERNAL_ERROR;
- import static com.bugsnag.android.SeverityReason.REASON_UNHANDLED_EXCEPTION;
- import com.bugsnag.android.internal.ImmutableConfig;
- import android.annotation.SuppressLint;
- import android.content.Context;
- import android.os.Build;
- import android.os.storage.StorageManager;
- import androidx.annotation.NonNull;
- import androidx.annotation.Nullable;
- import java.io.File;
- import java.io.IOException;
- import java.util.Date;
- import java.util.Map;
- import java.util.concurrent.RejectedExecutionException;
- class InternalReportDelegate implements EventStore.Delegate {
- static final String INTERNAL_DIAGNOSTICS_TAB = "BugsnagDiagnostics";
- final Logger logger;
- final ImmutableConfig config;
- @Nullable
- final StorageManager storageManager;
- final AppDataCollector appDataCollector;
- final DeviceDataCollector deviceDataCollector;
- final Context appContext;
- final SessionTracker sessionTracker;
- final Notifier notifier;
- final BackgroundTaskService backgroundTaskService;
- InternalReportDelegate(Context context,
- Logger logger,
- ImmutableConfig immutableConfig,
- @Nullable StorageManager storageManager,
- AppDataCollector appDataCollector,
- DeviceDataCollector deviceDataCollector,
- SessionTracker sessionTracker,
- Notifier notifier,
- BackgroundTaskService backgroundTaskService) {
- this.logger = logger;
- this.config = immutableConfig;
- this.storageManager = storageManager;
- this.appDataCollector = appDataCollector;
- this.deviceDataCollector = deviceDataCollector;
- this.appContext = context;
- this.sessionTracker = sessionTracker;
- this.notifier = notifier;
- this.backgroundTaskService = backgroundTaskService;
- }
- @Override
- public void onErrorIOFailure(Exception exc, File errorFile, String context) {
- // send an internal error to bugsnag with no cache
- SeverityReason severityReason = SeverityReason.newInstance(REASON_UNHANDLED_EXCEPTION);
- Event err = new Event(exc, config, severityReason, logger);
- err.setContext(context);
- err.addMetadata(INTERNAL_DIAGNOSTICS_TAB, "canRead", errorFile.canRead());
- err.addMetadata(INTERNAL_DIAGNOSTICS_TAB, "canWrite", errorFile.canWrite());
- err.addMetadata(INTERNAL_DIAGNOSTICS_TAB, "exists", errorFile.exists());
- @SuppressLint("UsableSpace") // storagemanager alternative API requires API 26
- long usableSpace = appContext.getCacheDir().getUsableSpace();
- err.addMetadata(INTERNAL_DIAGNOSTICS_TAB, "usableSpace", usableSpace);
- err.addMetadata(INTERNAL_DIAGNOSTICS_TAB, "filename", errorFile.getName());
- err.addMetadata(INTERNAL_DIAGNOSTICS_TAB, "fileLength", errorFile.length());
- recordStorageCacheBehavior(err);
- reportInternalBugsnagError(err);
- }
- void recordStorageCacheBehavior(Event event) {
- if (storageManager != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- File cacheDir = appContext.getCacheDir();
- File errDir = new File(cacheDir, "bugsnag-errors");
- try {
- boolean tombstone = storageManager.isCacheBehaviorTombstone(errDir);
- boolean group = storageManager.isCacheBehaviorGroup(errDir);
- event.addMetadata(INTERNAL_DIAGNOSTICS_TAB, "cacheTombstone", tombstone);
- event.addMetadata(INTERNAL_DIAGNOSTICS_TAB, "cacheGroup", group);
- } catch (IOException exc) {
- logger.w("Failed to record cache behaviour, skipping diagnostics", exc);
- }
- }
- }
- /**
- * Reports an event that occurred within the notifier to bugsnag. A lean event report will be
- * generated and sent asynchronously with no callbacks, retry attempts, or writing to disk.
- * This is intended for internal use only, and reports will not be visible to end-users.
- */
- void reportInternalBugsnagError(@NonNull Event event) {
- event.setApp(appDataCollector.generateAppWithState());
- event.setDevice(deviceDataCollector.generateDeviceWithState(new Date().getTime()));
- event.addMetadata(INTERNAL_DIAGNOSTICS_TAB, "notifierName", notifier.getName());
- event.addMetadata(INTERNAL_DIAGNOSTICS_TAB, "notifierVersion", notifier.getVersion());
- event.addMetadata(INTERNAL_DIAGNOSTICS_TAB, "apiKey", config.getApiKey());
- final EventPayload payload = new EventPayload(null, event, notifier, config);
- try {
- backgroundTaskService.submitTask(TaskType.INTERNAL_REPORT, new Runnable() {
- @Override
- public void run() {
- try {
- logger.d("InternalReportDelegate - sending internal event");
- Delivery delivery = config.getDelivery();
- DeliveryParams params = config.getErrorApiDeliveryParams(payload);
- // can only modify headers if DefaultDelivery is in use
- if (delivery instanceof DefaultDelivery) {
- Map<String, String> headers = params.getHeaders();
- headers.put(HEADER_INTERNAL_ERROR, "bugsnag-android");
- headers.remove(DeliveryHeadersKt.HEADER_API_KEY);
- DefaultDelivery defaultDelivery = (DefaultDelivery) delivery;
- defaultDelivery.deliver(params.getEndpoint(), payload, headers);
- }
- } catch (Exception exception) {
- logger.w("Failed to report internal event to Bugsnag", exception);
- }
- }
- });
- } catch (RejectedExecutionException ignored) {
- // drop internal report
- }
- }
- }