Skip to content

Commit 20facac

Browse files
authored
feat: include extra telemetry info (#847)
1 parent 2713313 commit 20facac

File tree

10 files changed

+308
-61
lines changed

10 files changed

+308
-61
lines changed

package-lock.json

Lines changed: 124 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@
436436
"json-to-ast": "^2.1.0",
437437
"minimatch": "^10.0.3",
438438
"mustache": "^4.2.0",
439+
"node-html-parser": "^7.0.1",
439440
"path": "^0.12.7",
440441
"tree-sitter-python": "^0.23.6",
441442
"web-tree-sitter": "^0.25.6"

src/caNotification.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { Uri } from 'vscode';
44
import { applySettingNameMappings } from './utils';
5+
import { ResponseMetrics } from './dependencyAnalysis/analysis';
56

67
/**
78
* Interface representing the data structure for a Component Analysis (CA) Notification.
@@ -12,6 +13,7 @@ export interface CANotificationData {
1213
done?: boolean | null;
1314
diagCount?: number | null;
1415
vulnCount?: Map<string, number> | null;
16+
metrics?: ResponseMetrics,
1517
}
1618

1719
/**

src/dependencyAnalysis/analysis.ts

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,30 @@ interface ISource {
2424
dependencies: DependencyReport[];
2525
}
2626

27+
export interface ResponseMetrics {
28+
scanned: {
29+
total: number,
30+
direct: number,
31+
transitive: number
32+
},
33+
providers: {
34+
[providers: string]: {
35+
[sources: string]: {
36+
total: number,
37+
direct: number,
38+
transitive: number,
39+
dependencies: number,
40+
critical: number,
41+
high: number,
42+
medium: number,
43+
low: number,
44+
remediations: number,
45+
recommendations: number,
46+
}
47+
}
48+
}
49+
}
50+
2751
/**
2852
* Implementation of IDependencyData interface.
2953
*/
@@ -37,32 +61,45 @@ class DependencyData {
3761
) { }
3862
}
3963

40-
/**
41-
* Represents the parsed response of Red Hat Dependency Analytics (RHDA) analysis, with dependencies mapped by reference string.
42-
*/
43-
interface IAnalysisResponse {
44-
dependencies: Map<string, DependencyData[]>;
45-
}
46-
47-
/**
48-
* Implementation of IAnalysisResponse interface.
49-
*/
50-
class AnalysisResponse implements IAnalysisResponse {
64+
class AnalysisResponse {
65+
metrics: ResponseMetrics = {
66+
scanned: {
67+
total: 0,
68+
direct: 0,
69+
transitive: 0
70+
},
71+
providers: {}
72+
};
5173
dependencies: Map<string, DependencyData[]> = new Map<string, DependencyData[]>();
5274
provider: IDependencyProvider;
5375

5476
constructor(resData: AnalysisReport, diagnosticFilePath: Uri, provider: IDependencyProvider) {
55-
5677
this.provider = provider;
5778
const failedProviders: string[] = [];
5879
const sources: ISource[] = [];
5980

6081
if (isDefined(resData, 'providers')) {
6182
Object.entries(resData.providers).map(([providerName, providerData]) => {
83+
this.metrics.providers[providerName] = {};
6284
if (isDefined(providerData, 'status', 'ok') && providerData.status.ok) {
6385
if (isDefined(providerData, 'sources')) {
6486
Object.entries(providerData.sources).map(([sourceName, sourceData]) => {
6587
sources.push({ id: `${providerName}(${sourceName})`, dependencies: this.getDependencies(sourceData) });
88+
89+
if (isDefined(sourceData, 'summary')) {
90+
this.metrics.providers[providerName][sourceName] = {
91+
dependencies: sourceData.summary.dependencies ?? 0,
92+
direct: sourceData.summary.direct ?? 0,
93+
transitive: sourceData.summary.transitive ?? 0,
94+
critical: sourceData.summary.critical ?? 0,
95+
high: sourceData.summary.high ?? 0,
96+
medium: sourceData.summary.dependencies ?? 0,
97+
low: sourceData.summary.low ?? 0,
98+
recommendations: sourceData.summary.recommendations ?? 0,
99+
remediations: sourceData.summary.remediations ?? 0,
100+
total: sourceData.summary.total ?? 0,
101+
};
102+
}
66103
});
67104
}
68105
} else {
@@ -97,6 +134,14 @@ class AnalysisResponse implements IAnalysisResponse {
97134
});
98135
});
99136
}
137+
138+
if (isDefined(resData, 'scanned')) {
139+
this.metrics.scanned = {
140+
direct: resData.scanned.direct ?? 0,
141+
total: resData.scanned.total ?? 0,
142+
transitive: resData.scanned.transitive ?? 0,
143+
};
144+
}
100145
}
101146

102147
/**

src/dependencyAnalysis/diagnostics.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ async function performDiagnostics(diagnosticFilePath: Uri, contents: string, pro
110110

111111
diagnosticsPipeline.runDiagnostics(response.dependencies, ecosystem);
112112

113-
diagnosticsPipeline.reportDiagnostics();
113+
diagnosticsPipeline.reportDiagnostics(response.metrics);
114114
} catch (error) {
115115
outputChannelDep.warn(`component analysis error: ${buildLogErrorMessage(error as Error)}`);
116116
notifications.emit('caError', {

src/diagnosticsPipeline.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import { Diagnostic, Uri } from 'vscode';
99
import * as vscode from 'vscode';
1010
import { notifications } from './extension';
11+
import { ResponseMetrics } from './dependencyAnalysis/analysis';
1112

1213
/**
1314
* Abstract class for implementing a diagnostics pipeline.
@@ -40,12 +41,13 @@ export abstract class AbstractDiagnosticsPipeline<T> {
4041
});
4142
}
4243

43-
reportDiagnostics() {
44+
reportDiagnostics(metrics?: ResponseMetrics) {
4445
notifications.emit('caNotification', {
4546
done: true,
4647
uri: this.diagnosticFilePath,
4748
diagCount: this.diagnostics.length,
4849
vulnCount: this.vulnCount,
50+
metrics,
4951
});
5052
}
5153

0 commit comments

Comments
 (0)