@cloudcare/browser-core 1.0.26 → 1.1.1

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.
@@ -53,6 +53,7 @@ var DEFAULT_CONFIGURATION = {
53
53
  // 是否不抛弃采样是数据, 采用在服务端菜样的方式
54
54
  isJsBirdge: false,
55
55
  // 是否需要对webview 发送数据,需要装我们对应ios sdk
56
+ isLineProtocolToJson: false,
56
57
  beforeSend: function beforeSend(event) {},
57
58
  isServerError: function isServerError(request) {
58
59
  return false;
@@ -108,6 +109,10 @@ function commonInit(userConfiguration, buildEnv) {
108
109
  transportConfiguration.isJsBirdge = userConfiguration.isJsBirdge;
109
110
  }
110
111
 
112
+ if ('isLineProtocolToJson' in userConfiguration) {
113
+ transportConfiguration.isLineProtocolToJson = userConfiguration.isLineProtocolToJson;
114
+ }
115
+
111
116
  if ('allowedDDTracingOrigins' in userConfiguration) {
112
117
  transportConfiguration.allowedTracingOrigins = userConfiguration.allowedDDTracingOrigins;
113
118
  }
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.userAgent = exports.jsBirdge = exports.isIos = exports.isAndroid = void 0;
6
+ exports.userAgent = exports.isIos = exports.isAndroid = exports.JsBirdge = void 0;
7
7
  var userAgent = navigator.userAgent.toLowerCase();
8
8
  exports.userAgent = userAgent;
9
9
 
@@ -29,6 +29,7 @@ var JsBirdge = function JsBirdge() {
29
29
  } catch (err) {}
30
30
  };
31
31
 
32
+ exports.JsBirdge = JsBirdge;
32
33
  JsBirdge.prototype = {
33
34
  initBridge: function initBridge() {
34
35
  var _this = this;
@@ -116,5 +117,5 @@ JsBirdge.prototype = {
116
117
  }
117
118
  }
118
119
  };
119
- var jsBirdge = new JsBirdge();
120
- exports.jsBirdge = jsBirdge;
120
+ var JsBirdge = JsBirdge;
121
+ exports.JsBirdge = JsBirdge;
@@ -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,7 +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;
25
+ exports.escapeJsonValue = escapeJsonValue;
22
26
  exports.escapeRowData = escapeRowData;
27
+ exports.escapeRowField = escapeRowField;
23
28
  exports.filter = exports.extend2Lev = exports.extend = void 0;
24
29
  exports.find = find;
25
30
  exports.findByPath = findByPath;
@@ -57,7 +62,10 @@ exports.replaceNumberCharByPath = replaceNumberCharByPath;
57
62
  exports.round = round;
58
63
  exports.safeJSONParse = void 0;
59
64
  exports.safeTruncate = safeTruncate;
60
- 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;
61
69
  exports.timeStampNow = timeStampNow;
62
70
  exports.toArray = exports.tirm = void 0;
63
71
  exports.toServerDuration = toServerDuration;
@@ -104,6 +112,21 @@ var each = function each(obj, iterator, context) {
104
112
 
105
113
  exports.each = each;
106
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
+
107
130
  var extend = function extend(obj) {
108
131
  each(slice.call(arguments, 1), function (source) {
109
132
  for (var prop in source) {
@@ -2033,4 +2056,26 @@ function escapeRowData(str) {
2033
2056
  return String(str).replace(reg, function (word) {
2034
2057
  return '\\' + word;
2035
2058
  });
2059
+ }
2060
+
2061
+ function escapeJsonValue(value) {
2062
+ if (isString(value)) {
2063
+ return value;
2064
+ } else {
2065
+ return jsonStringify(value);
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
+ }
2036
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,17 +22,37 @@ function addBatchPrecision(url) {
20
22
  return url + (url.indexOf('?') === -1 ? '?' : '&') + 'precision=ms';
21
23
  }
22
24
 
23
- var httpRequest = function httpRequest(endpointUrl, bytesLimit) {
25
+ var global = (0, _init.getGlobalObject)();
26
+
27
+ var httpRequest = function httpRequest(endpointUrl, bytesLimit, isLineProtocolToJson) {
24
28
  this.endpointUrl = endpointUrl;
25
29
  this.bytesLimit = bytesLimit;
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
+ }
26
39
  };
27
40
 
28
41
  httpRequest.prototype = {
29
42
  send: function send(data, size) {
30
43
  var url = addBatchPrecision(this.endpointUrl);
31
44
 
32
- if (navigator.sendBeacon && size < this.bytesLimit) {
33
- var isQueued = navigator.sendBeacon(url, data);
45
+ if (this.sendBeacon && size < this.bytesLimit && !this.isLineProtocolToJson) {
46
+ var isQueued = this.sendBeacon(url, data);
47
+
48
+ if (isQueued) {
49
+ return;
50
+ }
51
+ } else if (this.sendBeacon && size < this.bytesLimit && this.isLineProtocolToJson) {
52
+ var blob = new Blob([JSON.stringify(data)], {
53
+ type: 'application/json'
54
+ });
55
+ var isQueued = this.sendBeacon(url, blob);
34
56
 
35
57
  if (isQueued) {
36
58
  return;
@@ -40,7 +62,14 @@ httpRequest.prototype = {
40
62
  var request = new XMLHttpRequest();
41
63
  request.open('POST', url, true);
42
64
  request.withCredentials = true;
43
- request.send(data);
65
+
66
+ if (this.isLineProtocolToJson) {
67
+ request.setRequestHeader('Content-type', 'application/json');
68
+ request.send(JSON.stringify(data));
69
+ } else {
70
+ request.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
71
+ request.send(data);
72
+ }
44
73
  }
45
74
  };
46
75
  var HttpRequest = httpRequest;
@@ -63,7 +92,7 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
63
92
  rowData.measurement = key;
64
93
  var tagsStr = [];
65
94
  var tags = (0, _tools.extend)({}, _dataMap.commonTags, value.tags);
66
- var filterFileds = ['date', 'type']; // 已经在datamap中定义过的fields和tags
95
+ var filterFileds = ['date', 'type', CUSTOM_KEYS]; // 已经在datamap中定义过的fields和tags
67
96
 
68
97
  (0, _tools.each)(tags, function (value_path, _key) {
69
98
  var _value = (0, _tools.findByPath)(message, value_path);
@@ -71,33 +100,10 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
71
100
  filterFileds.push(_key);
72
101
 
73
102
  if (_value || (0, _tools.isNumber)(_value)) {
74
- rowData.tags[_key] = _value;
103
+ rowData.tags[_key] = (0, _tools.escapeJsonValue)(_value);
75
104
  tagsStr.push((0, _tools.escapeRowData)(_key) + '=' + (0, _tools.escapeRowData)(_value));
76
105
  }
77
106
  });
78
-
79
- if (message.tags && (0, _tools.isObject)(message.tags) && !(0, _tools.isEmptyObject)(message.tags)) {
80
- // 自定义tag
81
- var _tagKeys = [];
82
- (0, _tools.each)(message.tags, function (_value, _key) {
83
- // 如果和之前tag重名,则舍弃
84
- if (filterFileds.indexOf(_key) > -1) return;
85
- filterFileds.push(_key);
86
-
87
- if (_value || (0, _tools.isNumber)(_value)) {
88
- _tagKeys.push(_key);
89
-
90
- rowData.tags[_key] = _value;
91
- tagsStr.push((0, _tools.escapeRowData)(_key) + '=' + (0, _tools.escapeRowData)(_value));
92
- }
93
- });
94
-
95
- if (_tagKeys.length) {
96
- rowData.tags[CUSTOM_KEYS] = _tagKeys;
97
- tagsStr.push((0, _tools.escapeRowData)(CUSTOM_KEYS) + '=' + (0, _tools.escapeRowData)(_tagKeys));
98
- }
99
- }
100
-
101
107
  var fieldsStr = [];
102
108
  (0, _tools.each)(value.fields, function (_value, _key) {
103
109
  if ((0, _tools.isArray)(_value) && _value.length === 2) {
@@ -110,9 +116,14 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
110
116
 
111
117
  if (_valueData || (0, _tools.isNumber)(_valueData)) {
112
118
  rowData.fields[_key] = _valueData; // 这里不需要转译
113
-
114
- _valueData = type === 'string' ? '"' + _valueData.replace(/[\\]*"/g, '"').replace(/"/g, '\\"') + '"' : (0, _tools.escapeRowData)(_valueData);
115
- 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));
116
127
  }
117
128
  } else if ((0, _tools.isString)(_value)) {
118
129
  var _valueData = (0, _tools.findByPath)(message, _value);
@@ -122,17 +133,41 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
122
133
  if (_valueData || (0, _tools.isNumber)(_valueData)) {
123
134
  rowData.fields[_key] = _valueData; // 这里不需要转译
124
135
 
125
- _valueData = (0, _tools.escapeRowData)(_valueData);
126
- fieldsStr.push((0, _tools.escapeRowData)(_key) + '=' + _valueData);
136
+ fieldsStr.push((0, _tools.escapeRowData)(_key) + '=' + (0, _tools.escapeRowField)(_valueData));
127
137
  }
128
138
  }
129
139
  });
130
140
 
141
+ if (message.tags && (0, _tools.isObject)(message.tags) && !(0, _tools.isEmptyObject)(message.tags)) {
142
+ // 自定义tag, 存储成field
143
+ var _tagKeys = [];
144
+ (0, _tools.each)(message.tags, function (_value, _key) {
145
+ // 如果和之前tag重名,则舍弃
146
+ if (filterFileds.indexOf(_key) > -1) return;
147
+ filterFileds.push(_key);
148
+
149
+ if (_value || (0, _tools.isNumber)(_value)) {
150
+ _tagKeys.push(_key);
151
+
152
+ rowData.fields[_key] = _value; // 这里不需要转译
153
+
154
+ fieldsStr.push((0, _tools.escapeRowData)(_key) + '=' + (0, _tools.escapeRowField)(_value));
155
+ }
156
+ });
157
+
158
+ if (_tagKeys.length) {
159
+ rowData.fields[CUSTOM_KEYS] = (0, _tools.escapeRowField)(_tagKeys);
160
+ fieldsStr.push((0, _tools.escapeRowData)(CUSTOM_KEYS) + '=' + (0, _tools.escapeRowField)(_tagKeys));
161
+ }
162
+ }
163
+
131
164
  if (message.type === _enums.RumEventType.LOGGER) {
132
165
  // 这里处理日志类型数据自定义字段
133
166
  (0, _tools.each)(message, function (value, key) {
134
167
  if (filterFileds.indexOf(key) === -1 && ((0, _tools.isNumber)(value) || (0, _tools.isString)(value) || (0, _tools.isBoolean)(value))) {
135
- 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));
136
171
  }
137
172
  });
138
173
  }
@@ -159,12 +194,13 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
159
194
 
160
195
  exports.processedMessageByDataMap = processedMessageByDataMap;
161
196
 
162
- function batch(request, maxSize, bytesLimit, maxMessageSize, flushTimeout, beforeUnloadCallback) {
197
+ var batch = function batch(request, maxSize, bytesLimit, maxMessageSize, flushTimeout, isLineProtocolToJson, beforeUnloadCallback) {
163
198
  this.request = request;
164
199
  this.maxSize = maxSize;
165
200
  this.bytesLimit = bytesLimit;
166
201
  this.maxMessageSize = maxMessageSize;
167
202
  this.flushTimeout = flushTimeout;
203
+ this.isLineProtocolToJson = isLineProtocolToJson;
168
204
  this.beforeUnloadCallback = beforeUnloadCallback;
169
205
  this.pushOnlyBuffer = [];
170
206
  this.upsertBuffer = {};
@@ -172,7 +208,7 @@ function batch(request, maxSize, bytesLimit, maxMessageSize, flushTimeout, befor
172
208
  this.bufferMessageCount = 0;
173
209
  this.flushOnVisibilityHidden();
174
210
  this.flushPeriodically();
175
- }
211
+ };
176
212
 
177
213
  batch.prototype = {
178
214
  add: function add(message) {
@@ -184,7 +220,16 @@ batch.prototype = {
184
220
  flush: function flush() {
185
221
  if (this.bufferMessageCount !== 0) {
186
222
  var messages = this.pushOnlyBuffer.concat((0, _tools.values)(this.upsertBuffer));
187
- this.request.send(messages.join('\n'), this.bufferBytesSize);
223
+ if (messages.length === 0) return;
224
+
225
+ if (this.isLineProtocolToJson) {
226
+ this.request.send((0, _tools.map)(messages, function (rowdataStr) {
227
+ return JSON.parse(rowdataStr);
228
+ }), this.bufferBytesSize);
229
+ } else {
230
+ this.request.send(messages.join('\n'), this.bufferBytesSize);
231
+ }
232
+
188
233
  this.pushOnlyBuffer = [];
189
234
  this.upsertBuffer = {};
190
235
  this.bufferBytesSize = 0;
@@ -192,6 +237,10 @@ batch.prototype = {
192
237
  }
193
238
  },
194
239
  processSendData: function processSendData(message) {
240
+ if (this.isLineProtocolToJson) {
241
+ return JSON.stringify(processedMessageByDataMap(message).rowData);
242
+ }
243
+
195
244
  return processedMessageByDataMap(message).rowStr;
196
245
  },
197
246
  sizeInBytes: function sizeInBytes(candidate) {
@@ -291,7 +340,7 @@ batch.prototype = {
291
340
  // @ts-ignore this function is not always defined
292
341
 
293
342
 
294
- if (navigator.sendBeacon) {
343
+ if (global.navigator.sendBeacon) {
295
344
  /**
296
345
  * beforeunload is called before visibilitychange
297
346
  * register first to be sure to be called before flush on beforeunload
@@ -39,6 +39,7 @@ export var DEFAULT_CONFIGURATION = {
39
39
  // 是否不抛弃采样是数据, 采用在服务端菜样的方式
40
40
  isJsBirdge: false,
41
41
  // 是否需要对webview 发送数据,需要装我们对应ios sdk
42
+ isLineProtocolToJson: false,
42
43
  beforeSend: function beforeSend(event) {},
43
44
  isServerError: function isServerError(request) {
44
45
  return false;
@@ -93,6 +94,10 @@ export function commonInit(userConfiguration, buildEnv) {
93
94
  transportConfiguration.isJsBirdge = userConfiguration.isJsBirdge;
94
95
  }
95
96
 
97
+ if ('isLineProtocolToJson' in userConfiguration) {
98
+ transportConfiguration.isLineProtocolToJson = userConfiguration.isLineProtocolToJson;
99
+ }
100
+
96
101
  if ('allowedDDTracingOrigins' in userConfiguration) {
97
102
  transportConfiguration.allowedTracingOrigins = userConfiguration.allowedDDTracingOrigins;
98
103
  }
@@ -103,4 +103,4 @@ JsBirdge.prototype = {
103
103
  }
104
104
  }
105
105
  };
106
- export var jsBirdge = new JsBirdge();
106
+ export var JsBirdge = JsBirdge;
@@ -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) {
@@ -1726,4 +1739,23 @@ export function escapeRowData(str) {
1726
1739
  return String(str).replace(reg, function (word) {
1727
1740
  return '\\' + word;
1728
1741
  });
1742
+ }
1743
+ export function escapeJsonValue(value) {
1744
+ if (isString(value)) {
1745
+ return value;
1746
+ } else {
1747
+ return jsonStringify(value);
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
+ }
1729
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 } 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,17 +11,37 @@ function addBatchPrecision(url) {
10
11
  return url + (url.indexOf('?') === -1 ? '?' : '&') + 'precision=ms';
11
12
  }
12
13
 
13
- var httpRequest = function httpRequest(endpointUrl, bytesLimit) {
14
+ var global = getGlobalObject();
15
+
16
+ var httpRequest = function httpRequest(endpointUrl, bytesLimit, isLineProtocolToJson) {
14
17
  this.endpointUrl = endpointUrl;
15
18
  this.bytesLimit = bytesLimit;
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
+ }
16
28
  };
17
29
 
18
30
  httpRequest.prototype = {
19
31
  send: function send(data, size) {
20
32
  var url = addBatchPrecision(this.endpointUrl);
21
33
 
22
- if (navigator.sendBeacon && size < this.bytesLimit) {
23
- var isQueued = navigator.sendBeacon(url, data);
34
+ if (this.sendBeacon && size < this.bytesLimit && !this.isLineProtocolToJson) {
35
+ var isQueued = this.sendBeacon(url, data);
36
+
37
+ if (isQueued) {
38
+ return;
39
+ }
40
+ } else if (this.sendBeacon && size < this.bytesLimit && this.isLineProtocolToJson) {
41
+ var blob = new Blob([JSON.stringify(data)], {
42
+ type: 'application/json'
43
+ });
44
+ var isQueued = this.sendBeacon(url, blob);
24
45
 
25
46
  if (isQueued) {
26
47
  return;
@@ -30,7 +51,14 @@ httpRequest.prototype = {
30
51
  var request = new XMLHttpRequest();
31
52
  request.open('POST', url, true);
32
53
  request.withCredentials = true;
33
- request.send(data);
54
+
55
+ if (this.isLineProtocolToJson) {
56
+ request.setRequestHeader('Content-type', 'application/json');
57
+ request.send(JSON.stringify(data));
58
+ } else {
59
+ request.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
60
+ request.send(data);
61
+ }
34
62
  }
35
63
  };
36
64
  export var HttpRequest = httpRequest;
@@ -51,7 +79,7 @@ export var processedMessageByDataMap = function processedMessageByDataMap(messag
51
79
  rowData.measurement = key;
52
80
  var tagsStr = [];
53
81
  var tags = extend({}, commonTags, value.tags);
54
- var filterFileds = ['date', 'type']; // 已经在datamap中定义过的fields和tags
82
+ var filterFileds = ['date', 'type', CUSTOM_KEYS]; // 已经在datamap中定义过的fields和tags
55
83
 
56
84
  each(tags, function (value_path, _key) {
57
85
  var _value = findByPath(message, value_path);
@@ -59,33 +87,10 @@ export var processedMessageByDataMap = function processedMessageByDataMap(messag
59
87
  filterFileds.push(_key);
60
88
 
61
89
  if (_value || isNumber(_value)) {
62
- rowData.tags[_key] = _value;
90
+ rowData.tags[_key] = escapeJsonValue(_value);
63
91
  tagsStr.push(escapeRowData(_key) + '=' + escapeRowData(_value));
64
92
  }
65
93
  });
66
-
67
- if (message.tags && isObject(message.tags) && !isEmptyObject(message.tags)) {
68
- // 自定义tag
69
- var _tagKeys = [];
70
- each(message.tags, function (_value, _key) {
71
- // 如果和之前tag重名,则舍弃
72
- if (filterFileds.indexOf(_key) > -1) return;
73
- filterFileds.push(_key);
74
-
75
- if (_value || isNumber(_value)) {
76
- _tagKeys.push(_key);
77
-
78
- rowData.tags[_key] = _value;
79
- tagsStr.push(escapeRowData(_key) + '=' + escapeRowData(_value));
80
- }
81
- });
82
-
83
- if (_tagKeys.length) {
84
- rowData.tags[CUSTOM_KEYS] = _tagKeys;
85
- tagsStr.push(escapeRowData(CUSTOM_KEYS) + '=' + escapeRowData(_tagKeys));
86
- }
87
- }
88
-
89
94
  var fieldsStr = [];
90
95
  each(value.fields, function (_value, _key) {
91
96
  if (isArray(_value) && _value.length === 2) {
@@ -98,9 +103,14 @@ export var processedMessageByDataMap = function processedMessageByDataMap(messag
98
103
 
99
104
  if (_valueData || isNumber(_valueData)) {
100
105
  rowData.fields[_key] = _valueData; // 这里不需要转译
101
-
102
- _valueData = type === 'string' ? '"' + _valueData.replace(/[\\]*"/g, '"').replace(/"/g, '\\"') + '"' : escapeRowData(_valueData);
103
- 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));
104
114
  }
105
115
  } else if (isString(_value)) {
106
116
  var _valueData = findByPath(message, _value);
@@ -110,17 +120,41 @@ export var processedMessageByDataMap = function processedMessageByDataMap(messag
110
120
  if (_valueData || isNumber(_valueData)) {
111
121
  rowData.fields[_key] = _valueData; // 这里不需要转译
112
122
 
113
- _valueData = escapeRowData(_valueData);
114
- fieldsStr.push(escapeRowData(_key) + '=' + _valueData);
123
+ fieldsStr.push(escapeRowData(_key) + '=' + escapeRowField(_valueData));
115
124
  }
116
125
  }
117
126
  });
118
127
 
128
+ if (message.tags && isObject(message.tags) && !isEmptyObject(message.tags)) {
129
+ // 自定义tag, 存储成field
130
+ var _tagKeys = [];
131
+ each(message.tags, function (_value, _key) {
132
+ // 如果和之前tag重名,则舍弃
133
+ if (filterFileds.indexOf(_key) > -1) return;
134
+ filterFileds.push(_key);
135
+
136
+ if (_value || isNumber(_value)) {
137
+ _tagKeys.push(_key);
138
+
139
+ rowData.fields[_key] = _value; // 这里不需要转译
140
+
141
+ fieldsStr.push(escapeRowData(_key) + '=' + escapeRowField(_value));
142
+ }
143
+ });
144
+
145
+ if (_tagKeys.length) {
146
+ rowData.fields[CUSTOM_KEYS] = escapeRowField(_tagKeys);
147
+ fieldsStr.push(escapeRowData(CUSTOM_KEYS) + '=' + escapeRowField(_tagKeys));
148
+ }
149
+ }
150
+
119
151
  if (message.type === RumEventType.LOGGER) {
120
152
  // 这里处理日志类型数据自定义字段
121
153
  each(message, function (value, key) {
122
154
  if (filterFileds.indexOf(key) === -1 && (isNumber(value) || isString(value) || isBoolean(value))) {
123
- tagsStr.push(escapeRowData(key) + '=' + escapeRowData(value));
155
+ rowData.fields[key] = value; // 这里不需要转译
156
+
157
+ fieldsStr.push(escapeRowData(key) + '=' + escapeRowField(value));
124
158
  }
125
159
  });
126
160
  }
@@ -145,12 +179,13 @@ export var processedMessageByDataMap = function processedMessageByDataMap(messag
145
179
  };
146
180
  };
147
181
 
148
- function batch(request, maxSize, bytesLimit, maxMessageSize, flushTimeout, beforeUnloadCallback) {
182
+ var batch = function batch(request, maxSize, bytesLimit, maxMessageSize, flushTimeout, isLineProtocolToJson, beforeUnloadCallback) {
149
183
  this.request = request;
150
184
  this.maxSize = maxSize;
151
185
  this.bytesLimit = bytesLimit;
152
186
  this.maxMessageSize = maxMessageSize;
153
187
  this.flushTimeout = flushTimeout;
188
+ this.isLineProtocolToJson = isLineProtocolToJson;
154
189
  this.beforeUnloadCallback = beforeUnloadCallback;
155
190
  this.pushOnlyBuffer = [];
156
191
  this.upsertBuffer = {};
@@ -158,7 +193,7 @@ function batch(request, maxSize, bytesLimit, maxMessageSize, flushTimeout, befor
158
193
  this.bufferMessageCount = 0;
159
194
  this.flushOnVisibilityHidden();
160
195
  this.flushPeriodically();
161
- }
196
+ };
162
197
 
163
198
  batch.prototype = {
164
199
  add: function add(message) {
@@ -170,7 +205,16 @@ batch.prototype = {
170
205
  flush: function flush() {
171
206
  if (this.bufferMessageCount !== 0) {
172
207
  var messages = this.pushOnlyBuffer.concat(values(this.upsertBuffer));
173
- this.request.send(messages.join('\n'), this.bufferBytesSize);
208
+ if (messages.length === 0) return;
209
+
210
+ if (this.isLineProtocolToJson) {
211
+ this.request.send(map(messages, function (rowdataStr) {
212
+ return JSON.parse(rowdataStr);
213
+ }), this.bufferBytesSize);
214
+ } else {
215
+ this.request.send(messages.join('\n'), this.bufferBytesSize);
216
+ }
217
+
174
218
  this.pushOnlyBuffer = [];
175
219
  this.upsertBuffer = {};
176
220
  this.bufferBytesSize = 0;
@@ -178,6 +222,10 @@ batch.prototype = {
178
222
  }
179
223
  },
180
224
  processSendData: function processSendData(message) {
225
+ if (this.isLineProtocolToJson) {
226
+ return JSON.stringify(processedMessageByDataMap(message).rowData);
227
+ }
228
+
181
229
  return processedMessageByDataMap(message).rowStr;
182
230
  },
183
231
  sizeInBytes: function sizeInBytes(candidate) {
@@ -277,7 +325,7 @@ batch.prototype = {
277
325
  // @ts-ignore this function is not always defined
278
326
 
279
327
 
280
- if (navigator.sendBeacon) {
328
+ if (global.navigator.sendBeacon) {
281
329
  /**
282
330
  * beforeunload is called before visibilitychange
283
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.26",
3
+ "version": "1.1.1",
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": "8a8ee0b57af1e54f8b41100dfadf1477868cce56"
23
+ "gitHead": "6637896a7d66c35f8b37da75b14d234d049c79d5"
24
24
  }
@@ -41,6 +41,7 @@ export var DEFAULT_CONFIGURATION = {
41
41
  allowedTracingOrigins:[], // 新增
42
42
  isServiceSampling: false, // 是否不抛弃采样是数据, 采用在服务端菜样的方式
43
43
  isJsBirdge: false,// 是否需要对webview 发送数据,需要装我们对应ios sdk
44
+ isLineProtocolToJson: false,
44
45
  beforeSend: function (event) {},
45
46
  isServerError: function(request) {return false} // 判断请求是否为error 请求
46
47
  }
@@ -91,6 +92,9 @@ export function commonInit(userConfiguration, buildEnv) {
91
92
  if ('isJsBirdge' in userConfiguration) {
92
93
  transportConfiguration.isJsBirdge = userConfiguration.isJsBirdge
93
94
  }
95
+ if ('isLineProtocolToJson' in userConfiguration) {
96
+ transportConfiguration.isLineProtocolToJson = userConfiguration.isLineProtocolToJson
97
+ }
94
98
  if ('allowedDDTracingOrigins' in userConfiguration) {
95
99
  transportConfiguration.allowedTracingOrigins =
96
100
  userConfiguration.allowedDDTracingOrigins
@@ -99,4 +99,4 @@ JsBirdge.prototype = {
99
99
  }
100
100
  }
101
101
 
102
- export var jsBirdge = new JsBirdge()
102
+ export var JsBirdge = JsBirdge
@@ -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) {
@@ -1702,3 +1716,25 @@ export function escapeRowData(str) {
1702
1716
  return '\\' + word
1703
1717
  })
1704
1718
  }
1719
+
1720
+ export function escapeJsonValue(value) {
1721
+ if (isString(value)) {
1722
+ return value
1723
+ } else {
1724
+ return jsonStringify(value)
1725
+ }
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
@@ -11,10 +11,14 @@ import {
11
11
  toServerDuration,
12
12
  isBoolean,
13
13
  isEmptyObject,
14
- isObject
14
+ isObject,
15
+ map,
16
+ escapeJsonValue,
17
+ escapeRowField
15
18
  } from './helper/tools'
16
19
  import { DOM_EVENT, RumEventType } from './helper/enums'
17
20
  import { commonTags, dataMap } from './dataMap'
21
+ import { getGlobalObject } from'./init'
18
22
  // https://en.wikipedia.org/wiki/UTF-8
19
23
  var HAS_MULTI_BYTES_CHARACTERS = /[^\u0000-\u007F]/
20
24
  var CUSTOM_KEYS = 'custom_keys'
@@ -22,27 +26,59 @@ function addBatchPrecision(url) {
22
26
  if (!url) return url
23
27
  return url + (url.indexOf('?') === -1 ? '?' : '&') + 'precision=ms'
24
28
  }
25
- var httpRequest = function (endpointUrl, bytesLimit) {
29
+ var global = getGlobalObject()
30
+ var httpRequest = function (endpointUrl, bytesLimit, isLineProtocolToJson) {
26
31
  this.endpointUrl = endpointUrl
27
32
  this.bytesLimit = bytesLimit
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
+
28
42
  }
29
43
  httpRequest.prototype = {
30
44
  send: function (data, size) {
45
+
31
46
  var url = addBatchPrecision(this.endpointUrl)
32
- if (navigator.sendBeacon && size < this.bytesLimit) {
33
- var isQueued = navigator.sendBeacon(url, data)
47
+
48
+ if (this.sendBeacon && size < this.bytesLimit && !this.isLineProtocolToJson) {
49
+ var isQueued = this.sendBeacon(url, data)
50
+ if (isQueued) {
51
+ return
52
+ }
53
+ } else if (this.sendBeacon && size < this.bytesLimit && this.isLineProtocolToJson) {
54
+ const blob = new Blob([JSON.stringify(data)], {
55
+ type: 'application/json',
56
+ });
57
+ var isQueued = this.sendBeacon(url, blob)
34
58
  if (isQueued) {
35
59
  return
36
60
  }
37
61
  }
62
+
38
63
  var request = new XMLHttpRequest()
39
64
  request.open('POST', url, true)
40
65
  request.withCredentials = true
41
- request.send(data)
66
+ if (this.isLineProtocolToJson) {
67
+ request.setRequestHeader('Content-type', 'application/json')
68
+ request.send(JSON.stringify(data))
69
+ } else {
70
+
71
+ request.setRequestHeader('Content-type', 'text/plain;charset=UTF-8')
72
+ request.send(data)
73
+ }
74
+
75
+
76
+
42
77
  }
43
78
  }
44
79
 
45
80
  export var HttpRequest = httpRequest
81
+
46
82
  export var processedMessageByDataMap = function (message) {
47
83
  if (!message || !message.type) return {
48
84
  rowStr: '',
@@ -58,33 +94,16 @@ export var processedMessageByDataMap = function (message) {
58
94
  rowData.measurement = key
59
95
  var tagsStr = []
60
96
  var tags = extend({}, commonTags, value.tags)
61
- var filterFileds = ['date', 'type'] // 已经在datamap中定义过的fields和tags
97
+ var filterFileds = ['date', 'type', CUSTOM_KEYS] // 已经在datamap中定义过的fields和tags
62
98
  each(tags, function (value_path, _key) {
63
99
  var _value = findByPath(message, value_path)
64
100
  filterFileds.push(_key)
65
101
  if (_value || isNumber(_value)) {
66
- rowData.tags[_key] = _value
102
+ rowData.tags[_key] = escapeJsonValue(_value)
67
103
  tagsStr.push(escapeRowData(_key) + '=' + escapeRowData(_value))
68
104
  }
69
105
  })
70
- if (message.tags && isObject(message.tags) && !isEmptyObject(message.tags)) {
71
- // 自定义tag
72
- const _tagKeys = []
73
- each(message.tags, function (_value, _key) {
74
- // 如果和之前tag重名,则舍弃
75
- if (filterFileds.indexOf(_key) > -1) return
76
- filterFileds.push(_key)
77
- if (_value || isNumber(_value)) {
78
- _tagKeys.push(_key)
79
- rowData.tags[_key] = _value
80
- tagsStr.push(escapeRowData(_key) + '=' + escapeRowData(_value))
81
- }
82
- })
83
- if (_tagKeys.length) {
84
- rowData.tags[CUSTOM_KEYS] = _tagKeys
85
- tagsStr.push(escapeRowData(CUSTOM_KEYS) + '=' + escapeRowData(_tagKeys))
86
- }
87
- }
106
+
88
107
  var fieldsStr = []
89
108
  each(value.fields, function (_value, _key) {
90
109
  if (isArray(_value) && _value.length === 2) {
@@ -94,33 +113,50 @@ export var processedMessageByDataMap = function (message) {
94
113
  filterFileds.push(_key)
95
114
  if (_valueData || isNumber(_valueData)) {
96
115
  rowData.fields[_key] = _valueData // 这里不需要转译
97
- _valueData =
98
- type === 'string'
99
- ? '"' +
100
- _valueData.replace(/[\\]*"/g, '"').replace(/"/g, '\\"') +
101
- '"'
102
- : escapeRowData(_valueData)
103
- 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))
104
123
  }
105
124
  } else if (isString(_value)) {
106
125
  var _valueData = findByPath(message, _value)
107
126
  filterFileds.push(_key)
108
127
  if (_valueData || isNumber(_valueData)) {
109
128
  rowData.fields[_key] = _valueData // 这里不需要转译
110
- _valueData = escapeRowData(_valueData)
111
- fieldsStr.push(escapeRowData(_key) + '=' + _valueData)
129
+ fieldsStr.push(escapeRowData(_key) + '=' + escapeRowField(_valueData))
112
130
  }
113
131
  }
114
132
  })
133
+ if (message.tags && isObject(message.tags) && !isEmptyObject(message.tags)) {
134
+ // 自定义tag, 存储成field
135
+ const _tagKeys = []
136
+ each(message.tags, function (_value, _key) {
137
+ // 如果和之前tag重名,则舍弃
138
+ if (filterFileds.indexOf(_key) > -1) return
139
+ filterFileds.push(_key)
140
+ if (_value || isNumber(_value)) {
141
+ _tagKeys.push(_key)
142
+ rowData.fields[_key] = _value // 这里不需要转译
143
+ fieldsStr.push(escapeRowData(_key) + '=' + escapeRowField(_value))
144
+ }
145
+ })
146
+ if (_tagKeys.length) {
147
+ rowData.fields[CUSTOM_KEYS] = escapeRowField(_tagKeys)
148
+ fieldsStr.push(escapeRowData(CUSTOM_KEYS) + '=' + escapeRowField(_tagKeys))
149
+ }
150
+ }
115
151
  if (message.type === RumEventType.LOGGER) {
116
152
  // 这里处理日志类型数据自定义字段
117
-
118
153
  each(message, function (value, key) {
119
154
  if (
120
155
  filterFileds.indexOf(key) === -1 &&
121
156
  (isNumber(value) || isString(value) || isBoolean(value))
122
157
  ) {
123
- tagsStr.push(escapeRowData(key) + '=' + escapeRowData(value))
158
+ rowData.fields[key] = value // 这里不需要转译
159
+ fieldsStr.push(escapeRowData(key) + '=' + escapeRowField(value))
124
160
  }
125
161
  })
126
162
  }
@@ -141,40 +177,58 @@ export var processedMessageByDataMap = function (message) {
141
177
  rowData: hasFileds ? rowData : undefined
142
178
  }
143
179
  }
144
- function batch(
180
+ var batch = function(
145
181
  request,
146
182
  maxSize,
147
183
  bytesLimit,
148
184
  maxMessageSize,
149
185
  flushTimeout,
186
+ isLineProtocolToJson,
150
187
  beforeUnloadCallback
151
188
  ) {
189
+
152
190
  this.request = request
153
191
  this.maxSize = maxSize
154
192
  this.bytesLimit = bytesLimit
155
193
  this.maxMessageSize = maxMessageSize
156
194
  this.flushTimeout = flushTimeout
195
+ this.isLineProtocolToJson = isLineProtocolToJson
157
196
  this.beforeUnloadCallback = beforeUnloadCallback
197
+
158
198
  this.pushOnlyBuffer = []
159
199
  this.upsertBuffer = {}
160
200
  this.bufferBytesSize = 0
161
201
  this.bufferMessageCount = 0
202
+
162
203
  this.flushOnVisibilityHidden()
163
204
  this.flushPeriodically()
164
205
  }
165
206
  batch.prototype = {
207
+
166
208
  add: function (message) {
209
+
167
210
  this.addOrUpdate(message)
168
211
  },
169
212
 
170
213
  upsert: function (message, key) {
214
+
171
215
  this.addOrUpdate(message, key)
172
216
  },
173
217
 
174
218
  flush: function () {
219
+
175
220
  if (this.bufferMessageCount !== 0) {
176
221
  var messages = this.pushOnlyBuffer.concat(values(this.upsertBuffer))
177
- this.request.send(messages.join('\n'), this.bufferBytesSize)
222
+ if (messages.length === 0) return
223
+ if (this.isLineProtocolToJson) {
224
+ this.request.send(map(messages, function(rowdataStr) {
225
+ return JSON.parse(rowdataStr)
226
+ }), this.bufferBytesSize)
227
+ } else {
228
+
229
+ this.request.send(messages.join('\n'), this.bufferBytesSize)
230
+ }
231
+
178
232
  this.pushOnlyBuffer = []
179
233
  this.upsertBuffer = {}
180
234
  this.bufferBytesSize = 0
@@ -183,6 +237,10 @@ batch.prototype = {
183
237
  },
184
238
 
185
239
  processSendData: function (message) {
240
+ if (this.isLineProtocolToJson) {
241
+ return JSON.stringify(processedMessageByDataMap(message).rowData)
242
+ }
243
+
186
244
  return processedMessageByDataMap(message).rowStr
187
245
  },
188
246
  sizeInBytes: function (candidate) {
@@ -286,7 +344,7 @@ batch.prototype = {
286
344
  * With sendBeacon, requests are guaranteed to be successfully sent during document unload
287
345
  */
288
346
  // @ts-ignore this function is not always defined
289
- if (navigator.sendBeacon) {
347
+ if (global.navigator.sendBeacon) {
290
348
  /**
291
349
  * beforeunload is called before visibilitychange
292
350
  * register first to be sure to be called before flush on beforeunload