Files
flipper/desktop/plugins/public/crash_reporter/ios-crash-utils.tsx
Pascal Hartig 47099cfd31 Fix Flipper lints #16
Summary: Larger list of fixes. Adding another package to the flipper export is a bit nasty but it unblocks us for now and centralises `remote` access which seems like a win for FAAS.

Reviewed By: mweststrate

Differential Revision: D30785421

fbshipit-source-id: 931297e8566b5d8a213b69ae87d0cda7648b3ed4
2021-09-08 08:44:19 -07:00

97 lines
2.7 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import type {CrashLog} from './index';
import fs from 'fs-extra';
import os from 'os';
import path from 'path';
import {UNKNOWN_CRASH_REASON} from './crash-utils';
export function parseIosCrash(content: string) {
const regex = /Exception Type: *\w*/;
const arr = regex.exec(content);
const exceptionString = arr ? arr[0] : '';
const exceptionRegex = /\w*$/;
const tmp = exceptionRegex.exec(exceptionString);
const exception = tmp && tmp[0].length ? tmp[0] : UNKNOWN_CRASH_REASON;
const dateRegex = /Date\/Time: *[\w\s\.:-]*/;
const dateArr = dateRegex.exec(content);
const dateString = dateArr ? dateArr[0] : '';
const dateRegex2 = /[\w\s\.:-]*$/;
const tmp1 = dateRegex2.exec(dateString);
const extractedDateString: string | null =
tmp1 && tmp1[0].length ? tmp1[0] : null;
const date = extractedDateString
? new Date(extractedDateString).getTime()
: Date.now();
const crash: CrashLog = {
callstack: content,
name: exception,
reason: exception,
date,
};
return crash;
}
export function shouldShowiOSCrashNotification(
serial: string,
content: string,
): boolean {
const appPath = parsePath(content);
if (!appPath || !appPath.includes(serial)) {
// Do not show notifications for the app which are not running on this device
return false;
}
return true;
}
export function parsePath(content: string): string | null {
const regex = /(?<=.*Path: *)[^\n]*/;
const arr = regex.exec(content);
if (!arr || arr.length <= 0) {
return null;
}
const path = arr[0];
return path.trim();
}
export async function addFileWatcherForiOSCrashLogs(
serial: string,
reportCrash: (payload: CrashLog) => void,
) {
const dir = path.join(os.homedir(), 'Library', 'Logs', 'DiagnosticReports');
if (!(await fs.pathExists(dir))) {
// Directory doesn't exist
return;
}
return fs.watch(dir, async (_eventType, filename) => {
// We just parse the crash logs with extension `.crash`
const checkFileExtension = /.crash$/.exec(filename);
if (!filename || !checkFileExtension) {
return;
}
const filepath = path.join(dir, filename);
const exists = await fs.pathExists(filepath);
if (!exists) {
return;
}
fs.readFile(filepath, 'utf8', function (err, data) {
if (err) {
console.warn('Failed to read crash file', err);
return;
}
if (shouldShowiOSCrashNotification(serial, data)) {
reportCrash(parseIosCrash(data));
}
});
});
}