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:
parent
7aaf9d0eb7
commit
2158cc5157
26 changed files with 2879 additions and 2605 deletions
|
@ -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())
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
export function StatusViewModel(data) {
|
||||
this.Authentication = data.Authentication;
|
||||
this.Snapshot = data.Snapshot;
|
||||
this.Analytics = data.Analytics;
|
||||
this.Version = data.Version;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
})
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue