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

Adds a flag 'track' to allow users to configure analytics with flags #1450

Merged
merged 7 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions cli/analytics.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
import yargs from "yargs";

import Analytics from "analytics-node";
import { getConfigSettings, getConfigSettingsPath, upsertConfigSettings } from "df/cli/config";
import { ynQuestion } from "df/cli/console";
import { v4 as uuidv4 } from "uuid";
import {getConfigSettings, getConfigSettingsPath, upsertConfigSettings} from "df/cli/config";
import {ynQuestion} from "df/cli/console";
import {INamedOption} from "df/cli/yargswrapper";
import {v4 as uuidv4} from "uuid";

export const noTrackOption: INamedOption<yargs.Options> = {
GJMcGowan marked this conversation as resolved.
Show resolved Hide resolved
name: "no-track",
option: {
describe: `Disables analytics without asking the user. A settings.json file will be written at ${getConfigSettingsPath()} to store this setting`,
type: "boolean",
default: false
}
};

const analytics = new Analytics("eR24ln3MniE3TKZXkvAkOGkiSN02xXqw");

let currentCommand: string;
let allowAnonymousAnalytics: boolean;

export async function maybeConfigureAnalytics() {
export async function maybeConfigureAnalytics(noTrack: boolean) {
const settings = await getConfigSettings();
// We should only ask if users want to track analytics if they are in an interactive terminal;
GJMcGowan marked this conversation as resolved.
Show resolved Hide resolved
if (!process.stdout.isTTY) {
return;
}
if (settings.allowAnonymousAnalytics !== undefined) {
allowAnonymousAnalytics = settings.allowAnonymousAnalytics;
return;
}
if (noTrack) {
allowAnonymousAnalytics = false;
return;
}
GJMcGowan marked this conversation as resolved.
Show resolved Hide resolved

const optInResponse = ynQuestion(
`
To help improve the quality of our products, we collect anonymized usage data and anonymized stacktraces when crashes are encountered.
Expand All @@ -28,12 +47,13 @@ Would you like to opt-in to anonymous usage and error tracking?`,
allowAnonymousAnalytics: optInResponse,
anonymousUserId: uuidv4()
});
allowAnonymousAnalytics = optInResponse;
}

export async function trackCommand(command: string) {
currentCommand = command;
const config = await getConfigSettings();
if (!config.allowAnonymousAnalytics) {
if (!allowAnonymousAnalytics) {
return;
}
GJMcGowan marked this conversation as resolved.
Show resolved Hide resolved
await new Promise(resolve => {
Expand All @@ -55,7 +75,7 @@ export async function trackCommand(command: string) {

export async function trackError() {
const config = await getConfigSettings();
if (!config.allowAnonymousAnalytics) {
if (!allowAnonymousAnalytics) {
return;
}
GJMcGowan marked this conversation as resolved.
Show resolved Hide resolved
await new Promise(resolve => {
Expand Down
20 changes: 12 additions & 8 deletions cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { build, compile, credentials, init, install, run, table, test } from "df
import { CREDENTIALS_FILENAME } from "df/api/commands/credentials";
import * as dbadapters from "df/api/dbadapters";
import { prettyJsonStringify } from "df/api/utils";
import { trackError } from "df/cli/analytics";
import {noTrackOption, trackError} from "df/cli/analytics";
import {
print,
printCompiledGraph,
Expand Down Expand Up @@ -242,6 +242,7 @@ export function runCli() {
description: "Create a new dataform project.",
positionalOptions: [warehouseOption, projectDirOption],
options: [
noTrackOption,
{
name: defaultDatabaseOptionName,
option: {
Expand Down Expand Up @@ -316,7 +317,7 @@ export function runCli() {
format: `install [${projectDirMustExistOption.name}]`,
description: "Install a project's NPM dependencies.",
positionalOptions: [projectDirMustExistOption],
options: [],
options: [noTrackOption],
processFn: async argv => {
print("Installing NPM dependencies...\n");
await install(argv[projectDirMustExistOption.name]);
Expand All @@ -329,6 +330,7 @@ export function runCli() {
description: `Create a ${credentials.CREDENTIALS_FILENAME} file for Dataform to use when accessing your warehouse.`,
positionalOptions: [warehouseOption, projectDirMustExistOption],
options: [
noTrackOption,
{
name: testConnectionOptionName,
option: {
Expand Down Expand Up @@ -414,7 +416,8 @@ export function runCli() {
schemaSuffixOverrideOption,
jsonOutputOption,
varsOption,
timeoutOption
timeoutOption,
noTrackOption
],
processFn: async argv => {
const projectDir = argv[projectDirMustExistOption.name];
Expand Down Expand Up @@ -503,7 +506,7 @@ export function runCli() {
format: `test [${projectDirMustExistOption.name}]`,
description: "Run the dataform project's unit tests on the configured data warehouse.",
positionalOptions: [projectDirMustExistOption],
options: [credentialsOption, varsOption, timeoutOption],
options: [credentialsOption, varsOption, timeoutOption, noTrackOption],
processFn: async argv => {
print("Compiling...\n");
const compiledGraph = await compile({
Expand Down Expand Up @@ -574,7 +577,8 @@ export function runCli() {
credentialsOption,
jsonOutputOption,
varsOption,
timeoutOption
timeoutOption,
noTrackOption
],
processFn: async argv => {
if (!argv[jsonOutputOption.name]) {
Expand Down Expand Up @@ -692,7 +696,7 @@ export function runCli() {
format: `format [${projectDirMustExistOption.name}]`,
description: "Format the dataform project's files.",
positionalOptions: [projectDirMustExistOption],
options: [],
options: [noTrackOption],
processFn: async argv => {
const filenames = glob.sync("{definitions,includes}/**/*.{js,sqlx}", {
cwd: argv[projectDirMustExistOption.name]
Expand Down Expand Up @@ -722,7 +726,7 @@ export function runCli() {
format: `listtables <${warehouseOption.name}>`,
description: "List tables on the configured data warehouse.",
positionalOptions: [warehouseOption],
options: [credentialsOption],
options: [credentialsOption, noTrackOption],
processFn: async argv => {
const readCredentials = credentials.read(
argv[warehouseOption.name],
Expand Down Expand Up @@ -757,7 +761,7 @@ export function runCli() {
}
}
],
options: [credentialsOption],
options: [credentialsOption, noTrackOption],
processFn: async argv => {
const readCredentials = credentials.read(
argv[warehouseOption.name],
Expand Down
4 changes: 2 additions & 2 deletions cli/yargswrapper.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import yargs from "yargs";

import { maybeConfigureAnalytics, trackCommand } from "df/cli/analytics";
import {maybeConfigureAnalytics, noTrackOption, trackCommand} from "df/cli/analytics";

export interface ICli {
commands: ICommand[];
Expand Down Expand Up @@ -28,7 +28,7 @@ export function createYargsCli(cli: ICli) {
command.description,
(yargsChainer: yargs.Argv) => createOptionsChain(yargsChainer, command),
async (argv: { [argumentName: string]: any }) => {
await maybeConfigureAnalytics();
await maybeConfigureAnalytics(argv[noTrackOption.name]);
const analyticsTrack = trackCommand(command.format.split(" ")[0]);
const exitCode = await command.processFn(argv);
let timer: NodeJS.Timer;
Expand Down