@datadog/browser-logs
Version:
408 lines (353 loc) • 12.5 kB
text/typescript
import type { TrackingConsent, PublicApi, ContextManager, Account, Context, User } from '@datadog/browser-core'
import {
ContextManagerMethod,
CustomerContextKey,
addTelemetryUsage,
makePublicApi,
monitor,
sanitize,
displayAlreadyInitializedError,
deepClone,
createTrackingConsentState,
defineContextMethod,
startBufferingData,
callMonitored,
mockable,
} from '@datadog/browser-core'
import type { LogsInitConfiguration } from '../domain/configuration'
import type { HandlerType } from '../domain/logger'
import type { StatusType } from '../domain/logger/isAuthorized'
import { Logger } from '../domain/logger'
import { buildCommonContext } from '../domain/contexts/commonContext'
import type { InternalContext } from '../domain/contexts/internalContext'
import type { StartLogsResult } from './startLogs'
import { startLogs } from './startLogs'
import { createPreStartStrategy } from './preStartLogs'
export interface LoggerConfiguration {
level?: StatusType
handler?: HandlerType | HandlerType[]
context?: object
}
/**
* Public API for the Logs browser SDK.
*
* See [Browser Log Collection](https://docs.datadoghq.com/logs/log_collection/javascript) for further information.
*
* @category Main
*/
export interface LogsPublicApi extends PublicApi {
/**
* The default logger
*
* @category Logger
*/
logger: Logger
/**
* Init the Logs browser SDK.
*
* See [Browser Log Collection](https://docs.datadoghq.com/logs/log_collection/javascript) for further information.
*
* @category Init
* @param initConfiguration - Configuration options of the SDK
*/
init: (initConfiguration: LogsInitConfiguration) => void
/**
* Set the tracking consent of the current user.
*
* Logs will be sent only if it is set to "granted". This value won't be stored by the library
* across page loads: you will need to call this method or set the appropriate `trackingConsent`
* field in the init() method at each page load.
*
* If this method is called before the init() method, the provided value will take precedence
* over the one provided as initialization parameter.
*
* See [User tracking consent](https://docs.datadoghq.com/logs/log_collection/javascript/#user-tracking-consent) for further information.
*
* @category Privacy
* @param trackingConsent - The user tracking consent
*/
setTrackingConsent: (trackingConsent: TrackingConsent) => void
/**
* Set the global context information to all events, stored in `@context`
* See [Global context](https://docs.datadoghq.com/logs/log_collection/javascript/#overwrite-context) for further information.
*
* @category Context - Global Context
* @param context - Global context
*/
setGlobalContext: (context: any) => void
/**
* Get the global Context
*
* See [Global context](https://docs.datadoghq.com/logs/log_collection/javascript/#overwrite-context) for further information.
*
* @category Context - Global Context
*/
getGlobalContext: () => Context
/**
* Set or update a global context property, stored in `@context.<key>`
*
* See [Global context](https://docs.datadoghq.com/logs/log_collection/javascript/#overwrite-context) for further information.
*
* @category Context - Global Context
* @param key - Key of the property
* @param value - Value of the property
*/
setGlobalContextProperty: (key: any, value: any) => void
/**
* Remove a global context property
*
* See [Global context](https://docs.datadoghq.com/logs/log_collection/javascript/#overwrite-context) for further information.
*
* @category Context - Global Context
*/
removeGlobalContextProperty: (key: any) => void
/**
* Clear the global context
*
* See [Global context](https://docs.datadoghq.com/logs/log_collection/javascript/#overwrite-context) for further information.
*
* @category Context - Global Context
*/
clearGlobalContext: () => void
/**
* Set user information to all events, stored in `@usr`
*
* See [User session](https://docs.datadoghq.com/logs/log_collection/javascript/#user-context) for further information.
*
* @category Context - User
* @param newUser - User information
*/
setUser(newUser: User & { id: string }): void
/**
* Set user information to all events, stored in `@usr`
*
* @category Context - User
* @deprecated You must specify a user id, favor using {@link setUser} instead
* @param newUser - User information with optional id
*/
setUser(newUser: User): void
/**
* Get user information
*
* See [User session](https://docs.datadoghq.com/logs/log_collection/javascript/#user-context) for further information.
*
* @category Context - User
* @returns User information
*/
getUser: () => Context
/**
* Set or update the user property, stored in `@usr.<key>`
*
* See [User session](https://docs.datadoghq.com/logs/log_collection/javascript/#user-context) for further information.
*
* @category Context - User
* @param key - Key of the property
* @param property - Value of the property
*/
setUserProperty: (key: any, property: any) => void
/**
* Remove a user property
*
* @category Context - User
* @param key - Key of the property to remove
* @see [User session](https://docs.datadoghq.com/logs/log_collection/javascript/#user-context) for further information.
*/
removeUserProperty: (key: any) => void
/**
* Clear all user information
*
* See [User session](https://docs.datadoghq.com/logs/log_collection/javascript/#user-context) for further information.
*
* @category Context - User
*/
clearUser: () => void
/**
* Set account information to all events, stored in `@account`
*
* @category Context - Account
* @param newAccount - Account information
*/
setAccount: (newAccount: Account) => void
/**
* Get account information
*
* @category Context - Account
* @returns Account information
*/
getAccount: () => Context
/**
* Set or update the account property, stored in `@account.<key>`
*
* @category Context - Account
* @param key - Key of the property
* @param property - Value of the property
*/
setAccountProperty: (key: string, property: any) => void
/**
* Remove an account property
*
* @category Context - Account
* @param key - Key of the property to remove
*/
removeAccountProperty: (key: string) => void
/**
* Clear all account information
*
* @category Context - Account
* @returns Clear all account information
*/
clearAccount: () => void
/**
* The Datadog browser logs SDK contains a default logger `DD_LOGS.logger`, but this API allows to create different ones.
*
* See [Define multiple loggers](https://docs.datadoghq.com/logs/log_collection/javascript/#define-multiple-loggers) for further information.
*
* @category Logger
* @param name - Name of the logger
* @param conf - Configuration of the logger (level, handler, context)
*/
createLogger: (name: string, conf?: LoggerConfiguration) => Logger
/**
* Get a logger
*
* See [Define multiple loggers](https://docs.datadoghq.com/logs/log_collection/javascript/#define-multiple-loggers) for further information.
*
* @category Logger
* @param name - Name of the logger
*/
getLogger: (name: string) => Logger | undefined
/**
* Get the init configuration
*
* @category Init
* @returns The init configuration
*/
getInitConfiguration: () => LogsInitConfiguration | undefined
/**
* [Internal API] Get the internal SDK context
*
* See [Access internal context](https://docs.datadoghq.com/logs/log_collection/javascript/#access-internal-context) for further information.
*
* @internal
*/
getInternalContext: (startTime?: number) => InternalContext | undefined
}
export interface Strategy {
init: (initConfiguration: LogsInitConfiguration, errorStack?: string) => void
initConfiguration: LogsInitConfiguration | undefined
globalContext: ContextManager
accountContext: ContextManager
userContext: ContextManager
getInternalContext: StartLogsResult['getInternalContext']
handleLog: StartLogsResult['handleLog']
}
export function makeLogsPublicApi(): LogsPublicApi {
const trackingConsentState = createTrackingConsentState()
const bufferedDataObservable = startBufferingData().observable
let strategy = createPreStartStrategy(
buildCommonContext,
trackingConsentState,
(initConfiguration, configuration, hooks) => {
const startLogsResult = mockable(startLogs)(
configuration,
buildCommonContext,
trackingConsentState,
bufferedDataObservable,
hooks
)
strategy = createPostStartStrategy(initConfiguration, startLogsResult)
return startLogsResult
}
)
const getStrategy = () => strategy
const customLoggers: { [name: string]: Logger | undefined } = {}
const mainLogger = new Logger((...params) => strategy.handleLog(...params))
return makePublicApi<LogsPublicApi>({
logger: mainLogger,
init: (initConfiguration) => {
const errorStack = new Error().stack
callMonitored(() => strategy.init(initConfiguration, errorStack))
},
setTrackingConsent: monitor((trackingConsent) => {
trackingConsentState.update(trackingConsent)
addTelemetryUsage({ feature: 'set-tracking-consent', tracking_consent: trackingConsent })
}),
getGlobalContext: defineContextMethod(
getStrategy,
CustomerContextKey.globalContext,
ContextManagerMethod.getContext
),
setGlobalContext: defineContextMethod(
getStrategy,
CustomerContextKey.globalContext,
ContextManagerMethod.setContext
),
setGlobalContextProperty: defineContextMethod(
getStrategy,
CustomerContextKey.globalContext,
ContextManagerMethod.setContextProperty
),
removeGlobalContextProperty: defineContextMethod(
getStrategy,
CustomerContextKey.globalContext,
ContextManagerMethod.removeContextProperty
),
clearGlobalContext: defineContextMethod(
getStrategy,
CustomerContextKey.globalContext,
ContextManagerMethod.clearContext
),
createLogger: monitor((name, conf = {}) => {
customLoggers[name] = new Logger(
(...params) => strategy.handleLog(...params),
sanitize(name),
conf.handler,
conf.level,
sanitize(conf.context) as object
)
return customLoggers[name]
}),
getLogger: monitor((name) => customLoggers[name]),
getInitConfiguration: monitor(() => deepClone(strategy.initConfiguration)),
getInternalContext: monitor((startTime) => strategy.getInternalContext(startTime)),
setUser: defineContextMethod(getStrategy, CustomerContextKey.userContext, ContextManagerMethod.setContext),
getUser: defineContextMethod(getStrategy, CustomerContextKey.userContext, ContextManagerMethod.getContext),
setUserProperty: defineContextMethod(
getStrategy,
CustomerContextKey.userContext,
ContextManagerMethod.setContextProperty
),
removeUserProperty: defineContextMethod(
getStrategy,
CustomerContextKey.userContext,
ContextManagerMethod.removeContextProperty
),
clearUser: defineContextMethod(getStrategy, CustomerContextKey.userContext, ContextManagerMethod.clearContext),
setAccount: defineContextMethod(getStrategy, CustomerContextKey.accountContext, ContextManagerMethod.setContext),
getAccount: defineContextMethod(getStrategy, CustomerContextKey.accountContext, ContextManagerMethod.getContext),
setAccountProperty: defineContextMethod(
getStrategy,
CustomerContextKey.accountContext,
ContextManagerMethod.setContextProperty
),
removeAccountProperty: defineContextMethod(
getStrategy,
CustomerContextKey.accountContext,
ContextManagerMethod.removeContextProperty
),
clearAccount: defineContextMethod(
getStrategy,
CustomerContextKey.accountContext,
ContextManagerMethod.clearContext
),
})
}
function createPostStartStrategy(initConfiguration: LogsInitConfiguration, startLogsResult: StartLogsResult): Strategy {
return {
init: (initConfiguration: LogsInitConfiguration) => {
displayAlreadyInitializedError('DD_LOGS', initConfiguration)
},
initConfiguration,
...startLogsResult,
}
}