UNPKG

ask-cli

Version:

Alexa Skills Kit (ASK) Command Line Interfaces

212 lines (211 loc) 6.87 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MetricClient = exports.MetricAction = exports.MetricActionResult = void 0; const uuid_1 = require("uuid"); const axios_1 = __importDefault(require("axios")); const app_config_1 = __importDefault(require("../../model/app-config")); const profile_helper_1 = __importDefault(require("../../utils/profile-helper")); const constants_1 = require("../../utils/constants"); const package_json_1 = __importDefault(require("../../../package.json")); exports.MetricActionResult = { SUCCESS: "Success", FAILURE: "Failure", }; /** * Metric action includes the name and results of CLI command. */ class MetricAction { /** * @constructor * @param name - The action name. * @param type - The action type. */ constructor(name, type) { this.endTime = null; this.failureMessage = ""; this.name = name; this.result = null; this.startTime = new Date(); this.type = type; this.id = (0, uuid_1.v4)(); this.options = []; this.optionData = {}; this._ended = false; } /** * Add option to list, store value only if in {@link METRICS.STOREABLE_KEYS} * @param optionName name of the option * @param optionValue value of the option */ setOption(optionName, optionValue) { const schemaOption = optionName.split("-").join("_"); this.options.push(schemaOption); if (constants_1.METRICS.STOREABLE_KEYS.includes(schemaOption)) { this.optionData[schemaOption] = optionValue; } } /** * Closes action * @param error Error object or string indicating error. */ end(error = null) { if (this._ended) return; // if Error object extract error message, // otherwise error message string or null was passed as a parameter const errorMessage = error && error instanceof Error ? error.message : error; this.result = errorMessage ? exports.MetricActionResult.FAILURE : exports.MetricActionResult.SUCCESS; this.failureMessage = errorMessage || ""; this.endTime = new Date(); this._ended = true; } /** * Implementation of custom toJSON method to modify serialization with JSON.stringify */ toJSON() { return { end_time: this.endTime, failure_message: this.failureMessage, name: this.name, result: this.result, start_time: this.startTime, type: this.type, id: this.id, options: this.options, ...this.optionData, }; } } exports.MetricAction = MetricAction; /** * Client that communicates with telemetry endpoint. */ class MetricClient { /** * @constructor */ constructor() { this.httpClient = axios_1.default.create({ timeout: 3000, headers: { "Content-Type": "text/plain" }, }); this.serverUrl = constants_1.METRICS.ENDPOINT; this.postRetries = 3; this.enabled = this._isEnabled(); // initialize data this.data = { version: package_json_1.default.version, machineId: this._getMachineId(), timeStarted: new Date(), newUser: false, timeUploaded: null, clientId: package_json_1.default.name, actions: [], }; } /** * Starts action * @param name - The action name * @param type - The action type * @return the metric action that was started, {@link MetricAction} */ startAction(name, type) { const action = new MetricAction(name, type); this.data.actions.push(action); return action; } /** * Set option for the most recently started action * @param optionName name of the option * @param optionValue value of the option */ setOption(optionName, optionValue) { const actions = this.data.actions; if (actions.length) { actions[actions.length - 1].setOption(optionName, optionValue); } } /** * Returns current data store in the metric client * @return the metric data, {@link MetricClientData} */ getData() { return this.data; } /** * Sends data to the metric server * @param error - Error object or string indicating error. * @returns whether data was sent successfully */ async sendData(error = null) { if (!this.enabled) { this.data.actions = []; return { success: true }; } this.data.actions.forEach((action) => action.end(error)); try { await this._upload(); this.data.actions = []; return { success: true }; } catch (_a) { return { success: false }; } } /** * Implementation of custom toJSON method to modify serialization with JSON.stringify */ toJSON() { return { version: this.data.version, machine_id: this.data.machineId, time_started: this.data.timeStarted, new_user: this.data.newUser, time_uploaded: this.data.timeUploaded, client_id: this.data.clientId, actions: this.data.actions, }; } async _upload() { this.data.timeUploaded = new Date(); const payload = JSON.stringify({ payload: this }); const postPromise = () => this.httpClient.post(this.serverUrl, payload); await this._retry(this.postRetries, postPromise); } async _retry(retries, func) { try { await func(); } catch (error) { if (retries == 1) throw error; await this._retry(retries - 1, func); } } _isEnabled() { if (profile_helper_1.default.isEnvProfile()) return true; if (process.env.ASK_SHARE_USAGE === "false") return false; if (!app_config_1.default.configFileExists()) return false; new app_config_1.default(); return app_config_1.default.getInstance().getShareUsage(); } _getMachineId() { if (!this.enabled) return ""; if (profile_helper_1.default.isEnvProfile()) return "all_environmental"; const appConfig = app_config_1.default.getInstance(); if (!appConfig.getMachineId()) { appConfig.setMachineId((0, uuid_1.v4)()); appConfig.write(); } return appConfig.getMachineId(); } } exports.MetricClient = MetricClient;