/
githubmirror
/
atom
Обзор
Документация
Войти
/
githubmirror
/
atom
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
packages/exception-reporting/lib/reporter.js
302 строки
9 KB
Rafael Oleza
Reformat all JS files using prettier
31 май 2019, 19:33
31 май 2019, 19:33
7f3f040
Код
Авторство
О чём код?
/** @babel */ import os from 'os'; import stackTrace from 'stack-trace'; import fs from 'fs-plus'; import path from 'path'; const API_KEY = '7ddca14cb60cbd1cd12d1b252473b076'; const LIB_VERSION = require('../package.json')['version']; const StackTraceCache = new WeakMap(); export default class Reporter { constructor(params = {}) { this.request = params.request || window.fetch; this.alwaysReport = params.hasOwnProperty('alwaysReport') ? params.alwaysReport : false; this.reportPreviousErrors = params.hasOwnProperty('reportPreviousErrors') ? params.reportPreviousErrors : true; this.resourcePath = this.normalizePath( params.resourcePath || process.resourcesPath ); this.reportedErrors = []; this.reportedAssertionFailures = []; } buildNotificationJSON(error, params) { return { apiKey: API_KEY, notifier: { name: 'Atom', version: LIB_VERSION, url: 'https://www.atom.io' }, events: [ { payloadVersion: '2', exceptions: [this.buildExceptionJSON(error, params.projectRoot)], severity: params.severity, user: { id: params.userId }, app: { version: params.appVersion, releaseStage: params.releaseStage }, device: { osVersion: params.osVersion }, metaData: error.metadata } ] }; } buildExceptionJSON(error, projectRoot) { return { errorClass: error.constructor.name, message: error.message, stacktrace: this.buildStackTraceJSON(error, projectRoot) }; } buildStackTraceJSON(error, projectRoot) { return this.parseStackTrace(error).map(callSite => { return { file: this.scrubPath(callSite.getFileName()), method: callSite.getMethodName() || callSite.getFunctionName() || 'none', lineNumber: callSite.getLineNumber(), columnNumber: callSite.getColumnNumber(), inProject: !/node_modules/.test(callSite.getFileName()) }; }); } normalizePath(pathToNormalize) { return pathToNormalize .replace('file:///', '') // Sometimes it's a uri .replace(/\\/g, '/'); // Unify path separators across Win/macOS/Linux } scrubPath(pathToScrub) { const absolutePath = this.normalizePath(pathToScrub); if (this.isBundledFile(absolutePath)) { return this.normalizePath(path.relative(this.resourcePath, absolutePath)); } else { return absolutePath .replace(this.normalizePath(fs.getHomeDirectory()), '~') // Remove users home dir .replace(/.*(\/packages\/.*)/, '$1'); // Remove everything before app.asar or packages } } getDefaultNotificationParams() { return { userId: atom.config.get('exception-reporting.userId'), appVersion: atom.getVersion(), releaseStage: this.getReleaseChannel(atom.getVersion()), projectRoot: atom.getLoadSettings().resourcePath, osVersion: `${os.platform()}-${os.arch()}-${os.release()}` }; } getReleaseChannel(version) { return version.indexOf('beta') > -1 ? 'beta' : version.indexOf('dev') > -1 ? 'dev' : 'stable'; } performRequest(json) { this.request.call(null, 'https://notify.bugsnag.com', { method: 'POST', headers: new Headers({ 'Content-Type': 'application/json' }), body: JSON.stringify(json) }); } shouldReport(error) { if (this.alwaysReport) return true; // Used in specs if (atom.config.get('core.telemetryConsent') !== 'limited') return false; if (atom.inDevMode()) return false; const topFrame = this.parseStackTrace(error)[0]; const fileName = topFrame ? topFrame.getFileName() : null; return ( fileName && (this.isBundledFile(fileName) || this.isTeletypeFile(fileName)) ); } parseStackTrace(error) { let callSites = StackTraceCache.get(error); if (callSites) { return callSites; } else { callSites = stackTrace.parse(error); StackTraceCache.set(error, callSites); return callSites; } } requestPrivateMetadataConsent(error, message, reportFn) { let notification, dismissSubscription; function reportWithoutPrivateMetadata() { if (dismissSubscription) { dismissSubscription.dispose(); } delete error.privateMetadata; delete error.privateMetadataDescription; reportFn(error); if (notification) { notification.dismiss(); } } function reportWithPrivateMetadata() { if (error.metadata == null) { error.metadata = {}; } for (let key in error.privateMetadata) { let value = error.privateMetadata[key]; error.metadata[key] = value; } reportWithoutPrivateMetadata(); } const name = error.privateMetadataRequestName; if (name != null) { if (localStorage.getItem(`private-metadata-request:${name}`)) { return reportWithoutPrivateMetadata(error); } else { localStorage.setItem(`private-metadata-request:${name}`, true); } } notification = atom.notifications.addInfo(message, { detail: error.privateMetadataDescription, description: 'Are you willing to submit this information to a private server for debugging purposes?', dismissable: true, buttons: [ { text: 'No', onDidClick: reportWithoutPrivateMetadata }, { text: 'Yes, Submit for Debugging', onDidClick: reportWithPrivateMetadata } ] }); dismissSubscription = notification.onDidDismiss( reportWithoutPrivateMetadata ); } addPackageMetadata(error) { let activePackages = atom.packages.getActivePackages(); const availablePackagePaths = atom.packages.getPackageDirPaths(); if (activePackages.length > 0) { let userPackages = {}; let bundledPackages = {}; for (let pack of atom.packages.getActivePackages()) { if (availablePackagePaths.includes(path.dirname(pack.path))) { userPackages[pack.name] = pack.metadata.version; } else { bundledPackages[pack.name] = pack.metadata.version; } } if (error.metadata == null) { error.metadata = {}; } error.metadata.bundledPackages = bundledPackages; error.metadata.userPackages = userPackages; } } addPreviousErrorsMetadata(error) { if (!this.reportPreviousErrors) return; if (!error.metadata) error.metadata = {}; error.metadata.previousErrors = this.reportedErrors.map( error => error.message ); error.metadata.previousAssertionFailures = this.reportedAssertionFailures.map( error => error.message ); } reportUncaughtException(error) { if (!this.shouldReport(error)) return; this.addPackageMetadata(error); this.addPreviousErrorsMetadata(error); if ( error.privateMetadata != null && error.privateMetadataDescription != null ) { this.requestPrivateMetadataConsent( error, 'The Atom team would like to collect the following information to resolve this error:', error => this.reportUncaughtException(error) ); return; } let params = this.getDefaultNotificationParams(); params.severity = 'error'; this.performRequest(this.buildNotificationJSON(error, params)); this.reportedErrors.push(error); } reportFailedAssertion(error) { if (!this.shouldReport(error)) return; this.addPackageMetadata(error); this.addPreviousErrorsMetadata(error); if ( error.privateMetadata != null && error.privateMetadataDescription != null ) { this.requestPrivateMetadataConsent( error, 'The Atom team would like to collect some information to resolve an unexpected condition:', error => this.reportFailedAssertion(error) ); return; } let params = this.getDefaultNotificationParams(); params.severity = 'warning'; this.performRequest(this.buildNotificationJSON(error, params)); this.reportedAssertionFailures.push(error); } // Used in specs setRequestFunction(requestFunction) { this.request = requestFunction; } isBundledFile(fileName) { return this.normalizePath(fileName).indexOf(this.resourcePath) === 0; } isTeletypeFile(fileName) { const teletypePath = atom.packages.resolvePackagePath('teletype'); return ( teletypePath && this.normalizePath(fileName).indexOf(teletypePath) === 0 ); } } Reporter.API_KEY = API_KEY; Reporter.LIB_VERSION = LIB_VERSION;