Skip to content

Commit

Permalink
Improve logging mechanism (#149)
Browse files Browse the repository at this point in the history
  • Loading branch information
yahavi authored Jan 20, 2022
1 parent 77a0821 commit aca11e7
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 42 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ After your builds were fetched from Artifactory, press on the Builds ![Builds](r
![CI](resources/readme/gifs/ci.gif)

## Troubleshooting
Change the log level to 'debug', 'info', 'warn', or 'err' in the [Extension Settings](#extension-settings).

View the extension log:
![Logs](resources/readme/gifs/logs.gif)

Expand Down
12 changes: 12 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@
"default": "",
"scope": "application",
"markdownDescription": "Optionally use the project key field to allow the security and license compliance information displayed in VS-Code, to reflect the security policies required by your organization. This is done as follows:\n\nCreate a [JFrog Project](https://www.jfrog.com/confluence/display/JFROG/Projects), or obtain the relevant JFrog Project key.\n\nCreate a [Policy](https://www.jfrog.com/confluence/display/JFROG/Creating+Xray+Policies+and+Rules) on JFrog Xray.\n\nCreate a [Watch](https://www.jfrog.com/confluence/display/JFROG/Configuring+Xray+Watches) on JFrog Xray and assign your Policy and Project as resources to it."
},
"jfrog.logLevel": {
"type": "string",
"default": "info",
"enum": [
"debug",
"info",
"warn",
"err"
],
"scope": "application",
"markdownDescription": "The logging level the extension logs at, defaults to 'info'"
}
}
},
Expand Down
38 changes: 29 additions & 9 deletions src/main/log/logManager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as vscode from 'vscode';
import { ExtensionComponent } from '../extensionComponent';
import { Configuration } from '../utils/configuration';

type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERR';

Expand Down Expand Up @@ -28,12 +29,17 @@ export class LogManager implements ExtensionComponent {
* @param level - The log level
*/
public logMessage(message: string, level: LogLevel, focusOutput: boolean = false): void {
if (!!message) {
const title: string = new Date().toLocaleTimeString();
this._outputChannel.appendLine(`[${level} - ${title}] ${message}`);
if (focusOutput) {
this.showOutput();
}
if (!message) {
return;
}
let selectedLogLevel: LogLevel = Configuration.getLogLevel().toUpperCase() as LogLevel;
if (this.logLevelToNumber(level) < this.logLevelToNumber(selectedLogLevel)) {
return;
}
const title: string = new Date().toLocaleTimeString();
this._outputChannel.appendLine(`[${level} - ${title}] ${message}`);
if (focusOutput) {
this.showOutput();
}
}

Expand All @@ -44,16 +50,17 @@ export class LogManager implements ExtensionComponent {
*/
public logError(error: Error, shouldToast: boolean) {
this.setFailed();
this.logMessage(error.name, 'ERR');
let logMessage: string = error.name;
if (error.message) {
this._outputChannel.appendLine(error.message);
logMessage += ': ' + error.message;
if (shouldToast) {
vscode.window.showErrorMessage(error.message);
this.showOutput();
}
}
this.logMessage(logMessage, 'ERR');
if (error.stack) {
this._outputChannel.appendLine(error.stack);
this.logMessage(error.stack, 'DEBUG');
}
}

Expand All @@ -77,4 +84,17 @@ export class LogManager implements ExtensionComponent {
private setFailed() {
this._statusBar.text = 'JFrog: $(error)';
}

private logLevelToNumber(level: LogLevel): number {
switch (level) {
case 'DEBUG':
return 0;
case 'INFO':
return 1;
case 'WARN':
return 2;
case 'ERR':
return 3;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class DependenciesTreeDataProvider implements vscode.TreeDataProvider<Dep
}
this._scanInProgress = true;
ScanUtils.setScanInProgress(true);
this._treesManager.logManager.logMessage('Starting ' + (quickScan ? 'quick' : 'slow') + ' scan', 'INFO');
this._treesManager.logManager.logMessage('Starting ' + (quickScan ? 'quick' : 'full') + ' scan', 'INFO');
this.repopulateTree(quickScan, onChangeFire)
.then(() => {
vscode.commands.executeCommand('jfrog.xray.focus');
Expand All @@ -65,6 +65,7 @@ export class DependenciesTreeDataProvider implements vscode.TreeDataProvider<Dep
.finally(() => {
this._scanInProgress = false;
ScanUtils.setScanInProgress(false);
this._treesManager.logManager.logMessage('Xray scan completed', 'INFO');
});
}

Expand Down Expand Up @@ -126,27 +127,31 @@ export class DependenciesTreeDataProvider implements vscode.TreeDataProvider<Dep
}

private async repopulateTree(quickScan: boolean, onChangeFire: () => void) {
await ScanUtils.scanWithProgress(async (progress: vscode.Progress<{ message?: string; increment?: number }>, checkCanceled: () => void) => {
this.clearTree();
let workspaceRoot: DependenciesTreeNode = <DependenciesTreeNode>this.dependenciesTree;
let componentsToScan: Set<ComponentDetails> = new Set();
await DependenciesTreesFactory.createDependenciesTrees(
this._workspaceFolders,
componentsToScan,
this._treesManager,
workspaceRoot,
quickScan
);
await this._scanLogicManager.scanAndCache(progress, componentsToScan, checkCanceled);
for (let node of workspaceRoot.children) {
this.addXrayInfoToTree(node);
if (node instanceof RootNode) {
node.setUpgradableDependencies(this._treesManager.scanCacheManager);
await ScanUtils.scanWithProgress(
async (progress: vscode.Progress<{ message?: string; increment?: number }>, checkCanceled: () => void) => {
this.clearTree();
let workspaceRoot: DependenciesTreeNode = <DependenciesTreeNode>this.dependenciesTree;
let componentsToScan: Set<ComponentDetails> = new Set();
await DependenciesTreesFactory.createDependenciesTrees(
this._workspaceFolders,
componentsToScan,
this._treesManager,
workspaceRoot,
quickScan
);
await this._scanLogicManager.scanAndCache(progress, componentsToScan, checkCanceled);
for (let node of workspaceRoot.children) {
this.addXrayInfoToTree(node);
if (node instanceof RootNode) {
node.setUpgradableDependencies(this._treesManager.scanCacheManager);
}
node.issues = node.processTreeIssues();
}
node.issues = node.processTreeIssues();
}
onChangeFire();
}, 'Scanning project dependencies ');
onChangeFire();
},
'Scanning project dependencies ',
quickScan
);
}

private clearTree() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class NpmTreeNode extends RootNode {
this._treesManager.logManager.logMessage(
'Possible cause: The project needs to be installed by npm. Install it by running "npm install" from "' +
this.workspaceFolder +
'",.',
'".',
'INFO'
);
scopedProject.loadProjectDetails(JSON.parse((<any>error).stdout.toString()));
Expand Down
4 changes: 4 additions & 0 deletions src/main/utils/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,8 @@ export class Configuration {
.get('projectKey', '')
.trim();
}

public static getLogLevel(): string {
return vscode.workspace.getConfiguration('jfrog').get('logLevel', 'info');
}
}
2 changes: 1 addition & 1 deletion src/main/utils/goUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export class GoUtils {
}
treesManager.logManager.logMessage('go.mod files to scan: [' + goMods.toString() + ']', 'DEBUG');
if (!GoUtils.verifyGoInstalled()) {
vscode.window.showErrorMessage('Could not scan go project dependencies, because go CLI is not in the PATH.');
treesManager.logManager.logError(new Error('Could not scan go project dependencies, because go CLI is not in the PATH.'), !quickScan);
return;
}
for (let goMod of goMods) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/utils/mavenUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export class MavenUtils {
}
treesManager.logManager.logMessage('pom.xml files to scan: [' + pomXmls.toString() + ']', 'DEBUG');
if (!MavenUtils.verifyMavenInstalled()) {
vscode.window.showErrorMessage('Could not scan Maven project dependencies, because "mvn" is not in the PATH.');
treesManager.logManager.logError(new Error('Could not scan Maven project dependencies, because "mvn" is not in the PATH.'), !quickScan);
return;
}
treesManager.logManager.logMessage('Generating Maven Dependency Tree', 'INFO');
Expand Down
2 changes: 1 addition & 1 deletion src/main/utils/npmUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export class NpmUtils {
return;
}
if (!NpmUtils.verifyNpmInstalled()) {
vscode.window.showErrorMessage('Could not scan npm project dependencies, because npm CLI is not in the PATH.');
treesManager.logManager.logError(new Error('Could not scan npm project dependencies, because npm CLI is not in the PATH.'), !quickScan);
return;
}
treesManager.logManager.logMessage('package.json files to scan: [' + packageJsons.toString() + ']', 'DEBUG');
Expand Down
21 changes: 15 additions & 6 deletions src/main/utils/pypiUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,22 +102,31 @@ export class PypiUtils {
if (!pythonExtension) {
pythonExtension = await PypiUtils.getAndActivatePythonExtension();
if (!pythonExtension) {
vscode.window.showErrorMessage(
'Could not scan Pypi project dependencies, because python extension is not installed. ' +
'Please install Python extension: https://marketplace.visualstudio.com/items?itemName=ms-python.python'
treesManager.logManager.logError(
new Error(
'Could not scan Pypi project dependencies, because python extension is not installed. ' +
'Please install Python extension: https://marketplace.visualstudio.com/items?itemName=ms-python.python'
),
!quickScan
);
return;
}
}

let pythonPath: string | undefined = PypiUtils.getPythonPath(pythonExtension, workspaceFolder);
if (!pythonPath) {
vscode.window.showErrorMessage('Could not scan Pypi project dependencies, because python interpreter is not set.');
treesManager.logManager.logError(
new Error('Could not scan Pypi project dependencies, because python interpreter is not set.'),
!quickScan
);
return;
}
if (!PypiUtils.isInVirtualEnv(pythonPath, workspaceFolder.uri.fsPath, treesManager.logManager)) {
vscode.window.showErrorMessage(
'Please install and activate a virtual environment before running Xray scan. Then, install your Python project in that environment.'
treesManager.logManager.logError(
new Error(
'Please install and activate a virtual environment before running Xray scan. Then, install your Python project in that environment.'
),
!quickScan
);
return;
}
Expand Down
10 changes: 8 additions & 2 deletions src/main/utils/scanUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@ export class ScanUtils {

public static async scanWithProgress(
scanCbk: (progress: vscode.Progress<{ message?: string; increment?: number }>, checkCanceled: () => void) => Promise<void>,
title: string
title: string,
quickScan?: boolean
) {
if (quickScan) {
title = 'JFrog: ' + title;
}
await vscode.window.withProgress(
<vscode.ProgressOptions>{
location: vscode.ProgressLocation.Notification,
// Start progress in balloon only if the user initiated a full scan by clicking on the "Refresh" button.
// Otherwise - show the progress in the status bar.
location: quickScan ? vscode.ProgressLocation.Window : vscode.ProgressLocation.Notification,
title: title,
cancellable: true
},
Expand Down

0 comments on commit aca11e7

Please sign in to comment.