Add companion logging

Summary: Add top-level error logging to flipper-server. Use the top-level logging mechanism in flipper-companion.

Reviewed By: lblasa

Differential Revision: D36252218

fbshipit-source-id: 58d22b3b9bd51e597b5250478640f54d10277861
This commit is contained in:
Andrey Goncharov
2022-05-10 05:13:24 -07:00
committed by Facebook GitHub Bot
parent e218b79de2
commit 98dde53cda
4 changed files with 134 additions and 29 deletions

View File

@@ -41,6 +41,8 @@ export {
UserUnauthorizedError, UserUnauthorizedError,
UserNotSignedInError, UserNotSignedInError,
NoLongerConnectedToClientError, NoLongerConnectedToClientError,
UserError,
SystemError,
isConnectivityOrAuthError, isConnectivityOrAuthError,
isError, isError,
isAuthError, isAuthError,

View File

@@ -30,6 +30,24 @@ export function isConnectivityOrAuthError(
); );
} }
export class SystemError extends Error {
name = 'SystemError';
readonly context?: unknown;
constructor(msg: string, ...args: unknown[]) {
super(msg);
this.context = args;
}
}
export class UserError extends Error {
name = 'UserError';
readonly context?: unknown;
constructor(msg: string, ...args: unknown[]) {
super(msg);
this.context = args;
}
}
export class UnableToExtractClientQueryError extends Error { export class UnableToExtractClientQueryError extends Error {
constructor(msg: string) { constructor(msg: string) {
super(msg); super(msg);

View File

@@ -7,7 +7,7 @@
* @format * @format
*/ */
import {FlipperServer, Logger} from 'flipper-common'; import {FlipperServer, Logger, UserError, SystemError} from 'flipper-common';
import {BaseDevice} from 'flipper-frontend-core'; import {BaseDevice} from 'flipper-frontend-core';
import {_SandyPluginDefinition} from 'flipper-plugin'; import {_SandyPluginDefinition} from 'flipper-plugin';
import {HeadlessClient} from './HeadlessClient'; import {HeadlessClient} from './HeadlessClient';
@@ -121,8 +121,9 @@ export class FlipperServerCompanion {
destroyClient(clientId: string) { destroyClient(clientId: string) {
const client = this.clients.get(clientId); const client = this.clients.get(clientId);
if (!client) { if (!client) {
throw new Error( throw new UserError(
'FlipperServerCompanion.destroyClient -> client not found', 'FlipperServerCompanion.destroyClient -> client not found',
client,
); );
} }
client.destroy(); client.destroy();
@@ -136,8 +137,9 @@ export class FlipperServerCompanion {
destroyDevice(deviceSerial: string) { destroyDevice(deviceSerial: string) {
const device = this.devices.get(deviceSerial); const device = this.devices.get(deviceSerial);
if (!device) { if (!device) {
throw new Error( throw new UserError(
'FlipperServerCompanion.destroyDevice -> device not found', 'FlipperServerCompanion.destroyDevice -> device not found',
deviceSerial,
); );
} }
device.destroy(); device.destroy();
@@ -159,8 +161,9 @@ export class FlipperServerCompanion {
const clientInfo = await this.flipperServer.exec('client-find', clientId); const clientInfo = await this.flipperServer.exec('client-find', clientId);
if (!clientInfo) { if (!clientInfo) {
throw new Error( throw new UserError(
'FlipperServerCompanion.createHeadlessClientIfNeeded -> client not found', 'FlipperServerCompanion.createHeadlessClientIfNeeded -> client not found',
clientId,
); );
} }
@@ -206,8 +209,9 @@ export class FlipperServerCompanion {
deviceSerial, deviceSerial,
); );
if (!deviceInfo) { if (!deviceInfo) {
throw new Error( throw new UserError(
'FlipperServerCompanion.createHeadlessDeviceIfNeeded -> device not found', 'FlipperServerCompanion.createHeadlessDeviceIfNeeded -> device not found',
deviceSerial,
); );
} }
@@ -228,8 +232,9 @@ export class FlipperServerCompanion {
const handler: (...args: any[]) => Promise<any> = const handler: (...args: any[]) => Promise<any> =
this.commandHandler[event]; this.commandHandler[event];
if (!handler) { if (!handler) {
throw new Error( throw new UserError(
`Unimplemented FlipperServerCompanion command: ${event}`, `Unimplemented FlipperServerCompanion command`,
event,
); );
} }
const result = await handler(...args); const result = await handler(...args);
@@ -267,14 +272,18 @@ export class FlipperServerCompanion {
const pluginInstance = client.sandyPluginStates.get(pluginId); const pluginInstance = client.sandyPluginStates.get(pluginId);
if (!pluginInstance) { if (!pluginInstance) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-plugin-start -> plugin not found', 'FlipperServerCompanion.companion-plugin-start -> plugin not found',
clientId,
pluginId,
); );
} }
if (!client.connected.get()) { if (!client.connected.get()) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-plugin-start -> client not connected', 'FlipperServerCompanion.companion-plugin-start -> client not connected',
clientId,
pluginId,
); );
} }
@@ -283,15 +292,19 @@ export class FlipperServerCompanion {
'companion-plugin-stop': async (clientId, pluginId) => { 'companion-plugin-stop': async (clientId, pluginId) => {
const client = this.clients.get(clientId); const client = this.clients.get(clientId);
if (!client) { if (!client) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-plugin-stop -> client not found', 'FlipperServerCompanion.companion-plugin-stop -> client not found',
clientId,
pluginId,
); );
} }
const pluginInstance = client.sandyPluginStates.get(pluginId); const pluginInstance = client.sandyPluginStates.get(pluginId);
if (!pluginInstance) { if (!pluginInstance) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-plugin-stop -> plugin not found', 'FlipperServerCompanion.companion-plugin-stop -> plugin not found',
clientId,
pluginId,
); );
} }
@@ -302,8 +315,10 @@ export class FlipperServerCompanion {
} }
if (!pluginInstance.activated) { if (!pluginInstance.activated) {
throw new Error( throw new SystemError(
'FlipperServerCompanion.companion-plugin-stop -> plugin not activated', 'FlipperServerCompanion.companion-plugin-stop -> plugin not activated',
clientId,
pluginId,
); );
} }
@@ -312,33 +327,53 @@ export class FlipperServerCompanion {
'companion-plugin-exec': async (clientId, pluginId, api, params) => { 'companion-plugin-exec': async (clientId, pluginId, api, params) => {
const client = this.clients.get(clientId); const client = this.clients.get(clientId);
if (!client) { if (!client) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-plugin-exec -> client not found', 'FlipperServerCompanion.companion-plugin-exec -> client not found',
clientId,
pluginId,
api,
params,
); );
} }
const pluginInstance = client.sandyPluginStates.get(pluginId); const pluginInstance = client.sandyPluginStates.get(pluginId);
if (!pluginInstance) { if (!pluginInstance) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-plugin-exec -> plugin not found', 'FlipperServerCompanion.companion-plugin-exec -> plugin not found',
clientId,
pluginId,
api,
params,
); );
} }
if (!client.connected.get()) { if (!client.connected.get()) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-plugin-exec -> client not connected', 'FlipperServerCompanion.companion-plugin-exec -> client not connected',
clientId,
pluginId,
api,
params,
); );
} }
if (!pluginInstance.companionApi) { if (!pluginInstance.companionApi) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-plugin-exec -> plugin does not expose API', 'FlipperServerCompanion.companion-plugin-exec -> plugin does not expose API',
clientId,
pluginId,
api,
params,
); );
} }
if (typeof pluginInstance.companionApi[api] !== 'function') { if (typeof pluginInstance.companionApi[api] !== 'function') {
throw new Error( throw new SystemError(
'FlipperServerCompanion.companion-plugin-exec -> plugin does not expose requested API method or it is not callable', 'FlipperServerCompanion.companion-plugin-exec -> plugin does not expose requested API method or it is not callable',
clientId,
pluginId,
api,
params,
); );
} }
@@ -368,20 +403,26 @@ export class FlipperServerCompanion {
const pluginDefinition = this.loadablePlugins.get(pluginId); const pluginDefinition = this.loadablePlugins.get(pluginId);
if (!pluginDefinition) { if (!pluginDefinition) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-device-plugin-start -> plugin definition not found', 'FlipperServerCompanion.companion-device-plugin-start -> plugin definition not found',
deviceSerial,
pluginId,
); );
} }
if (!device.connected.get()) { if (!device.connected.get()) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-device-plugin-start -> device not connected', 'FlipperServerCompanion.companion-device-plugin-start -> device not connected',
deviceSerial,
pluginId,
); );
} }
if (!device.supportsPlugin(pluginDefinition)) { if (!device.supportsPlugin(pluginDefinition)) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-device-plugin-start -> device does not support plugin', 'FlipperServerCompanion.companion-device-plugin-start -> device does not support plugin',
deviceSerial,
pluginId,
); );
} }
@@ -391,27 +432,35 @@ export class FlipperServerCompanion {
'companion-device-plugin-stop': async (deviceSerial, pluginId) => { 'companion-device-plugin-stop': async (deviceSerial, pluginId) => {
const device = this.devices.get(deviceSerial); const device = this.devices.get(deviceSerial);
if (!device) { if (!device) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-device-plugin-stop -> client not found', 'FlipperServerCompanion.companion-device-plugin-stop -> client not found',
deviceSerial,
pluginId,
); );
} }
const pluginInstance = device.sandyPluginStates.get(pluginId); const pluginInstance = device.sandyPluginStates.get(pluginId);
if (!pluginInstance) { if (!pluginInstance) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-device-plugin-stop -> plugin not found', 'FlipperServerCompanion.companion-device-plugin-stop -> plugin not found',
deviceSerial,
pluginId,
); );
} }
if (!device.connected.get()) { if (!device.connected.get()) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-device-plugin-stop -> device not connected', 'FlipperServerCompanion.companion-device-plugin-stop -> device not connected',
deviceSerial,
pluginId,
); );
} }
if (!pluginInstance.activated) { if (!pluginInstance.activated) {
throw new Error( throw new SystemError(
'FlipperServerCompanion.companion-device-plugin-stop -> plugin not activated', 'FlipperServerCompanion.companion-device-plugin-stop -> plugin not activated',
deviceSerial,
pluginId,
); );
} }
@@ -425,33 +474,53 @@ export class FlipperServerCompanion {
) => { ) => {
const device = this.devices.get(deviceSerial); const device = this.devices.get(deviceSerial);
if (!device) { if (!device) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-device-plugin-exec -> device not found', 'FlipperServerCompanion.companion-device-plugin-exec -> device not found',
deviceSerial,
pluginId,
api,
params,
); );
} }
const pluginInstance = device.sandyPluginStates.get(pluginId); const pluginInstance = device.sandyPluginStates.get(pluginId);
if (!pluginInstance) { if (!pluginInstance) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-device-plugin-exec -> plugin not found', 'FlipperServerCompanion.companion-device-plugin-exec -> plugin not found',
deviceSerial,
pluginId,
api,
params,
); );
} }
if (!device.connected.get()) { if (!device.connected.get()) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-plugin-exec -> client not connected', 'FlipperServerCompanion.companion-plugin-exec -> client not connected',
deviceSerial,
pluginId,
api,
params,
); );
} }
if (!pluginInstance.companionApi) { if (!pluginInstance.companionApi) {
throw new Error( throw new UserError(
'FlipperServerCompanion.companion-plugin-exec -> plugin does not expose API', 'FlipperServerCompanion.companion-plugin-exec -> plugin does not expose API',
deviceSerial,
pluginId,
api,
params,
); );
} }
if (typeof pluginInstance.companionApi[api] !== 'function') { if (typeof pluginInstance.companionApi[api] !== 'function') {
throw new Error( throw new SystemError(
'FlipperServerCompanion.companion-plugin-exec -> plugin does not expose requested API method or it is not callable', 'FlipperServerCompanion.companion-plugin-exec -> plugin does not expose requested API method or it is not callable',
deviceSerial,
pluginId,
api,
params,
); );
} }

View File

@@ -14,6 +14,8 @@ import {
ExecResponseErrorWebSocketMessage, ExecResponseErrorWebSocketMessage,
ServerEventWebSocketMessage, ServerEventWebSocketMessage,
GenericWebSocketError, GenericWebSocketError,
UserError,
SystemError,
} from 'flipper-common'; } from 'flipper-common';
import {FlipperServerImpl} from 'flipper-server-core'; import {FlipperServerImpl} from 'flipper-server-core';
import {WebSocketServer} from 'ws'; import {WebSocketServer} from 'ws';
@@ -99,6 +101,20 @@ export function startSocketServer(
} }
}) })
.catch((error: any) => { .catch((error: any) => {
if (error instanceof UserError) {
console.warn(
`flipper-server.startSocketServer.exec: ${error.message}`,
error.context,
error.stack,
);
}
if (error instanceof SystemError) {
console.error(
`flipper-server.startSocketServer.exec: ${error.message}`,
error.context,
error.stack,
);
}
if (connected) { if (connected) {
// TODO: Serialize error // TODO: Serialize error
// TODO: log if verbose console.warn('Failed to handle response', error); // TODO: log if verbose console.warn('Failed to handle response', error);