Skip to content

Commit

Permalink
Merge pull request #2139 from snyk/test/analytics
Browse files Browse the repository at this point in the history
Migrate Tap tests for Analytics to Jest
  • Loading branch information
maxjeffos committed Aug 9, 2021
2 parents 1506aaf + 4ac3d5f commit 755f586
Show file tree
Hide file tree
Showing 12 changed files with 988 additions and 594 deletions.
1 change: 1 addition & 0 deletions .circleci/config.yml
Expand Up @@ -308,6 +308,7 @@ jobs:
<<: *defaults
docker:
- image: circleci/node:<< parameters.node_version >>
resource_class: large
steps:
- install_sdkman_linux
- install_jdk_linux
Expand Down
66 changes: 66 additions & 0 deletions src/lib/analytics/getStandardData.ts
@@ -0,0 +1,66 @@
import * as version from '../version';
import { v4 as uuidv4 } from 'uuid';
import * as os from 'os';
const osName = require('os-name');
import * as crypto from 'crypto';
import { isCI } from '../is-ci';
import {
getIntegrationName,
getIntegrationVersion,
getIntegrationEnvironment,
getIntegrationEnvironmentVersion,
getCommandVersion,
} from './sources';

import { StandardAnalyticsData } from './types';
import { MetricsCollector } from '../metrics';
import * as createDebug from 'debug';
import { ArgsOptions } from '../../cli/args';

const debug = createDebug('snyk');
const START_TIME = Date.now();

function getMetrics(durationMs: number): any[] | undefined {
try {
const networkTime = MetricsCollector.NETWORK_TIME.getTotal();
const cpuTime = durationMs - networkTime;
MetricsCollector.CPU_TIME.createInstance().setValue(cpuTime);
return MetricsCollector.getAllMetrics();
} catch (err) {
debug('Error with metrics', err);
}
}

export async function getStandardData(
args: ArgsOptions[],
): Promise<StandardAnalyticsData> {
const isStandalone = version.isStandaloneBuild();
const snykVersion = await version.getVersion();
const seed = uuidv4();
const shasum = crypto.createHash('sha1');
const environment = isStandalone
? {}
: {
npmVersion: await getCommandVersion('npm'),
};
const durationMs = Date.now() - START_TIME;

const metrics = getMetrics(durationMs);

const data = {
os: osName(os.platform(), os.release()),
version: snykVersion,
nodeVersion: process.version,
standalone: isStandalone,
integrationName: getIntegrationName(args),
integrationVersion: getIntegrationVersion(args),
integrationEnvironment: getIntegrationEnvironment(args),
integrationEnvironmentVersion: getIntegrationEnvironmentVersion(args),
id: shasum.update(seed).digest('hex'),
ci: isCI(),
environment,
durationMs,
metrics,
};
return data;
}
69 changes: 12 additions & 57 deletions src/lib/analytics/index.ts
@@ -1,27 +1,13 @@
import { v4 as uuidv4 } from 'uuid';
const snyk = require('../../lib');
const config = require('../config');
const version = require('../version');
import { makeRequest } from '../request';
const {
getIntegrationName,
getIntegrationVersion,
getIntegrationEnvironment,
getIntegrationEnvironmentVersion,
getCommandVersion,
} = require('./sources');
const isCI = require('../is-ci').isCI;
const debug = require('debug')('snyk');
const os = require('os');
const osName = require('os-name');
const crypto = require('crypto');
const stripAnsi = require('strip-ansi');
import * as needle from 'needle';
const { MetricsCollector } = require('../metrics');
import { getStandardData } from './getStandardData';

const metadata = {};
// analytics module is required at the beginning of the CLI run cycle
const startTime = Date.now();

/**
*
Expand Down Expand Up @@ -59,10 +45,10 @@ export function allowAnalytics(): boolean {
/**
* Actually send the analytics to the backend. This can be used standalone to send only the data
* given by the data parameter, or called from {@link addDataAndSend}.
* @param data the analytics data to send to the backend.
* @param customData the analytics data to send to the backend.
*/
export async function postAnalytics(
data,
customData,
): Promise<void | { res: needle.NeedleResponse; body: any }> {
// if the user opt'ed out of analytics, then let's bail out early
// ths applies to all sending to protect user's privacy
Expand All @@ -72,60 +58,29 @@ export async function postAnalytics(
}

try {
const isStandalone = version.isStandaloneBuild();
const snykVersion = await version.getVersion();

data.version = snykVersion;
data.os = osName(os.platform(), os.release());
data.nodeVersion = process.version;
data.standalone = isStandalone;
data.integrationName = getIntegrationName(data.args);
data.integrationVersion = getIntegrationVersion(data.args);
data.integrationEnvironment = getIntegrationEnvironment(data.args);
data.integrationEnvironmentVersion = getIntegrationEnvironmentVersion(
data.args,
);

const seed = uuidv4();
const shasum = crypto.createHash('sha1');
data.id = shasum.update(seed).digest('hex');
const standardData = await getStandardData(customData.args);
const analyticsData = {
...customData,
...standardData,
};
debug('analytics', JSON.stringify(analyticsData, null, ' '));

const headers = {};
if (snyk.api) {
headers['authorization'] = 'token ' + snyk.api;
}

data.ci = isCI();

data.environment = {};
if (!isStandalone) {
data.environment.npmVersion = await getCommandVersion('npm');
}

data.durationMs = Date.now() - startTime;

try {
const networkTime = MetricsCollector.NETWORK_TIME.getTotal();
const cpuTime = data.durationMs - networkTime;
MetricsCollector.CPU_TIME.createInstance().setValue(cpuTime);
data.metrics = MetricsCollector.getAllMetrics();
} catch (err) {
debug('Error with metrics', err);
}

const queryStringParams = {};
if (data.org) {
queryStringParams['org'] = data.org;
if (analyticsData.org) {
queryStringParams['org'] = analyticsData.org;
}

debug('analytics', JSON.stringify(data, null, ' '));

const queryString =
Object.keys(queryStringParams).length > 0 ? queryStringParams : undefined;

return makeRequest({
body: {
data: data,
data: analyticsData,
},
qs: queryString,
url: config.API + '/analytics/cli',
Expand Down
19 changes: 19 additions & 0 deletions src/lib/analytics/types.ts
@@ -0,0 +1,19 @@
export type Environment = {
npmVersion?: string | undefined;
};

export type StandardAnalyticsData = {
version: string;
os: string;
nodeVersion: string;
standalone: boolean;
integrationName: string;
integrationVersion: string;
integrationEnvironment: string;
integrationEnvironmentVersion: string;
id: string;
ci: boolean;
environment: Environment;
durationMs: number;
metrics: any[] | undefined;
};

0 comments on commit 755f586

Please sign in to comment.