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

Metrics events all #327

Merged
merged 5 commits into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
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 });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. We don't have the amount on the success here, but that's not a hard requirement imo

};

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.
};