@cloudcare/browser-core 1.0.29 → 1.1.2

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.
@@ -8,7 +8,9 @@ exports.UUID = UUID;
8
8
  exports.addEvent = exports._URL = void 0;
9
9
  exports.addEventListener = addEventListener;
10
10
  exports.addEventListeners = addEventListeners;
11
- exports.base64Encode = exports.autoExeQueue = exports.ajax = exports.addSinglePageEvent = exports.addHashEvent = void 0;
11
+ exports.ajax = exports.addSinglePageEvent = exports.addHashEvent = void 0;
12
+ exports.assign = assign;
13
+ exports.base64Encode = exports.autoExeQueue = void 0;
12
14
  exports.clocksNow = clocksNow;
13
15
  exports.clocksOrigin = clocksOrigin;
14
16
  exports.coverExtend = exports.cookie = void 0;
@@ -19,8 +21,10 @@ exports.deepSnakeCase = deepSnakeCase;
19
21
  exports.each = void 0;
20
22
  exports.elapsed = elapsed;
21
23
  exports.encodeDates = void 0;
24
+ exports.escapeFieldValueStr = escapeFieldValueStr;
22
25
  exports.escapeJsonValue = escapeJsonValue;
23
26
  exports.escapeRowData = escapeRowData;
27
+ exports.escapeRowField = escapeRowField;
24
28
  exports.filter = exports.extend2Lev = exports.extend = void 0;
25
29
  exports.find = find;
26
30
  exports.findByPath = findByPath;
@@ -58,7 +62,10 @@ exports.replaceNumberCharByPath = replaceNumberCharByPath;
58
62
  exports.round = round;
59
63
  exports.safeJSONParse = void 0;
60
64
  exports.safeTruncate = safeTruncate;
61
- exports.throttle = exports.strip_sa_properties = exports.strip_empty_properties = exports.stringSplice = exports.strToUnicode = exports.sessionStorage = exports.searchObjString = exports.searchObjDate = exports.searchConfigData = void 0;
65
+ exports.sessionStorage = exports.searchObjString = exports.searchObjDate = exports.searchConfigData = void 0;
66
+ exports.shallowClone = shallowClone;
67
+ exports.strToUnicode = void 0;
68
+ exports.throttle = exports.strip_sa_properties = exports.strip_empty_properties = exports.stringSplice = void 0;
62
69
  exports.timeStampNow = timeStampNow;
63
70
  exports.toArray = exports.tirm = void 0;
64
71
  exports.toServerDuration = toServerDuration;
@@ -105,6 +112,21 @@ var each = function each(obj, iterator, context) {
105
112
 
106
113
  exports.each = each;
107
114
 
115
+ function assign(target) {
116
+ each(slice.call(arguments, 1), function (source) {
117
+ for (var prop in source) {
118
+ if (Object.prototype.hasOwnProperty.call(source, prop)) {
119
+ target[prop] = source[prop];
120
+ }
121
+ }
122
+ });
123
+ return target;
124
+ }
125
+
126
+ function shallowClone(object) {
127
+ return assign({}, object);
128
+ }
129
+
108
130
  var extend = function extend(obj) {
109
131
  each(slice.call(arguments, 1), function (source) {
110
132
  for (var prop in source) {
@@ -1812,7 +1834,7 @@ function clocksNow() {
1812
1834
  }
1813
1835
 
1814
1836
  function timeStampNow() {
1815
- return Date.now();
1837
+ return new Date().getTime();
1816
1838
  }
1817
1839
 
1818
1840
  function elapsed(start, end) {
@@ -2042,4 +2064,18 @@ function escapeJsonValue(value) {
2042
2064
  } else {
2043
2065
  return jsonStringify(value);
2044
2066
  }
2067
+ }
2068
+
2069
+ function escapeFieldValueStr(str) {
2070
+ return '"' + str.replace(/[\\]*"/g, '"').replace(/"/g, '\\"') + '"';
2071
+ }
2072
+
2073
+ function escapeRowField(value) {
2074
+ if (_typeof(value) === 'object' && value) {
2075
+ return escapeFieldValueStr(jsonStringify(value));
2076
+ } else if (isString(value)) {
2077
+ return escapeFieldValueStr(value);
2078
+ } else {
2079
+ return value;
2080
+ }
2045
2081
  }
package/cjs/transport.js CHANGED
@@ -11,6 +11,8 @@ var _enums = require("./helper/enums");
11
11
 
12
12
  var _dataMap = require("./dataMap");
13
13
 
14
+ var _init = require("./init");
15
+
14
16
  // https://en.wikipedia.org/wiki/UTF-8
15
17
  var HAS_MULTI_BYTES_CHARACTERS = /[^\u0000-\u007F]/;
16
18
  var CUSTOM_KEYS = 'custom_keys';
@@ -20,27 +22,37 @@ function addBatchPrecision(url) {
20
22
  return url + (url.indexOf('?') === -1 ? '?' : '&') + 'precision=ms';
21
23
  }
22
24
 
25
+ var global = (0, _init.getGlobalObject)();
26
+
23
27
  var httpRequest = function httpRequest(endpointUrl, bytesLimit, isLineProtocolToJson) {
24
28
  this.endpointUrl = endpointUrl;
25
29
  this.bytesLimit = bytesLimit;
26
30
  this.isLineProtocolToJson = isLineProtocolToJson;
31
+ var isRealNavigator = Object.prototype.toString.call(global && global.navigator) === '[object Navigator]';
32
+ var hasSendBeacon = isRealNavigator && typeof global.navigator.sendBeacon === 'function';
33
+
34
+ if (hasSendBeacon) {
35
+ this.sendBeacon = global.navigator.sendBeacon.bind(global.navigator);
36
+ } else {
37
+ this.sendBeacon = undefined;
38
+ }
27
39
  };
28
40
 
29
41
  httpRequest.prototype = {
30
42
  send: function send(data, size) {
31
43
  var url = addBatchPrecision(this.endpointUrl);
32
44
 
33
- if (navigator.sendBeacon && size < this.bytesLimit && !this.isLineProtocolToJson) {
34
- var isQueued = navigator.sendBeacon(url, data);
45
+ if (this.sendBeacon && size < this.bytesLimit && !this.isLineProtocolToJson) {
46
+ var isQueued = this.sendBeacon(url, data);
35
47
 
36
48
  if (isQueued) {
37
49
  return;
38
50
  }
39
- } else if (navigator.sendBeacon && size < this.bytesLimit && this.isLineProtocolToJson) {
51
+ } else if (this.sendBeacon && size < this.bytesLimit && this.isLineProtocolToJson) {
40
52
  var blob = new Blob([JSON.stringify(data)], {
41
53
  type: 'application/json'
42
54
  });
43
- var isQueued = navigator.sendBeacon(url, blob);
55
+ var isQueued = this.sendBeacon(url, blob);
44
56
 
45
57
  if (isQueued) {
46
58
  return;
@@ -80,7 +92,7 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
80
92
  rowData.measurement = key;
81
93
  var tagsStr = [];
82
94
  var tags = (0, _tools.extend)({}, _dataMap.commonTags, value.tags);
83
- var filterFileds = ['date', 'type']; // 已经在datamap中定义过的fields和tags
95
+ var filterFileds = ['date', 'type', CUSTOM_KEYS]; // 已经在datamap中定义过的fields和tags
84
96
 
85
97
  (0, _tools.each)(tags, function (value_path, _key) {
86
98
  var _value = (0, _tools.findByPath)(message, value_path);
@@ -104,9 +116,14 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
104
116
 
105
117
  if (_valueData || (0, _tools.isNumber)(_valueData)) {
106
118
  rowData.fields[_key] = _valueData; // 这里不需要转译
107
-
108
- _valueData = type === 'string' ? '"' + _valueData.replace(/[\\]*"/g, '"').replace(/"/g, '\\"') + '"' : (0, _tools.escapeRowData)(_valueData);
109
- fieldsStr.push((0, _tools.escapeRowData)(_key) + '=' + _valueData);
119
+ // _valueData =
120
+ // type === 'string'
121
+ // ? '"' +
122
+ // _valueData.replace(/[\\]*"/g, '"').replace(/"/g, '\\"') +
123
+ // '"'
124
+ // : escapeRowData(_valueData)
125
+
126
+ fieldsStr.push((0, _tools.escapeRowData)(_key) + '=' + (0, _tools.escapeRowField)(_valueData));
110
127
  }
111
128
  } else if ((0, _tools.isString)(_value)) {
112
129
  var _valueData = (0, _tools.findByPath)(message, _value);
@@ -116,14 +133,13 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
116
133
  if (_valueData || (0, _tools.isNumber)(_valueData)) {
117
134
  rowData.fields[_key] = _valueData; // 这里不需要转译
118
135
 
119
- _valueData = (0, _tools.escapeRowData)(_valueData);
120
- fieldsStr.push((0, _tools.escapeRowData)(_key) + '=' + _valueData);
136
+ fieldsStr.push((0, _tools.escapeRowData)(_key) + '=' + (0, _tools.escapeRowField)(_valueData));
121
137
  }
122
138
  }
123
139
  });
124
140
 
125
141
  if (message.tags && (0, _tools.isObject)(message.tags) && !(0, _tools.isEmptyObject)(message.tags)) {
126
- // 自定义tag
142
+ // 自定义tag, 存储成field
127
143
  var _tagKeys = [];
128
144
  (0, _tools.each)(message.tags, function (_value, _key) {
129
145
  // 如果和之前tag重名,则舍弃
@@ -133,14 +149,15 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
133
149
  if (_value || (0, _tools.isNumber)(_value)) {
134
150
  _tagKeys.push(_key);
135
151
 
136
- rowData.tags[_key] = (0, _tools.escapeJsonValue)(_value);
137
- tagsStr.push((0, _tools.escapeRowData)(_key) + '=' + (0, _tools.escapeRowData)(_value));
152
+ rowData.fields[_key] = _value; // 这里不需要转译
153
+
154
+ fieldsStr.push((0, _tools.escapeRowData)(_key) + '=' + (0, _tools.escapeRowField)(_value));
138
155
  }
139
156
  });
140
157
 
141
158
  if (_tagKeys.length) {
142
- rowData.tags[CUSTOM_KEYS] = (0, _tools.escapeJsonValue)(_tagKeys);
143
- tagsStr.push((0, _tools.escapeRowData)(CUSTOM_KEYS) + '=' + (0, _tools.escapeRowData)(_tagKeys));
159
+ rowData.fields[CUSTOM_KEYS] = (0, _tools.escapeRowField)(_tagKeys);
160
+ fieldsStr.push((0, _tools.escapeRowData)(CUSTOM_KEYS) + '=' + (0, _tools.escapeRowField)(_tagKeys));
144
161
  }
145
162
  }
146
163
 
@@ -148,8 +165,9 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
148
165
  // 这里处理日志类型数据自定义字段
149
166
  (0, _tools.each)(message, function (value, key) {
150
167
  if (filterFileds.indexOf(key) === -1 && ((0, _tools.isNumber)(value) || (0, _tools.isString)(value) || (0, _tools.isBoolean)(value))) {
151
- rowData.tags[key] = (0, _tools.escapeJsonValue)(value);
152
- tagsStr.push((0, _tools.escapeRowData)(key) + '=' + (0, _tools.escapeRowData)(value));
168
+ rowData.fields[key] = value; // 这里不需要转译
169
+
170
+ fieldsStr.push((0, _tools.escapeRowData)(key) + '=' + (0, _tools.escapeRowField)(value));
153
171
  }
154
172
  });
155
173
  }
@@ -176,20 +194,21 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
176
194
 
177
195
  exports.processedMessageByDataMap = processedMessageByDataMap;
178
196
 
179
- function batch(request, maxSize, bytesLimit, maxMessageSize, flushTimeout, isLineProtocolToJson, beforeUnloadCallback) {
197
+ var batch = function batch(request, maxSize, bytesLimit, maxMessageSize, flushTimeout, isLineProtocolToJson, beforeUnloadCallback) {
180
198
  this.request = request;
181
199
  this.maxSize = maxSize;
182
200
  this.bytesLimit = bytesLimit;
183
201
  this.maxMessageSize = maxMessageSize;
184
202
  this.flushTimeout = flushTimeout;
185
- this.isLineProtocolToJson = isLineProtocolToJson, this.beforeUnloadCallback = beforeUnloadCallback;
203
+ this.isLineProtocolToJson = isLineProtocolToJson;
204
+ this.beforeUnloadCallback = beforeUnloadCallback;
186
205
  this.pushOnlyBuffer = [];
187
206
  this.upsertBuffer = {};
188
207
  this.bufferBytesSize = 0;
189
208
  this.bufferMessageCount = 0;
190
209
  this.flushOnVisibilityHidden();
191
210
  this.flushPeriodically();
192
- }
211
+ };
193
212
 
194
213
  batch.prototype = {
195
214
  add: function add(message) {
@@ -321,7 +340,7 @@ batch.prototype = {
321
340
  // @ts-ignore this function is not always defined
322
341
 
323
342
 
324
- if (navigator.sendBeacon) {
343
+ if (global.navigator.sendBeacon) {
325
344
  /**
326
345
  * beforeunload is called before visibilitychange
327
346
  * register first to be sure to be called before flush on beforeunload
@@ -30,6 +30,19 @@ export var each = function each(obj, iterator, context) {
30
30
  }
31
31
  }
32
32
  };
33
+ export function assign(target) {
34
+ each(slice.call(arguments, 1), function (source) {
35
+ for (var prop in source) {
36
+ if (Object.prototype.hasOwnProperty.call(source, prop)) {
37
+ target[prop] = source[prop];
38
+ }
39
+ }
40
+ });
41
+ return target;
42
+ }
43
+ export function shallowClone(object) {
44
+ return assign({}, object);
45
+ }
33
46
  export var extend = function extend(obj) {
34
47
  each(slice.call(arguments, 1), function (source) {
35
48
  for (var prop in source) {
@@ -1526,7 +1539,7 @@ export function clocksNow() {
1526
1539
  };
1527
1540
  }
1528
1541
  export function timeStampNow() {
1529
- return Date.now();
1542
+ return new Date().getTime();
1530
1543
  }
1531
1544
  export function elapsed(start, end) {
1532
1545
  return end - start;
@@ -1733,4 +1746,16 @@ export function escapeJsonValue(value) {
1733
1746
  } else {
1734
1747
  return jsonStringify(value);
1735
1748
  }
1749
+ }
1750
+ export function escapeFieldValueStr(str) {
1751
+ return '"' + str.replace(/[\\]*"/g, '"').replace(/"/g, '\\"') + '"';
1752
+ }
1753
+ export function escapeRowField(value) {
1754
+ if (typeof value === 'object' && value) {
1755
+ return escapeFieldValueStr(jsonStringify(value));
1756
+ } else if (isString(value)) {
1757
+ return escapeFieldValueStr(value);
1758
+ } else {
1759
+ return value;
1760
+ }
1736
1761
  }
package/esm/transport.js CHANGED
@@ -1,6 +1,7 @@
1
- import { addEventListener, values, findByPath, escapeRowData, each, isNumber, isArray, extend, isString, toServerDuration, isBoolean, isEmptyObject, isObject, map, escapeJsonValue } from './helper/tools';
1
+ import { addEventListener, values, findByPath, escapeRowData, each, isNumber, isArray, extend, isString, toServerDuration, isBoolean, isEmptyObject, isObject, map, escapeJsonValue, escapeRowField } from './helper/tools';
2
2
  import { DOM_EVENT, RumEventType } from './helper/enums';
3
- import { commonTags, dataMap } from './dataMap'; // https://en.wikipedia.org/wiki/UTF-8
3
+ import { commonTags, dataMap } from './dataMap';
4
+ import { getGlobalObject } from './init'; // https://en.wikipedia.org/wiki/UTF-8
4
5
 
5
6
  var HAS_MULTI_BYTES_CHARACTERS = /[^\u0000-\u007F]/;
6
7
  var CUSTOM_KEYS = 'custom_keys';
@@ -10,27 +11,37 @@ function addBatchPrecision(url) {
10
11
  return url + (url.indexOf('?') === -1 ? '?' : '&') + 'precision=ms';
11
12
  }
12
13
 
14
+ var global = getGlobalObject();
15
+
13
16
  var httpRequest = function httpRequest(endpointUrl, bytesLimit, isLineProtocolToJson) {
14
17
  this.endpointUrl = endpointUrl;
15
18
  this.bytesLimit = bytesLimit;
16
19
  this.isLineProtocolToJson = isLineProtocolToJson;
20
+ var isRealNavigator = Object.prototype.toString.call(global && global.navigator) === '[object Navigator]';
21
+ var hasSendBeacon = isRealNavigator && typeof global.navigator.sendBeacon === 'function';
22
+
23
+ if (hasSendBeacon) {
24
+ this.sendBeacon = global.navigator.sendBeacon.bind(global.navigator);
25
+ } else {
26
+ this.sendBeacon = undefined;
27
+ }
17
28
  };
18
29
 
19
30
  httpRequest.prototype = {
20
31
  send: function send(data, size) {
21
32
  var url = addBatchPrecision(this.endpointUrl);
22
33
 
23
- if (navigator.sendBeacon && size < this.bytesLimit && !this.isLineProtocolToJson) {
24
- var isQueued = navigator.sendBeacon(url, data);
34
+ if (this.sendBeacon && size < this.bytesLimit && !this.isLineProtocolToJson) {
35
+ var isQueued = this.sendBeacon(url, data);
25
36
 
26
37
  if (isQueued) {
27
38
  return;
28
39
  }
29
- } else if (navigator.sendBeacon && size < this.bytesLimit && this.isLineProtocolToJson) {
40
+ } else if (this.sendBeacon && size < this.bytesLimit && this.isLineProtocolToJson) {
30
41
  var blob = new Blob([JSON.stringify(data)], {
31
42
  type: 'application/json'
32
43
  });
33
- var isQueued = navigator.sendBeacon(url, blob);
44
+ var isQueued = this.sendBeacon(url, blob);
34
45
 
35
46
  if (isQueued) {
36
47
  return;
@@ -68,7 +79,7 @@ export var processedMessageByDataMap = function processedMessageByDataMap(messag
68
79
  rowData.measurement = key;
69
80
  var tagsStr = [];
70
81
  var tags = extend({}, commonTags, value.tags);
71
- var filterFileds = ['date', 'type']; // 已经在datamap中定义过的fields和tags
82
+ var filterFileds = ['date', 'type', CUSTOM_KEYS]; // 已经在datamap中定义过的fields和tags
72
83
 
73
84
  each(tags, function (value_path, _key) {
74
85
  var _value = findByPath(message, value_path);
@@ -92,9 +103,14 @@ export var processedMessageByDataMap = function processedMessageByDataMap(messag
92
103
 
93
104
  if (_valueData || isNumber(_valueData)) {
94
105
  rowData.fields[_key] = _valueData; // 这里不需要转译
95
-
96
- _valueData = type === 'string' ? '"' + _valueData.replace(/[\\]*"/g, '"').replace(/"/g, '\\"') + '"' : escapeRowData(_valueData);
97
- fieldsStr.push(escapeRowData(_key) + '=' + _valueData);
106
+ // _valueData =
107
+ // type === 'string'
108
+ // ? '"' +
109
+ // _valueData.replace(/[\\]*"/g, '"').replace(/"/g, '\\"') +
110
+ // '"'
111
+ // : escapeRowData(_valueData)
112
+
113
+ fieldsStr.push(escapeRowData(_key) + '=' + escapeRowField(_valueData));
98
114
  }
99
115
  } else if (isString(_value)) {
100
116
  var _valueData = findByPath(message, _value);
@@ -104,14 +120,13 @@ export var processedMessageByDataMap = function processedMessageByDataMap(messag
104
120
  if (_valueData || isNumber(_valueData)) {
105
121
  rowData.fields[_key] = _valueData; // 这里不需要转译
106
122
 
107
- _valueData = escapeRowData(_valueData);
108
- fieldsStr.push(escapeRowData(_key) + '=' + _valueData);
123
+ fieldsStr.push(escapeRowData(_key) + '=' + escapeRowField(_valueData));
109
124
  }
110
125
  }
111
126
  });
112
127
 
113
128
  if (message.tags && isObject(message.tags) && !isEmptyObject(message.tags)) {
114
- // 自定义tag
129
+ // 自定义tag, 存储成field
115
130
  var _tagKeys = [];
116
131
  each(message.tags, function (_value, _key) {
117
132
  // 如果和之前tag重名,则舍弃
@@ -121,14 +136,15 @@ export var processedMessageByDataMap = function processedMessageByDataMap(messag
121
136
  if (_value || isNumber(_value)) {
122
137
  _tagKeys.push(_key);
123
138
 
124
- rowData.tags[_key] = escapeJsonValue(_value);
125
- tagsStr.push(escapeRowData(_key) + '=' + escapeRowData(_value));
139
+ rowData.fields[_key] = _value; // 这里不需要转译
140
+
141
+ fieldsStr.push(escapeRowData(_key) + '=' + escapeRowField(_value));
126
142
  }
127
143
  });
128
144
 
129
145
  if (_tagKeys.length) {
130
- rowData.tags[CUSTOM_KEYS] = escapeJsonValue(_tagKeys);
131
- tagsStr.push(escapeRowData(CUSTOM_KEYS) + '=' + escapeRowData(_tagKeys));
146
+ rowData.fields[CUSTOM_KEYS] = escapeRowField(_tagKeys);
147
+ fieldsStr.push(escapeRowData(CUSTOM_KEYS) + '=' + escapeRowField(_tagKeys));
132
148
  }
133
149
  }
134
150
 
@@ -136,8 +152,9 @@ export var processedMessageByDataMap = function processedMessageByDataMap(messag
136
152
  // 这里处理日志类型数据自定义字段
137
153
  each(message, function (value, key) {
138
154
  if (filterFileds.indexOf(key) === -1 && (isNumber(value) || isString(value) || isBoolean(value))) {
139
- rowData.tags[key] = escapeJsonValue(value);
140
- tagsStr.push(escapeRowData(key) + '=' + escapeRowData(value));
155
+ rowData.fields[key] = value; // 这里不需要转译
156
+
157
+ fieldsStr.push(escapeRowData(key) + '=' + escapeRowField(value));
141
158
  }
142
159
  });
143
160
  }
@@ -162,20 +179,21 @@ export var processedMessageByDataMap = function processedMessageByDataMap(messag
162
179
  };
163
180
  };
164
181
 
165
- function batch(request, maxSize, bytesLimit, maxMessageSize, flushTimeout, isLineProtocolToJson, beforeUnloadCallback) {
182
+ var batch = function batch(request, maxSize, bytesLimit, maxMessageSize, flushTimeout, isLineProtocolToJson, beforeUnloadCallback) {
166
183
  this.request = request;
167
184
  this.maxSize = maxSize;
168
185
  this.bytesLimit = bytesLimit;
169
186
  this.maxMessageSize = maxMessageSize;
170
187
  this.flushTimeout = flushTimeout;
171
- this.isLineProtocolToJson = isLineProtocolToJson, this.beforeUnloadCallback = beforeUnloadCallback;
188
+ this.isLineProtocolToJson = isLineProtocolToJson;
189
+ this.beforeUnloadCallback = beforeUnloadCallback;
172
190
  this.pushOnlyBuffer = [];
173
191
  this.upsertBuffer = {};
174
192
  this.bufferBytesSize = 0;
175
193
  this.bufferMessageCount = 0;
176
194
  this.flushOnVisibilityHidden();
177
195
  this.flushPeriodically();
178
- }
196
+ };
179
197
 
180
198
  batch.prototype = {
181
199
  add: function add(message) {
@@ -307,7 +325,7 @@ batch.prototype = {
307
325
  // @ts-ignore this function is not always defined
308
326
 
309
327
 
310
- if (navigator.sendBeacon) {
328
+ if (global.navigator.sendBeacon) {
311
329
  /**
312
330
  * beforeunload is called before visibilitychange
313
331
  * register first to be sure to be called before flush on beforeunload
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudcare/browser-core",
3
- "version": "1.0.29",
3
+ "version": "1.1.2",
4
4
  "main": "cjs/index.js",
5
5
  "module": "esm/index.js",
6
6
  "scripts": {
@@ -20,5 +20,5 @@
20
20
  "author": "dataflux",
21
21
  "license": "MIT",
22
22
  "description": "DataFlux RUM Web 端数据指标监控",
23
- "gitHead": "34770c27f33e4fbaaafc8743aa5e9f5ffd14bc14"
23
+ "gitHead": "5cbe53e30874a6c365a4e1e31353da8b02d0e0f3"
24
24
  }
@@ -29,6 +29,20 @@ export var each = function (obj, iterator, context) {
29
29
  }
30
30
  }
31
31
  }
32
+ export function assign(target) {
33
+ each(slice.call(arguments, 1), function (source) {
34
+ for (var prop in source) {
35
+ if (Object.prototype.hasOwnProperty.call(source, prop)) {
36
+ target[prop] = source[prop]
37
+ }
38
+ }
39
+ })
40
+ return target
41
+ }
42
+
43
+ export function shallowClone(object){
44
+ return assign({}, object)
45
+ }
32
46
  export var extend = function (obj) {
33
47
  each(slice.call(arguments, 1), function (source) {
34
48
  for (var prop in source) {
@@ -1500,7 +1514,7 @@ export function clocksNow() {
1500
1514
  return { relative: relativeNow(), timeStamp: timeStampNow() }
1501
1515
  }
1502
1516
  export function timeStampNow() {
1503
- return Date.now()
1517
+ return new Date().getTime()
1504
1518
  }
1505
1519
  export function elapsed(start, end) {
1506
1520
  return end - start
@@ -1709,4 +1723,18 @@ export function escapeJsonValue(value) {
1709
1723
  } else {
1710
1724
  return jsonStringify(value)
1711
1725
  }
1712
- }
1726
+ }
1727
+ export function escapeFieldValueStr(str) {
1728
+ return '"' +
1729
+ str.replace(/[\\]*"/g, '"').replace(/"/g, '\\"') +
1730
+ '"'
1731
+ }
1732
+ export function escapeRowField(value) {
1733
+ if (typeof value === 'object' && value) {
1734
+ return escapeFieldValueStr(jsonStringify(value))
1735
+ } else if (isString(value)) {
1736
+ return escapeFieldValueStr(value)
1737
+ } else {
1738
+ return value
1739
+ }
1740
+ }
package/src/transport.js CHANGED
@@ -13,10 +13,12 @@ import {
13
13
  isEmptyObject,
14
14
  isObject,
15
15
  map,
16
- escapeJsonValue
16
+ escapeJsonValue,
17
+ escapeRowField
17
18
  } from './helper/tools'
18
19
  import { DOM_EVENT, RumEventType } from './helper/enums'
19
20
  import { commonTags, dataMap } from './dataMap'
21
+ import { getGlobalObject } from'./init'
20
22
  // https://en.wikipedia.org/wiki/UTF-8
21
23
  var HAS_MULTI_BYTES_CHARACTERS = /[^\u0000-\u007F]/
22
24
  var CUSTOM_KEYS = 'custom_keys'
@@ -24,29 +26,40 @@ function addBatchPrecision(url) {
24
26
  if (!url) return url
25
27
  return url + (url.indexOf('?') === -1 ? '?' : '&') + 'precision=ms'
26
28
  }
29
+ var global = getGlobalObject()
27
30
  var httpRequest = function (endpointUrl, bytesLimit, isLineProtocolToJson) {
28
31
  this.endpointUrl = endpointUrl
29
32
  this.bytesLimit = bytesLimit
30
33
  this.isLineProtocolToJson = isLineProtocolToJson
34
+ var isRealNavigator = Object.prototype.toString.call(global && global.navigator) === '[object Navigator]';
35
+ var hasSendBeacon = isRealNavigator && typeof global.navigator.sendBeacon === 'function';
36
+ if (hasSendBeacon) {
37
+ this.sendBeacon = global.navigator.sendBeacon.bind(global.navigator);
38
+ } else {
39
+ this.sendBeacon = undefined
40
+ }
41
+
31
42
  }
32
43
  httpRequest.prototype = {
33
44
  send: function (data, size) {
34
45
 
35
46
  var url = addBatchPrecision(this.endpointUrl)
36
- if (navigator.sendBeacon && size < this.bytesLimit && !this.isLineProtocolToJson) {
37
- var isQueued = navigator.sendBeacon(url, data)
47
+
48
+ if (this.sendBeacon && size < this.bytesLimit && !this.isLineProtocolToJson) {
49
+ var isQueued = this.sendBeacon(url, data)
38
50
  if (isQueued) {
39
- return
51
+ return
40
52
  }
41
- } else if (navigator.sendBeacon && size < this.bytesLimit && this.isLineProtocolToJson) {
53
+ } else if (this.sendBeacon && size < this.bytesLimit && this.isLineProtocolToJson) {
42
54
  const blob = new Blob([JSON.stringify(data)], {
43
55
  type: 'application/json',
44
56
  });
45
- var isQueued = navigator.sendBeacon(url, blob)
57
+ var isQueued = this.sendBeacon(url, blob)
46
58
  if (isQueued) {
47
59
  return
48
60
  }
49
61
  }
62
+
50
63
  var request = new XMLHttpRequest()
51
64
  request.open('POST', url, true)
52
65
  request.withCredentials = true
@@ -54,6 +67,7 @@ httpRequest.prototype = {
54
67
  request.setRequestHeader('Content-type', 'application/json')
55
68
  request.send(JSON.stringify(data))
56
69
  } else {
70
+
57
71
  request.setRequestHeader('Content-type', 'text/plain;charset=UTF-8')
58
72
  request.send(data)
59
73
  }
@@ -80,7 +94,7 @@ export var processedMessageByDataMap = function (message) {
80
94
  rowData.measurement = key
81
95
  var tagsStr = []
82
96
  var tags = extend({}, commonTags, value.tags)
83
- var filterFileds = ['date', 'type'] // 已经在datamap中定义过的fields和tags
97
+ var filterFileds = ['date', 'type', CUSTOM_KEYS] // 已经在datamap中定义过的fields和tags
84
98
  each(tags, function (value_path, _key) {
85
99
  var _value = findByPath(message, value_path)
86
100
  filterFileds.push(_key)
@@ -99,26 +113,25 @@ export var processedMessageByDataMap = function (message) {
99
113
  filterFileds.push(_key)
100
114
  if (_valueData || isNumber(_valueData)) {
101
115
  rowData.fields[_key] = _valueData // 这里不需要转译
102
- _valueData =
103
- type === 'string'
104
- ? '"' +
105
- _valueData.replace(/[\\]*"/g, '"').replace(/"/g, '\\"') +
106
- '"'
107
- : escapeRowData(_valueData)
108
- fieldsStr.push(escapeRowData(_key) + '=' + _valueData)
116
+ // _valueData =
117
+ // type === 'string'
118
+ // ? '"' +
119
+ // _valueData.replace(/[\\]*"/g, '"').replace(/"/g, '\\"') +
120
+ // '"'
121
+ // : escapeRowData(_valueData)
122
+ fieldsStr.push(escapeRowData(_key) + '=' + escapeRowField(_valueData))
109
123
  }
110
124
  } else if (isString(_value)) {
111
125
  var _valueData = findByPath(message, _value)
112
126
  filterFileds.push(_key)
113
127
  if (_valueData || isNumber(_valueData)) {
114
128
  rowData.fields[_key] = _valueData // 这里不需要转译
115
- _valueData = escapeRowData(_valueData)
116
- fieldsStr.push(escapeRowData(_key) + '=' + _valueData)
129
+ fieldsStr.push(escapeRowData(_key) + '=' + escapeRowField(_valueData))
117
130
  }
118
131
  }
119
132
  })
120
133
  if (message.tags && isObject(message.tags) && !isEmptyObject(message.tags)) {
121
- // 自定义tag
134
+ // 自定义tag, 存储成field
122
135
  const _tagKeys = []
123
136
  each(message.tags, function (_value, _key) {
124
137
  // 如果和之前tag重名,则舍弃
@@ -126,25 +139,24 @@ export var processedMessageByDataMap = function (message) {
126
139
  filterFileds.push(_key)
127
140
  if (_value || isNumber(_value)) {
128
141
  _tagKeys.push(_key)
129
- rowData.tags[_key] = escapeJsonValue(_value)
130
- tagsStr.push(escapeRowData(_key) + '=' + escapeRowData(_value))
142
+ rowData.fields[_key] = _value // 这里不需要转译
143
+ fieldsStr.push(escapeRowData(_key) + '=' + escapeRowField(_value))
131
144
  }
132
145
  })
133
146
  if (_tagKeys.length) {
134
- rowData.tags[CUSTOM_KEYS] = escapeJsonValue(_tagKeys)
135
- tagsStr.push(escapeRowData(CUSTOM_KEYS) + '=' + escapeRowData(_tagKeys))
147
+ rowData.fields[CUSTOM_KEYS] = escapeRowField(_tagKeys)
148
+ fieldsStr.push(escapeRowData(CUSTOM_KEYS) + '=' + escapeRowField(_tagKeys))
136
149
  }
137
150
  }
138
151
  if (message.type === RumEventType.LOGGER) {
139
152
  // 这里处理日志类型数据自定义字段
140
-
141
153
  each(message, function (value, key) {
142
154
  if (
143
155
  filterFileds.indexOf(key) === -1 &&
144
156
  (isNumber(value) || isString(value) || isBoolean(value))
145
157
  ) {
146
- rowData.tags[key] = escapeJsonValue(value)
147
- tagsStr.push(escapeRowData(key) + '=' + escapeRowData(value))
158
+ rowData.fields[key] = value // 这里不需要转译
159
+ fieldsStr.push(escapeRowData(key) + '=' + escapeRowField(value))
148
160
  }
149
161
  })
150
162
  }
@@ -165,7 +177,7 @@ export var processedMessageByDataMap = function (message) {
165
177
  rowData: hasFileds ? rowData : undefined
166
178
  }
167
179
  }
168
- function batch(
180
+ var batch = function(
169
181
  request,
170
182
  maxSize,
171
183
  bytesLimit,
@@ -174,30 +186,37 @@ function batch(
174
186
  isLineProtocolToJson,
175
187
  beforeUnloadCallback
176
188
  ) {
189
+
177
190
  this.request = request
178
191
  this.maxSize = maxSize
179
192
  this.bytesLimit = bytesLimit
180
193
  this.maxMessageSize = maxMessageSize
181
194
  this.flushTimeout = flushTimeout
182
- this.isLineProtocolToJson = isLineProtocolToJson,
195
+ this.isLineProtocolToJson = isLineProtocolToJson
183
196
  this.beforeUnloadCallback = beforeUnloadCallback
197
+
184
198
  this.pushOnlyBuffer = []
185
199
  this.upsertBuffer = {}
186
200
  this.bufferBytesSize = 0
187
201
  this.bufferMessageCount = 0
202
+
188
203
  this.flushOnVisibilityHidden()
189
204
  this.flushPeriodically()
190
205
  }
191
206
  batch.prototype = {
207
+
192
208
  add: function (message) {
209
+
193
210
  this.addOrUpdate(message)
194
211
  },
195
212
 
196
213
  upsert: function (message, key) {
214
+
197
215
  this.addOrUpdate(message, key)
198
216
  },
199
217
 
200
218
  flush: function () {
219
+
201
220
  if (this.bufferMessageCount !== 0) {
202
221
  var messages = this.pushOnlyBuffer.concat(values(this.upsertBuffer))
203
222
  if (messages.length === 0) return
@@ -206,6 +225,7 @@ batch.prototype = {
206
225
  return JSON.parse(rowdataStr)
207
226
  }), this.bufferBytesSize)
208
227
  } else {
228
+
209
229
  this.request.send(messages.join('\n'), this.bufferBytesSize)
210
230
  }
211
231
 
@@ -220,6 +240,7 @@ batch.prototype = {
220
240
  if (this.isLineProtocolToJson) {
221
241
  return JSON.stringify(processedMessageByDataMap(message).rowData)
222
242
  }
243
+
223
244
  return processedMessageByDataMap(message).rowStr
224
245
  },
225
246
  sizeInBytes: function (candidate) {
@@ -323,7 +344,7 @@ batch.prototype = {
323
344
  * With sendBeacon, requests are guaranteed to be successfully sent during document unload
324
345
  */
325
346
  // @ts-ignore this function is not always defined
326
- if (navigator.sendBeacon) {
347
+ if (global.navigator.sendBeacon) {
327
348
  /**
328
349
  * beforeunload is called before visibilitychange
329
350
  * register first to be sure to be called before flush on beforeunload