-
Notifications
You must be signed in to change notification settings - Fork 0
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
Add telemetry enable/disable command #2
base: main
Are you sure you want to change the base?
Changes from all commits
f48f010
6bdda48
97d460b
232f4d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'@vercel-internals/types': patch | ||
'vercel': patch | ||
--- | ||
|
||
Add a command for enabling and disabling telemetry. Telemetry collection is not currently enabled and when it is, will be a major version bump for the CLI. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
export const telemetryCommand = { | ||
name: 'telemetry', | ||
description: 'Allows you to enable or disable telemetry collection.', | ||
arguments: [ | ||
{ | ||
name: 'command', | ||
required: false, | ||
}, | ||
], | ||
subcommands: [ | ||
{ | ||
name: 'status', | ||
description: 'Shows whether telemetry collection is enabled or disabled', | ||
arguments: [], | ||
options: [], | ||
examples: [], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Add an example for the 'status' subcommand to improve user guidance |
||
}, | ||
{ | ||
name: 'enable', | ||
description: 'Enables telemetry collection', | ||
arguments: [], | ||
options: [], | ||
examples: [], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Add an example for the 'enable' subcommand to improve user guidance |
||
}, | ||
{ | ||
name: 'disable', | ||
description: 'Disables telemetry collection', | ||
arguments: [], | ||
options: [], | ||
examples: [], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Add an example for the 'disable' subcommand to improve user guidance |
||
}, | ||
], | ||
options: [], | ||
examples: [], | ||
} as const; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import Client from '../../util/client'; | ||
import { writeToConfigFile } from '../../util/config/files'; | ||
import status from './status'; | ||
|
||
export default async function disable(client: Client) { | ||
client.config = { | ||
...client.config, | ||
telemetry: { | ||
...client.config.telemetry, | ||
enabled: false, | ||
}, | ||
}; | ||
|
||
writeToConfigFile(client.output, client.config); | ||
await status(client); | ||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import Client from '../../util/client'; | ||
import { writeToConfigFile } from '../../util/config/files'; | ||
import status from './status'; | ||
|
||
export default async function enable(client: Client) { | ||
client.config = { | ||
...client.config, | ||
telemetry: { | ||
...client.config.telemetry, | ||
enabled: true, | ||
}, | ||
}; | ||
|
||
writeToConfigFile(client.output, client.config); | ||
await status(client); | ||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { handleError } from '../../util/error'; | ||
import Client from '../../util/client'; | ||
import { parseArguments } from '../../util/get-args'; | ||
import getSubcommand from '../../util/get-subcommand'; | ||
import { help } from '../help'; | ||
import status from './status'; | ||
import enable from './enable'; | ||
import disable from './disable'; | ||
import { telemetryCommand } from './command'; | ||
import { getFlagsSpecification } from '../../util/get-flags-specification'; | ||
import chalk from 'chalk'; | ||
|
||
const COMMAND_CONFIG = { | ||
status: ['status'], | ||
enable: ['enable'], | ||
disable: ['disable'], | ||
}; | ||
|
||
export default async function telemetry(client: Client) { | ||
let parsedArguments; | ||
|
||
const flagsSpecification = getFlagsSpecification(telemetryCommand.options); | ||
|
||
try { | ||
parsedArguments = parseArguments(client.argv.slice(2), flagsSpecification); | ||
} catch (err) { | ||
handleError(err); | ||
return 1; | ||
} | ||
|
||
if (parsedArguments.flags['--help']) { | ||
client.output.print( | ||
help(telemetryCommand, { columns: client.stderr.columns }) | ||
); | ||
} | ||
Comment on lines
+31
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. logic: The function returns undefined after printing help. Consider returning 0 to indicate successful execution. |
||
|
||
const { subcommand } = getSubcommand( | ||
parsedArguments.args.slice(1), | ||
COMMAND_CONFIG | ||
); | ||
Comment on lines
+37
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Consider using parsedArguments.args[1] instead of slicing, as you're only interested in the second argument. |
||
|
||
switch (subcommand) { | ||
case 'status': | ||
return status(client); | ||
case 'enable': | ||
return enable(client); | ||
case 'disable': | ||
return disable(client); | ||
default: { | ||
const errorMessage = | ||
parsedArguments.args.length !== 2 | ||
? `Invalid number of arguments` | ||
: `Invalid subcommand`; | ||
client.output.print( | ||
`${chalk.red('Error')}: ${errorMessage}. See help instructions for usage:\n` | ||
); | ||
client.output.print( | ||
help(telemetryCommand, { columns: client.stderr.columns }) | ||
); | ||
return 2; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import chalk from 'chalk'; | ||
import Client from '../../util/client'; | ||
|
||
export default async function status(client: Client) { | ||
const status: 'disabled' | 'enabled' = | ||
client.config.telemetry?.enabled === false ? 'disabled' : 'enabled'; | ||
Comment on lines
+5
to
+6
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Consider using a boolean type for |
||
|
||
const message = | ||
status === 'disabled' ? chalk.red('Disabled') : chalk.green('Enabled'); | ||
await client.output.print( | ||
`\n${chalk.bold('Telemetry status')}: ${message}\n\n` | ||
); | ||
|
||
// TODO: enable this message when we have a proper URL | ||
// const learnMoreMessage = `\n\nLearn more: ${chalk.cyan(`https://vercel.com/some-link`)}\n`; | ||
const learnMoreMessage = ``; | ||
const optedInMessage = `You have opted in to Vercel CLI telemetry${learnMoreMessage}`; | ||
const optedOutMessage = `You have opted out of Vercel CLI telemetry\nNo data will be collected from your machine${learnMoreMessage}`; | ||
const optedInorOutMessage = | ||
status === 'disabled' ? optedOutMessage : optedInMessage; | ||
await client.output.print(optedInorOutMessage); | ||
|
||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import { randomUUID } from 'node:crypto'; | ||
import type { Output } from '../output'; | ||
import { GlobalConfig } from '@vercel-internals/types'; | ||
|
||
const LogLabel = `['telemetry']:`; | ||
|
||
|
@@ -113,12 +114,18 @@ export class TelemetryEventStore { | |
private output: Output; | ||
private isDebug: boolean; | ||
private sessionId: string; | ||
private config: GlobalConfig['telemetry']; | ||
|
||
constructor(opts: { output: Output; isDebug?: boolean }) { | ||
constructor(opts: { | ||
output: Output; | ||
isDebug?: boolean; | ||
config: GlobalConfig['telemetry']; | ||
}) { | ||
Comment on lines
+119
to
+123
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Consider making |
||
this.isDebug = opts.isDebug || false; | ||
this.output = opts.output; | ||
this.sessionId = randomUUID(); | ||
this.events = []; | ||
this.config = opts.config; | ||
} | ||
|
||
add(event: Event) { | ||
|
@@ -134,12 +141,19 @@ export class TelemetryEventStore { | |
this.events = []; | ||
} | ||
|
||
enabled() { | ||
return this.config?.enabled === false ? false : true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Consider simplifying this to |
||
} | ||
|
||
save() { | ||
if (this.isDebug) { | ||
this.output.debug(`${LogLabel} Flushing Events`); | ||
this.events.forEach(event => { | ||
this.output.debug(JSON.stringify(event)); | ||
}); | ||
} | ||
if (this.enabled()) { | ||
// send events to the server | ||
} | ||
Comment on lines
+155
to
+157
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. logic: Implement the logic to send events to the server |
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Consider adding a comment explaining the purpose of the telemetry command for better code documentation