diff --git a/bin/paragon-scripts.js b/bin/paragon-scripts.js index dbc9329699..8b35a7c5a4 100755 --- a/bin/paragon-scripts.js +++ b/bin/paragon-scripts.js @@ -5,6 +5,7 @@ const helpCommand = require('../lib/help'); const buildTokensCommand = require('../lib/build-tokens'); const replaceVariablesCommand = require('../lib/replace-variables'); const buildScssCommand = require('../lib/build-scss'); +const { sendTrackInfo } = require('../utils'); const COMMANDS = { /** @@ -181,9 +182,11 @@ const COMMANDS = { try { await executor.executor(commandArgs); + sendTrackInfo('openedx.paragon.cli-command.used', { command, status: 'success' }); } catch (error) { // eslint-disable-next-line no-console console.error(chalk.red.bold('An error occurred:', error.message)); + sendTrackInfo('openedx.paragon.cli-command.used', { command, status: 'error', errorMsg: error.message }); process.exit(1); } })(); diff --git a/component-generator/index.js b/component-generator/index.js index f27712a22e..7f37f7bf9b 100644 --- a/component-generator/index.js +++ b/component-generator/index.js @@ -4,17 +4,17 @@ const path = require('path'); const { COMPONENT_FILES } = require('./constants'); const { validateComponentName, - sendTrackInfo, createFile, addComponentToExports, addComponentToGit, } = require('./utils'); +const { sendTrackInfo } = require('../utils'); program .argument('', 'Component must have a name', validateComponentName) .action((componentName) => { // send data to analytics - sendTrackInfo(componentName); + sendTrackInfo('openedx.paragon.functions.track-generate-component.created', { componentName }); const componentDir = path.resolve(__dirname, `../src/${componentName}`); // create directory for the component files fs.mkdirSync(componentDir); diff --git a/component-generator/utils.js b/component-generator/utils.js index 5d4b4c2585..f742c3bff5 100644 --- a/component-generator/utils.js +++ b/component-generator/utils.js @@ -1,7 +1,6 @@ const { InvalidOptionArgumentError } = require('commander'); const fs = require('fs'); const path = require('path'); -const axios = require('axios'); const { exec } = require('child_process'); require('dotenv').config(); @@ -32,25 +31,6 @@ function validateComponentName(value) { return value; } -/** - * Sends request to the Netlify function to inform about generate-component usage. - * @param {string} componentName - component name - */ -function sendTrackInfo(componentName) { - const { BASE_URL, TRACK_ANONYMOUS_ANALYTICS } = process.env; - if (TRACK_ANONYMOUS_ANALYTICS) { - const url = `${BASE_URL}/.netlify/functions/trackGenerateComponent`; - axios.post(url, { componentName }) - .then(result => { - // eslint-disable-next-line no-console - console.log(`Track info is successfully sent (status ${result.status})`); - }).catch(error => { - // eslint-disable-next-line no-console - console.log(`Track info request failed (${error})`); - }); - } -} - /** * Creates a file for the component based on the template. * Note that 'componentName' string is a reserved placeholder, @@ -97,7 +77,6 @@ function addComponentToGit(componentName) { } exports.validateComponentName = validateComponentName; -exports.sendTrackInfo = sendTrackInfo; exports.createFile = createFile; exports.addComponentToExports = addComponentToExports; exports.addComponentToGit = addComponentToGit; diff --git a/package-lock.json b/package-lock.json index f49d9b1b7f..019fc845d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ ], "dependencies": { "@popperjs/core": "^2.11.4", + "axios": "^0.27.2", "bootstrap": "^4.6.2", "chalk": "^4.1.2", "child_process": "^1.0.2", diff --git a/package.json b/package.json index 8690ee1f6a..7fd4fcfc07 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ }, "dependencies": { "@popperjs/core": "^2.11.4", + "axios": "^0.27.2", "bootstrap": "^4.6.2", "chalk": "^4.1.2", "child_process": "^1.0.2", diff --git a/utils.js b/utils.js new file mode 100644 index 0000000000..667932a4e8 --- /dev/null +++ b/utils.js @@ -0,0 +1,23 @@ +const axios = require('axios'); + +/** + * Sends request to the Netlify function to inform about specified event. + * @param {string} eventId - tracking event id + * @param {object} properties - tracking properties + */ +function sendTrackInfo(eventId, properties) { + const { BASE_URL, TRACK_ANONYMOUS_ANALYTICS } = process.env; + if (TRACK_ANONYMOUS_ANALYTICS) { + const url = `${BASE_URL}/.netlify/functions/sendTrackData`; + axios.post(url, { eventId, properties }) + .then(result => { + // eslint-disable-next-line no-console + console.log(`Track info is successfully sent (status ${result.status})`); + }).catch(error => { + // eslint-disable-next-line no-console + console.log(`Track info request failed (${error})`); + }); + } +} + +module.exports = { sendTrackInfo }; diff --git a/www/netlify/functions/sendAnalyticsData.js b/www/netlify/functions/sendAnalyticsData.js new file mode 100644 index 0000000000..964bf57869 --- /dev/null +++ b/www/netlify/functions/sendAnalyticsData.js @@ -0,0 +1,23 @@ +const { v4: uuidv4 } = require('uuid'); +const Analytics = require('analytics-node'); + +const analytics = new Analytics(process.env.SEGMENT_KEY); + +exports.handler = async function eventHandler(event) { + // Only allow POST + if (event.httpMethod !== 'POST') { + return { statusCode: 405, body: 'Method Not Allowed' }; + } + const { eventId, properties } = JSON.parse(event.body); + // dispatch event to Segment + analytics.track({ + anonymousId: uuidv4(), + event: eventId, + properties, + }); + + return { + statusCode: 200, + body: JSON.stringify({ success: true }), + }; +};