Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Osm 566 use formatted logging for error catalogue errors in the cli #5054

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4,257 changes: 2,057 additions & 2,200 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Expand Up @@ -67,6 +67,7 @@
"@snyk/code-client": "^4.23.5",
"@snyk/dep-graph": "^2.7.4",
"@snyk/docker-registry-v2-client": "^2.11.0",
"@snyk/error-catalog-nodejs-public": "^5.14.2",
"@snyk/fix": "file:packages/snyk-fix",
"@snyk/gemfile": "1.2.0",
"@snyk/snyk-cocoapods-plugin": "2.5.3",
Expand All @@ -84,6 +85,7 @@
"env-paths": "^2.0.0",
"glob": "^7.1.7",
"global-agent": "^2.1.12",
"http-status-codes": "^2.3.0",
"jest-json-schema": "^6.1.0",
"json-stream-stringify": "^3.1.1",
"lodash.assign": "^4.2.0",
Expand Down
33 changes: 18 additions & 15 deletions src/cli/commands/monitor/index.ts
Expand Up @@ -40,7 +40,6 @@ import { PluginMetadata } from '@snyk/cli-interface/legacy/plugin';
import { getContributors } from '../../../lib/monitor/dev-count-analysis';
import {
FailedToRunTestError,
MonitorError,
MissingArgError,
ValidationError,
} from '../../../lib/errors';
Expand All @@ -49,7 +48,12 @@ import { getEcosystem, monitorEcosystem } from '../../../lib/ecosystems';
import { getFormattedMonitorOutput } from '../../../lib/ecosystems/monitor';
import { processCommandArgs } from '../process-command-args';
import { hasFeatureFlag } from '../../../lib/feature-flags';

import {
cliOutputFormatter,
} from '../../../lib/formatters/cliErrorFormatter';
import {
UnableToCreateMonitorError
} from "@snyk/error-catalog-nodejs-public/src/catalogs/CLI-error-catalog";
const SEPARATOR = '\n-------------------------------------------------------\n';
const debug = Debug('snyk');
const appVulnsReleaseWarningMsg = `${theme.icon.WARNING} Important: Beginning January 24th, 2023, application dependencies in container
Expand Down Expand Up @@ -231,7 +235,10 @@ export default async function monitor(...args0: MethodArgs): Promise<any> {
failedResults.forEach((result) => {
results.push({
ok: false,
data: new MonitorError(500, result.errMessage),
data: new UnableToCreateMonitorError(
'Unexpected issues when fetching dependancies from plugin',
{ result },
),
path: result.targetFile || '',
});
});
Expand Down Expand Up @@ -305,7 +312,13 @@ export default async function monitor(...args0: MethodArgs): Promise<any> {
} catch (err) {
// pushing this error allow this inner loop to keep scanning the projects
// even if 1 in 100 fails
results.push({ ok: false, data: err, path });
results.push({
ok: false,
data: new UnableToCreateMonitorError('Error creating monitor', {
err,
}),
path,
});
}
}
} catch (err) {
Expand All @@ -325,17 +338,7 @@ export default async function monitor(...args0: MethodArgs): Promise<any> {
if (res.ok) {
return res.data;
}

const errorMessage =
res.data && res.data.userMessage
? chalk.bold.red(res.data.userMessage)
: res.data
? res.data.message
: 'Unknown error occurred.';

return (
chalk.bold.white('\nMonitoring ' + res.path + '...\n\n') + errorMessage
);
return cliOutputFormatter.error(res.data);
})
.join('\n' + SEPARATOR);

Expand Down
4 changes: 2 additions & 2 deletions src/cli/commands/monitor/types.ts
@@ -1,4 +1,4 @@
import { MonitorError } from '../../../lib/errors';
import { ProblemError } from '@snyk/error-catalog-nodejs-public';

export interface GoodResult {
ok: true;
Expand All @@ -9,6 +9,6 @@ export interface GoodResult {

export interface BadResult {
ok: false;
data: MonitorError;
data: ProblemError;
path: string;
}
37 changes: 19 additions & 18 deletions src/lib/ecosystems/monitor.ts
Expand Up @@ -9,11 +9,7 @@ import { getPlugin } from './plugins';
import { BadResult, GoodResult } from '../../cli/commands/monitor/types';
import { formatErrorMonitorOutput, formatMonitorOutput } from '../formatters';
import { getExtraProjectCount } from '../plugins/get-extra-project-count';
import {
AuthFailedError,
DockerImageNotFoundError,
MonitorError,
} from '../errors';
import { AuthFailedError, DockerImageNotFoundError } from '../errors';
import {
Ecosystem,
ScanResult,
Expand All @@ -33,6 +29,11 @@ import {
} from '../../cli/commands/monitor';
import { isUnmanagedEcosystem } from './common';
import { findAndLoadPolicy } from '../policy';
import {
cliOutputFormatter,
isErrorOfTypeProblemError,
} from '../formatters/cliErrorFormatter';
import { UnableToCreateMonitorError } from '@snyk/error-catalog-nodejs-public/src/catalogs/CLI-error-catalog';

const SEPARATOR = '\n-------------------------------------------------------\n';

Expand Down Expand Up @@ -165,7 +166,14 @@ async function monitorDependencies(
throw AuthFailedError();
}
if (error.code >= 400 && error.code < 500) {
throw new MonitorError(error.code, error.message);
throw new UnableToCreateMonitorError(
'Could not monitor dependencies in ' + path,
{
error: error.message,
path,
scanResult,
},
);
}
errors.push({
error: 'Could not monitor dependencies in ' + path,
Expand Down Expand Up @@ -218,7 +226,10 @@ export async function getFormattedMonitorOutput(
for (const monitorError of errors) {
results.push({
ok: false,
data: new MonitorError(500, monitorError.error),
data: new UnableToCreateMonitorError(
'Unable to create monitor for ' + monitorError.path,
monitorError,
),
path: monitorError.path,
});
}
Expand All @@ -228,17 +239,7 @@ export async function getFormattedMonitorOutput(
if (res.ok) {
return res.data;
}

const errorMessage =
res.data && res.data.userMessage
? chalk.bold.red(res.data.userMessage)
: res.data
? res.data.message
: 'Unknown error occurred.';

return (
chalk.bold.white('\nMonitoring ' + res.path + '...\n\n') + errorMessage
);
return cliOutputFormatter.error(res.data);
})
.join('\n' + SEPARATOR);

Expand Down
8 changes: 6 additions & 2 deletions src/lib/ecosystems/resolve-monitor-facts.ts
Expand Up @@ -10,8 +10,9 @@ import {
pollingMonitorWithTokenUntilDone,
} from '../polling/polling-monitor';
import { extractAndApplyPluginAnalytics } from './plugin-analytics';
import { AuthFailedError, MonitorError } from '../errors';
import { AuthFailedError } from '../errors';
import { extractResolutionMetaFromScanResult } from '../polling/common';
import { UnableToCreateMonitorError } from '@snyk/error-catalog-nodejs-public/src/catalogs/CLI-error-catalog';

export async function resolveAndMonitorFacts(
scans: {
Expand Down Expand Up @@ -58,7 +59,10 @@ export async function resolveAndMonitorFacts(
}

if (error.code >= 400 && error.code < 500) {
throw new MonitorError(error.code, error.message);
throw new UnableToCreateMonitorError(
'Could not monitor dependencies in ' + path,
error,
);
}
errors.push({
error: 'Could not monitor dependencies in ' + path,
Expand Down
1 change: 0 additions & 1 deletion src/lib/errors/index.ts
Expand Up @@ -4,7 +4,6 @@ export { MissingTargetFileError } from './missing-targetfile-error';
export { NoSupportedManifestsFoundError } from './no-supported-manifests-found';
export { NoSupportedSastFiles } from './no-supported-sast-files-found';
export { CustomError } from './custom-error';
export { MonitorError } from './monitor-error';
export { ValidationError } from './validation-error';
export { ConnectionTimeoutError } from './connection-timeout-error';
export { FailedToLoadPolicyError } from './failed-to-load-policy-error';
Expand Down
14 changes: 0 additions & 14 deletions src/lib/errors/monitor-error.ts

This file was deleted.

49 changes: 49 additions & 0 deletions src/lib/formatters/cliErrorFormatter.ts
@@ -0,0 +1,49 @@
import chalk from 'chalk';
import { getReasonPhrase } from 'http-status-codes';
import {ProblemError} from "@snyk/error-catalog-nodejs-public";

export function isErrorOfTypeProblemError(
error: Error | ProblemError,
): error is ProblemError {
return (error as ProblemError)?.isErrorCatalogError === true;
}
function successLogger(message: string) {
console.log('🙌', chalk.bgGreen(' Awesome, No issues were found. '));
console.log(message);
}
function errorLoggerFactory(logLevel: 'info' | 'warn' | 'error') {
const createLogger = (color: string) => (
error: ProblemError | Error,
callback?: (err: Error) => void,
) => {
if (isErrorOfTypeProblemError(error)) {
const jsonResponse = error.toJsonApiErrorObject();
let output = `${chalk[color](`${logLevel.toUpperCase()} `)} ${chalk[
color
](` ${jsonResponse.title} `)} (${jsonResponse.code}) \nInfo: ${
jsonResponse.detail
} \nHTTP: ${jsonResponse.status} ${getReasonPhrase(
jsonResponse.status,
)}`;
if (jsonResponse.links) {
output += `\nHelp: ${jsonResponse.links.about}`;
}
return output;
}
if (callback) {
return callback(error);
}
};
const loglevelColorMap = {
info: 'bgBlue',
warn: 'bgYellow',
error: 'bgRed',
};
return createLogger(loglevelColorMap[logLevel]);
}
export const cliOutputFormatter = {
error: errorLoggerFactory('error'),
warn: errorLoggerFactory('warn'),
info: errorLoggerFactory('info'),
success: successLogger,
};
18 changes: 14 additions & 4 deletions src/lib/monitor/index.ts
Expand Up @@ -21,7 +21,6 @@ import {
} from '../types';
import * as projectMetadata from '../project-metadata';
import {
MonitorError,
ConnectionTimeoutError,
FailedToRunTestError,
errorMessageWithRetry,
Expand All @@ -43,6 +42,7 @@ import {
getTargetFile,
} from './utils';
import { countPathsToGraphRoot } from '../utils';
import { UnableToCreateMonitorError } from '@snyk/error-catalog-nodejs-public/src/catalogs/CLI-error-catalog';

const debug = Debug('snyk');

Expand Down Expand Up @@ -269,7 +269,10 @@ async function monitorDepTree(
if (!userMessage && res.statusCode === 504) {
throw new ConnectionTimeoutError();
} else {
throw new MonitorError(res.statusCode, userMessage);
throw new UnableToCreateMonitorError(
'Unable to create monitor, unexpected error from API',
{ userMessage, path: '/monitor/' + packageManager, target },
);
}
}
}
Expand Down Expand Up @@ -384,7 +387,11 @@ export async function monitorDepGraph(
if (!userMessage && res.statusCode === 504) {
throw new ConnectionTimeoutError();
} else {
throw new MonitorError(res.statusCode, userMessage);
throw new UnableToCreateMonitorError(userMessage, {
url: `${config.API}/monitor/${packageManager}/graph`,
method: 'PUT',
response: res.body,
});
}
}
}
Expand Down Expand Up @@ -518,7 +525,10 @@ async function monitorDepGraphFromDepTree(
if (!userMessage && res.statusCode === 504) {
throw new ConnectionTimeoutError();
} else {
throw new MonitorError(res.statusCode, userMessage);
throw new UnableToCreateMonitorError(
'Unexpected error when posting depGraph to Snyk API',
{ userMessage, path: `/monitor/${packageManager}/graph`, target },
);
}
}
}