Skip to content
This repository has been archived by the owner on Oct 4, 2024. It is now read-only.

Commit

Permalink
Metrics events all (#327)
Browse files Browse the repository at this point in the history
* Fix test .sh file (remove copy of testsettings)

* Add tracking to all the shell commands

* A few minor fixes + adding comments to unused event types

* Fix lint issues
  • Loading branch information
janedegtiareva authored Apr 24, 2020
1 parent 64ffae3 commit 022f9c2
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 50 deletions.
15 changes: 2 additions & 13 deletions bin/near-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,22 +114,11 @@ const callViewFunction = {
handler: exitOnError(main.callViewFunction)
};

const { spawn } = require('child_process');

const build = {
command: 'build',
desc: 'build your smart contract',
handler: () => {
const gulp = spawn('gulp', [], {shell: process.platform == 'win32'});
gulp.stdout.on('data', function (data) {
console.log(data.toString());
});
gulp.stderr.on('data', function (data) {
console.log(data.toString());
});
gulp.on('exit', function (code) {
process.exit(code);
});
}
handler: exitOnError(main.build)
};

const clean = {
Expand Down
3 changes: 3 additions & 0 deletions commands/call.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const { utils } = nearlib;
const exitOnError = require('../utils/exit-on-error');
const connect = require('../utils/connect');
const inspectResponse = require('../utils/inspect-response');
const eventtracking = require('../utils/eventtracking');

module.exports = {
command: 'call <contractName> <methodName> [args]',
Expand All @@ -22,6 +23,7 @@ module.exports = {
};

async function scheduleFunctionCall(options) {
await eventtracking.track(eventtracking.EVENT_ID_SCHEDULE_FN_CALL_START, { node: options.nodeUrl });
console.log(`Scheduling a call: ${options.contractName}.${options.methodName}(${options.args || ''})` +
(options.amount && options.amount != '0' ? ` with attached ${options.amount} NEAR` : ''));
const near = await connect(options);
Expand All @@ -34,4 +36,5 @@ async function scheduleFunctionCall(options) {
utils.format.parseNearAmount(options.amount));
const result = nearlib.providers.getTransactionLastResult(functionCallResponse);
console.log(inspectResponse(result));
await eventtracking.track(eventtracking.EVENT_ID_SCHEDULE_FN_CALL_END, { node: options.nodeUrl, success: true });
}
4 changes: 2 additions & 2 deletions commands/create-account.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module.exports = {
};

async function createAccount(options) {
await eventtracking.track(eventtracking.EVENT_ID_CREATE_ACCOUNT_START, {});
await eventtracking.track(eventtracking.EVENT_ID_CREATE_ACCOUNT_START, { nodeUrl: options.nodeUrl });
// NOTE: initialBalance is passed as part of config here, parsed in middleware/initial-balance
let near = await connect(options);
let keyPair;
Expand All @@ -48,5 +48,5 @@ async function createAccount(options) {
await near.connection.signer.keyStore.setKey(options.networkId, options.accountId, keyPair);
}
console.log(`Account ${options.accountId} for network "${options.networkId}" was created.`);
await eventtracking.track(eventtracking.EVENT_ID_CREATE_ACCOUNT_SUCCESS, {});
await eventtracking.track(eventtracking.EVENT_ID_CREATE_ACCOUNT_END, { node: options.nodeUrl, success: true });
}
5 changes: 4 additions & 1 deletion commands/dev-deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ const { KeyPair } = require('near-api-js');
const exitOnError = require('../utils/exit-on-error');
const connect = require('../utils/connect');
const { readFile, writeFile } = require('fs').promises;
const eventtracking = require('../utils/eventtracking');

module.exports = {
command: 'dev-deploy [wasmFile]',
desc: 'deploy your smart contract using temporary account (TestNet only)',
builder: (yargs) => yargs
.option('wasmFile',{
.option('wasmFile', {
desc: 'Path to wasm file to deploy',
type: 'string',
default: './out/main.wasm'
Expand All @@ -29,6 +30,7 @@ module.exports = {
};

async function devDeploy(options) {
await eventtracking.track(eventtracking.EVENT_ID_DEV_DEPLOY_START, { node: options.nodeUrl });
const { nodeUrl, helperUrl, masterAccount, wasmFile } = options;

if (!helperUrl && !masterAccount) {
Expand All @@ -43,6 +45,7 @@ async function devDeploy(options) {
const account = await near.account(accountId);
await account.deployContract(contractData);
console.log(`Done deploying to ${accountId}`);
await eventtracking.track(eventtracking.EVENT_ID_DEV_DEPLOY_END, { node: options.nodeUrl, success: true });
}

async function createDevAccountIfNeeded({ near, keyStore, networkId, init }) {
Expand Down
5 changes: 4 additions & 1 deletion commands/generate-key.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
const KeyPair = require('near-api-js').KeyPair;
const exitOnError = require('../utils/exit-on-error');
const eventtracking = require('../utils/eventtracking');

module.exports = {
command: 'generate-key <account-id>',
desc: 'generate key ',
builder: (yargs) => yargs,
handler: exitOnError(async (argv) => {
await eventtracking.track(eventtracking.EVENT_ID_GENERATE_KEY_START, { network: argv.networkId });
let near = await require('../utils/connect')(argv);
if (argv.accountId) {
const { deps: { keyStore }} = near.config;
const { deps: { keyStore } } = near.config;
const existingKey = await keyStore.getKey(argv.networkId, argv.accountId);
if (existingKey) {
console.log(`Account has existing key pair with ${existingKey.publicKey} public key`);
Expand All @@ -18,5 +20,6 @@ module.exports = {
console.log(`Generated key pair with ${keyPair.publicKey} public key`);
}
}
await eventtracking.track(eventtracking.EVENT_ID_GENERATE_KEY_END, { network: argv.networkId, success: true });
})
};
4 changes: 2 additions & 2 deletions commands/tx-status.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module.exports = {
required: true
}),
handler: exitOnError(async (argv) => {
await eventtracking.track(eventtracking.EVENT_ID_TX_STATUS_START, {});
await eventtracking.track(eventtracking.EVENT_ID_TX_STATUS_START, { node: argv.nodeUrl });
const near = await connect(argv);

const hashParts = argv.hash.split(':');
Expand All @@ -35,6 +35,6 @@ module.exports = {
const status = await near.connection.provider.txStatus(bs58.decode(hash), accountId);
console.log(`Transaction ${accountId}:${hash}`);
console.log(inspectResponse(status));
await eventtracking.track(eventtracking.EVENT_ID_TX_STATUS_SUCCESS, {});
await eventtracking.track(eventtracking.EVENT_ID_TX_STATUS_END, { node: argv.nodeUrl, success: true });
})
};
70 changes: 49 additions & 21 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const readline = require('readline');
const URL = require('url').URL;
const chalk = require('chalk'); // colorize output
const open = require('open'); // open URL in default browser
const { spawn } = require('child_process');
const { KeyPair, utils } = require('near-api-js');

const connect = require('./utils/connect');
Expand All @@ -19,35 +20,41 @@ const eventtracking = require('./utils/eventtracking');
// TODO: Fix promisified wrappers to handle error properly

// For smart contract:
exports.clean = async function() {
exports.clean = async function () {
await eventtracking.track(eventtracking.EVENT_ID_CLEAN_START, {});
const rmDirFn = () => {
return new Promise(resolve => {
rimraf(yargs.argv.outDir, response => resolve(response));
});};
});
};
await rmDirFn();
console.log('Clean complete.');
await eventtracking.track(eventtracking.EVENT_ID_CLEAN_END, { success: true });
};

exports.deploy = async function(options) {
exports.deploy = async function (options) {
await eventtracking.track(eventtracking.EVENT_ID_DEPLOY_START, { node: options.nodeUrl });
console.log(
`Starting deployment. Account id: ${options.accountId}, node: ${options.nodeUrl}, helper: ${options.helperUrl}, file: ${options.wasmFile}`);
const near = await connect(options);
const contractData = [...fs.readFileSync(options.wasmFile)];
const account = await near.account(options.accountId);
await account.deployContract(contractData);
await eventtracking.track(eventtracking.EVENT_ID_DEPLOY_END, { node: options.nodeUrl, success: true });
};

exports.callViewFunction = async function(options) {
exports.callViewFunction = async function (options) {
await eventtracking.track(eventtracking.EVENT_ID_CALL_VIEW_FN_START, { node: options.nodeUrl });
console.log(`View call: ${options.contractName}.${options.methodName}(${options.args || ''})`);
const near = await connect(options);
// TODO: Figure out how to run readonly calls without account
const account = await near.account(options.accountId || options.masterAccount || 'register.near');
console.log(inspectResponse(await account.viewFunction(options.contractName, options.methodName, JSON.parse(options.args || '{}'))));
await eventtracking.track(eventtracking.EVENT_ID_CALL_VIEW_FN_END, { node: options.nodeUrl, success: true });
};

// For account:

exports.login = async function(options) {
exports.login = async function (options) {
await eventtracking.track(eventtracking.EVENT_ID_LOGIN_START, { node: options.nodeUrl });
if (!options.walletUrl) {
console.log('Log in is not needed on this environment. Please use appropriate master account for shell operations.');
} else {
Expand Down Expand Up @@ -105,16 +112,16 @@ exports.login = async function(options) {
return await new Promise((resolve) => {
rl.question(
chalk`Please authorize at least one account at the URL above.\n\n` +
chalk`Which account did you authorize for use with NEAR Shell?\n` +
chalk`Which account did you authorize for use with NEAR Shell?\n` +
chalk`{bold Enter it here (if not redirected automatically):}\n`, async (accountId) => {
resolve(accountId);
resolve(accountId);
});
});
};

let accountId;
if (!tempUrl) {
accountId = await getAccountFromConsole();
accountId = await getAccountFromConsole();
} else {
accountId = await new Promise((resolve, reject) => {
let resolved = false;
Expand All @@ -135,10 +142,11 @@ exports.login = async function(options) {
console.error('Failed to verify accountId.', error.message);
}
}
await eventtracking.track(eventtracking.EVENT_ID_LOGIN_END, { node: options.nodeUrl, success: true });
};

exports.viewAccount = async function(options) {
await eventtracking.track(eventtracking.EVENT_ID_ACCOUNT_STATE_START, {});
exports.viewAccount = async function (options) {
await eventtracking.track(eventtracking.EVENT_ID_ACCOUNT_STATE_START, { node: options.nodeUrl });
let near = await connect(options);
let account = await near.account(options.accountId);
let state = await account.state();
Expand All @@ -147,41 +155,61 @@ exports.viewAccount = async function(options) {
}
console.log(`Account ${options.accountId}`);
console.log(inspectResponse(state));
await eventtracking.track(eventtracking.EVENT_ID_ACCOUNT_STATE_SUCCESS, {});
await eventtracking.track(eventtracking.EVENT_ID_ACCOUNT_STATE_END, { node: options.nodeUrl, success: true });
};

exports.deleteAccount = async function(options) {
await eventtracking.track(eventtracking.EVENT_ID_DELETE_ACCOUNT_START, {});
exports.deleteAccount = async function (options) {
await eventtracking.track(eventtracking.EVENT_ID_DELETE_ACCOUNT_START, { node: options.nodeUrl });

console.log(
`Deleting account. Account id: ${options.accountId}, node: ${options.nodeUrl}, helper: ${options.helperUrl}, beneficiary: ${options.beneficiaryId}`);
const near = await connect(options);
const account = await near.account(options.accountId);
await account.deleteAccount(options.beneficiaryId);
console.log(`Account ${options.accountId} for network "${options.networkId}" was deleted.`);
await eventtracking.track(eventtracking.EVENT_ID_DELETE_ACCOUNT_SUCCESS, {});
await eventtracking.track(eventtracking.EVENT_ID_DELETE_ACCOUNT_END, { node: options.nodeUrl, success: true });
};

exports.keys = async function(options) {
await eventtracking.track(eventtracking.EVENT_ID_ACCOUNT_KEYS_START, {});
exports.keys = async function (options) {
await eventtracking.track(eventtracking.EVENT_ID_ACCOUNT_KEYS_START, { node: options.nodeUrl });
let near = await connect(options);
let account = await near.account(options.accountId);
let accessKeys = await account.getAccessKeys();
console.log(`Keys for account ${options.accountId}`);
console.log(inspectResponse(accessKeys));
await eventtracking.track(eventtracking.EVENT_ID_ACCOUNT_KEYS_SUCCESS, {});
await eventtracking.track(eventtracking.EVENT_ID_ACCOUNT_KEYS_END, { node: options.nodeUrl, success: true });
};

exports.sendMoney = async function(options) {
exports.sendMoney = async function (options) {
await eventtracking.track(eventtracking.EVENT_ID_SEND_TOKENS_START, { node: options.nodeUrl, amount: options.amount });
console.log(`Sending ${options.amount} NEAR to ${options.receiver} from ${options.sender}`);
const near = await connect(options);
const account = await near.account(options.sender);
console.log(inspectResponse(await account.sendMoney(options.receiver, utils.format.parseNearAmount(options.amount))));
await eventtracking.track(eventtracking.EVENT_ID_SEND_TOKENS_END, { node: options.nodeUrl, success: true });
};

exports.stake = async function(options) {
exports.stake = async function (options) {
await eventtracking.track(eventtracking.EVENT_ID_STAKE_START, { node: options.nodeUrl, amount: options.amount });
console.log(`Staking ${options.amount} (${utils.format.parseNearAmount(options.amount)}) on ${options.accountId} with public key = ${options.stakingKey}.`);
const near = await connect(options);
const account = await near.account(options.accountId);
const result = await account.stake(options.stakingKey, utils.format.parseNearAmount(options.amount));
console.log(inspectResponse(result));
await eventtracking.track(eventtracking.EVENT_ID_STAKE_END, { node: options.nodeUrl, success: true });
};

exports.build = async function () {
await eventtracking.track(eventtracking.EVENT_ID_BUILD_START, {});
const gulp = spawn('gulp', [], { shell: process.platform == 'win32' });
gulp.stdout.on('data', function (data) {
console.log(data.toString());
});
gulp.stderr.on('data', function (data) {
console.log(data.toString());
});
gulp.on('exit', function (code) {
process.exit(code);
});
await eventtracking.track(eventtracking.EVENT_ID_BUILD_END, { success: true });
};
39 changes: 29 additions & 10 deletions utils/eventtracking.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const track = async (eventType, eventProperties) => {
distinct_id: shellSettings[TRACKING_SESSION_ID_KEY]
};
Object.assign(mixPanelProperties, eventProperties);
mixpanel.track(eventType, mixPanelProperties);
await mixpanel.track(eventType, mixPanelProperties);
}
catch (e) {
console.log('Warning: problem while sending developer event tracking data. This is not critical. Error: ', e);
Expand All @@ -66,20 +66,39 @@ const track = async (eventType, eventProperties) => {

module.exports = {
track,

// Event ids used in mixpanel. Note that we want to mention shell to make it very easy to tell that an event came from shell,
// since mixpanel might be used for other components as well.
EVENT_ID_ACCOUNT_STATE_START: 'shell_account_state_start',
EVENT_ID_ACCOUNT_STATE_SUCCESS: 'shell_account_state_success',
EVENT_ID_ACCOUNT_STATE_END: 'shell_account_state_end',
EVENT_ID_DELETE_ACCOUNT_START: 'shell_delete_account_start',
EVENT_ID_DELETE_ACCOUNT_SUCCESS: 'shell_delete_account_success',
EVENT_ID_DELETE_ACCOUNT_END: 'shell_delete_account_end',
EVENT_ID_ACCOUNT_KEYS_START: 'shell_account_keys_start',
EVENT_ID_ACCOUNT_KEYS_SUCCESS: 'shell_account_keys_success',
EVENT_ID_ACCOUNT_KEYS_END: 'shell_account_keys_end',
EVENT_ID_TX_STATUS_START: 'shell_tx_status_start',
EVENT_ID_TX_STATUS_SUCCESS: 'shell_tx_status_success',
EVENT_ID_LOGIN: 'shell_login',
EVENT_ID_DEPLOY: 'shell_deploy',
EVENT_ID_DEV_DEPLOY: 'shell_dev_deploy',
EVENT_ID_TX_STATUS_END: 'shell_tx_status_end',
EVENT_ID_BUILD_START: 'shell_build_start',
EVENT_ID_BUILD_END: 'shell_build_end',
EVENT_ID_LOGIN_START: 'shell_login_start',
EVENT_ID_LOGIN_END: 'shell_login_end',
EVENT_ID_DEPLOY_START: 'shell_deploy_start',
EVENT_ID_DEPLOY_END: 'shell_deploy_end',
EVENT_ID_DEV_DEPLOY_START: 'shell_dev_deploy_start',
EVENT_ID_DEV_DEPLOY_END: 'shell_dev_deploy_end',
EVENT_ID_CALL_VIEW_FN_START: 'shell_call_view_function_start',
EVENT_ID_CALL_VIEW_FN_END: 'shell_call_view_function_end',
EVENT_ID_SCHEDULE_FN_CALL_START: 'shell_schedule_fn_call_start',
EVENT_ID_SCHEDULE_FN_CALL_END: 'shell_schedule_fn_call_end',
EVENT_ID_SEND_TOKENS_START: 'shell_send_tokens_start',
EVENT_ID_SEND_TOKENS_END: 'shell_send_tokens_end',
EVENT_ID_CLEAN_START: 'shell_clean_start',
EVENT_ID_CLEAN_END: 'shell_clean_end',
EVENT_ID_STAKE_START: 'event_id_stake_start',
EVENT_ID_STAKE_END: 'event_id_stake_end',
EVENT_ID_CREATE_ACCOUNT_START: 'shell_create_account_start',
EVENT_ID_CREATE_ACCOUNT_SUCCESS: 'shell_create_account_success'
EVENT_ID_CREATE_ACCOUNT_END: 'shell_create_account_end',
EVENT_ID_REPL_START: 'shell_repl_start', // repl is currently broken so this is not used.
EVENT_ID_REPL_END: 'shell_repl_end',
EVENT_ID_GENERATE_KEY_START: 'shell_generate_key_start',
EVENT_ID_GENERATE_KEY_END: 'shell_id_generate_key_end',
EVENT_ID_ERROR: 'shell_error' // This is not used right now because of mixpanel bug.
};

0 comments on commit 022f9c2

Please sign in to comment.