@capillarytech/cap-ui-utils 1.2.2 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/GA/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import ReactGA from 'react-ga';
2
- // import ttiPolyfill from 'tti-polyfill';
2
+ import ttiPolyfill from 'tti-polyfill';
3
+
3
4
  import timeTracker from './utils/timeTracker';
4
5
  import tracker from './utils/tracker';
5
6
  import routeTrackerWrapper from './utils/routeTrackerWrapper';
@@ -9,18 +10,18 @@ import warn from '../utils/console/warn';
9
10
  import log from '../utils/console/log';
10
11
 
11
12
  const _initialize = (GAConfigs) => {
12
- if (!GAConfigs.accessKey) {
13
+ const { accessKey, trackUIError, trackLoadPerformance } = GAConfigs || {}
14
+ if (!accessKey) {
13
15
  warn("Cannot initialize GA without accessKey");
14
16
  return;
17
+ } else {
18
+ ReactGA.initialize(accessKey,{debug: true,});
15
19
  }
16
- if(GAConfigs.accessKey) {
17
- ReactGA.initialize(GAConfigs.accessKey,{debug: true,});
20
+ if(trackUIError){
21
+ errorTracks();
18
22
  }
19
- if(GAConfigs.trackError){
20
- //Track Error
21
- window.addEventListener('error', (e) =>{
22
- tracker.trackException(`UI Error ${e.message}`);
23
- });
23
+ if(trackLoadPerformance){
24
+ loadPerformanceTracking(trackLoadPerformance);
24
25
  }
25
26
  eventsAfterInitialize();
26
27
  log("Cap GA initialized");
@@ -28,19 +29,67 @@ const _initialize = (GAConfigs) => {
28
29
  const setCustomDimension= value => {
29
30
  ReactGA.set(value);
30
31
  }
32
+ const loadPerformanceTracking = module =>{
33
+ //requestStart: when the browser issues a request to get the webpage from the server
34
+ // responsesStart: when the first byte of the website arrives
35
+ // responseEnd: When the last byte of the website arrives
36
+
37
+ const callback = list => {
38
+ list.getEntries().forEach(entry => {
39
+ const { responseStart = 0, requestStart = 0, responseEnd = 0 } = entry || {};
40
+ const serverLatency = Math.round((responseStart - requestStart).toFixed(2));
41
+ const downloadTime = Math.round((responseEnd - responseStart).toFixed(2));
42
+ const loadTime = Math.round((responseEnd - requestStart).toFixed(2));
43
+ // Server latency:
44
+ ReactGA.timing({
45
+ category: "performance- server latentcy",
46
+ variable: module,
47
+ value: serverLatency,
48
+ })
49
+ // Download time:
50
+ ReactGA.timing({
51
+ category: "performance- download time",
52
+ variable: module,
53
+ value: downloadTime
54
+ })
55
+ // Total app load time:
56
+ ReactGA.timing({
57
+ category: "performance- load time",
58
+ variable: module,
59
+ value: loadTime
60
+ })
61
+ });
62
+ };
63
+
64
+ try {
65
+ var observer = new PerformanceObserver(callback);
66
+ observer.observe({ entryTypes: ['navigation'] });
67
+ // Time to Interactive metric is essentially how long it takes for a user to be able to interact with your site.
68
+ // Time to Interactive is defined as the point at which the layout has stabilized, key webfonts are visible,
69
+ // and the main thread is available enough to handle user input.
70
+ ttiPolyfill.getFirstConsistentlyInteractive().then((tti) => {
71
+ ReactGA.timing({
72
+ category: "Time to Interactive",
73
+ variable: module,
74
+ value: Math.round(tti.toFixed(2))
75
+ })
76
+ });
77
+ }catch(e){
78
+ console.log(e);
79
+ }
80
+ }
31
81
  const initialize = (GAConfigs) =>{
32
82
  if (isEmpty(GAConfigs)) {
33
83
  warn("Cannot initialize empty object");
34
84
  return;
35
85
  }
36
86
  for ( const config in GAConfigs) {
37
- if (isEmpty(GAConfigs[config])) {
87
+ if (!GAConfigs[config]) {
38
88
  warn("Config is empty");
39
89
  return;
40
90
  }
41
91
  }
42
92
  _initialize(GAConfigs);
43
-
44
93
  return true;
45
94
  }
46
95
  const eventsAfterInitialize = () => {
@@ -52,39 +101,56 @@ const eventsAfterInitialize = () => {
52
101
  });
53
102
  }
54
103
 
104
+ const errorTracks = () => {
105
+ window.onerror = function (msg, url, lineNo, columnNo, error) {
106
+ // to avoid 2 times same error log
107
+ if (error.hasBeenCaught !== undefined){
108
+ return false
109
+ }
110
+ error.hasBeenCaught = true
111
+ const message = [
112
+ 'Message: ' + msg,
113
+ 'URL: ' + url,
114
+ ].join(' - ');
115
+ tracker.trackException({
116
+ description: message,
117
+ fatal: true,
118
+ });
119
+ };
120
+ }
121
+ const getCallerName = () => {
122
+ let nameTrace;
123
+ try {
124
+ throw new Error();
125
+ } catch (e) {
126
+ // Error.prototype.stack Manually throw an error and catch the function name by tracing the stack
127
+ //As per MDN, the use of Error.prototype.stack is discouraged because of it's non-standard behaviour and it's behaviour might change on different browsers
128
+ //once we find better solution we will make the changes
129
+ let stackLines = e.stack.split('\n');
130
+ let callerIndex = 0;
131
+ for (let i in stackLines) {
132
+ if (stackLines.hasOwnProperty(i)) {
133
+ if (!stackLines[i].match(/http[s]?:\/\//)) continue;
134
+ callerIndex = Number(i) + 2;
135
+ break;
136
+ }
137
+ }
138
+ nameTrace = stackLines[callerIndex].match(/([^(]+)@|at ([^(]+) \(/);
139
+ if (nameTrace === null) {
140
+ callerIndex = callerIndex - 2;
141
+ nameTrace = stackLines[callerIndex].match(/([^(]+)@|at ([^(]+) \(/);
142
+ }
143
+ }
144
+ return nameTrace !== null ? nameTrace[1] || nameTrace[2] : '';
145
+ }
55
146
 
56
- // ttiPolyfill.getFirstConsistentlyInteractive().then(tti => {
57
- // console.log('performance tti', tti);
58
- // });
59
-
60
- // const callback = list => {
61
- // list.getEntries().forEach(entry => {
62
- // console.log('performance callback entry', entry);
63
- // console.log(
64
- // 'performance callback server latentcy',
65
- // entry.responseStart - entry.requestStart,
66
- // );
67
- // console.log(
68
- // 'performance callback download time',
69
- // entry.responseEnd - entry.responseStart,
70
- // );
71
- // console.log(
72
- // 'performance callback load time',
73
- // entry.responseEnd - entry.requestStart,
74
- // );
75
- // });
76
- // };
77
147
 
78
- // var observer = new PerformanceObserver(callback);
79
- // observer.observe({ entryTypes: ['navigation'] });
80
- // var perfData = window.performance.timing;
81
- // var pageLoadTime = perfData.loadEventEnd - perfData.navigationStart;
82
- // console.log('Performance metrics', perfData, pageLoadTime);
83
148
 
84
149
  export default{
85
150
  initialize,
86
151
  timeTracker,
87
152
  tracker,
88
153
  routeTrackerWrapper,
89
- setCustomDimension
154
+ setCustomDimension,
155
+ getCallerName,
90
156
  }
@@ -8,7 +8,7 @@ const trackTiming = () => {}
8
8
 
9
9
  const trackPageView = () => {}
10
10
 
11
- const trackException = (description, fatal = true) => {
11
+ const trackException = ({description, fatal = true}) => {
12
12
  ReactGA.exception({
13
13
  description,
14
14
  fatal,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capillarytech/cap-ui-utils",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "Utility functions shared accross all the modules",
5
5
  "main": "index.js",
6
6
  "scripts": {