From 370412aab46f45ec92b93c66cade24e713a09df4 Mon Sep 17 00:00:00 2001 From: Roy Razon Date: Wed, 7 Feb 2024 10:49:59 +0200 Subject: [PATCH] better error logging with `--json` flag --- packages/cli-common/src/commands/base-command.ts | 9 +++++++-- packages/cli-common/src/index.ts | 1 + packages/cli-common/src/lib/errors.ts | 12 ++++++++++++ packages/cli/src/hooks/init/load-plugins.ts | 6 +++--- 4 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 packages/cli-common/src/lib/errors.ts diff --git a/packages/cli-common/src/commands/base-command.ts b/packages/cli-common/src/commands/base-command.ts index 453c8c1a..d0ab35e0 100644 --- a/packages/cli-common/src/commands/base-command.ts +++ b/packages/cli-common/src/commands/base-command.ts @@ -8,6 +8,7 @@ import { mergeWith } from 'lodash-es' import { commandLogger } from '../lib/log.js' import { composeFlags, pluginFlags } from '../lib/common-flags/index.js' import { PreevyConfig } from '../../../core/src/config.js' +import { errorToJson } from '../lib/errors.js' // eslint-disable-next-line no-use-before-define export type Flags = Interfaces.InferredFlags @@ -139,17 +140,21 @@ abstract class BaseCommand extends Comm this.stdErrLogger.info(message, ...args) } - // eslint-disable-next-line class-methods-use-this async catch(error: Error) { const emitter = telemetryEmitter() emitter.capture('error', { - error, + error: errorToJson(error), }) emitter.unref() await emitter.flush() // eslint-disable-next-line @typescript-eslint/return-await return await super.catch(error) } + + // eslint-disable-next-line class-methods-use-this + protected toErrorJson(err: unknown) { + return { error: errorToJson(err) } + } } export default BaseCommand diff --git a/packages/cli-common/src/index.ts b/packages/cli-common/src/index.ts index 8a11d3cf..aa6b7ce7 100644 --- a/packages/cli-common/src/index.ts +++ b/packages/cli-common/src/index.ts @@ -2,6 +2,7 @@ export * from './lib/plugins/model.js' export * as text from './lib/text.js' export { HookName, HookFunc, HooksListeners, Hooks } from './lib/hooks.js' export { PluginContext, PluginInitContext } from './lib/plugins/context.js' +export { errorToJson } from './lib/errors.js' export { composeFlags, pluginFlags, envIdFlags, tunnelServerFlags, urlFlags, buildFlags, tableFlags, parseBuildFlags, } from './lib/common-flags/index.js' diff --git a/packages/cli-common/src/lib/errors.ts b/packages/cli-common/src/lib/errors.ts new file mode 100644 index 00000000..c9930505 --- /dev/null +++ b/packages/cli-common/src/lib/errors.ts @@ -0,0 +1,12 @@ +export const errorToJson = (e: unknown) => { + if (!(e instanceof Error)) { + return e + } + return { + ...e, + name: e.name, + class: e.constructor.name, + message: e.message, + stack: e.stack, + } +} diff --git a/packages/cli/src/hooks/init/load-plugins.ts b/packages/cli/src/hooks/init/load-plugins.ts index 4e12bd96..9627d50d 100644 --- a/packages/cli/src/hooks/init/load-plugins.ts +++ b/packages/cli/src/hooks/init/load-plugins.ts @@ -1,5 +1,5 @@ import { Hook as OclifHook } from '@oclif/core' -import { initHook } from '@preevy/cli-common' +import { errorToJson, initHook } from '@preevy/cli-common' import { telemetryEmitter } from '@preevy/core' const wrappedHook: OclifHook<'init'> = async function wrappedHook(...args) { @@ -7,8 +7,8 @@ const wrappedHook: OclifHook<'init'> = async function wrappedHook(...args) { await initHook.call(this, ...args) } catch (e) { // eslint-disable-next-line no-console - console.warn(`warning: failed to init context: ${(e as Error).stack || e}`) - telemetryEmitter().capture('plugin-init-error', { error: e }) + console.error(`init plugin failed: ${(e as Error).stack || e}`) + telemetryEmitter().capture('plugin-init-error', { error: errorToJson(e) }) await telemetryEmitter().flush() process.exit(1) }