@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.
- package/cjs/helper/tools.js +39 -3
- package/cjs/transport.js +40 -21
- package/esm/helper/tools.js +26 -1
- package/esm/transport.js +41 -23
- package/package.json +2 -2
- package/src/helper/tools.js +30 -2
- package/src/transport.js +48 -27
package/cjs/helper/tools.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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 (
|
|
34
|
-
var isQueued =
|
|
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 (
|
|
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 =
|
|
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
|
-
|
|
109
|
-
|
|
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
|
-
|
|
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.
|
|
137
|
-
|
|
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.
|
|
143
|
-
|
|
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.
|
|
152
|
-
|
|
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
|
|
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
|
package/esm/helper/tools.js
CHANGED
|
@@ -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.
|
|
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';
|
|
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 (
|
|
24
|
-
var isQueued =
|
|
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 (
|
|
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 =
|
|
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
|
-
|
|
97
|
-
|
|
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
|
-
|
|
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.
|
|
125
|
-
|
|
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.
|
|
131
|
-
|
|
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.
|
|
140
|
-
|
|
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
|
|
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.
|
|
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": "
|
|
23
|
+
"gitHead": "5cbe53e30874a6c365a4e1e31353da8b02d0e0f3"
|
|
24
24
|
}
|
package/src/helper/tools.js
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
37
|
-
|
|
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 (
|
|
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 =
|
|
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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
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.
|
|
130
|
-
|
|
142
|
+
rowData.fields[_key] = _value // 这里不需要转译
|
|
143
|
+
fieldsStr.push(escapeRowData(_key) + '=' + escapeRowField(_value))
|
|
131
144
|
}
|
|
132
145
|
})
|
|
133
146
|
if (_tagKeys.length) {
|
|
134
|
-
rowData.
|
|
135
|
-
|
|
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.
|
|
147
|
-
|
|
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
|
-
|
|
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
|