@cloudcare/browser-logs 1.1.24 → 1.2.0
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/README.md +5 -4
- package/bundle/dataflux-logs.js +1 -1
- package/cjs/boot/buildEnv.js +1 -1
- package/cjs/boot/logsPublicApi.js +133 -0
- package/cjs/boot/startLogs.js +63 -0
- package/cjs/domain/assembly.js +74 -0
- package/cjs/domain/configuration.js +55 -0
- package/cjs/domain/internalContext.js +22 -0
- package/cjs/domain/logger.js +28 -36
- package/cjs/domain/logsCollection/console/consoleCollection.js +39 -0
- package/cjs/domain/logsCollection/logger/loggerCollection.js +51 -0
- package/cjs/domain/logsCollection/networkError/networkErrorCollection.js +238 -0
- package/cjs/domain/logsCollection/report/reportCollection.js +50 -0
- package/cjs/domain/logsCollection/rumtimeError/runtimeErrorCollection.js +46 -0
- package/cjs/domain/{loggerSession.js → logsSessionManager.js} +19 -23
- package/cjs/entries/main.js +16 -0
- package/cjs/index.js +2 -2
- package/cjs/transport/startLogsBatch.js +15 -0
- package/esm/boot/buildEnv.js +1 -1
- package/esm/boot/logsPublicApi.js +122 -0
- package/esm/boot/startLogs.js +45 -0
- package/esm/domain/assembly.js +59 -0
- package/esm/domain/configuration.js +41 -0
- package/esm/domain/internalContext.js +15 -0
- package/esm/domain/logger.js +26 -36
- package/esm/domain/logsCollection/console/consoleCollection.js +31 -0
- package/esm/domain/logsCollection/logger/loggerCollection.js +38 -0
- package/esm/domain/logsCollection/networkError/networkErrorCollection.js +223 -0
- package/esm/domain/logsCollection/report/reportCollection.js +40 -0
- package/esm/domain/logsCollection/rumtimeError/runtimeErrorCollection.js +37 -0
- package/esm/domain/logsSessionManager.js +45 -0
- package/esm/entries/main.js +5 -0
- package/esm/index.js +1 -1
- package/esm/transport/startLogsBatch.js +7 -0
- package/package.json +3 -3
- package/src/boot/logsPublicApi.js +140 -0
- package/src/boot/startLogs.js +51 -0
- package/src/domain/assembly.js +101 -0
- package/src/domain/configuration.js +70 -0
- package/src/domain/internalContext.js +15 -0
- package/src/domain/logger.js +37 -58
- package/src/domain/logsCollection/console/consoleCollection.js +36 -0
- package/src/domain/logsCollection/logger/loggerCollection.js +48 -0
- package/src/domain/logsCollection/networkError/networkErrorCollection.js +260 -0
- package/src/domain/logsCollection/report/reportCollection.js +49 -0
- package/src/domain/logsCollection/rumtimeError/runtimeErrorCollection.js +35 -0
- package/src/domain/logsSessionManager.js +52 -0
- package/src/entries/main.js +7 -0
- package/src/index.js +1 -1
- package/src/transport/startLogsBatch.js +17 -0
- package/cjs/boot/log.entry.js +0 -115
- package/cjs/boot/log.js +0 -132
- package/esm/boot/log.entry.js +0 -87
- package/esm/boot/log.js +0 -115
- package/esm/domain/loggerSession.js +0 -46
- package/src/boot/log.entry.js +0 -119
- package/src/boot/log.js +0 -185
- package/src/domain/loggerSession.js +0 -56
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { timeStampNow, ConsoleApiName, ErrorSource, initConsoleObservable, LifeCycleEventType } from '@cloudcare/browser-core'
|
|
2
|
+
import { StatusType } from '../../logger'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
var LogStatusForApi = {
|
|
6
|
+
[ConsoleApiName.log]: StatusType.info,
|
|
7
|
+
[ConsoleApiName.debug]: StatusType.debug,
|
|
8
|
+
[ConsoleApiName.info]: StatusType.info,
|
|
9
|
+
[ConsoleApiName.warn]: StatusType.warn,
|
|
10
|
+
[ConsoleApiName.error]: StatusType.error,
|
|
11
|
+
}
|
|
12
|
+
export function startConsoleCollection(configuration, lifeCycle) {
|
|
13
|
+
var consoleSubscription = initConsoleObservable(configuration.forwardConsoleLogs).subscribe(function(log) {
|
|
14
|
+
lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {
|
|
15
|
+
rawLogsEvent: {
|
|
16
|
+
date: timeStampNow(),
|
|
17
|
+
message: log.message,
|
|
18
|
+
origin: ErrorSource.CONSOLE,
|
|
19
|
+
error:
|
|
20
|
+
log.api === ConsoleApiName.error
|
|
21
|
+
? {
|
|
22
|
+
origin: ErrorSource.CONSOLE, // Todo: Remove in the next major release
|
|
23
|
+
stack: log.stack,
|
|
24
|
+
}
|
|
25
|
+
: undefined,
|
|
26
|
+
status: LogStatusForApi[log.api],
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
stop: function(){
|
|
33
|
+
consoleSubscription.unsubscribe()
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { includes, display, extend2Lev, ErrorSource, timeStampNow, LifeCycleEventType, isArray } from '@cloudcare/browser-core'
|
|
2
|
+
import { StatusType, HandlerType } from '../../logger'
|
|
3
|
+
|
|
4
|
+
export var STATUS_PRIORITIES = {
|
|
5
|
+
[StatusType.debug]: 0,
|
|
6
|
+
[StatusType.info]: 1,
|
|
7
|
+
[StatusType.warn]: 2,
|
|
8
|
+
[StatusType.error]: 3,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function startLoggerCollection(lifeCycle) {
|
|
12
|
+
function handleLog(
|
|
13
|
+
logsMessage,
|
|
14
|
+
logger,
|
|
15
|
+
savedCommonContext,
|
|
16
|
+
savedDate
|
|
17
|
+
) {
|
|
18
|
+
var messageContext = logsMessage.context
|
|
19
|
+
|
|
20
|
+
if (isAuthorized(logsMessage.status, HandlerType.console, logger)) {
|
|
21
|
+
display(logsMessage.status, logsMessage.message, extend2Lev(logger.getContext(), messageContext))
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {
|
|
25
|
+
rawLogsEvent: {
|
|
26
|
+
date: savedDate || timeStampNow(),
|
|
27
|
+
message: logsMessage.message,
|
|
28
|
+
status: logsMessage.status,
|
|
29
|
+
origin: ErrorSource.LOGGER,
|
|
30
|
+
},
|
|
31
|
+
messageContext: messageContext,
|
|
32
|
+
savedCommonContext: savedCommonContext,
|
|
33
|
+
logger: logger,
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
handleLog: handleLog,
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function isAuthorized(status, handlerType, logger) {
|
|
43
|
+
var loggerHandler = logger.getHandler()
|
|
44
|
+
var sanitizedHandlerType = isArray(loggerHandler) ? loggerHandler : [loggerHandler]
|
|
45
|
+
return (
|
|
46
|
+
STATUS_PRIORITIES[status] >= STATUS_PRIORITIES[logger.getLevel()] && includes(sanitizedHandlerType, handlerType)
|
|
47
|
+
)
|
|
48
|
+
}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ErrorSource,
|
|
3
|
+
initXhrObservable,
|
|
4
|
+
RequestType,
|
|
5
|
+
initFetchObservable,
|
|
6
|
+
computeStackTrace,
|
|
7
|
+
toStackTraceString,
|
|
8
|
+
noop,
|
|
9
|
+
each,
|
|
10
|
+
LifeCycleEventType,
|
|
11
|
+
getStatusGroup,
|
|
12
|
+
urlParse,
|
|
13
|
+
replaceNumberCharByPath
|
|
14
|
+
} from '@cloudcare/browser-core'
|
|
15
|
+
import { StatusType } from '../../logger'
|
|
16
|
+
|
|
17
|
+
export function startNetworkErrorCollection(configuration, lifeCycle) {
|
|
18
|
+
if (!configuration.forwardErrorsToLogs) {
|
|
19
|
+
return { stop: noop }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
var xhrSubscription = initXhrObservable().subscribe(function(context){
|
|
23
|
+
if (context.state === 'complete') {
|
|
24
|
+
handleCompleteRequest(RequestType.XHR, context, configuration)
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
var fetchSubscription = initFetchObservable().subscribe(function(context) {
|
|
28
|
+
if (context.state === 'complete') {
|
|
29
|
+
handleCompleteRequest(RequestType.FETCH, context, configuration)
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
function handleCompleteRequest(type, request) {
|
|
34
|
+
if (!configuration.isIntakeUrl(request.url) && (isRejected(request) || isServerError(request) || configuration.isServerError(request))) {
|
|
35
|
+
if ('xhr' in request) {
|
|
36
|
+
computeXhrResponseData(request.xhr, configuration, onResponseDataAvailable)
|
|
37
|
+
} else if (request.response) {
|
|
38
|
+
computeFetchResponseText(request.response, configuration, onResponseDataAvailable)
|
|
39
|
+
} else if (request.error) {
|
|
40
|
+
computeFetchErrorText(request.error, configuration, onResponseDataAvailable)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function onResponseDataAvailable(responseData) {
|
|
45
|
+
var urlObj = urlParse(request.url).getParse()
|
|
46
|
+
lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {
|
|
47
|
+
rawLogsEvent: {
|
|
48
|
+
message: format(type) + ' error ' + request.method +' ' + request.url,
|
|
49
|
+
date: request.startClocks.timeStamp,
|
|
50
|
+
error: {
|
|
51
|
+
origin: ErrorSource.NETWORK, // Todo: Remove in the next major release
|
|
52
|
+
stack: responseData || 'Failed to load',
|
|
53
|
+
},
|
|
54
|
+
http: {
|
|
55
|
+
method: request.method, // Cast resource method because of case mismatch cf issue RUMF-1152
|
|
56
|
+
status_code: request.status,
|
|
57
|
+
url: request.url,
|
|
58
|
+
statusGroup: getStatusGroup(request.status),
|
|
59
|
+
urlHost: urlObj.Host,
|
|
60
|
+
urlPath: urlObj.Path,
|
|
61
|
+
urlPathGroup: replaceNumberCharByPath(urlObj.Path)
|
|
62
|
+
},
|
|
63
|
+
status: StatusType.error,
|
|
64
|
+
origin: ErrorSource.NETWORK,
|
|
65
|
+
},
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
stop: function() {
|
|
72
|
+
xhrSubscription.unsubscribe()
|
|
73
|
+
fetchSubscription.unsubscribe()
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// TODO: ideally, computeXhrResponseData should always call the callback with a string instead of
|
|
79
|
+
// `unknown`. But to keep backward compatibility, in the case of XHR with a `responseType` different
|
|
80
|
+
// than "text", the response data should be whatever `xhr.response` is. This is a bit confusing as
|
|
81
|
+
// Logs event 'stack' is expected to be a string. This should be changed in a future major version
|
|
82
|
+
// as it could be a breaking change.
|
|
83
|
+
export function computeXhrResponseData(
|
|
84
|
+
xhr,
|
|
85
|
+
configuration,
|
|
86
|
+
callback
|
|
87
|
+
) {
|
|
88
|
+
if (typeof xhr.response === 'string') {
|
|
89
|
+
callback(truncateResponseText(xhr.response, configuration))
|
|
90
|
+
} else {
|
|
91
|
+
callback(xhr.response)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function computeFetchErrorText(
|
|
96
|
+
error,
|
|
97
|
+
configuration,
|
|
98
|
+
callback
|
|
99
|
+
) {
|
|
100
|
+
callback(truncateResponseText(toStackTraceString(computeStackTrace(error)), configuration))
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function computeFetchResponseText(
|
|
104
|
+
response,
|
|
105
|
+
configuration,
|
|
106
|
+
callback
|
|
107
|
+
) {
|
|
108
|
+
if (!window.TextDecoder) {
|
|
109
|
+
// If the browser doesn't support TextDecoder, let's read the whole response then truncate it.
|
|
110
|
+
//
|
|
111
|
+
// This should only be the case on early versions of Edge (before they migrated to Chromium).
|
|
112
|
+
// Even if it could be possible to implement a workaround for the missing TextDecoder API (using
|
|
113
|
+
// a Blob and FileReader), we found another issue preventing us from reading only the first
|
|
114
|
+
// bytes from the response: contrary to other browsers, when reading from the cloned response,
|
|
115
|
+
// if the original response gets canceled, the cloned response is also canceled and we can't
|
|
116
|
+
// know about it. In the following illustration, the promise returned by `reader.read()` may
|
|
117
|
+
// never be fulfilled:
|
|
118
|
+
//
|
|
119
|
+
// fetch('/').then((response) => {
|
|
120
|
+
// const reader = response.clone().body.getReader()
|
|
121
|
+
// readMore()
|
|
122
|
+
// function readMore() {
|
|
123
|
+
// reader.read().then(
|
|
124
|
+
// (result) => {
|
|
125
|
+
// if (result.done) {
|
|
126
|
+
// console.log('done')
|
|
127
|
+
// } else {
|
|
128
|
+
// readMore()
|
|
129
|
+
// }
|
|
130
|
+
// },
|
|
131
|
+
// () => console.log('error')
|
|
132
|
+
// )
|
|
133
|
+
// }
|
|
134
|
+
// response.body.getReader().cancel()
|
|
135
|
+
// })
|
|
136
|
+
response
|
|
137
|
+
.clone()
|
|
138
|
+
.text()
|
|
139
|
+
.then(
|
|
140
|
+
function(text) { return callback(truncateResponseText(text, configuration)) },
|
|
141
|
+
function(error) { return callback('Unable to retrieve response: ' + error ) }
|
|
142
|
+
)
|
|
143
|
+
} else if (!response.body) {
|
|
144
|
+
callback()
|
|
145
|
+
} else {
|
|
146
|
+
truncateResponseStream(
|
|
147
|
+
response.clone().body,
|
|
148
|
+
configuration.requestErrorResponseLengthLimit,
|
|
149
|
+
function(error, responseText){
|
|
150
|
+
if (error) {
|
|
151
|
+
callback('Unable to retrieve response: ' + error)
|
|
152
|
+
} else {
|
|
153
|
+
callback(responseText)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function isRejected(request) {
|
|
161
|
+
return request.status === 0 && request.responseType !== 'opaque'
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function isServerError(request) {
|
|
165
|
+
return request.status >= 500
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function truncateResponseText(responseText, configuration) {
|
|
169
|
+
if (responseText.length > configuration.requestErrorResponseLengthLimit) {
|
|
170
|
+
return responseText.substring(0, configuration.requestErrorResponseLengthLimit) + '...'
|
|
171
|
+
}
|
|
172
|
+
return responseText
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function format(type) {
|
|
176
|
+
if (RequestType.XHR === type) {
|
|
177
|
+
return 'XHR'
|
|
178
|
+
}
|
|
179
|
+
return 'Fetch'
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function truncateResponseStream(
|
|
183
|
+
stream,
|
|
184
|
+
limit,
|
|
185
|
+
callback
|
|
186
|
+
) {
|
|
187
|
+
readLimitedAmountOfBytes(stream, limit, function(error, bytes, limitExceeded){
|
|
188
|
+
if (error) {
|
|
189
|
+
callback(error)
|
|
190
|
+
} else {
|
|
191
|
+
var responseText = new TextDecoder().decode(bytes)
|
|
192
|
+
if (limitExceeded) {
|
|
193
|
+
responseText += '...'
|
|
194
|
+
}
|
|
195
|
+
callback(undefined, responseText)
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Read bytes from a ReadableStream until at least `limit` bytes have been read (or until the end of
|
|
202
|
+
* the stream). The callback is invoked with the at most `limit` bytes, and indicates that the limit
|
|
203
|
+
* has been exceeded if more bytes were available.
|
|
204
|
+
*/
|
|
205
|
+
function readLimitedAmountOfBytes(
|
|
206
|
+
stream,
|
|
207
|
+
limit,
|
|
208
|
+
callback
|
|
209
|
+
) {
|
|
210
|
+
var reader = stream.getReader()
|
|
211
|
+
var chunks = []
|
|
212
|
+
var readBytesCount = 0
|
|
213
|
+
|
|
214
|
+
readMore()
|
|
215
|
+
|
|
216
|
+
function readMore() {
|
|
217
|
+
reader.read().then(
|
|
218
|
+
function(result){
|
|
219
|
+
if (result.done) {
|
|
220
|
+
onDone()
|
|
221
|
+
return
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
chunks.push(result.value)
|
|
225
|
+
readBytesCount += result.value.length
|
|
226
|
+
|
|
227
|
+
if (readBytesCount > limit) {
|
|
228
|
+
onDone()
|
|
229
|
+
} else {
|
|
230
|
+
readMore()
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
function(error) { return callback(error) }
|
|
234
|
+
)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function onDone() {
|
|
238
|
+
reader.cancel().catch(
|
|
239
|
+
// we don't care if cancel fails, but we still need to catch the error to avoid reporting it
|
|
240
|
+
// as an unhandled rejection
|
|
241
|
+
noop
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
var completeBuffer
|
|
245
|
+
if (chunks.length === 1) {
|
|
246
|
+
// optim: if the response is small enough to fit in a single buffer (provided by the browser), just
|
|
247
|
+
// use it directly.
|
|
248
|
+
completeBuffer = chunks[0]
|
|
249
|
+
} else {
|
|
250
|
+
// else, we need to copy buffers into a larger buffer to concatenate them.
|
|
251
|
+
completeBuffer = new Uint8Array(readBytesCount)
|
|
252
|
+
var offset = 0
|
|
253
|
+
each(chunks, function(chunk) {
|
|
254
|
+
completeBuffer.set(chunk, offset)
|
|
255
|
+
offset += chunk.length
|
|
256
|
+
})
|
|
257
|
+
}
|
|
258
|
+
callback(undefined, completeBuffer.slice(0, limit), completeBuffer.length > limit)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {
|
|
2
|
+
timeStampNow,
|
|
3
|
+
ErrorSource,
|
|
4
|
+
RawReportType,
|
|
5
|
+
getFileFromStackTraceString,
|
|
6
|
+
initReportObservable,
|
|
7
|
+
LifeCycleEventType
|
|
8
|
+
} from '@cloudcare/browser-core'
|
|
9
|
+
import { StatusType } from '../../logger'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
var LogStatusForReport = {
|
|
13
|
+
[RawReportType.cspViolation]: StatusType.error,
|
|
14
|
+
[RawReportType.intervention]: StatusType.error,
|
|
15
|
+
[RawReportType.deprecation]: StatusType.warn,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function startReportCollection(configuration, lifeCycle) {
|
|
19
|
+
var reportSubscription = initReportObservable(configuration.forwardReports).subscribe(function(report) {
|
|
20
|
+
var message = report.message
|
|
21
|
+
var status = LogStatusForReport[report.type]
|
|
22
|
+
var error
|
|
23
|
+
if (status === StatusType.error) {
|
|
24
|
+
error = {
|
|
25
|
+
kind: report.subtype,
|
|
26
|
+
origin: ErrorSource.REPORT, // Todo: Remove in the next major release
|
|
27
|
+
stack: report.stack,
|
|
28
|
+
}
|
|
29
|
+
} else if (report.stack) {
|
|
30
|
+
message += ' Found in '+ getFileFromStackTraceString(report.stack)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {
|
|
34
|
+
rawLogsEvent: {
|
|
35
|
+
date: timeStampNow(),
|
|
36
|
+
message: message,
|
|
37
|
+
origin: ErrorSource.REPORT,
|
|
38
|
+
error: error,
|
|
39
|
+
status: status,
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
stop: function(){
|
|
46
|
+
reportSubscription.unsubscribe()
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { noop, ErrorSource, trackRuntimeError, Observable, LifeCycleEventType } from '@cloudcare/browser-core'
|
|
2
|
+
import { StatusType } from '../../logger'
|
|
3
|
+
|
|
4
|
+
export function startRuntimeErrorCollection(configuration, lifeCycle) {
|
|
5
|
+
if (!configuration.forwardErrorsToLogs) {
|
|
6
|
+
return { stop: noop }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
var rawErrorObservable = new Observable()
|
|
10
|
+
|
|
11
|
+
var _trackRuntimeError = trackRuntimeError(rawErrorObservable)
|
|
12
|
+
|
|
13
|
+
var rawErrorSubscription = rawErrorObservable.subscribe(function(rawError) {
|
|
14
|
+
lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, {
|
|
15
|
+
rawLogsEvent: {
|
|
16
|
+
message: rawError.message,
|
|
17
|
+
date: rawError.startClocks.timeStamp,
|
|
18
|
+
error: {
|
|
19
|
+
kind: rawError.type,
|
|
20
|
+
origin: ErrorSource.SOURCE, // Todo: Remove in the next major release
|
|
21
|
+
stack: rawError.stack,
|
|
22
|
+
},
|
|
23
|
+
origin: ErrorSource.SOURCE,
|
|
24
|
+
status: StatusType.error,
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
stop: function() {
|
|
31
|
+
_trackRuntimeError.stop()
|
|
32
|
+
rawErrorSubscription.unsubscribe()
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { performDraw, startSessionManager } from '@cloudcare/browser-core'
|
|
2
|
+
|
|
3
|
+
export var LOGS_SESSION_KEY = 'logs'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export var LoggerTrackingType = {
|
|
7
|
+
NOT_TRACKED: '0',
|
|
8
|
+
TRACKED: '1',
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function startLogsSessionManager(configuration) {
|
|
12
|
+
var sessionManager = startSessionManager(configuration.cookieOptions, LOGS_SESSION_KEY, function(rawTrackingType) {
|
|
13
|
+
return computeSessionState(configuration, rawTrackingType)
|
|
14
|
+
})
|
|
15
|
+
return {
|
|
16
|
+
findTrackedSession: function(startTime){
|
|
17
|
+
var session = sessionManager.findActiveSession(startTime)
|
|
18
|
+
return session && session.trackingType === LoggerTrackingType.TRACKED
|
|
19
|
+
? {
|
|
20
|
+
id: session.id,
|
|
21
|
+
}
|
|
22
|
+
: undefined
|
|
23
|
+
},
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// export function startLogsSessionManagerStub(configuration) {
|
|
28
|
+
// var isTracked = computeTrackingType(configuration) === LoggerTrackingType.TRACKED
|
|
29
|
+
// var session = isTracked ? {} : undefined
|
|
30
|
+
// return {
|
|
31
|
+
// findTrackedSession: function() { return session },
|
|
32
|
+
// }
|
|
33
|
+
// }
|
|
34
|
+
|
|
35
|
+
function computeTrackingType(configuration) {
|
|
36
|
+
if (!performDraw(configuration.sampleRate)) {
|
|
37
|
+
return LoggerTrackingType.NOT_TRACKED
|
|
38
|
+
}
|
|
39
|
+
return LoggerTrackingType.TRACKED
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function computeSessionState(configuration, rawSessionType) {
|
|
43
|
+
var trackingType = hasValidLoggerSession(rawSessionType) ? rawSessionType : computeTrackingType(configuration)
|
|
44
|
+
return {
|
|
45
|
+
trackingType: trackingType,
|
|
46
|
+
isTracked: trackingType === LoggerTrackingType.TRACKED,
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function hasValidLoggerSession(trackingType){
|
|
51
|
+
return trackingType === LoggerTrackingType.NOT_TRACKED || trackingType === LoggerTrackingType.TRACKED
|
|
52
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { defineGlobal, getGlobalObject } from '@cloudcare/browser-core'
|
|
2
|
+
import { makeLogsPublicApi } from '../boot/logsPublicApi'
|
|
3
|
+
import { startLogs } from '../boot/startLogs'
|
|
4
|
+
|
|
5
|
+
export const datafluxLogs = makeLogsPublicApi(startLogs)
|
|
6
|
+
|
|
7
|
+
defineGlobal(getGlobalObject(), 'DATAFLUX_LOGS', datafluxLogs)
|
package/src/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { datafluxLogs } from './
|
|
1
|
+
import { datafluxLogs } from './entries/main'
|
|
2
2
|
export { datafluxLogs }
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { startBatchWithReplica, LifeCycleEventType } from '@cloudcare/browser-core'
|
|
2
|
+
|
|
3
|
+
export function startLogsBatch(
|
|
4
|
+
configuration,
|
|
5
|
+
lifeCycle,
|
|
6
|
+
reportError
|
|
7
|
+
) {
|
|
8
|
+
var batch = startBatchWithReplica(
|
|
9
|
+
configuration,
|
|
10
|
+
configuration.logsEndpoint,
|
|
11
|
+
reportError
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
lifeCycle.subscribe(LifeCycleEventType.LOG_COLLECTED, function(serverLogsEvent) {
|
|
15
|
+
batch.add(serverLogsEvent)
|
|
16
|
+
})
|
|
17
|
+
}
|
package/cjs/boot/log.entry.js
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.datafluxLogs = void 0;
|
|
7
|
-
exports.makeLogsPublicApi = makeLogsPublicApi;
|
|
8
|
-
|
|
9
|
-
var _browserCore = require("@cloudcare/browser-core");
|
|
10
|
-
|
|
11
|
-
var _log = require("./log");
|
|
12
|
-
|
|
13
|
-
var _logger = require("../domain/logger");
|
|
14
|
-
|
|
15
|
-
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
16
|
-
|
|
17
|
-
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
18
|
-
|
|
19
|
-
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
20
|
-
|
|
21
|
-
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
22
|
-
|
|
23
|
-
function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
|
|
24
|
-
|
|
25
|
-
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
26
|
-
|
|
27
|
-
var datafluxLogs = makeLogsPublicApi(_log.startLogs);
|
|
28
|
-
exports.datafluxLogs = datafluxLogs;
|
|
29
|
-
(0, _browserCore.defineGlobal)((0, _browserCore.getGlobalObject)(), 'DATAFLUX_LOGS', datafluxLogs);
|
|
30
|
-
|
|
31
|
-
function makeLogsPublicApi(startLogsImpl) {
|
|
32
|
-
var isAlreadyInitialized = false;
|
|
33
|
-
var globalContextManager = (0, _browserCore.createContextManager)();
|
|
34
|
-
var customLoggers = {};
|
|
35
|
-
var beforeInitSendLog = new _browserCore.BoundedBuffer();
|
|
36
|
-
|
|
37
|
-
var sendLogStrategy = function sendLogStrategy(message, currentContext) {
|
|
38
|
-
beforeInitSendLog.add([message, currentContext]);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
var logger = new _logger.Logger(sendLog);
|
|
42
|
-
return (0, _browserCore.makePublicApi)({
|
|
43
|
-
logger: logger,
|
|
44
|
-
init: function init(userConfiguration) {
|
|
45
|
-
if (!canInitLogs(userConfiguration)) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
sendLogStrategy = startLogsImpl(userConfiguration, logger, globalContextManager.get);
|
|
50
|
-
beforeInitSendLog.drain(function (_ref) {
|
|
51
|
-
var _ref2 = _slicedToArray(_ref, 2),
|
|
52
|
-
message = _ref2[0],
|
|
53
|
-
context = _ref2[1];
|
|
54
|
-
|
|
55
|
-
return sendLogStrategy(message, context);
|
|
56
|
-
});
|
|
57
|
-
isAlreadyInitialized = true;
|
|
58
|
-
},
|
|
59
|
-
getLoggerGlobalContext: globalContextManager.get,
|
|
60
|
-
setLoggerGlobalContext: globalContextManager.set,
|
|
61
|
-
addLoggerGlobalContext: globalContextManager.add,
|
|
62
|
-
removeLoggerGlobalContext: globalContextManager.remove,
|
|
63
|
-
createLogger: function createLogger(name, conf) {
|
|
64
|
-
if (typeof conf === 'undefined') {
|
|
65
|
-
conf = {};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
customLoggers[name] = new _logger.Logger(sendLog, conf.handler, conf.level, (0, _browserCore.extend)({}, conf.context, {
|
|
69
|
-
logger: {
|
|
70
|
-
name: name
|
|
71
|
-
}
|
|
72
|
-
}));
|
|
73
|
-
return customLoggers[name];
|
|
74
|
-
},
|
|
75
|
-
getLogger: function getLogger(name) {
|
|
76
|
-
return customLoggers[name];
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
function canInitLogs(userConfiguration) {
|
|
81
|
-
if (isAlreadyInitialized) {
|
|
82
|
-
if (!userConfiguration.silentMultipleInit) {
|
|
83
|
-
console.error('DATAFLUX_LOGS is already initialized.');
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (!userConfiguration.datakitUrl && !userConfiguration.datakitOrigin) {
|
|
90
|
-
console.error('datakitOrigin is not configured, no RUM data will be collected.');
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (userConfiguration.sampleRate !== undefined && !(0, _browserCore.isPercentage)(userConfiguration.sampleRate)) {
|
|
95
|
-
console.error('Sample Rate should be a number between 0 and 100');
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function sendLog(message) {
|
|
103
|
-
sendLogStrategy(message, (0, _browserCore.extend2Lev)({
|
|
104
|
-
date: new Date().getTime(),
|
|
105
|
-
view: {
|
|
106
|
-
referrer: document.referrer,
|
|
107
|
-
url: window.location.href,
|
|
108
|
-
host: window.location.host,
|
|
109
|
-
path: window.location.pathname,
|
|
110
|
-
pathGroup: (0, _browserCore.replaceNumberCharByPath)(window.location.pathname),
|
|
111
|
-
urlQuery: (0, _browserCore.jsonStringify)((0, _browserCore.getQueryParamsFromUrl)(window.location.href))
|
|
112
|
-
}
|
|
113
|
-
}, globalContextManager.get()));
|
|
114
|
-
}
|
|
115
|
-
}
|