@@ -4,8 +4,9 @@ import { Command, Flags } from '@oclif/core';
4
4
import ora from 'ora' ;
5
5
import { submitScan } from '../../api/nes.client.ts' ;
6
6
import { config , filenamePrefix } from '../../config/constants.ts' ;
7
+ import { track } from '../../service/analytics.svc.ts' ;
7
8
import { createSbom } from '../../service/cdx.svc.ts' ;
8
- import { formatScanResults , formatWebReportUrl } from '../../service/display.svc.ts' ;
9
+ import { countComponentsByStatus , formatScanResults , formatWebReportUrl } from '../../service/display.svc.ts' ;
9
10
import { readSbomFromFile , saveReportToFile , saveSbomToFile , validateDirectory } from '../../service/file.svc.ts' ;
10
11
import { getErrorMessage } from '../../service/log.svc.ts' ;
11
12
@@ -56,23 +57,72 @@ export default class ScanEol extends Command {
56
57
public async run ( ) : Promise < EolReport | undefined > {
57
58
const { flags } = await this . parse ( ScanEol ) ;
58
59
60
+ track ( 'CLI EOL Scan Started' , ( context ) => ( {
61
+ command : context . command ,
62
+ command_flags : context . command_flags ,
63
+ scan_location : flags . dir ,
64
+ } ) ) ;
65
+
66
+ const sbomStartTime = performance . now ( ) ;
59
67
const sbom = await this . loadSbom ( ) ;
68
+ const sbomEndTime = performance . now ( ) ;
69
+
70
+ if ( ! flags . file ) {
71
+ track ( 'CLI SBOM Generated' , ( context ) => ( {
72
+ command : context . command ,
73
+ command_flags : context . command_flags ,
74
+ scan_location : flags . dir ,
75
+ sbom_generation_time : ( sbomEndTime - sbomStartTime ) / 1000 ,
76
+ } ) ) ;
77
+ }
60
78
61
79
if ( ! sbom . components ?. length ) {
80
+ track ( 'CLI EOL Scan Ended, No Components Found' , ( context ) => ( {
81
+ command : context . command ,
82
+ command_flags : context . command_flags ,
83
+ scan_location : flags . dir ,
84
+ } ) ) ;
62
85
this . log ( 'No components found in scan. Report not generated.' ) ;
63
86
return ;
64
87
}
65
88
89
+ const scanStartTime = performance . now ( ) ;
66
90
const scan = await this . scanSbom ( sbom ) ;
91
+ const scanEndTime = performance . now ( ) ;
92
+
93
+ const componentCounts = countComponentsByStatus ( scan ) ;
94
+ track ( 'CLI EOL Scan Completed' , ( context ) => ( {
95
+ command : context . command ,
96
+ command_flags : context . command_flags ,
97
+ eol_true_count : componentCounts . EOL ,
98
+ eol_unknown_count : componentCounts . UNKNOWN ,
99
+ nes_available_count : componentCounts . NES_AVAILABLE ,
100
+ number_of_packages : componentCounts . TOTAL ,
101
+ sbom_created : ! flags . file ,
102
+ scan_location : flags . dir ,
103
+ scan_load_time : ( scanEndTime - scanStartTime ) / 1000 ,
104
+ scanned_ecosystems : componentCounts . ECOSYSTEMS ,
105
+ web_report_link : scan . id ? `${ config . eolReportUrl } /${ scan . id } ` : undefined ,
106
+ } ) ) ;
67
107
68
108
if ( flags . save ) {
69
109
const reportPath = this . saveReport ( scan , flags . dir ) ;
70
110
this . log ( `Report saved to ${ reportPath } ` ) ;
111
+ track ( 'CLI JSON Scan Output Saved' , ( context ) => ( {
112
+ command : context . command ,
113
+ command_flags : context . command_flags ,
114
+ report_output_path : reportPath ,
115
+ } ) ) ;
71
116
}
72
117
73
118
if ( flags . saveSbom && ! flags . file ) {
74
119
const sbomPath = this . saveSbom ( flags . dir , sbom ) ;
75
120
this . log ( `SBOM saved to ${ sbomPath } ` ) ;
121
+ track ( 'CLI SBOM Output Saved' , ( context ) => ( {
122
+ command : context . command ,
123
+ command_flags : context . command_flags ,
124
+ sbom_output_path : sbomPath ,
125
+ } ) ) ;
76
126
}
77
127
78
128
if ( ! this . jsonEnabled ( ) ) {
@@ -107,23 +157,34 @@ export default class ScanEol extends Command {
107
157
return scan ;
108
158
} catch ( error ) {
109
159
spinner . fail ( 'Scanning failed' ) ;
110
- this . error ( `Failed to submit scan to NES. ${ getErrorMessage ( error ) } ` ) ;
160
+ const errorMessage = getErrorMessage ( error ) ;
161
+ track ( 'CLI EOL Scan Failed' , ( context ) => ( {
162
+ command : context . command ,
163
+ command_flags : context . command_flags ,
164
+ scan_location : context . scan_location ,
165
+ scan_failure_reason : errorMessage ,
166
+ } ) ) ;
167
+ this . error ( `Failed to submit scan to NES. ${ errorMessage } ` ) ;
111
168
}
112
169
}
113
170
114
171
private saveReport ( report : EolReport , dir : string ) : string {
115
172
try {
116
173
return saveReportToFile ( dir , report ) ;
117
174
} catch ( error ) {
118
- this . error ( getErrorMessage ( error ) ) ;
175
+ const errorMessage = getErrorMessage ( error ) ;
176
+ track ( 'CLI Error Encountered' , ( ) => ( { error : errorMessage } ) ) ;
177
+ this . error ( errorMessage ) ;
119
178
}
120
179
}
121
180
122
181
private saveSbom ( dir : string , sbom : CdxBom ) : string {
123
182
try {
124
183
return saveSbomToFile ( dir , sbom ) ;
125
184
} catch ( error ) {
126
- this . error ( getErrorMessage ( error ) ) ;
185
+ const errorMessage = getErrorMessage ( error ) ;
186
+ track ( 'CLI Error Encountered' , ( ) => ( { error : errorMessage } ) ) ;
187
+ this . error ( errorMessage ) ;
127
188
}
128
189
}
129
190
@@ -154,15 +215,19 @@ export default class ScanEol extends Command {
154
215
}
155
216
return sbom ;
156
217
} catch ( error ) {
157
- this . error ( `Failed to scan directory: ${ getErrorMessage ( error ) } ` ) ;
218
+ const errorMessage = getErrorMessage ( error ) ;
219
+ track ( 'CLI Error Encountered' , ( ) => ( { error : errorMessage } ) ) ;
220
+ this . error ( `Failed to scan directory: ${ errorMessage } ` ) ;
158
221
}
159
222
}
160
223
161
224
private getSbomFromFile ( filePath : string ) : CdxBom {
162
225
try {
163
226
return readSbomFromFile ( filePath ) ;
164
227
} catch ( error ) {
165
- this . error ( getErrorMessage ( error ) ) ;
228
+ const errorMessage = getErrorMessage ( error ) ;
229
+ track ( 'CLI Error Encountered' , ( ) => ( { error : errorMessage } ) ) ;
230
+ this . error ( errorMessage ) ;
166
231
}
167
232
}
168
233
}
0 commit comments