@kubesense/kubesense-browser-logs 0.0.0-stage → 2.0.0-beta.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.
- package/LICENSE +201 -0
- package/README.md +90 -2
- package/bundle/kubesense-logs.js +1 -0
- package/cjs/boot/logsPublicApi.d.ts +231 -0
- package/cjs/boot/logsPublicApi.js +75 -0
- package/cjs/boot/logsPublicApi.js.map +1 -0
- package/cjs/boot/preStartLogs.d.ts +8 -0
- package/cjs/boot/preStartLogs.js +105 -0
- package/cjs/boot/preStartLogs.js.map +1 -0
- package/cjs/boot/startLogs.d.ts +35 -0
- package/cjs/boot/startLogs.js +54 -0
- package/cjs/boot/startLogs.js.map +1 -0
- package/cjs/domain/assembly.d.ts +5 -0
- package/cjs/domain/assembly.js +35 -0
- package/cjs/domain/assembly.js.map +1 -0
- package/cjs/domain/configuration.d.ts +306 -0
- package/cjs/domain/configuration.js +86 -0
- package/cjs/domain/configuration.js.map +1 -0
- package/cjs/domain/console/consoleCollection.d.ts +20 -0
- package/cjs/domain/console/consoleCollection.js +37 -0
- package/cjs/domain/console/consoleCollection.js.map +1 -0
- package/cjs/domain/contexts/commonContext.d.ts +2 -0
- package/cjs/domain/contexts/commonContext.js +13 -0
- package/cjs/domain/contexts/commonContext.js.map +1 -0
- package/cjs/domain/contexts/internalContext.d.ts +7 -0
- package/cjs/domain/contexts/internalContext.js +11 -0
- package/cjs/domain/contexts/internalContext.js.map +1 -0
- package/cjs/domain/contexts/rumInternalContext.d.ts +2 -0
- package/cjs/domain/contexts/rumInternalContext.js +32 -0
- package/cjs/domain/contexts/rumInternalContext.js.map +1 -0
- package/cjs/domain/contexts/sessionContext.d.ts +4 -0
- package/cjs/domain/contexts/sessionContext.js +20 -0
- package/cjs/domain/contexts/sessionContext.js.map +1 -0
- package/cjs/domain/contexts/trackingConsentContext.d.ts +3 -0
- package/cjs/domain/contexts/trackingConsentContext.js +14 -0
- package/cjs/domain/contexts/trackingConsentContext.js.map +1 -0
- package/cjs/domain/createErrorFieldFromRawError.d.ts +10 -0
- package/cjs/domain/createErrorFieldFromRawError.js +15 -0
- package/cjs/domain/createErrorFieldFromRawError.js.map +1 -0
- package/cjs/domain/hooks.d.ts +28 -0
- package/cjs/domain/hooks.js +13 -0
- package/cjs/domain/hooks.js.map +1 -0
- package/cjs/domain/lifeCycle.d.ts +24 -0
- package/cjs/domain/lifeCycle.js +6 -0
- package/cjs/domain/lifeCycle.js.map +1 -0
- package/cjs/domain/logger/isAuthorized.d.ts +17 -0
- package/cjs/domain/logger/isAuthorized.js +34 -0
- package/cjs/domain/logger/isAuthorized.js.map +1 -0
- package/cjs/domain/logger/loggerCollection.d.ts +7 -0
- package/cjs/domain/logger/loggerCollection.js +47 -0
- package/cjs/domain/logger/loggerCollection.js.map +1 -0
- package/cjs/domain/logger.d.ts +48 -0
- package/cjs/domain/logger.js +112 -0
- package/cjs/domain/logger.js.map +1 -0
- package/cjs/domain/networkError/networkErrorCollection.d.ts +9 -0
- package/cjs/domain/networkError/networkErrorCollection.js +57 -0
- package/cjs/domain/networkError/networkErrorCollection.js.map +1 -0
- package/cjs/domain/plugins.d.ts +49 -0
- package/cjs/domain/plugins.js +12 -0
- package/cjs/domain/plugins.js.map +1 -0
- package/cjs/domain/remoteSdkConfiguration.d.ts +26 -0
- package/cjs/domain/remoteSdkConfiguration.js +67 -0
- package/cjs/domain/remoteSdkConfiguration.js.map +1 -0
- package/cjs/domain/report/reportCollection.d.ts +13 -0
- package/cjs/domain/report/reportCollection.js +30 -0
- package/cjs/domain/report/reportCollection.js.map +1 -0
- package/cjs/domain/reportError.d.ts +2 -0
- package/cjs/domain/reportError.js +20 -0
- package/cjs/domain/reportError.js.map +1 -0
- package/cjs/domain/runtimeError/runtimeErrorCollection.d.ts +14 -0
- package/cjs/domain/runtimeError/runtimeErrorCollection.js +29 -0
- package/cjs/domain/runtimeError/runtimeErrorCollection.js.map +1 -0
- package/cjs/domainContext.types.d.ts +11 -0
- package/cjs/entries/main.d.ts +33 -0
- package/cjs/entries/main.js +31 -0
- package/cjs/entries/main.js.map +1 -0
- package/cjs/logsEvent.types.d.ts +192 -0
- package/cjs/rawLogsEvent.types.d.ts +59 -0
- package/cjs/transport/startLogsBatch.d.ts +4 -0
- package/cjs/transport/startLogsBatch.js +22 -0
- package/cjs/transport/startLogsBatch.js.map +1 -0
- package/cjs/transport/startLogsBridge.d.ts +2 -0
- package/cjs/transport/startLogsBridge.js +13 -0
- package/cjs/transport/startLogsBridge.js.map +1 -0
- package/esm/boot/logsPublicApi.mjs +75 -0
- package/esm/boot/logsPublicApi.mjs.map +1 -0
- package/esm/boot/preStartLogs.mjs +105 -0
- package/esm/boot/preStartLogs.mjs.map +1 -0
- package/esm/boot/startLogs.mjs +54 -0
- package/esm/boot/startLogs.mjs.map +1 -0
- package/esm/domain/assembly.mjs +35 -0
- package/esm/domain/assembly.mjs.map +1 -0
- package/esm/domain/configuration.mjs +84 -0
- package/esm/domain/configuration.mjs.map +1 -0
- package/esm/domain/console/consoleCollection.mjs +36 -0
- package/esm/domain/console/consoleCollection.mjs.map +1 -0
- package/esm/domain/contexts/commonContext.mjs +13 -0
- package/esm/domain/contexts/commonContext.mjs.map +1 -0
- package/esm/domain/contexts/internalContext.mjs +11 -0
- package/esm/domain/contexts/internalContext.mjs.map +1 -0
- package/esm/domain/contexts/rumInternalContext.mjs +32 -0
- package/esm/domain/contexts/rumInternalContext.mjs.map +1 -0
- package/esm/domain/contexts/sessionContext.mjs +20 -0
- package/esm/domain/contexts/sessionContext.mjs.map +1 -0
- package/esm/domain/contexts/trackingConsentContext.mjs +14 -0
- package/esm/domain/contexts/trackingConsentContext.mjs.map +1 -0
- package/esm/domain/createErrorFieldFromRawError.mjs +15 -0
- package/esm/domain/createErrorFieldFromRawError.mjs.map +1 -0
- package/esm/domain/hooks.mjs +13 -0
- package/esm/domain/hooks.mjs.map +1 -0
- package/esm/domain/lifeCycle.mjs +7 -0
- package/esm/domain/lifeCycle.mjs.map +1 -0
- package/esm/domain/logger/isAuthorized.mjs +32 -0
- package/esm/domain/logger/isAuthorized.mjs.map +1 -0
- package/esm/domain/logger/loggerCollection.mjs +47 -0
- package/esm/domain/logger/loggerCollection.mjs.map +1 -0
- package/esm/domain/logger.mjs +110 -0
- package/esm/domain/logger.mjs.map +1 -0
- package/esm/domain/networkError/networkErrorCollection.mjs +56 -0
- package/esm/domain/networkError/networkErrorCollection.mjs.map +1 -0
- package/esm/domain/plugins.mjs +12 -0
- package/esm/domain/plugins.mjs.map +1 -0
- package/esm/domain/remoteSdkConfiguration.mjs +65 -0
- package/esm/domain/remoteSdkConfiguration.mjs.map +1 -0
- package/esm/domain/report/reportCollection.mjs +30 -0
- package/esm/domain/report/reportCollection.mjs.map +1 -0
- package/esm/domain/reportError.mjs +20 -0
- package/esm/domain/reportError.mjs.map +1 -0
- package/esm/domain/runtimeError/runtimeErrorCollection.mjs +29 -0
- package/esm/domain/runtimeError/runtimeErrorCollection.mjs.map +1 -0
- package/esm/entries/main.mjs +27 -0
- package/esm/entries/main.mjs.map +1 -0
- package/esm/transport/startLogsBatch.mjs +22 -0
- package/esm/transport/startLogsBatch.mjs.map +1 -0
- package/esm/transport/startLogsBridge.mjs +13 -0
- package/esm/transport/startLogsBridge.mjs.map +1 -0
- package/package.json +53 -3
- package/src/boot/logsPublicApi.ts +427 -0
- package/src/boot/preStartLogs.ts +192 -0
- package/src/boot/startLogs.ts +83 -0
- package/src/domain/assembly.ts +73 -0
- package/src/domain/configuration.ts +176 -0
- package/src/domain/console/consoleCollection.ts +58 -0
- package/src/domain/contexts/commonContext.ts +15 -0
- package/src/domain/contexts/internalContext.ts +19 -0
- package/src/domain/contexts/rumInternalContext.ts +60 -0
- package/src/domain/contexts/sessionContext.ts +34 -0
- package/src/domain/contexts/trackingConsentContext.ts +18 -0
- package/src/domain/createErrorFieldFromRawError.ts +22 -0
- package/src/domain/hooks.ts +40 -0
- package/src/domain/lifeCycle.ts +25 -0
- package/src/domain/logger/isAuthorized.ts +33 -0
- package/src/domain/logger/loggerCollection.ts +69 -0
- package/src/domain/logger.ts +202 -0
- package/src/domain/networkError/networkErrorCollection.ts +104 -0
- package/src/domain/plugins.ts +72 -0
- package/src/domain/remoteSdkConfiguration.ts +105 -0
- package/src/domain/report/reportCollection.ts +47 -0
- package/src/domain/reportError.ts +20 -0
- package/src/domain/runtimeError/runtimeErrorCollection.ts +51 -0
- package/src/domainContext.types.ts +21 -0
- package/src/entries/main.ts +65 -0
- package/src/logsEvent.types.ts +198 -0
- package/src/rawLogsEvent.types.ts +74 -0
- package/src/transport/startLogsBatch.ts +29 -0
- package/src/transport/startLogsBridge.ts +13 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { BufferedObservable, BufferedData, SessionManager } from '@kubesense/kubesense-browser-core'
|
|
2
|
+
import {
|
|
3
|
+
sendToExtension,
|
|
4
|
+
canUseEventBridge,
|
|
5
|
+
startAccountContext,
|
|
6
|
+
startGlobalContext,
|
|
7
|
+
startUserContext,
|
|
8
|
+
startTabContext,
|
|
9
|
+
} from '@kubesense/kubesense-browser-core'
|
|
10
|
+
import type { LogsConfiguration } from '../domain/configuration'
|
|
11
|
+
import { startLogsAssembly } from '../domain/assembly'
|
|
12
|
+
import { startConsoleCollection } from '../domain/console/consoleCollection'
|
|
13
|
+
import { startReportCollection } from '../domain/report/reportCollection'
|
|
14
|
+
import { startNetworkErrorCollection } from '../domain/networkError/networkErrorCollection'
|
|
15
|
+
import { startRuntimeErrorCollection } from '../domain/runtimeError/runtimeErrorCollection'
|
|
16
|
+
import { LifeCycle, LifeCycleEventType } from '../domain/lifeCycle'
|
|
17
|
+
import { startLoggerCollection } from '../domain/logger/loggerCollection'
|
|
18
|
+
import { startLogsBatch } from '../transport/startLogsBatch'
|
|
19
|
+
import { startLogsBridge } from '../transport/startLogsBridge'
|
|
20
|
+
import { startInternalContext } from '../domain/contexts/internalContext'
|
|
21
|
+
import { startReportError } from '../domain/reportError'
|
|
22
|
+
import type { CommonContext } from '../rawLogsEvent.types'
|
|
23
|
+
import type { Hooks } from '../domain/hooks'
|
|
24
|
+
import { startRUMInternalContext } from '../domain/contexts/rumInternalContext'
|
|
25
|
+
import { startSessionContext } from '../domain/contexts/sessionContext'
|
|
26
|
+
|
|
27
|
+
const LOGS_STORAGE_KEY = 'logs'
|
|
28
|
+
|
|
29
|
+
export type StartLogs = typeof startLogs
|
|
30
|
+
export type StartLogsResult = ReturnType<StartLogs>
|
|
31
|
+
|
|
32
|
+
export function startLogs(
|
|
33
|
+
configuration: LogsConfiguration,
|
|
34
|
+
sessionManager: SessionManager,
|
|
35
|
+
getCommonContext: () => CommonContext,
|
|
36
|
+
bufferedDataObservable: BufferedObservable<BufferedData>,
|
|
37
|
+
hooks: Hooks
|
|
38
|
+
) {
|
|
39
|
+
const lifeCycle = new LifeCycle()
|
|
40
|
+
const cleanupTasks: Array<() => void> = []
|
|
41
|
+
|
|
42
|
+
lifeCycle.subscribe(LifeCycleEventType.LOG_COLLECTED, (log) => sendToExtension('logs', log))
|
|
43
|
+
|
|
44
|
+
const reportError = startReportError(lifeCycle)
|
|
45
|
+
|
|
46
|
+
// Start user and account context first to allow overrides from global context
|
|
47
|
+
const { assembleEventDefaults: assembleHook } = hooks
|
|
48
|
+
startSessionContext(assembleHook, configuration, sessionManager)
|
|
49
|
+
const accountContext = startAccountContext(assembleHook, configuration, LOGS_STORAGE_KEY)
|
|
50
|
+
const userContext = startUserContext(assembleHook, configuration, sessionManager, LOGS_STORAGE_KEY)
|
|
51
|
+
const globalContext = startGlobalContext(assembleHook, configuration, LOGS_STORAGE_KEY, false)
|
|
52
|
+
startRUMInternalContext(hooks)
|
|
53
|
+
startTabContext(assembleHook)
|
|
54
|
+
|
|
55
|
+
startNetworkErrorCollection(configuration, lifeCycle, bufferedDataObservable)
|
|
56
|
+
startRuntimeErrorCollection(configuration, lifeCycle, bufferedDataObservable)
|
|
57
|
+
startConsoleCollection(configuration, lifeCycle, bufferedDataObservable)
|
|
58
|
+
bufferedDataObservable.unbuffer()
|
|
59
|
+
startReportCollection(configuration, lifeCycle)
|
|
60
|
+
const { handleLog } = startLoggerCollection(lifeCycle)
|
|
61
|
+
|
|
62
|
+
startLogsAssembly(configuration, lifeCycle, hooks, getCommonContext, reportError)
|
|
63
|
+
|
|
64
|
+
if (!canUseEventBridge()) {
|
|
65
|
+
const { stop: stopLogsBatch } = startLogsBatch(configuration, lifeCycle, reportError, sessionManager)
|
|
66
|
+
cleanupTasks.push(() => stopLogsBatch())
|
|
67
|
+
} else {
|
|
68
|
+
startLogsBridge(lifeCycle)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const internalContext = startInternalContext(sessionManager)
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
handleLog,
|
|
75
|
+
getInternalContext: internalContext.get,
|
|
76
|
+
accountContext,
|
|
77
|
+
globalContext,
|
|
78
|
+
userContext,
|
|
79
|
+
stop: () => {
|
|
80
|
+
cleanupTasks.forEach((task) => task())
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { Context, EventRateLimiter } from '@kubesense/kubesense-browser-core'
|
|
2
|
+
import { ErrorSource, buildTags, createEventRateLimiter } from '@kubesense/kubesense-browser-core'
|
|
3
|
+
import { toRelativeTime } from '@kubesense/kubesense-js-core/time'
|
|
4
|
+
import { DISCARDED } from '@kubesense/kubesense-js-core/assembly'
|
|
5
|
+
import { combine } from '@kubesense/kubesense-js-core/util'
|
|
6
|
+
import type { CommonContext } from '../rawLogsEvent.types'
|
|
7
|
+
import type { LogsEvent } from '../logsEvent.types'
|
|
8
|
+
import type { LogsConfiguration } from './configuration'
|
|
9
|
+
import type { LifeCycle } from './lifeCycle'
|
|
10
|
+
import { LifeCycleEventType } from './lifeCycle'
|
|
11
|
+
import { STATUSES } from './logger'
|
|
12
|
+
import type { Hooks, AssembleHookParams } from './hooks'
|
|
13
|
+
|
|
14
|
+
export function startLogsAssembly(
|
|
15
|
+
configuration: LogsConfiguration,
|
|
16
|
+
lifeCycle: LifeCycle,
|
|
17
|
+
hooks: Hooks,
|
|
18
|
+
getCommonContext: () => CommonContext,
|
|
19
|
+
reportError: (message: string) => void,
|
|
20
|
+
eventRateLimit?: number
|
|
21
|
+
) {
|
|
22
|
+
const statusWithCustom = (STATUSES as string[]).concat(['custom'])
|
|
23
|
+
const logRateLimiters: { [key: string]: EventRateLimiter } = {}
|
|
24
|
+
statusWithCustom.forEach((status) => {
|
|
25
|
+
logRateLimiters[status] = createEventRateLimiter(status, reportError, eventRateLimit)
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
lifeCycle.subscribe(
|
|
29
|
+
LifeCycleEventType.RAW_LOG_COLLECTED,
|
|
30
|
+
({ rawLogsEvent, savedCommonContext = undefined, domainContext, ktags = [] }) => {
|
|
31
|
+
const startTime = toRelativeTime(rawLogsEvent.date)
|
|
32
|
+
const commonContext = savedCommonContext || getCommonContext()
|
|
33
|
+
const assemblyParams: AssembleHookParams = {
|
|
34
|
+
startTime,
|
|
35
|
+
rawLogsEvent: rawLogsEvent as AssembleHookParams['rawLogsEvent'],
|
|
36
|
+
domainContext,
|
|
37
|
+
}
|
|
38
|
+
const defaultLogsEventAttributes = hooks.assembleEventDefaults.trigger(assemblyParams)
|
|
39
|
+
if (defaultLogsEventAttributes === DISCARDED) {
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const logsEventAttributes = hooks.assembleEvent.trigger(assemblyParams)!
|
|
44
|
+
if (logsEventAttributes === DISCARDED) {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const defaultKtags = buildTags(configuration)
|
|
49
|
+
|
|
50
|
+
const log = combine(
|
|
51
|
+
{
|
|
52
|
+
view: commonContext.view,
|
|
53
|
+
},
|
|
54
|
+
defaultLogsEventAttributes,
|
|
55
|
+
rawLogsEvent,
|
|
56
|
+
logsEventAttributes,
|
|
57
|
+
{
|
|
58
|
+
ktags: defaultKtags.concat(ktags).join(','),
|
|
59
|
+
}
|
|
60
|
+
) as LogsEvent & Context
|
|
61
|
+
|
|
62
|
+
if (
|
|
63
|
+
configuration.beforeSend?.(log, domainContext) === false ||
|
|
64
|
+
(log.origin !== ErrorSource.AGENT &&
|
|
65
|
+
(logRateLimiters[log.status] ?? logRateLimiters['custom']).isLimitReached())
|
|
66
|
+
) {
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
lifeCycle.notify(LifeCycleEventType.LOG_COLLECTED, log)
|
|
71
|
+
}
|
|
72
|
+
)
|
|
73
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import type { InitConfiguration, RawTelemetryConfiguration } from '@kubesense/kubesense-browser-core'
|
|
2
|
+
import { ConsoleApiName } from '@kubesense/kubesense-js-core/util'
|
|
3
|
+
import {
|
|
4
|
+
serializeConfiguration,
|
|
5
|
+
catchUserErrors,
|
|
6
|
+
display,
|
|
7
|
+
RawReportType,
|
|
8
|
+
BROWSER_CORE_SCHEMA,
|
|
9
|
+
} from '@kubesense/kubesense-browser-core'
|
|
10
|
+
import { validateAndBuildConfiguration } from '@kubesense/kubesense-js-core/configuration'
|
|
11
|
+
import type { InferredConfig } from '@kubesense/kubesense-js-core/configuration'
|
|
12
|
+
import type { LogsEvent } from '../logsEvent.types'
|
|
13
|
+
import type { LogsEventDomainContext } from '../domainContext.types'
|
|
14
|
+
import type { LogsPlugin } from './plugins'
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Init Configuration for the Logs browser SDK.
|
|
18
|
+
*
|
|
19
|
+
* @category Main
|
|
20
|
+
* @example NPM
|
|
21
|
+
* ```ts
|
|
22
|
+
* import { kubesenseLogs } from '@kubesense/kubesense-browser-logs'
|
|
23
|
+
*
|
|
24
|
+
* kubesenseLogs.init({
|
|
25
|
+
* clientToken: '<KUBESENSE_CLIENT_TOKEN>',
|
|
26
|
+
* kubesenseRumEndpoint: '<KUBESENSE_RUM_ENDPOINT>',
|
|
27
|
+
* // ...
|
|
28
|
+
* })
|
|
29
|
+
* ```
|
|
30
|
+
* @example CDN
|
|
31
|
+
* ```ts
|
|
32
|
+
* KUBESENSE_LOGS.init({
|
|
33
|
+
* clientToken: '<KUBESENSE_CLIENT_TOKEN>',
|
|
34
|
+
* kubesenseRumEndpoint: '<KUBESENSE_RUM_ENDPOINT>',
|
|
35
|
+
* // ...
|
|
36
|
+
* })
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export interface LogsInitConfiguration extends InitConfiguration {
|
|
40
|
+
/**
|
|
41
|
+
* Access to every logs collected by the Logs SDK before they are sent to KubeSense.
|
|
42
|
+
* It allows:
|
|
43
|
+
* - Enrich your logs with additional context attributes
|
|
44
|
+
* - Modify your logs to modify their content, or redact sensitive sequences (see the list of editable properties)
|
|
45
|
+
* - Discard selected logs
|
|
46
|
+
*
|
|
47
|
+
* @category Data Collection
|
|
48
|
+
*/
|
|
49
|
+
beforeSend?: LogsBeforeSend | undefined
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Forward uncaught exceptions and network errors to KubeSense.
|
|
53
|
+
*
|
|
54
|
+
* To capture `console.error` calls, use {@link forwardConsoleLogs} with `"error"` (or `"all"`).
|
|
55
|
+
*
|
|
56
|
+
* @category Data Collection
|
|
57
|
+
* @defaultValue true
|
|
58
|
+
* @see forwardConsoleLogs
|
|
59
|
+
*/
|
|
60
|
+
forwardErrorsToLogs?: boolean | undefined
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Forward logs from console.* to KubeSense. Use "all" to forward everything or an array of console API names to forward only a subset.
|
|
64
|
+
*
|
|
65
|
+
* @category Data Collection
|
|
66
|
+
*/
|
|
67
|
+
forwardConsoleLogs?: ConsoleApiName[] | 'all' | undefined
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Forward reports from the [Reporting API](https://developer.mozilla.org/en-US/docs/Web/API/Reporting_API) to KubeSense. Use "all" to forward everything or an array of report types to forward only a subset.
|
|
71
|
+
*
|
|
72
|
+
* @category Data Collection
|
|
73
|
+
*/
|
|
74
|
+
forwardReports?: RawReportType[] | 'all' | undefined
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* List of plugins to enable. The plugins API is unstable and experimental, and may change without
|
|
78
|
+
* notice. Please use only plugins provided by KubeSense matching the version of the SDK you are
|
|
79
|
+
* using.
|
|
80
|
+
*
|
|
81
|
+
* @experimental
|
|
82
|
+
*/
|
|
83
|
+
plugins?: LogsPlugin[] | undefined
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Enable dashboard-managed SDK settings served by the KubeSense collector.
|
|
87
|
+
*
|
|
88
|
+
* Logs reads the same cached document as RUM, but only consumes the `features.logs` switch and
|
|
89
|
+
* the `logs` section. The document is fetched asynchronously after the SDK starts, so it never
|
|
90
|
+
* delays initialization, and cached settings are applied on the next page load.
|
|
91
|
+
*
|
|
92
|
+
* @category Data Collection
|
|
93
|
+
* @defaultValue false
|
|
94
|
+
*/
|
|
95
|
+
enableRemoteSdkConfiguration?: boolean | undefined
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Function called before a Log event is sent to KubeSense. See {@link LogsInitConfiguration.beforeSend}
|
|
100
|
+
*
|
|
101
|
+
* @param event - The log event
|
|
102
|
+
* @param context - The log event domain context
|
|
103
|
+
* @returns true if the event should be sent to KubeSense, false otherwise
|
|
104
|
+
*/
|
|
105
|
+
export type LogsBeforeSend = (event: LogsEvent, context: LogsEventDomainContext) => boolean
|
|
106
|
+
|
|
107
|
+
export const LOGS_SCHEMA = {
|
|
108
|
+
...BROWSER_CORE_SCHEMA,
|
|
109
|
+
forwardErrorsToLogs: { type: 'boolean', default: true, strict: false },
|
|
110
|
+
enableRemoteSdkConfiguration: { type: 'boolean', default: false, strict: false },
|
|
111
|
+
forwardConsoleLogs: {
|
|
112
|
+
type: 'enum',
|
|
113
|
+
values: ConsoleApiName,
|
|
114
|
+
multiple: true,
|
|
115
|
+
allowAll: true,
|
|
116
|
+
default: [] as ConsoleApiName[],
|
|
117
|
+
},
|
|
118
|
+
forwardReports: {
|
|
119
|
+
type: 'enum',
|
|
120
|
+
values: RawReportType,
|
|
121
|
+
multiple: true,
|
|
122
|
+
allowAll: true,
|
|
123
|
+
default: [] as RawReportType[],
|
|
124
|
+
},
|
|
125
|
+
plugins: {
|
|
126
|
+
type: 'schema',
|
|
127
|
+
multiple: true,
|
|
128
|
+
strict: false,
|
|
129
|
+
default: [] as LogsPlugin[],
|
|
130
|
+
schema: {
|
|
131
|
+
name: { type: 'string', required: true },
|
|
132
|
+
getConfigurationTelemetry: {
|
|
133
|
+
type: 'function',
|
|
134
|
+
strict: false,
|
|
135
|
+
signature: undefined as LogsPlugin['getConfigurationTelemetry'],
|
|
136
|
+
},
|
|
137
|
+
onInit: { type: 'function', strict: false, signature: undefined as LogsPlugin['onInit'] },
|
|
138
|
+
onLogsStart: { type: 'function', strict: false, signature: undefined as LogsPlugin['onLogsStart'] },
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
} as const
|
|
142
|
+
|
|
143
|
+
export type LogsConfiguration = InferredConfig<typeof LOGS_SCHEMA>
|
|
144
|
+
|
|
145
|
+
export function validateAndBuildLogsConfiguration(
|
|
146
|
+
initConfiguration: LogsInitConfiguration
|
|
147
|
+
): LogsConfiguration | undefined {
|
|
148
|
+
const config = validateAndBuildConfiguration(
|
|
149
|
+
initConfiguration as unknown as Record<string, unknown>,
|
|
150
|
+
LOGS_SCHEMA,
|
|
151
|
+
display
|
|
152
|
+
)
|
|
153
|
+
if (!config) {
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
...config,
|
|
158
|
+
beforeSend: config.beforeSend ? catchUserErrors(config.beforeSend as any, 'beforeSend threw an error:') : undefined,
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function serializeLogsConfiguration(configuration: LogsInitConfiguration) {
|
|
163
|
+
const baseSerializedInitConfiguration = serializeConfiguration(configuration)
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
forward_errors_to_logs: configuration.forwardErrorsToLogs,
|
|
167
|
+
enable_remote_sdk_configuration: !!configuration.enableRemoteSdkConfiguration,
|
|
168
|
+
forward_console_logs: configuration.forwardConsoleLogs,
|
|
169
|
+
forward_reports: configuration.forwardReports,
|
|
170
|
+
plugins: configuration.plugins?.map((plugin) => ({
|
|
171
|
+
name: plugin.name,
|
|
172
|
+
...plugin.getConfigurationTelemetry?.(),
|
|
173
|
+
})),
|
|
174
|
+
...baseSerializedInitConfiguration,
|
|
175
|
+
} satisfies RawTelemetryConfiguration
|
|
176
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { ClocksState } from '@kubesense/kubesense-js-core/time'
|
|
2
|
+
import { combine, ConsoleApiName } from '@kubesense/kubesense-js-core/util'
|
|
3
|
+
import type { Context, Observable, BufferedData } from '@kubesense/kubesense-browser-core'
|
|
4
|
+
import { timeStampNow } from '@kubesense/kubesense-js-core/time'
|
|
5
|
+
import { BufferedDataType, ErrorSource } from '@kubesense/kubesense-browser-core'
|
|
6
|
+
import type { LogsConfiguration } from '../configuration'
|
|
7
|
+
import type { LifeCycle, RawLogsEventCollectedData } from '../lifeCycle'
|
|
8
|
+
import { LifeCycleEventType } from '../lifeCycle'
|
|
9
|
+
import { StatusType } from '../logger/isAuthorized'
|
|
10
|
+
import type { RawLogsEvent } from '../../rawLogsEvent.types'
|
|
11
|
+
import { createErrorFieldFromRawError } from '../createErrorFieldFromRawError'
|
|
12
|
+
|
|
13
|
+
export interface ProvidedError {
|
|
14
|
+
startClocks: ClocksState
|
|
15
|
+
error: unknown
|
|
16
|
+
context?: Context
|
|
17
|
+
handlingStack: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const LogStatusForApi = {
|
|
21
|
+
[ConsoleApiName.log]: StatusType.info,
|
|
22
|
+
[ConsoleApiName.debug]: StatusType.debug,
|
|
23
|
+
[ConsoleApiName.info]: StatusType.info,
|
|
24
|
+
[ConsoleApiName.warn]: StatusType.warn,
|
|
25
|
+
[ConsoleApiName.error]: StatusType.error,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function startConsoleCollection(
|
|
29
|
+
configuration: LogsConfiguration,
|
|
30
|
+
lifeCycle: LifeCycle,
|
|
31
|
+
bufferedDataObservable: Observable<BufferedData>
|
|
32
|
+
) {
|
|
33
|
+
const subscription = bufferedDataObservable.subscribe(({ data: log, type }) => {
|
|
34
|
+
if (type !== BufferedDataType.CONSOLE || !configuration.forwardConsoleLogs.includes(log.api)) {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
const collectedData: RawLogsEventCollectedData<RawLogsEvent> = {
|
|
38
|
+
rawLogsEvent: combine(
|
|
39
|
+
{
|
|
40
|
+
date: timeStampNow(),
|
|
41
|
+
message: log.message,
|
|
42
|
+
origin: ErrorSource.CONSOLE,
|
|
43
|
+
error: log.error && createErrorFieldFromRawError(log.error),
|
|
44
|
+
_kubesense: log.error && { debug_ids: log.error.debugIds },
|
|
45
|
+
status: LogStatusForApi[log.api],
|
|
46
|
+
},
|
|
47
|
+
log.error?.context
|
|
48
|
+
),
|
|
49
|
+
domainContext: {
|
|
50
|
+
handlingStack: log.handlingStack,
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
lifeCycle.notify(LifeCycleEventType.RAW_LOG_COLLECTED, collectedData)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
return { stop: () => subscription.unsubscribe() }
|
|
58
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { isWorkerEnvironment } from '@kubesense/kubesense-js-core/util'
|
|
2
|
+
import type { CommonContext } from '../../rawLogsEvent.types'
|
|
3
|
+
|
|
4
|
+
export function buildCommonContext(): CommonContext {
|
|
5
|
+
if (isWorkerEnvironment) {
|
|
6
|
+
return {}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
view: {
|
|
11
|
+
referrer: document.referrer,
|
|
12
|
+
url: window.location.href,
|
|
13
|
+
},
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RelativeTime } from '@kubesense/kubesense-js-core/time'
|
|
2
|
+
import type { SessionManager } from '@kubesense/kubesense-browser-core'
|
|
3
|
+
|
|
4
|
+
export interface InternalContext {
|
|
5
|
+
session_id: string | undefined
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function startInternalContext(sessionManager: SessionManager) {
|
|
9
|
+
return {
|
|
10
|
+
get: (startTime?: number): InternalContext | undefined => {
|
|
11
|
+
const trackedSession = sessionManager.findTrackedSession(startTime as RelativeTime)
|
|
12
|
+
if (trackedSession) {
|
|
13
|
+
return {
|
|
14
|
+
session_id: trackedSession.id,
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { globalObject } from '@kubesense/kubesense-js-core/util'
|
|
2
|
+
import type { RelativeTime } from '@kubesense/kubesense-js-core/time'
|
|
3
|
+
import type { RumInternalContext } from '@kubesense/kubesense-browser-core'
|
|
4
|
+
import { willSyntheticsInjectRum } from '@kubesense/kubesense-browser-core'
|
|
5
|
+
import { SKIPPED } from '@kubesense/kubesense-js-core/assembly'
|
|
6
|
+
import type { Hooks } from '../hooks'
|
|
7
|
+
|
|
8
|
+
interface Rum {
|
|
9
|
+
getInternalContext?: (startTime?: RelativeTime) => RumInternalContext | undefined
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface BrowserWindow {
|
|
13
|
+
KUBESENSE_SDK?: Rum
|
|
14
|
+
KUBESENSE_SDK_SYNTHETICS?: Rum
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function startRUMInternalContext(hooks: Hooks) {
|
|
18
|
+
const browserWindow = globalObject as BrowserWindow
|
|
19
|
+
|
|
20
|
+
hooks.assembleEventDefaults.register(({ startTime }) => {
|
|
21
|
+
const internalContext = getRUMInternalContext(startTime)
|
|
22
|
+
if (!internalContext) {
|
|
23
|
+
return SKIPPED
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return internalContext
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
hooks.assembleTelemetry.register(({ startTime }) => {
|
|
30
|
+
const internalContext = getRUMInternalContext(startTime)
|
|
31
|
+
|
|
32
|
+
if (!internalContext) {
|
|
33
|
+
return SKIPPED
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
application: { id: internalContext.application_id },
|
|
38
|
+
view: { id: internalContext.view?.id },
|
|
39
|
+
action: { id: internalContext.user_action?.id as string },
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
function getRUMInternalContext(startTime?: RelativeTime) {
|
|
44
|
+
const willSyntheticsInjectRumResult = willSyntheticsInjectRum()
|
|
45
|
+
const rumSource = willSyntheticsInjectRumResult
|
|
46
|
+
? browserWindow.KUBESENSE_SDK_SYNTHETICS
|
|
47
|
+
: browserWindow.KUBESENSE_SDK
|
|
48
|
+
const rumContext = getInternalContextFromRumGlobal(startTime, rumSource)
|
|
49
|
+
|
|
50
|
+
if (rumContext) {
|
|
51
|
+
return rumContext
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function getInternalContextFromRumGlobal(startTime?: RelativeTime, rumGlobal?: Rum): RumInternalContext | undefined {
|
|
56
|
+
if (rumGlobal?.getInternalContext) {
|
|
57
|
+
return rumGlobal.getInternalContext(startTime)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { SessionManager } from '@kubesense/kubesense-browser-core'
|
|
2
|
+
import { DISCARDED } from '@kubesense/kubesense-js-core/assembly'
|
|
3
|
+
import type { LogsConfiguration } from '../configuration'
|
|
4
|
+
import type { AssembleHook } from '../hooks'
|
|
5
|
+
|
|
6
|
+
export function startSessionContext(
|
|
7
|
+
hook: AssembleHook,
|
|
8
|
+
configuration: LogsConfiguration,
|
|
9
|
+
sessionManager: SessionManager
|
|
10
|
+
) {
|
|
11
|
+
hook.register(({ startTime }) => {
|
|
12
|
+
// Used to attach a (fresh, safe-to-reference) session id: subject to the default
|
|
13
|
+
// TRACKED_SESSION_MAX_AGE, so it becomes undefined once the session is too old to reference.
|
|
14
|
+
const session = sessionManager.findTrackedSession(startTime)
|
|
15
|
+
|
|
16
|
+
// Used for the discard decision: unlike `session` above, this ignores session age (logs
|
|
17
|
+
// should keep being sent indefinitely, with or without a session, once a session was
|
|
18
|
+
// legitimately tracked here) but still respects sampling.
|
|
19
|
+
const isSessionTracked = sessionManager.findTrackedSession(startTime, {
|
|
20
|
+
returnInactive: true,
|
|
21
|
+
maxAge: Infinity,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
if (!isSessionTracked) {
|
|
25
|
+
return DISCARDED
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
service: configuration.service,
|
|
30
|
+
session_id: session ? session.id : undefined,
|
|
31
|
+
session: session ? { id: session.id } : undefined,
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { DISCARDED, SKIPPED } from '@kubesense/kubesense-js-core/assembly'
|
|
2
|
+
import type { TrackingConsentState } from '@kubesense/kubesense-browser-core'
|
|
3
|
+
import type { Hooks } from '../hooks'
|
|
4
|
+
|
|
5
|
+
export function startTrackingConsentContext(hooks: Hooks, trackingConsentState: TrackingConsentState) {
|
|
6
|
+
function isConsented() {
|
|
7
|
+
const wasConsented = trackingConsentState.isGranted()
|
|
8
|
+
|
|
9
|
+
if (!wasConsented) {
|
|
10
|
+
return DISCARDED
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return SKIPPED
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
hooks.assembleEventDefaults.register(isConsented)
|
|
17
|
+
hooks.assembleTelemetry.register(isConsented)
|
|
18
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { RawError } from '@kubesense/kubesense-browser-core'
|
|
2
|
+
import type { RawLoggerLogsEvent } from '../rawLogsEvent.types'
|
|
3
|
+
|
|
4
|
+
export function createErrorFieldFromRawError(
|
|
5
|
+
rawError: RawError,
|
|
6
|
+
{
|
|
7
|
+
/**
|
|
8
|
+
* Set this to `true` to include the error message in the error field. In most cases, the error
|
|
9
|
+
* message is already included in the log message, so we don't need to include it again.
|
|
10
|
+
*/
|
|
11
|
+
includeMessage = false,
|
|
12
|
+
} = {}
|
|
13
|
+
): NonNullable<RawLoggerLogsEvent['error']> {
|
|
14
|
+
return {
|
|
15
|
+
stack: rawError.stack,
|
|
16
|
+
kind: rawError.type,
|
|
17
|
+
message: includeMessage ? rawError.message : undefined,
|
|
18
|
+
causes: rawError.causes,
|
|
19
|
+
fingerprint: rawError.fingerprint,
|
|
20
|
+
handling: rawError.handling,
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { RelativeTime } from '@kubesense/kubesense-js-core/time'
|
|
2
|
+
import type { TelemetryEvent } from '@kubesense/kubesense-browser-core'
|
|
3
|
+
import { createHook } from '@kubesense/kubesense-js-core/assembly'
|
|
4
|
+
import type { Hook } from '@kubesense/kubesense-js-core/assembly'
|
|
5
|
+
import type { RecursivePartial } from '@kubesense/kubesense-js-core/util'
|
|
6
|
+
import type { LogsEvent } from '../logsEvent.types'
|
|
7
|
+
import type { RawLogsEvent } from '../rawLogsEvent.types'
|
|
8
|
+
import type { LogsEventDomainContext } from '../domainContext.types'
|
|
9
|
+
|
|
10
|
+
export type DefaultLogsEventAttributes = RecursivePartial<LogsEvent>
|
|
11
|
+
export type DefaultTelemetryEventAttributes = RecursivePartial<TelemetryEvent>
|
|
12
|
+
|
|
13
|
+
type DeepReadonly<T> = {
|
|
14
|
+
readonly [K in keyof T]: DeepReadonly<T[K]>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Use readonly and DeepReadonly to prevent assemble hook callbacks from mutating the inputs.
|
|
18
|
+
// DeepReadonly is only applied to objects rather than the entire AssembleHookParams to avoid casts for primitives.
|
|
19
|
+
export interface AssembleHookParams {
|
|
20
|
+
readonly startTime: RelativeTime
|
|
21
|
+
rawLogsEvent: DeepReadonly<RawLogsEvent>
|
|
22
|
+
domainContext: DeepReadonly<LogsEventDomainContext>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type AssembleHook = Hook<AssembleHookParams, DefaultLogsEventAttributes>
|
|
26
|
+
export type AssembleTelemetryHook = Hook<{ startTime: RelativeTime }, DefaultTelemetryEventAttributes>
|
|
27
|
+
|
|
28
|
+
export interface Hooks {
|
|
29
|
+
assembleEventDefaults: AssembleHook
|
|
30
|
+
assembleTelemetry: AssembleTelemetryHook
|
|
31
|
+
assembleEvent: AssembleHook
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function createHooks(): Hooks {
|
|
35
|
+
return {
|
|
36
|
+
assembleEventDefaults: createHook(),
|
|
37
|
+
assembleTelemetry: createHook(),
|
|
38
|
+
assembleEvent: createHook(),
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AbstractLifeCycle } from '@kubesense/kubesense-browser-core'
|
|
2
|
+
import type { Context } from '@kubesense/kubesense-browser-core'
|
|
3
|
+
import type { LogsEvent } from '../logsEvent.types'
|
|
4
|
+
import type { CommonContext, RawLogsEvent } from '../rawLogsEvent.types'
|
|
5
|
+
import type { LogsEventDomainContext } from '../domainContext.types'
|
|
6
|
+
|
|
7
|
+
export const enum LifeCycleEventType {
|
|
8
|
+
RAW_LOG_COLLECTED,
|
|
9
|
+
LOG_COLLECTED,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface LifeCycleEventMap {
|
|
13
|
+
[LifeCycleEventType.RAW_LOG_COLLECTED]: RawLogsEventCollectedData
|
|
14
|
+
[LifeCycleEventType.LOG_COLLECTED]: LogsEvent & Context
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const LifeCycle = AbstractLifeCycle<LifeCycleEventMap>
|
|
18
|
+
export type LifeCycle = AbstractLifeCycle<LifeCycleEventMap>
|
|
19
|
+
|
|
20
|
+
export interface RawLogsEventCollectedData<E extends RawLogsEvent = RawLogsEvent> {
|
|
21
|
+
rawLogsEvent: E
|
|
22
|
+
savedCommonContext?: CommonContext
|
|
23
|
+
domainContext?: LogsEventDomainContext<E['origin']>
|
|
24
|
+
ktags?: string[]
|
|
25
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Logger, HandlerType } from '../logger'
|
|
2
|
+
|
|
3
|
+
export function isAuthorized(status: StatusType, handlerType: HandlerType, logger: Logger) {
|
|
4
|
+
const loggerHandler = logger.getHandler()
|
|
5
|
+
const sanitizedHandlerType = Array.isArray(loggerHandler) ? loggerHandler : [loggerHandler]
|
|
6
|
+
return STATUS_PRIORITIES[status] >= STATUS_PRIORITIES[logger.getLevel()] && sanitizedHandlerType.includes(handlerType)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const StatusType = {
|
|
10
|
+
ok: 'ok',
|
|
11
|
+
debug: 'debug',
|
|
12
|
+
info: 'info',
|
|
13
|
+
notice: 'notice',
|
|
14
|
+
warn: 'warn',
|
|
15
|
+
error: 'error',
|
|
16
|
+
critical: 'critical',
|
|
17
|
+
alert: 'alert',
|
|
18
|
+
emerg: 'emerg',
|
|
19
|
+
} as const
|
|
20
|
+
|
|
21
|
+
export const STATUS_PRIORITIES: { [key in StatusType]: number } = {
|
|
22
|
+
[StatusType.ok]: 0,
|
|
23
|
+
[StatusType.debug]: 1,
|
|
24
|
+
[StatusType.info]: 2,
|
|
25
|
+
[StatusType.notice]: 4,
|
|
26
|
+
[StatusType.warn]: 5,
|
|
27
|
+
[StatusType.error]: 6,
|
|
28
|
+
[StatusType.critical]: 7,
|
|
29
|
+
[StatusType.alert]: 8,
|
|
30
|
+
[StatusType.emerg]: 9,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type StatusType = (typeof StatusType)[keyof typeof StatusType]
|