1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-09 07:45:22 +02:00

feat(telemetry): replace GA with matomo (#4140)

* feat(core/telemetry): add posthog

* feat(core/telemetry): add posthog

* feat(core/telemetry): add matomo

* feat(core/telemetry): update matomo

* feat(core/telemetry): update matomo

* feat(core/telemetry): update matomo

* feat(telemetry): remove google analytics code

* refactor(telemetry): move matomo code to bundle

* refactor(telemetry): move matomo lib to assets

* refactor(telemetry): depreciate --no-analytics

* feat(settings): introduce a setting to enable telemetry

* fix(cli): fix typo

* feat(settings): allow toggle telemetry from settings

* fix(settings): handle case where AuthenticationMethod is missing

* feat(admin): set telemetry on admin init

* refactor(app); revert file

* refactor(state-manager): move optout to state manager

* feat(telemetry): set matomo url

* feat(core/settings): minor UI update

* feat(core/telemetry): update custom URL

* feat(core/telemetry): add placeholder for privacy policy

* feat(core/telemetry): add privacy policy link

Co-authored-by: Anthony Lapenna <lapenna.anthony@gmail.com>
This commit is contained in:
Chaim Lev-Ari 2020-08-07 01:46:25 +03:00 committed by GitHub
parent 7aaf9d0eb7
commit 2158cc5157
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 2879 additions and 2605 deletions

View file

@ -15,16 +15,6 @@ async function initAuthentication(authManager, Authentication, $rootScope, $stat
await Authentication.init();
}
function initAnalytics(Analytics, $rootScope) {
Analytics.offline(false);
Analytics.registerScriptTags();
Analytics.registerTrackers();
$rootScope.$on('$stateChangeSuccess', function (event, toState) {
Analytics.trackPage(toState.url);
Analytics.pageView();
});
}
angular.module('portainer.app', ['portainer.oauth']).config([
'$stateRegistryProvider',
function ($stateRegistryProvider) {
@ -38,23 +28,19 @@ angular.module('portainer.app', ['portainer.oauth']).config([
'StateManager',
'Authentication',
'Notifications',
'Analytics',
'authManager',
'$rootScope',
'$state',
'$async',
'$q',
(StateManager, Authentication, Notifications, Analytics, authManager, $rootScope, $state, $async, $q) => {
(StateManager, Authentication, Notifications, authManager, $rootScope, $state, $async, $q) => {
const deferred = $q.defer();
const appState = StateManager.getState();
if (!appState.loading) {
deferred.resolve();
} else {
StateManager.initialize()
.then(function success(state) {
if (state.application.analytics) {
initAnalytics(Analytics, $rootScope);
}
.then(function success() {
return $async(initAuthentication, authManager, Authentication, $rootScope, $state);
})
.then(() => deferred.resolve())

View file

@ -17,6 +17,7 @@ export function SettingsViewModel(data) {
this.EdgeAgentCheckinInterval = data.EdgeAgentCheckinInterval;
this.EnableEdgeComputeFeatures = data.EnableEdgeComputeFeatures;
this.UserSessionTimeout = data.UserSessionTimeout;
this.EnableTelemetry = data.EnableTelemetry;
}
export function PublicSettingsViewModel(settings) {
@ -32,6 +33,7 @@ export function PublicSettingsViewModel(settings) {
this.EnableEdgeComputeFeatures = settings.EnableEdgeComputeFeatures;
this.LogoURL = settings.LogoURL;
this.OAuthLoginURI = settings.OAuthLoginURI;
this.EnableTelemetry = settings.EnableTelemetry;
}
export function LDAPSettingsViewModel(data) {

View file

@ -1,7 +1,6 @@
export function StatusViewModel(data) {
this.Authentication = data.Authentication;
this.Snapshot = data.Snapshot;
this.Analytics = data.Analytics;
this.Version = data.Version;
}

View file

@ -11,7 +11,19 @@ angular.module('portainer.app').factory('StateManager', [
'StatusService',
'APPLICATION_CACHE_VALIDITY',
'AgentPingService',
function StateManagerFactory($q, SystemService, InfoHelper, EndpointProvider, LocalStorage, SettingsService, StatusService, APPLICATION_CACHE_VALIDITY, AgentPingService) {
'$analytics',
function StateManagerFactory(
$q,
SystemService,
InfoHelper,
EndpointProvider,
LocalStorage,
SettingsService,
StatusService,
APPLICATION_CACHE_VALIDITY,
AgentPingService,
$analytics
) {
'use strict';
var manager = {};
@ -106,9 +118,15 @@ angular.module('portainer.app').factory('StateManager', [
LocalStorage.storeApplicationState(state.application);
};
manager.updateEnableTelemetry = function updateEnableTelemetry(enableTelemetry) {
state.application.enableTelemetry = enableTelemetry;
$analytics.setOptOut(!enableTelemetry);
LocalStorage.storeApplicationState(state.application);
};
function assignStateFromStatusAndSettings(status, settings) {
state.application.analytics = status.Analytics;
state.application.version = status.Version;
state.application.enableTelemetry = settings.EnableTelemetry;
state.application.logo = settings.LogoURL;
state.application.snapshotInterval = settings.SnapshotInterval;
state.application.enableHostManagementFeatures = settings.EnableHostManagementFeatures;
@ -134,6 +152,7 @@ angular.module('portainer.app').factory('StateManager', [
var status = data.status;
var settings = data.settings;
assignStateFromStatusAndSettings(status, settings);
$analytics.setOptOut(!settings.EnableTelemetry);
LocalStorage.storeApplicationState(state.application);
deferred.resolve(state);
})
@ -176,6 +195,7 @@ angular.module('portainer.app').factory('StateManager', [
} else {
state.application = applicationState;
state.loading = false;
$analytics.setOptOut(!state.application.enableTelemetry);
deferred.resolve(state);
}
} else {

View file

@ -29,20 +29,16 @@
<div>
<i class="fa fa-chevron-circle-right" aria-hidden="true"></i> <u>Opt-out</u>
<ul>
<li>You may opt-out by passing the <em>--no-analytics</em> flag as part of the docker run command when starting Portainer.</li>
<li
>If you believe that we could improve our analytics approach make sure to let us know! There is an open discussion on
<a target="_blank" href="https://github.com/portainer/portainer/issues/3310"><i class="fab fa-github" aria-hidden="true"></i> Github</a></li
>
<li>You may opt-out by turning off the analytics in the settings page.</li>
</ul>
</div>
<div>
<i class="fa fa-chevron-circle-right" aria-hidden="true"></i> <u>What we collect & GDPR</u>
<ul>
<li
>We dont know who uses Portainer, where its used, to what scale its used, all we know (from analytics) is how often Portainer is used and which pages within the app
are most frequently used.</li
>
<li>
We don't know who uses Portainer, where its used, to what scale its used, all we know (from analytics) is how often Portainer is used and which pages within the app
are most frequently used.
</li>
<li>As we are only collecting a very small amount of totally anonymous data, it is deemed that opt-in is not required.</li>
</ul>
</div>

View file

@ -82,6 +82,17 @@
</div>
</div>
<!-- !actions -->
<!-- enableTelemetry-->
<div class="form-group">
<div class="col-sm-12">
<input type="checkbox" name="toggle_enableTelemetry" ng-model="formValues.enableTelemetry" />
<span class="text-muted small" style="margin-left: 2px;"
>Allow collection of anonymous statistics. You can find more information about this in our
<a href="https://www.portainer.io/documentation/in-app-analytics-and-privacy-policy/" target="_blank">privacy policy</a>.</span
>
</div>
</div>
<!-- !enableTelemetry-->
</form>
<!-- !init password form -->
</div>

View file

@ -5,16 +5,18 @@ angular.module('portainer.app').controller('InitAdminController', [
'Notifications',
'Authentication',
'StateManager',
'SettingsService',
'UserService',
'EndpointService',
'ExtensionService',
function ($async, $scope, $state, Notifications, Authentication, StateManager, UserService, EndpointService, ExtensionService) {
function ($async, $scope, $state, Notifications, Authentication, StateManager, SettingsService, UserService, EndpointService, ExtensionService) {
$scope.logo = StateManager.getState().application.logo;
$scope.formValues = {
Username: 'admin',
Password: '',
ConfirmPassword: '',
enableTelemetry: true,
};
$scope.state = {
@ -45,6 +47,10 @@ angular.module('portainer.app').controller('InitAdminController', [
.then(function success() {
return retrieveAndSaveEnabledExtensions();
})
.then(function success() {
StateManager.updateEnableTelemetry($scope.formValues.enableTelemetry);
return SettingsService.update({ enableTelemetry: $scope.formValues.enableTelemetry });
})
.then(function () {
return EndpointService.endpoints(0, 100);
})

View file

@ -26,6 +26,18 @@
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" name="toggle_logo" ng-model="formValues.customLogo" /><i></i> </label>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<label for="toggle_enableTelemetry" class="control-label text-left">
Allow the collection of anonymous statistics
</label>
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" name="toggle_enableTelemetry" ng-model="formValues.enableTelemetry" /><i></i> </label>
</div>
<div class="col-sm-12 text-muted small" style="margin-top: 10px;">
You can find more information about this in our
<a href="https://www.portainer.io/documentation/in-app-analytics-and-privacy-policy/" target="_blank">privacy policy</a>.
</div>
</div>
<div ng-if="formValues.customLogo">
<div class="form-group">
<span class="col-sm-12 text-muted small">

View file

@ -36,6 +36,7 @@ angular.module('portainer.app').controller('SettingsController', [
allowDeviceMappingForRegularUsers: false,
allowStackManagementForRegularUsers: false,
disableContainerCapabilitiesForRegularUsers: false,
enableTelemetry: false,
};
$scope.isContainerEditDisabled = function isContainerEditDisabled() {
@ -85,6 +86,7 @@ angular.module('portainer.app').controller('SettingsController', [
settings.AllowDeviceMappingForRegularUsers = !$scope.formValues.disableDeviceMappingForRegularUsers;
settings.AllowStackManagementForRegularUsers = !$scope.formValues.disableStackManagementForRegularUsers;
settings.AllowContainerCapabilitiesForRegularUsers = !$scope.formValues.disableContainerCapabilitiesForRegularUsers;
settings.EnableTelemetry = $scope.formValues.enableTelemetry;
$scope.state.actionInProgress = true;
updateSettings(settings);
@ -105,6 +107,7 @@ angular.module('portainer.app').controller('SettingsController', [
StateManager.updateAllowContainerCapabilitiesForRegularUsers(settings.AllowContainerCapabilitiesForRegularUsers);
StateManager.updateAllowPrivilegedModeForRegularUsers(settings.AllowPrivilegedModeForRegularUsers);
StateManager.updateAllowBindMountsForRegularUsers(settings.AllowBindMountsForRegularUsers);
StateManager.updateEnableTelemetry(settings.EnableTelemetry);
$state.reload();
})
.catch(function error(err) {
@ -133,6 +136,7 @@ angular.module('portainer.app').controller('SettingsController', [
$scope.formValues.disableDeviceMappingForRegularUsers = !settings.AllowDeviceMappingForRegularUsers;
$scope.formValues.disableStackManagementForRegularUsers = !settings.AllowStackManagementForRegularUsers;
$scope.formValues.disableContainerCapabilitiesForRegularUsers = !settings.AllowContainerCapabilitiesForRegularUsers;
$scope.formValues.enableTelemetry = settings.EnableTelemetry;
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve application settings');