diff --git a/src/server.js b/src/server.js index 8873fc74b..168f3529c 100644 --- a/src/server.js +++ b/src/server.js @@ -13,6 +13,7 @@ import CertificateProvider from './utils/CertificateProvider'; import {RSocketServer, ReactiveSocket} from 'rsocket-core'; import RSocketTCPServer from 'rsocket-tcp-server'; import Client from './Client.js'; +import {RecurringError} from './utils/errors'; const EventEmitter = (require('events'): any); const invariant = require('invariant'); @@ -261,10 +262,11 @@ class ConnectionTracker { this.connectionAttempts.set(key, entry); if (entry.length >= this.connectionProblemThreshold) { console.error( - `Connection loop detected with ${key}. Connected ${ - entry.length - } times in ${(time - entry[0]) / 1000}s.`, - 'ConnectionTracker', + new RecurringError( + `Connection loop detected with ${key}. Connected ${ + this.connectionProblemThreshold + } times within ${this.timeWindowMillis / 1000}s.`, + ), ); } } diff --git a/src/utils/CertificateProvider.js b/src/utils/CertificateProvider.js index 605b00793..5739d336b 100644 --- a/src/utils/CertificateProvider.js +++ b/src/utils/CertificateProvider.js @@ -6,6 +6,7 @@ */ import LogManager from '../fb-stubs/Logger'; +import {RecurringError} from './errors'; const fs = require('fs'); const adb = require('adbkit-fb'); import { @@ -82,7 +83,7 @@ export default class CertificateProvider { this.ensureOpenSSLIsAvailable(); if (!appDirectory.match(allowedAppDirectoryRegex)) { return Promise.reject( - new Error( + new RecurringError( `Invalid appDirectory recieved from ${os} device: ${appDirectory}`, ), ); @@ -174,7 +175,7 @@ export default class CertificateProvider { fs.writeFileSync(destination + filename, contents); return Promise.resolve(); } - return Promise.reject(new Error(`Unsupported device os: ${os}`)); + return Promise.reject(new RecurringError(`Unsupported device os: ${os}`)); } getTargetDeviceId( @@ -209,7 +210,9 @@ export default class CertificateProvider { return Promise.all(deviceMatchList).then(devices => { const matchingIds = devices.filter(m => m.isMatch).map(m => m.id); if (matchingIds.length == 0) { - throw new Error(`No matching device found for app: ${appName}`); + throw new RecurringError( + `No matching device found for app: ${appName}`, + ); } return matchingIds[0]; }); @@ -261,11 +264,13 @@ export default class CertificateProvider { command: string, ): Promise { if (!user.match(allowedAppNameRegex)) { - return Promise.reject(new Error(`Disallowed run-as user: ${user}`)); + return Promise.reject( + new RecurringError(`Disallowed run-as user: ${user}`), + ); } if (command.match(/[']/)) { return Promise.reject( - new Error(`Disallowed escaping command: ${command}`), + new RecurringError(`Disallowed escaping command: ${command}`), ); } return this.adb @@ -274,14 +279,14 @@ export default class CertificateProvider { .then(buffer => buffer.toString()) .then(output => { if (output.match(appNotDebuggableRegex)) { - const e = new Error( + const e = new RecurringError( `Android app ${user} is not debuggable. To use it with sonar, add android:debuggable="true" to the application section of AndroidManifest.xml`, ); this.server.emit('error', e); throw e; } if (output.toLowerCase().match(operationNotPermittedRegex)) { - const e = new Error( + const e = new RecurringError( `Your android device (${deviceId}) does not support the adb shell run-as command. We're tracking this at https://github.com/facebook/Sonar/issues/92`, ); this.server.emit('error', e); @@ -307,13 +312,13 @@ export default class CertificateProvider { .then(subject => { const matches = subject.trim().match(x509SubjectCNRegex); if (!matches || matches.length < 2) { - throw new Error(`Cannot extract CN from ${subject}`); + throw new RecurringError(`Cannot extract CN from ${subject}`); } return matches[1]; }) .then(appName => { if (!appName.match(allowedAppNameRegex)) { - throw new Error( + throw new RecurringError( `Disallowed app name in CSR: ${appName}. Only alphanumeric characters and '.' allowed.`, ); } diff --git a/src/utils/errors.js b/src/utils/errors.js new file mode 100644 index 000000000..eca461f07 --- /dev/null +++ b/src/utils/errors.js @@ -0,0 +1,14 @@ +/** + * Copyright 2018-present Facebook. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * @format + */ + +// Class of errors that may keep repeating but should only be logged once. +export class RecurringError extends Error { + constructor(message: string) { + super(message); + this.name = 'RecurringError'; + } +}