-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlogging.js
More file actions
216 lines (199 loc) · 6.85 KB
/
Copy pathlogging.js
File metadata and controls
216 lines (199 loc) · 6.85 KB
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
// CHANGE ME: point this to your own spreadsheet to log
// your own data by modifying the function at the bottom.
//
// A simple Google-spreadsheet-based event logging framework.
//
// This is currently set up to log every mousedown and keydown
// event, as well as any events that might be triggered within
// the app by triggering the 'log' event anywhere in the doc
// as follows:
//
// $(element).trigger('log', ['myevent', {key1: val1, key2: val2}]);
var ENABLE_NETWORK_LOGGING = true; // Controls network logging.
var ENABLE_CONSOLE_LOGGING = false; // Controls console logging.
var LOG_VERSION = 'B'; // Labels every entry with version: "A".
// These event types are intercepted for logging before jQuery handlers.
var EVENT_TYPES_TO_LOG = {
mousedown: true,
keydown: true
};
// These event properties are copied to the log if present.
var EVENT_PROPERTIES_TO_LOG = {
which: true,
pageX: true,
pageY: true
};
// This function is called to record some global state on each event.
var GLOBAL_STATE_TO_LOG = function() {
return {};
};
(function() {
// A persistent unique id for the user.
var uid = getUniqueId();
// Hooks up all the event listeners.
function hookEventsToLog() {
// Set up low-level event capturing. This intercepts all
// native events before they bubble, so we log the state
// *before* normal event processing.
for (var event_type in EVENT_TYPES_TO_LOG) {
document.addEventListener(event_type, logEvent, true);
}
// Once the page is loaded, show our own unique id.
Util.events(document, {
// Final initalization entry point: the Javascript code inside this block
// runs at the end of start-up when the DOM is ready
"DOMContentLoaded": function() {
console.log('Your unique id is', uid);
Util.one('#bottomtext').innerHTML = 'Logging to the network as <nobr>' + uid + '</nobr>';
},
// Listen to 'log' events which are triggered anywhere in the document.
"log": function(evt) {
var detail = evt.detail;
logEvent(null, detail.name, detail.info);
}
});
}
// Returns a CSS selector that is descriptive of
// the element, for example, "td.left div" for
// a class-less div within a td of class "left".
function elementDesc(elt) {
if (elt == document) {
return 'document';
} else if (elt == window) {
return 'window';
}
function descArray(elt) {
var desc = [elt.tagName.toLowerCase()];
if (elt.id) {
desc.push('#' + elt.id);
}
for (var j = 0; j < elt.classList.length; j++) {
desc.push('.' + elt.classList[j]);
}
return desc;
}
var desc = [];
while (elt && desc.length <= 1) {
var desc2 = descArray(elt);
if (desc.length == 0) {
desc = desc2;
} else if (desc2.length > 1) {
desc2.push(' ', desc[0]);
desc = desc2;
}
elt = elt.parentElement;
}
return desc.join('');
}
// Parse user agent string by looking for recognized substring.
function findFirstString(str, choices) {
for (var j = 0; j < choices.length; j++) {
if (str.indexOf(choices[j]) >= 0) {
return choices[j];
}
}
return '?';
}
// Genrates or remembers a somewhat-unique ID with distilled user-agent info.
function getUniqueId() {
if (!('uid' in localStorage)) {
var browser = findFirstString(navigator.userAgent, [
'Seamonkey', 'Firefox', 'Chromium', 'Chrome', 'Safari', 'OPR', 'Opera',
'Edge', 'MSIE', 'Blink', 'Webkit', 'Gecko', 'Trident', 'Mozilla']);
var os = findFirstString(navigator.userAgent, [
'Android', 'iOS', 'Symbian', 'Blackberry', 'Windows Phone', 'Windows',
'OS X', 'Linux', 'iOS', 'CrOS']).replace(/ /g, '_');
var unique = ('' + Math.random()).substr(2);
localStorage['uid'] = os + '-' + browser + '-' + unique;
}
return localStorage['uid'];
}
// Log the given event.
function logEvent(event, customName, customInfo) {
var time = (new Date).getTime();
var name = customName || event.type;
// By default, monitor some global state on every event.
var infoObj = GLOBAL_STATE_TO_LOG();
// And monitor a few interesting fields from the event, if present.
for (var key in EVENT_PROPERTIES_TO_LOG) {
if (event) {
if (key in event) {
infoObj[key] = event[key];
}
}
}
// Let a custom event add fields to the info.
if (customInfo) {
infoObj = Object.assign(infoObj, customInfo);
}
var info = JSON.stringify(infoObj);
var target = document;
if (event) {
var target = elementDesc(event.target);
}
var state = location.hash;
if (ENABLE_CONSOLE_LOGGING) {
console.log(uid, time, name, target, info, state, LOG_VERSION);
}
if (ENABLE_NETWORK_LOGGING) {
sendNetworkLog(uid, time, name, target, info, state, LOG_VERSION);
}
}
// OK, go.
if (ENABLE_NETWORK_LOGGING) {
hookEventsToLog();
}
})();
/////////////////////////////////////////////////////////////////////////////
// CHANGE ME:
// ** Replace the function below by substituting your own google form. **
/////////////////////////////////////////////////////////////////////////////
//
// 1. Create a Google form called "Network Log" at forms.google.com.
// 2. Set it up to have several "short answer" questions; here we assume
// seven questions: uid, time, name, target, info, state, version.
// 3. Run googlesender.py (at goo.gl/jUkahv) to make a javascript
// function that submits records directly to the form.
// 4. Put that function in here, and replace the current sendNetworkLog
// so that your version is called to log events to your form.
//
// For example, the following code was written as follows:
// curl -sL goo.gl/jUkahv | python - https://docs.google.com/forms/d/1A...0/edit
//
// This preocess changes the ids below to direct your data into your own
// form and spreadsheet. The formid must be customized, and also the form
// field names such as "entry.1291686978" must be matched to your form.
// (The numerical field names for a Google form can be found by inspecting
// the form input fields.) This can be done manually, but since this is an
// error-prone process, it can be easier to use googlesender.py.
//
/////////////////////////////////////////////////////////////////////////////
// Network Logging submission function
// submits to the google form at this URL:
// docs.google.com/forms/d/1d2p3mG2MLDllRJ3OTl7x7NznqaiHR0O20gISVq4_sno/edit
function sendNetworkLog(
uid,
time,
name,
target,
info,
state,
version) {
var formid = "e/1FAIpQLSc2yHFS3o4tVlvPCQGnzeHxFzfTdVo_Jbu300to9KHk6g720A";
var data = {
"entry.1736239450": uid,
"entry.1397555684": time,
"entry.1802681682": name,
"entry.517971661": target,
"entry.1285080009": info,
"entry.1403476897": state,
"entry.336449894": version
};
var params = [];
for (key in data) {
params.push(key + "=" + encodeURIComponent(data[key]));
}
// Submit the form using an image to avoid CORS warnings.
(new Image).src = "https://docs.google.com/forms/d/" + formid +
"/formResponse?" + params.join("&");
}