Files
flipper/desktop/plugins/public/crash_reporter/ios-crash-utils.tsx
Michel Weststrate 01ea822341 Code shuffle
Summary:
Moved a lot of utility logic in separate files for Android and iOS, to make cleanup in next diffs easier by having a bit smaller files.

Purely a code shuffle, no functional changes

Reviewed By: passy

Differential Revision: D28102399

fbshipit-source-id: 2fd8f6669bdd2804fa8a7e1791c610ae7883eda6
2021-05-04 13:50:31 -07:00

105 lines
2.8 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 {Crash, CrashLog} from './index';
import {parseCrashLog} from './crash-utils';
import fs from 'fs';
import os from 'os';
import path from 'path';
import {promisify} from 'util';
export function parseIosCrash(
content: string,
fallbackReason: string,
logDate?: Date,
) {
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] : fallbackReason;
let date = logDate;
if (!date) {
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;
date = extractedDateString ? new Date(extractedDateString) : logDate;
}
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 function addFileWatcherForiOSCrashLogs(
deviceOs: string,
serial: string,
reportCrash: (payload: CrashLog | Crash) => void,
) {
const dir = path.join(os.homedir(), 'Library', 'Logs', 'DiagnosticReports');
if (!fs.existsSync(dir)) {
// Directory doesn't exist
return;
}
return fs.watch(dir, (_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);
promisify(fs.exists)(filepath).then((exists) => {
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(parseCrashLog(data, deviceOs, undefined));
}
});
});
});
}