浏览代码

feat(Analytics): Multiple analytics handlers support

j8
hristoterezov 8 年前
父节点
当前提交
dc0a7e7628
共有 5 个文件被更改,包括 139 次插入30 次删除
  1. 3
    1
      analytics.js
  2. 7
    23
      conference.js
  3. 128
    0
      modules/analytics/analytics.js
  4. 1
    1
      modules/config/URLProcessor.js
  5. 0
    5
      modules/settings/Settings.js

+ 3
- 1
analytics.js 查看文件

27
         action + '.' + data.browserName, label, value);
27
         action + '.' + data.browserName, label, value);
28
   };
28
   };
29
 
29
 
30
-  ctx.Analytics = Analytics;
30
+  if(typeof ctx.analyticsHandlers === "undefined")
31
+    ctx.analyticsHandlers = [];
32
+  ctx.analyticsHandlers.push(Analytics);
31
 }(window));
33
 }(window));

+ 7
- 23
conference.js 查看文件

13
 import UIEvents from './service/UI/UIEvents';
13
 import UIEvents from './service/UI/UIEvents';
14
 import UIUtil from './modules/UI/util/UIUtil';
14
 import UIUtil from './modules/UI/util/UIUtil';
15
 
15
 
16
+import analytics from './modules/analytics/analytics';
17
+
16
 const ConnectionEvents = JitsiMeetJS.events.connection;
18
 const ConnectionEvents = JitsiMeetJS.events.connection;
17
 const ConnectionErrors = JitsiMeetJS.errors.connection;
19
 const ConnectionErrors = JitsiMeetJS.errors.connection;
18
 
20
 
438
     return Promise.resolve();
440
     return Promise.resolve();
439
 }
441
 }
440
 
442
 
441
-/**
442
- * Set permanent properties to analytics.
443
- * NOTE: Has to be used after JitsiMeetJS.init. Otherwise analytics will be
444
- * null.
445
- */
446
-function setAnalyticsPermanentProperties() {
447
-    let permanentProperties = {
448
-        userAgent: navigator.userAgent,
449
-        roomName: APP.conference.roomName
450
-    };
451
-    let {server, group} = APP.tokenData;
452
-    if(server) {
453
-        permanentProperties.server = server;
454
-    }
455
-    if(group) {
456
-        permanentProperties.group = group;
457
-    }
458
-    JitsiMeetJS.analytics.addPermanentProperties(permanentProperties);
459
-}
460
-
461
 export default {
443
 export default {
462
     isModerator: false,
444
     isModerator: false,
463
     audioMuted: false,
445
     audioMuted: false,
504
             };
486
             };
505
         }
487
         }
506
 
488
 
507
-        return JitsiMeetJS.init(config)
508
-            .then(() => {
509
-                setAnalyticsPermanentProperties();
489
+        return JitsiMeetJS.init(
490
+            Object.assign(
491
+                {enableAnalyticsLogging: analytics.isEnabled()}, config)
492
+            ).then(() => {
493
+                analytics.init();
510
                 return createInitialLocalTracksAndConnect(options.roomName);
494
                 return createInitialLocalTracksAndConnect(options.roomName);
511
             }).then(([tracks, con]) => {
495
             }).then(([tracks, con]) => {
512
                 console.log('initialized with %s local tracks', tracks.length);
496
                 console.log('initialized with %s local tracks', tracks.length);

+ 128
- 0
modules/analytics/analytics.js 查看文件

1
+/* global JitsiMeetJS, config, APP */
2
+/**
3
+ * Load the integration of a third-party analytics API such as Google
4
+ * Analytics. Since we cannot guarantee the quality of the third-party service
5
+ * (e.g. their server may take noticeably long time to respond), it is in our
6
+ * best interest (in the sense that the intergration of the analytics API is
7
+ * important to us but not enough to allow it to prevent people from joining
8
+ * a conference) to download the API asynchronously. Additionally, Google
9
+ * Analytics will download its implementation asynchronously anyway so it makes
10
+ * sense to append the loading on our side rather than prepend it.
11
+ * @param {string} url the url to be loaded
12
+ * @returns {Promise} resolved with no arguments when the script is loaded and
13
+ * rejected with the error from JitsiMeetJS.ScriptUtil.loadScript method
14
+ */
15
+function loadScript(url) {
16
+    return new Promise((resolve, reject) =>
17
+        JitsiMeetJS.util.ScriptUtil.loadScript(
18
+            url,
19
+            /* async */ true,
20
+            /* prepend */ false,
21
+            /* relativeURL */ false,
22
+            /* loadCallback */ () => resolve(),
23
+            /* errorCallback */ error => reject(error)));
24
+}
25
+
26
+/**
27
+ * Handles the initialization of analytics.
28
+ */
29
+class Analytics {
30
+    constructor() {
31
+        this._scriptURLs = Array.isArray(config.analyticsScriptUrls)
32
+            ? config.analyticsScriptUrls : [];
33
+        this._enabled = !!this._scriptURLs.length
34
+            && !config.disableThirdPartyRequests;
35
+        window.analyticsHandlers = [];
36
+        const machineId = JitsiMeetJS.getMachineId();
37
+        this._handlerConstructorOptions = {
38
+            product: "lib-jitsi-meet",
39
+            version: JitsiMeetJS.version,
40
+            session: machineId,
41
+            user:  "uid-" + machineId
42
+        };
43
+    }
44
+
45
+    /**
46
+     * Returns whether analytics is enabled or not.
47
+     * @returns {boolean} whether analytics is enabled or not.
48
+     */
49
+    isEnabled() {
50
+        return this._enabled;
51
+    }
52
+
53
+    /**
54
+     * Tries to load the scripts for the analytics handlers.
55
+     * @returns {Promise} resolves with the handlers that have been
56
+     * successfully loaded and rejects if there are no handlers loaded or the
57
+     * analytics is disabled.
58
+     */
59
+    _loadHandlers() {
60
+        if(!this.isEnabled()) {
61
+            return Promise.reject(new Error("Analytics is disabled!"));
62
+        }
63
+        let handlersPromises = [];
64
+        this._scriptURLs.forEach(url =>
65
+            handlersPromises.push(
66
+                loadScript(url).then(
67
+                    () => {
68
+                        return {type: "success"};
69
+                    },
70
+                    error => {
71
+                        return {type: "error", error, url};
72
+                    }))
73
+        );
74
+        return new Promise((resolve, reject) =>
75
+        {
76
+            Promise.all(handlersPromises).then(values => {
77
+                values.forEach(el => {
78
+                    if(el.type === "error") {
79
+                        console.log("Fialed to load " + el.url);
80
+                        console.error(el.error);
81
+                    }
82
+                });
83
+
84
+                if(window.analyticsHandlers.length === 0) {
85
+                    reject(new Error("No analytics handlers available"));
86
+                } else {
87
+                    let handlerInstances = [];
88
+                    window.analyticsHandlers.forEach(
89
+                        Handler => handlerInstances.push(
90
+                            new Handler(this._handlerConstructorOptions)));
91
+                    resolve(handlerInstances);
92
+                }
93
+            });
94
+        });
95
+    }
96
+
97
+    /**
98
+     * Loads the analytics scripts and inits JitsiMeetJS.analytics by setting
99
+     * permanent properties and setting the handlers from the loaded scripts.
100
+     * NOTE: Has to be used after JitsiMeetJS.init. Otherwise analytics will be
101
+     * null.
102
+     */
103
+    init() {
104
+        let analytics = JitsiMeetJS.analytics;
105
+        if(!this.isEnabled() || !analytics)
106
+            return;
107
+
108
+        this._loadHandlers()
109
+            .then(handlers => {
110
+                let permanentProperties = {
111
+                    userAgent: navigator.userAgent,
112
+                    roomName: APP.conference.roomName
113
+                };
114
+                let {server, group} = APP.tokenData;
115
+                if(server) {
116
+                    permanentProperties.server = server;
117
+                }
118
+                if(group) {
119
+                    permanentProperties.group = group;
120
+                }
121
+                analytics.addPermanentProperties(permanentProperties);
122
+                analytics.setAnalyticsHandlers(handlers);
123
+            }, error => analytics.dispose() && console.error(error));
124
+
125
+    }
126
+}
127
+
128
+export default new Analytics();

+ 1
- 1
modules/config/URLProcessor.js 查看文件

38
                 confKey = key.substr("config.".length);
38
                 confKey = key.substr("config.".length);
39
 
39
 
40
                 // prevent passing some parameters which can inject scripts
40
                 // prevent passing some parameters which can inject scripts
41
-                if (confKey === 'analyticsScriptUrl'
41
+                if (confKey === 'analyticsScriptUrls'
42
                     || confKey === 'callStatsCustomScriptUrl')
42
                     || confKey === 'callStatsCustomScriptUrl')
43
                     continue;
43
                     continue;
44
 
44
 

+ 0
- 5
modules/settings/Settings.js 查看文件

9
     return _p8() + _p8() + _p8() + _p8();
9
     return _p8() + _p8() + _p8() + _p8();
10
 }
10
 }
11
 
11
 
12
-if (!jitsiLocalStorage.getItem("jitsiMeetId")) {
13
-    jitsiLocalStorage.setItem("jitsiMeetId",generateUniqueId());
14
-    console.log("generated id", jitsiLocalStorage.getItem("jitsiMeetId"));
15
-}
16
-
17
 let avatarUrl = '';
12
 let avatarUrl = '';
18
 
13
 
19
 let email = UIUtil.unescapeHtml(jitsiLocalStorage.getItem("email") || '');
14
 let email = UIUtil.unescapeHtml(jitsiLocalStorage.getItem("email") || '');

正在加载...
取消
保存