/
ft_trackusage.m
162 lines (138 loc) · 6.32 KB
/
ft_trackusage.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
function ft_trackusage(event, varargin)
% FT_TRACKUSAGE tracks the usage of specific FieldTrip components using a central
% tracking server. This involves sending a small snippet of information to the
% server. Tracking is only used to gather data on the usage of the FieldTrip
% toolbox, to get information on the number of users and on the frequency of use
% of specific toolbox functions. This allows the toolbox developers to improve the
% FIeldTrip toolbox source code, documentation and to provide better support.
%
% This function will NOT upload any information about the data, nor about the
% configuration that you are using in your analyses.
%
% This function will NOT upload any identifying details about you. Your username
% and computer name are "salted" and subsequently converted with the MD5
% cryptographic hashing function into a unique identifier. Not knowing the salt,
% it is impossible to decode these MD5 hashes and recover the original
% identifiers.
%
% It is possible to disable the tracking for all functions by specifying
% the following
% global ft_defaults
% ft_default.trackusage = 'no'
%
% See the following online documentation for more information
% http://en.wikipedia.org/wiki/MD5
% http://en.wikipedia.org/wiki/Salt_(cryptography)
% http://www.fieldtriptoolbox.org/faq/tracking
%
% See also FT_DEFAULTS
% Copyright (C) 2015, Robert Oostenveld
%
% This file is part of FieldTrip, see http://www.ru.nl/donders/fieldtrip
% for the documentation and details.
%
% FieldTrip is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% FieldTrip is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
%
% $Id$
try
global ft_default
persistent initialized
if isempty(initialized)
initialized = false;
end
if nargin<1
% there is nothing to track
return
end
if ~strcmp(mfilename, 'ft_trackusage')
% this function should not be used outside of the FieldTrip toolbox without updating the token (see below)
return
end
if ~ft_platform_supports('rng')
% this function should not (yet) be used on Octave
return
end
%% The first part pertains to keeping the tracking settings consistent over multiple MATLAB sessions
% This functionality overlaps in part with what normally would be done using
% ft_defaults, but is replicated here to make the tracking independent from the path
% settings in ft_defaults.
% locate the file that contains the persistent FieldTrip preferences
fieldtripprefs = fullfile(prefdir, 'fieldtripprefs.mat');
if ~isfield(ft_default, 'trackusage')
% read options from the preferences file
if exist(fieldtripprefs, 'file')
prefs = load(fieldtripprefs); % the file contains multiple fields
ft_default = mergestruct(ft_default, prefs);
end
end
if ~isfield(ft_default, 'trackusage')
% the default is to allow tracking
% create a salt for one-way encryption of identifying information
rng('shuffle');
trackusage = dec2hex(intmax('uint32')*rand(1)); % create a secret salt, this is never shared
ft_warning('enabling online tracking of FieldTrip usage, see http://www.fieldtriptoolbox.org/faq/tracking');
if exist(fieldtripprefs, 'file')
% update the existing preferences file
save(fieldtripprefs, 'trackusage', '-append');
end
% keep it in the global variable
ft_default.trackusage = trackusage;
clear trackusage
end
if ~exist(fieldtripprefs, 'file')
% save it to a new preferences file
trackusage = ft_default.trackusage;
save(fieldtripprefs, 'trackusage');
clear trackusage
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% The second part pertains to the actual tracking
if isequal(ft_default.trackusage, false) || isequal(ft_default.trackusage, 'no') || isequal(ft_default.trackusage, 'off')
return
end
% these are the default properties to track
properties.token = '1187d9a6959c39d0e733d6273d1658a5'; % this is specific for the FieldTrip project
properties.user = ft_hash(sprintf('%s%s', ft_default.trackusage, getusername)); % hash it with a secret salt
properties.host = ft_hash(sprintf('%s%s', ft_default.trackusage, gethostname)); % hash it with a secret salt
properties.matlab = version('-release');
properties.fieldtrip = ft_version;
properties.computer = lower(computer);
properties.distinct_id = properties.user; % this links the event to the profile
% user information only gets send once at startup
if ~initialized
% construct the HTTP request for Mixpanel, see https://mixpanel.com/help/reference/http
user_json = sprintf('{"$token": "%s", "$distinct_id": "%s", "$ip": "%s", "$set": { "Computer": "%s", "Matlab": "%s" } }', properties.token, properties.user, getaddress(), properties.computer, properties.matlab);
user_base64 = base64encode(user_json);
user_http = sprintf('http://api.mixpanel.com/engage/?data=%s', user_base64);
[output, status] = ft_urlread(user_http);
initialized = true;
end % if initialized
% add the properties for the particular event, these come in key-value pairs
for i=1:2:numel(varargin)
properties.(varargin{i}) = varargin{i+1};
end
% construct the HTTP request for Mixpanel, see https://mixpanel.com/help/reference/http
event_json = sprintf('{"event": "%s", "properties": {%s}}', event, ft_struct2json(properties));
event_base64 = base64encode(event_json);
event_http = sprintf('http://api.mixpanel.com/track/?data=%s', event_base64);
[output, status] = ft_urlread(event_http);
if ~status
disp(output);
ft_warning('could not send tracker information for "%s"', event);
return
end
catch
% there are multiple reasons why this might fail, e.g. because Java is not available
% see https://github.com/fieldtrip/fieldtrip/issues/539
end