appcenter-cli
Version:
Command line tool for Visual Studio App Center
210 lines (209 loc) • 10.9 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var ShowCommand_1;
Object.defineProperty(exports, "__esModule", { value: true });
const commandline_1 = require("../../../util/commandline");
const interaction_1 = require("../../../util/interaction");
const util_1 = require("util");
const _ = require("lodash");
const date_parsing_helper_1 = require("../lib/date-parsing-helper");
const percent_change_helper_1 = require("../lib/percent-change-helper");
const analytics_constants_1 = require("../lib/analytics-constants");
const debug = require("debug")("appcenter-cli:commands:analytics:events:show");
const pLimit = require("p-limit");
let ShowCommand = ShowCommand_1 = class ShowCommand extends commandline_1.AppCommand {
constructor(args) {
super(args);
interaction_1.supportsCsv(this.additionalSupportedOutputFormats);
}
run(client) {
return __awaiter(this, void 0, void 0, function* () {
const app = this.app;
const appVersion = this.toArrayWithSingleElement(this.appVersion);
const eventName = this.toArrayWithSingleElement(this.eventName);
const startDate = date_parsing_helper_1.parseDate(this.startDate, new Date(new Date().setHours(0, 0, 0, 0)), `start date value ${this.startDate} is not a valid date string`);
const endDate = date_parsing_helper_1.parseDate(this.endDate, new Date(), `end date value ${this.endDate} is not a valid date string`);
const eventCount = this.getEventCount();
const events = yield interaction_1.out.progress(`Loading statistics...`, this.getEvents(client, app, startDate, endDate, eventCount, this.properties, appVersion, eventName));
this.outputStatistics(events);
return commandline_1.success();
});
}
toArrayWithSingleElement(value) {
return !_.isNil(value) ? [value] : undefined;
}
getEventCount() {
const eventCount = Number(this.eventCount);
if (Number.isSafeInteger(eventCount) && eventCount >= 0) {
return eventCount;
}
else {
throw commandline_1.failure(commandline_1.ErrorCodes.InvalidParameter, "--number-of-events should be non-negative integer");
}
}
getEvents(client, app, startDate, endDate, eventCount, loadProperties, appVersions, eventNames) {
return __awaiter(this, void 0, void 0, function* () {
let eventsStatistics;
try {
const result = yield client.analytics.events(startDate, app.ownerName, app.appName, {
end: endDate,
versions: appVersions,
orderby: "count desc",
top: eventCount,
skip: 0,
eventName: eventNames,
inlinecount: "allpages",
});
eventsStatistics = result.events.map((event) => ({
name: event.name,
count: event.count,
countChange: percent_change_helper_1.calculatePercentChange(event.count, event.previousCount),
users: event.deviceCount,
userChange: percent_change_helper_1.calculatePercentChange(event.deviceCount, event.previousDeviceCount),
perUser: event.countPerDevice,
perSession: event.countPerSession,
}));
}
catch (error) {
debug(`Failed to get events statistics - ${util_1.inspect(error)}`);
throw commandline_1.failure(commandline_1.ErrorCodes.Exception, "failed to get events statistics");
}
if (loadProperties) {
const limit = pLimit(ShowCommand_1.numberOfParallelRequests);
const propertiesPromises = eventsStatistics.map((eventStats) => this.getProperties(client, app, eventStats.name, startDate, endDate, appVersions, limit));
(yield Promise.all(propertiesPromises)).forEach((properties, index) => (eventsStatistics[index].properties = properties));
}
return eventsStatistics;
});
}
getProperties(client, app, eventName, startDate, endDate, appVersions, limit) {
return __awaiter(this, void 0, void 0, function* () {
let propertiesNames;
try {
const httpContent = yield limit(() => client.analytics.eventProperties(eventName, app.ownerName, app.appName));
propertiesNames = httpContent.eventProperties;
}
catch (error) {
debug(`Failed to get event properties of event ${eventName} - ${util_1.inspect(error)}`);
throw commandline_1.failure(commandline_1.ErrorCodes.Exception, `failed to get event properties of event ${eventName}`);
}
const valuesStatsPromises = propertiesNames.map((propertyName) => this.getPropertyValueStatistics(client, app, eventName, propertyName, startDate, endDate, appVersions, limit));
return (yield Promise.all(valuesStatsPromises)).map((valueStats, index) => ({
name: propertiesNames[index],
valuesStatistics: valueStats,
}));
});
}
getPropertyValueStatistics(client, app, eventName, eventPropertyName, startDate, endDate, appVersions, limit) {
return __awaiter(this, void 0, void 0, function* () {
try {
const result = yield client.analytics.eventPropertyCounts(eventName, eventPropertyName, startDate, app.ownerName, app.appName, {
end: endDate,
versions: appVersions,
});
return result.values.map((value) => ({
value: value.name,
count: value.count,
countChange: percent_change_helper_1.calculatePercentChange(value.count, value.previousCount),
}));
}
catch (error) {
debug(`Failed to get values of property ${eventPropertyName} of event ${eventName} - ${util_1.inspect(error)}`);
throw commandline_1.failure(commandline_1.ErrorCodes.Exception, `failed to get values of property ${eventPropertyName} of event ${eventName}`);
}
});
}
outputStatistics(statistics) {
interaction_1.out.reportObjectAsTitledTables((events, numberFormatter, dateFormatter, percentageFormatter) => {
const table = [];
const eventsTable = {
name: "Events",
content: [["Name", "Count", "Count Change", "Users", "User Change", "Per User", "Per Session"]],
};
table.push(eventsTable);
for (const event of events) {
eventsTable.content.push([
event.name,
numberFormatter(event.count),
percentageFormatter(event.countChange),
numberFormatter(event.users),
percentageFormatter(event.userChange),
numberFormatter(event.perUser),
numberFormatter(event.perSession),
]);
if (event.properties) {
for (const property of event.properties) {
eventsTable.content.push({
name: property.name,
content: [["Value", "Count", "Count Change"]].concat(property.valuesStatistics.map((valueStats) => [
valueStats.value,
numberFormatter(valueStats.count),
percentageFormatter(valueStats.countChange),
])),
});
}
}
}
return table;
}, statistics);
}
};
ShowCommand.numberOfParallelRequests = 10;
__decorate([
commandline_1.help("Show statistics about event properties"),
commandline_1.longName("properties")
], ShowCommand.prototype, "properties", void 0);
__decorate([
commandline_1.help(analytics_constants_1.startDateHelpMessage),
commandline_1.shortName("s"),
commandline_1.longName("start"),
commandline_1.hasArg
], ShowCommand.prototype, "startDate", void 0);
__decorate([
commandline_1.help(analytics_constants_1.endDateHelpMessage),
commandline_1.shortName("e"),
commandline_1.longName("end"),
commandline_1.hasArg
], ShowCommand.prototype, "endDate", void 0);
__decorate([
commandline_1.help("Filter the list of events by app version"),
commandline_1.shortName("V"),
commandline_1.longName("app-version"),
commandline_1.hasArg
], ShowCommand.prototype, "appVersion", void 0);
__decorate([
commandline_1.help("Introduce the number of events that are being displayed. By default, all the events will be shown"),
commandline_1.shortName("c"),
commandline_1.longName("number-of-events"),
commandline_1.hasArg,
commandline_1.defaultValue("200")
], ShowCommand.prototype, "eventCount", void 0);
__decorate([
commandline_1.help("Filter the metrics to a specific event name"),
commandline_1.shortName("n"),
commandline_1.longName("event-name"),
commandline_1.hasArg
], ShowCommand.prototype, "eventName", void 0);
__decorate([
commandline_1.longName("output"),
commandline_1.help("Format of output for this command: json, csv"),
commandline_1.hasArg
], ShowCommand.prototype, "format", void 0);
ShowCommand = ShowCommand_1 = __decorate([
commandline_1.help("Show statistics for events")
], ShowCommand);
exports.default = ShowCommand;