Merge pull request #2420 from resin-io/better-analytics

fix(GUI): Additional data on events
This commit is contained in:
Lorenzo Alberto Maria Ambrosi 2018-08-07 19:40:53 +02:00 committed by GitHub
commit ea834f6778
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 226 additions and 54 deletions

View File

@ -29,6 +29,7 @@ var angular = require('angular')
const electron = require('electron') const electron = require('electron')
const Bluebird = require('bluebird') const Bluebird = require('bluebird')
const semver = require('semver') const semver = require('semver')
const uuidV4 = require('uuid/v4')
const EXIT_CODES = require('../../shared/exit-codes') const EXIT_CODES = require('../../shared/exit-codes')
const messages = require('../../shared/messages') const messages = require('../../shared/messages')
const s3Packages = require('../../shared/s3-packages') const s3Packages = require('../../shared/s3-packages')
@ -58,6 +59,21 @@ const updateLock = require('./modules/update-lock')
process.env.DRIVELIST_DEBUG = /drivelist|^\*$/i.test(process.env.DEBUG) ? '1' : '' process.env.DRIVELIST_DEBUG = /drivelist|^\*$/i.test(process.env.DEBUG) ? '1' : ''
window.localStorage.debug = process.env.DEBUG window.localStorage.debug = process.env.DEBUG
// Set application session UUID
store.dispatch({
type: store.Actions.SET_APPLICATION_SESSION_UUID,
data: uuidV4()
})
// Set first flashing workflow UUID
store.dispatch({
type: store.Actions.SET_FLASHING_WORKFLOW_UUID,
data: uuidV4()
})
const applicationSessionUuid = store.getState().toJS().applicationSessionUuid
const flashingWorkflowUuid = store.getState().toJS().flashingWorkflowUuid
const app = angular.module('Etcher', [ const app = angular.module('Etcher', [
require('angular-ui-router'), require('angular-ui-router'),
require('angular-ui-bootstrap'), require('angular-ui-bootstrap'),
@ -103,7 +119,8 @@ app.run(() => {
analytics.logEvent('Application start', { analytics.logEvent('Application start', {
packageType: packageJSON.packageType, packageType: packageJSON.packageType,
version: currentVersion version: currentVersion,
applicationSessionUuid
}) })
const shouldCheckForUpdates = updateNotifier.shouldCheckForUpdates({ const shouldCheckForUpdates = updateNotifier.shouldCheckForUpdates({
@ -119,7 +136,8 @@ app.run(() => {
analytics.logEvent('Not checking for updates', { analytics.logEvent('Not checking for updates', {
shouldCheckForUpdates, shouldCheckForUpdates,
updatesEnabled, updatesEnabled,
stable: isStableRelease stable: isStableRelease,
applicationSessionUuid
}) })
return Bluebird.resolve() return Bluebird.resolve()
@ -132,7 +150,8 @@ app.run(() => {
currentVersion, currentVersion,
stable: isStableRelease, stable: isStableRelease,
updateSemverRange, updateSemverRange,
includeUnstableChannel includeUnstableChannel,
applicationSessionUuid
}) })
return s3Packages.getLatestVersion(release.getReleaseType(currentVersion), { return s3Packages.getLatestVersion(release.getReleaseType(currentVersion), {
@ -141,7 +160,8 @@ app.run(() => {
}).then((latestVersion) => { }).then((latestVersion) => {
if (semver.gte(currentVersion, latestVersion || '0.0.0')) { if (semver.gte(currentVersion, latestVersion || '0.0.0')) {
analytics.logEvent('Update notification skipped', { analytics.logEvent('Update notification skipped', {
reason: 'Latest version' reason: 'Latest version',
applicationSessionUuid
}) })
return Bluebird.resolve() return Bluebird.resolve()
} }
@ -153,13 +173,15 @@ app.run(() => {
// might be annoying. // might be annoying.
if (selectionState.hasImage()) { if (selectionState.hasImage()) {
analytics.logEvent('Update notification skipped', { analytics.logEvent('Update notification skipped', {
reason: 'Image selected' reason: 'Image selected',
applicationSessionUuid
}) })
return Bluebird.resolve() return Bluebird.resolve()
} }
analytics.logEvent('Notifying update', { analytics.logEvent('Notifying update', {
latestVersion latestVersion,
applicationSessionUuid
}) })
return updateNotifier.notify(latestVersion, { return updateNotifier.notify(latestVersion, {
@ -174,7 +196,8 @@ app.run(() => {
}, (error) => { }, (error) => {
analytics.logEvent('Update check user error', { analytics.logEvent('Update check user error', {
title: errors.getTitle(error), title: errors.getTitle(error),
description: errors.getDescription(error) description: errors.getDescription(error),
applicationSessionUuid
}) })
}).catch(exceptionReporter.report) }).catch(exceptionReporter.report)
}) })
@ -247,7 +270,8 @@ app.run(($window) => {
$window.addEventListener('beforeunload', (event) => { $window.addEventListener('beforeunload', (event) => {
if (!flashState.isFlashing() || popupExists) { if (!flashState.isFlashing() || popupExists) {
analytics.logEvent('Close application', { analytics.logEvent('Close application', {
isFlashing: flashState.isFlashing() isFlashing: flashState.isFlashing(),
applicationSessionUuid
}) })
return return
} }
@ -258,7 +282,7 @@ app.run(($window) => {
// Don't open any more popups // Don't open any more popups
popupExists = true popupExists = true
analytics.logEvent('Close attempt while flashing') analytics.logEvent('Close attempt while flashing', { applicationSessionUuid, flashingWorkflowUuid })
osDialog.showWarning({ osDialog.showWarning({
confirmationLabel: 'Yes, quit', confirmationLabel: 'Yes, quit',
@ -268,7 +292,9 @@ app.run(($window) => {
}).then((confirmed) => { }).then((confirmed) => {
if (confirmed) { if (confirmed) {
analytics.logEvent('Close confirmed while flashing', { analytics.logEvent('Close confirmed while flashing', {
uuid: flashState.getFlashUuid() flashInstanceUuid: flashState.getFlashUuid(),
applicationSessionUuid,
flashingWorkflowUuid
}) })
// This circumvents the 'beforeunload' event unlike // This circumvents the 'beforeunload' event unlike
@ -276,7 +302,7 @@ app.run(($window) => {
electron.remote.process.exit(EXIT_CODES.SUCCESS) electron.remote.process.exit(EXIT_CODES.SUCCESS)
} }
analytics.logEvent('Close rejected while flashing') analytics.logEvent('Close rejected while flashing', { applicationSessionUuid, flashingWorkflowUuid })
popupExists = false popupExists = false
}).catch(exceptionReporter.report) }).catch(exceptionReporter.report)
}) })
@ -308,7 +334,8 @@ app.run(($rootScope) => {
analytics.logEvent('Navigate', { analytics.logEvent('Navigate', {
to: toState.name, to: toState.name,
from: fromState.name from: fromState.name,
applicationSessionUuid
}) })
}) })
}) })

View File

@ -20,6 +20,7 @@ const angular = require('angular')
const _ = require('lodash') const _ = require('lodash')
const Bluebird = require('bluebird') const Bluebird = require('bluebird')
const constraints = require('../../../../../shared/drive-constraints') const constraints = require('../../../../../shared/drive-constraints')
const store = require('../../../models/store')
const analytics = require('../../../modules/analytics') const analytics = require('../../../modules/analytics')
const availableDrives = require('../../../models/available-drives') const availableDrives = require('../../../models/available-drives')
const selectionState = require('../../../models/selection-state') const selectionState = require('../../../models/selection-state')
@ -96,7 +97,9 @@ module.exports = function (
if (canChangeDriveSelectionState) { if (canChangeDriveSelectionState) {
analytics.logEvent('Toggle drive', { analytics.logEvent('Toggle drive', {
drive, drive,
previouslySelected: selectionState.isCurrentDrive(drive.device) previouslySelected: selectionState.isCurrentDrive(drive.device),
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
}) })
selectionState.toggleDrive(drive.device) selectionState.toggleDrive(drive.device)
@ -125,7 +128,9 @@ module.exports = function (
this.installMissingDrivers = (drive) => { this.installMissingDrivers = (drive) => {
if (drive.link) { if (drive.link) {
analytics.logEvent('Open driver link modal', { analytics.logEvent('Open driver link modal', {
url: drive.link url: drive.link,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
}) })
return ConfirmModalService.show({ return ConfirmModalService.show({
@ -187,7 +192,10 @@ module.exports = function (
if (canChangeDriveSelectionState) { if (canChangeDriveSelectionState) {
selectionState.selectDrive(drive.device) selectionState.selectDrive(drive.device)
analytics.logEvent('Drive selected (double click)') analytics.logEvent('Drive selected (double click)', {
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
})
this.closeModal() this.closeModal()
} }

View File

@ -177,7 +177,11 @@ class FileSelector extends React.PureComponent {
}) })
osDialog.showError(invalidImageError) osDialog.showError(invalidImageError)
analytics.logEvent('Invalid image', image) analytics.logEvent('Invalid image', {
image,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
})
return return
} }
@ -185,10 +189,18 @@ class FileSelector extends React.PureComponent {
let message = null let message = null
if (supportedFormats.looksLikeWindowsImage(image.path)) { if (supportedFormats.looksLikeWindowsImage(image.path)) {
analytics.logEvent('Possibly Windows image', image) analytics.logEvent('Possibly Windows image', {
image,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
})
message = messages.warning.looksLikeWindowsImage() message = messages.warning.looksLikeWindowsImage()
} else if (!image.hasMBR) { } else if (!image.hasMBR) {
analytics.logEvent('Missing partition table', image) analytics.logEvent('Missing partition table', {
image,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
})
message = messages.warning.missingPartitionTable() message = messages.warning.missingPartitionTable()
} }
@ -218,7 +230,11 @@ class FileSelector extends React.PureComponent {
image.logo = Boolean(image.logo) image.logo = Boolean(image.logo)
image.bmap = Boolean(image.bmap) image.bmap = Boolean(image.bmap)
analytics.logEvent('Select image', image) analytics.logEvent('Select image', {
image,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
})
}).catch(exceptionReporter.report) }).catch(exceptionReporter.report)
} }

View File

@ -18,6 +18,7 @@
const flashState = require('../../../models/flash-state') const flashState = require('../../../models/flash-state')
const selectionState = require('../../../models/selection-state') const selectionState = require('../../../models/selection-state')
const store = require('../../../models/store')
const analytics = require('../../../modules/analytics') const analytics = require('../../../modules/analytics')
module.exports = function (WarningModalService) { module.exports = function (WarningModalService) {
@ -40,7 +41,10 @@ module.exports = function (WarningModalService) {
flashState.resetState() flashState.resetState()
if (confirmed) { if (confirmed) {
analytics.logEvent('Restart after failure') analytics.logEvent('Restart after failure', {
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
})
} else { } else {
selectionState.clear() selectionState.clear()
} }

View File

@ -17,6 +17,7 @@
'use strict' 'use strict'
const _ = require('lodash') const _ = require('lodash')
const store = require('../../../models/store')
const analytics = require('../../../modules/analytics') const analytics = require('../../../modules/analytics')
module.exports = function ($uibModal, $q) { module.exports = function ($uibModal, $q) {
@ -45,7 +46,9 @@ module.exports = function ($uibModal, $q) {
}) })
analytics.logEvent('Open modal', { analytics.logEvent('Open modal', {
name: options.name name: options.name,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
}) })
const modal = $uibModal.open({ const modal = $uibModal.open({
@ -62,7 +65,9 @@ module.exports = function ($uibModal, $q) {
modal.result.then((value) => { modal.result.then((value) => {
analytics.logEvent('Modal accepted', { analytics.logEvent('Modal accepted', {
name: options.name, name: options.name,
value value,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
}) })
resolve(value) resolve(value)
@ -71,7 +76,9 @@ module.exports = function ($uibModal, $q) {
if (error === 'escape key press' || error === 'backdrop click') { if (error === 'escape key press' || error === 'backdrop click') {
analytics.logEvent('Modal rejected', { analytics.logEvent('Modal rejected', {
name: options.name, name: options.name,
method: error method: error,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
}) })
return resolve() return resolve()
@ -79,7 +86,9 @@ module.exports = function ($uibModal, $q) {
analytics.logEvent('Modal rejected', { analytics.logEvent('Modal rejected', {
name: options.name, name: options.name,
value: error value: error,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
}) })
return reject(error) return reject(error)

View File

@ -25,6 +25,7 @@ const react = require('react')
const propTypes = require('prop-types') const propTypes = require('prop-types')
const { react2angular } = require('react2angular') const { react2angular } = require('react2angular')
const analytics = require('../modules/analytics') const analytics = require('../modules/analytics')
const store = require('../models/store')
const settings = require('../models/settings') const settings = require('../models/settings')
const packageJSON = require('../../../../package.json') const packageJSON = require('../../../../package.json')
@ -198,7 +199,10 @@ class SafeWebview extends react.PureComponent {
if (event.resourceType === 'mainFrame') { if (event.resourceType === 'mainFrame') {
const HTTP_OK = 200 const HTTP_OK = 200
analytics.logEvent(event) analytics.logEvent(event, {
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
})
this.setState({ this.setState({
shouldShow: event.httpResponseCode === HTTP_OK shouldShow: event.httpResponseCode === HTTP_OK
@ -248,7 +252,10 @@ class SafeWebview extends react.PureComponent {
if (message.command === 'error') { if (message.command === 'error') {
analytics.logException(message.data) analytics.logException(message.data)
} else { } else {
analytics.logEvent(message.data || message) analytics.logEvent(message.data || message, {
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
})
} }
} }
} }

View File

@ -19,6 +19,7 @@
const electron = require('electron') const electron = require('electron')
const Bluebird = require('bluebird') const Bluebird = require('bluebird')
const _ = require('lodash') const _ = require('lodash')
const store = require('../models/store')
const settings = require('../models/settings') const settings = require('../models/settings')
const analytics = require('../modules/analytics') const analytics = require('../modules/analytics')
const units = require('../../../shared/units') const units = require('../../../shared/units')
@ -145,7 +146,9 @@ exports.notify = (version, options = {}) => {
sleepUpdateCheck: results.sleepUpdateCheck, sleepUpdateCheck: results.sleepUpdateCheck,
notifyVersion: version, notifyVersion: version,
currentVersion: packageJSON.version, currentVersion: packageJSON.version,
agreed: results.agreed agreed: results.agreed,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
}) })
if (results.agreed) { if (results.agreed) {

View File

@ -80,6 +80,8 @@ const selectImageNoNilFields = [
* @private * @private
*/ */
const DEFAULT_STATE = Immutable.fromJS({ const DEFAULT_STATE = Immutable.fromJS({
applicationSessionUuid: '',
flashingWorkflowUuid: '',
availableDrives: [], availableDrives: [],
selection: { selection: {
devices: new Immutable.OrderedSet() devices: new Immutable.OrderedSet()
@ -111,7 +113,9 @@ const ACTIONS = _.fromPairs(_.map([
'SELECT_DRIVE', 'SELECT_DRIVE',
'SELECT_IMAGE', 'SELECT_IMAGE',
'DESELECT_DRIVE', 'DESELECT_DRIVE',
'DESELECT_IMAGE' 'DESELECT_IMAGE',
'SET_APPLICATION_SESSION_UUID',
'SET_FLASHING_WORKFLOW_UUID'
], (message) => { ], (message) => {
return [ message, message ] return [ message, message ]
})) }))
@ -499,6 +503,14 @@ const storeReducer = (state = DEFAULT_STATE, action) => {
return state.deleteIn([ 'selection', 'image' ]) return state.deleteIn([ 'selection', 'image' ])
} }
case ACTIONS.SET_APPLICATION_SESSION_UUID: {
return state.set('applicationSessionUuid', action.data)
}
case ACTIONS.SET_FLASHING_WORKFLOW_UUID: {
return state.set('flashingWorkflowUuid', action.data)
}
default: { default: {
return state return state
} }

View File

@ -23,6 +23,7 @@ const os = require('os')
const ipc = require('node-ipc') const ipc = require('node-ipc')
const isRunningInAsar = require('electron-is-running-in-asar') const isRunningInAsar = require('electron-is-running-in-asar')
const electron = require('electron') const electron = require('electron')
const store = require('../models/store')
const settings = require('../models/settings') const settings = require('../models/settings')
const flashState = require('../models/flash-state') const flashState = require('../models/flash-state')
const errors = require('../../../shared/errors') const errors = require('../../../shared/errors')
@ -74,20 +75,26 @@ const getApplicationEntryPoint = () => {
* handleErrorLogging({ code: 'EUNPLUGGED' }, { image: 'resin.img' }) * handleErrorLogging({ code: 'EUNPLUGGED' }, { image: 'resin.img' })
*/ */
const handleErrorLogging = (error, analyticsData) => { const handleErrorLogging = (error, analyticsData) => {
const eventData = _.assign({
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
flashInstanceUuid: flashState.getFlashUuid()
}, analyticsData)
if (error.code === 'EVALIDATION') { if (error.code === 'EVALIDATION') {
analytics.logEvent('Validation error', analyticsData) analytics.logEvent('Validation error', eventData)
} else if (error.code === 'EUNPLUGGED') { } else if (error.code === 'EUNPLUGGED') {
analytics.logEvent('Drive unplugged', analyticsData) analytics.logEvent('Drive unplugged', eventData)
} else if (error.code === 'EIO') { } else if (error.code === 'EIO') {
analytics.logEvent('Input/output error', analyticsData) analytics.logEvent('Input/output error', eventData)
} else if (error.code === 'ENOSPC') { } else if (error.code === 'ENOSPC') {
analytics.logEvent('Out of space', analyticsData) analytics.logEvent('Out of space', eventData)
} else if (error.code === 'ECHILDDIED') { } else if (error.code === 'ECHILDDIED') {
analytics.logEvent('Child died unexpectedly', analyticsData) analytics.logEvent('Child died unexpectedly', eventData)
} else { } else {
analytics.logEvent('Flash error', _.merge({ analytics.logEvent('Flash error', _.merge({
error: errors.toJSON(error) error: errors.toJSON(error)
}, analyticsData)) }, eventData))
} }
} }
@ -163,6 +170,7 @@ exports.performWrite = (image, drives, onProgress) => {
drives, drives,
driveCount: drives.length, driveCount: drives.length,
uuid: flashState.getFlashUuid(), uuid: flashState.getFlashUuid(),
flashInstanceUuid: flashState.getFlashUuid(),
unmountOnSuccess: settings.get('unmountOnSuccess'), unmountOnSuccess: settings.get('unmountOnSuccess'),
validateWriteOnSuccess: settings.get('validateWriteOnSuccess') validateWriteOnSuccess: settings.get('validateWriteOnSuccess')
} }
@ -306,8 +314,12 @@ exports.flash = (image, drives) => {
drives, drives,
driveCount: drives.length, driveCount: drives.length,
uuid: flashState.getFlashUuid(), uuid: flashState.getFlashUuid(),
status: 'started',
flashInstanceUuid: flashState.getFlashUuid(),
unmountOnSuccess: settings.get('unmountOnSuccess'), unmountOnSuccess: settings.get('unmountOnSuccess'),
validateWriteOnSuccess: settings.get('validateWriteOnSuccess') validateWriteOnSuccess: settings.get('validateWriteOnSuccess'),
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
} }
analytics.logEvent('Flash', analyticsData) analytics.logEvent('Flash', analyticsData)
@ -315,10 +327,17 @@ exports.flash = (image, drives) => {
return exports.performWrite(image, drives, (state) => { return exports.performWrite(image, drives, (state) => {
flashState.setProgressState(state) flashState.setProgressState(state)
}).then(flashState.unsetFlashingFlag).then(() => { }).then(flashState.unsetFlashingFlag).then(() => {
const { results } = flashState.getFlashResults()
const event = _.assign({
errors: results.errors,
devices: results.devices,
status: 'finished'
},
analyticsData)
if (flashState.wasLastFlashCancelled()) { if (flashState.wasLastFlashCancelled()) {
analytics.logEvent('Elevation cancelled', analyticsData) analytics.logEvent('Elevation cancelled', event)
} else { } else {
analytics.logEvent('Done', analyticsData) analytics.logEvent('Done', event)
} }
}).catch((error) => { }).catch((error) => {
flashState.unsetFlashingFlag({ flashState.unsetFlashingFlag({
@ -327,7 +346,14 @@ exports.flash = (image, drives) => {
// eslint-disable-next-line no-magic-numbers // eslint-disable-next-line no-magic-numbers
if (drives.length > 1) { if (drives.length > 1) {
analytics.logEvent('Write failed', analyticsData) const { results } = flashState.getFlashResults()
const event = _.assign({
errors: results.errors,
devices: results.devices,
status: 'failed'
},
analyticsData)
analytics.logEvent('Write failed', event)
} }
return Bluebird.reject(error) return Bluebird.reject(error)
@ -346,14 +372,25 @@ exports.flash = (image, drives) => {
*/ */
exports.cancel = () => { exports.cancel = () => {
const drives = selectionState.getSelectedDevices() const drives = selectionState.getSelectedDevices()
analytics.logEvent('Cancel', { const { results } = flashState.getFlashResults()
const analyticsData = {
image: selectionState.getImagePath(), image: selectionState.getImagePath(),
drives, drives,
driveCount: drives.length, driveCount: drives.length,
uuid: flashState.getFlashUuid(), uuid: flashState.getFlashUuid(),
flashInstanceUuid: flashState.getFlashUuid(),
unmountOnSuccess: settings.get('unmountOnSuccess'), unmountOnSuccess: settings.get('unmountOnSuccess'),
validateWriteOnSuccess: settings.get('validateWriteOnSuccess') validateWriteOnSuccess: settings.get('validateWriteOnSuccess'),
}) applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
}
const event = _.assign({
errors: results.errors,
devices: results.devices,
status: 'finished'
},
analyticsData)
analytics.logEvent('Cancel', event)
// Re-enable lock release on inactivity // Re-enable lock release on inactivity
updateLock.resume() updateLock.resume()

View File

@ -17,6 +17,7 @@
'use strict' 'use strict'
const electron = require('electron') const electron = require('electron')
const store = require('../../../models/store')
const analytics = require('../../../modules/analytics') const analytics = require('../../../modules/analytics')
const settings = require('../../../models/settings') const settings = require('../../../models/settings')
@ -38,7 +39,8 @@ module.exports = function () {
} }
analytics.logEvent('Open external link', { analytics.logEvent('Open external link', {
url url,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid
}) })
if (url) { if (url) {

View File

@ -17,6 +17,8 @@
'use strict' 'use strict'
const _ = require('lodash') const _ = require('lodash')
const uuidV4 = require('uuid/v4')
const store = require('../../../models/store')
const settings = require('../../../models/settings') const settings = require('../../../models/settings')
const flashState = require('../../../models/flash-state') const flashState = require('../../../models/flash-state')
const selectionState = require('../../../models/selection-state') const selectionState = require('../../../models/selection-state')
@ -57,10 +59,20 @@ module.exports = function ($state) {
selectionState.deselectImage() selectionState.deselectImage()
} }
selectionState.deselectAllDrives() selectionState.deselectAllDrives()
analytics.logEvent('Restart', options) analytics.logEvent('Restart', _.assign({
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
}, options))
// Re-enable lock release on inactivity // Re-enable lock release on inactivity
updateLock.resume() updateLock.resume()
// Reset the flashing workflow uuid
store.dispatch({
type: 'SET_FLASHING_WORKFLOW_UUID',
data: uuidV4()
})
$state.go('main') $state.go('main')
} }

View File

@ -19,6 +19,7 @@
const _ = require('lodash') const _ = require('lodash')
const angular = require('angular') const angular = require('angular')
const prettyBytes = require('pretty-bytes') const prettyBytes = require('pretty-bytes')
const store = require('../../../models/store')
const settings = require('../../../models/settings') const settings = require('../../../models/settings')
const selectionState = require('../../../models/selection-state') const selectionState = require('../../../models/selection-state')
const analytics = require('../../../modules/analytics') const analytics = require('../../../modules/analytics')
@ -109,7 +110,9 @@ module.exports = function (DriveSelectorService) {
analytics.logEvent('Select drive', { analytics.logEvent('Select drive', {
device: drive.device, device: drive.device,
unsafeMode: settings.get('unsafeMode') && !settings.get('disableUnsafeMode') unsafeMode: settings.get('unsafeMode') && !settings.get('disableUnsafeMode'),
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
}) })
}).catch(exceptionReporter.report) }).catch(exceptionReporter.report)
} }
@ -124,7 +127,10 @@ module.exports = function (DriveSelectorService) {
*/ */
this.reselectDrive = () => { this.reselectDrive = () => {
this.openDriveSelector() this.openDriveSelector()
analytics.logEvent('Reselect drive') analytics.logEvent('Reselect drive', {
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
})
} }
/** /**

View File

@ -19,6 +19,7 @@
const _ = require('lodash') const _ = require('lodash')
const Bluebird = require('bluebird') const Bluebird = require('bluebird')
const path = require('path') const path = require('path')
const store = require('../../../models/store')
const messages = require('../../../../../shared/messages') const messages = require('../../../../../shared/messages')
const errors = require('../../../../../shared/errors') const errors = require('../../../../../shared/errors')
const imageStream = require('../../../../../sdk/image-stream') const imageStream = require('../../../../../sdk/image-stream')
@ -76,7 +77,10 @@ module.exports = function (
}) })
osDialog.showError(invalidImageError) osDialog.showError(invalidImageError)
analytics.logEvent('Invalid image', image) analytics.logEvent('Invalid image', _.merge({
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
}, image))
return return
} }
@ -84,10 +88,18 @@ module.exports = function (
let message = null let message = null
if (supportedFormats.looksLikeWindowsImage(image.path)) { if (supportedFormats.looksLikeWindowsImage(image.path)) {
analytics.logEvent('Possibly Windows image', image) analytics.logEvent('Possibly Windows image', {
image,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
})
message = messages.warning.looksLikeWindowsImage() message = messages.warning.looksLikeWindowsImage()
} else if (!image.hasMBR) { } else if (!image.hasMBR) {
analytics.logEvent('Missing partition table', image) analytics.logEvent('Missing partition table', {
image,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
})
message = messages.warning.missingPartitionTable() message = messages.warning.missingPartitionTable()
} }
@ -114,7 +126,11 @@ module.exports = function (
image.logo = Boolean(image.logo) image.logo = Boolean(image.logo)
image.bmap = Boolean(image.bmap) image.bmap = Boolean(image.bmap)
return analytics.logEvent('Select image', image) return analytics.logEvent('Select image', {
image,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
})
}).catch(exceptionReporter.report) }).catch(exceptionReporter.report)
} }
@ -155,7 +171,10 @@ module.exports = function (
* ImageSelectionController.openImageSelector(); * ImageSelectionController.openImageSelector();
*/ */
this.openImageSelector = () => { this.openImageSelector = () => {
analytics.logEvent('Open image selector') analytics.logEvent('Open image selector', {
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
})
if (settings.get('experimentalFilePicker')) { if (settings.get('experimentalFilePicker')) {
FileSelectorService.open() FileSelectorService.open()
@ -164,7 +183,10 @@ module.exports = function (
// Avoid analytics and selection state changes // Avoid analytics and selection state changes
// if no file was resolved from the dialog. // if no file was resolved from the dialog.
if (!imagePath) { if (!imagePath) {
analytics.logEvent('Image selector closed') analytics.logEvent('Image selector closed', {
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
})
return return
} }
@ -183,7 +205,9 @@ module.exports = function (
*/ */
this.reselectImage = () => { this.reselectImage = () => {
analytics.logEvent('Reselect image', { analytics.logEvent('Reselect image', {
previousImage: selectionState.getImage() previousImage: selectionState.getImage(),
applicationSessionUuid: store.getState().toJS().applicationSessionUuid,
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid
}) })
this.openImageSelector() this.openImageSelector()

View File

@ -16,6 +16,7 @@
'use strict' 'use strict'
const store = require('../../../models/store')
const settings = require('../../../models/settings') const settings = require('../../../models/settings')
const flashState = require('../../../models/flash-state') const flashState = require('../../../models/flash-state')
const analytics = require('../../../modules/analytics') const analytics = require('../../../modules/analytics')
@ -82,7 +83,9 @@ module.exports = function (
*/ */
this.showSelectedImageDetails = () => { this.showSelectedImageDetails = () => {
analytics.logEvent('Show selected image tooltip', { analytics.logEvent('Show selected image tooltip', {
imagePath: selectionState.getImagePath() imagePath: selectionState.getImagePath(),
flashingWorkflowUuid: store.getState().toJS().flashingWorkflowUuid,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid
}) })
return TooltipModalService.show({ return TooltipModalService.show({

View File

@ -18,6 +18,7 @@
const os = require('os') const os = require('os')
const _ = require('lodash') const _ = require('lodash')
const store = require('../../../models/store')
const settings = require('../../../models/settings') const settings = require('../../../models/settings')
const analytics = require('../../../modules/analytics') const analytics = require('../../../modules/analytics')
const exceptionReporter = require('../../../modules/exception-reporter') const exceptionReporter = require('../../../modules/exception-reporter')
@ -87,7 +88,8 @@ module.exports = function (WarningModalService) {
analytics.logEvent('Toggle setting', { analytics.logEvent('Toggle setting', {
setting, setting,
value, value,
dangerous dangerous,
applicationSessionUuid: store.getState().toJS().applicationSessionUuid
}) })
if (!value || !dangerous) { if (!value || !dangerous) {