Files
flipper/desktop/plugins/public/crash_reporter/ios-crash-utils.tsx
Andrey Goncharov 5610f8f058 Remove 'path' from plugins
Summary:
1. Add `path` replacement
1. Remove Node's path for all plugins but MobileBuildsPluginContainer (it is probably going to be moved to the server)

Reviewed By: mweststrate

Differential Revision: D32766327

fbshipit-source-id: e636f273842506e752b97cf1b28ce7ac51ce9a12
2021-12-02 04:14:51 -08: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 'flipper-plugin';
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));
}
});
});
}