@datadog/mobile-react-native
Version:
A client-side React Native module to interact with Datadog
137 lines (134 loc) • 5.25 kB
JavaScript
/*
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
* This product includes software developed at Datadog (https://www.datadoghq.com/).
* Copyright 2016-Present Datadog, Inc.
*/
import { DATADOG_MESSAGE_PREFIX, InternalLog } from '../InternalLog';
import { SdkVerbosity } from '../SdkVerbosity';
import { debugId } from '../metro/debugIdResolver';
import { DdAttributes } from '../rum/DdAttributes';
import { validateContext } from '../utils/argsUtils';
import { generateEventMapper } from './eventMapper';
const SDK_NOT_INITIALIZED_MESSAGE = 'DD_INTERNAL_LOG_SENT_BEFORE_SDK_INIT';
const generateEmptyPromise = () => new Promise(resolve => resolve());
/**
* We consider that if either one of `errorKind`, `errorMessage` or `stacktrace` is a string,
* then the log contains an error.
*/
const isLogWithError = args => {
return typeof args[1] === 'string' || typeof args[2] === 'string' || typeof args[3] === 'string' || typeof args[4] === 'object' || typeof args[5] === 'string';
};
class DdLogsWrapper {
// eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
nativeLogs = require('../specs/NativeDdLogs').default;
logEventMapper = generateEventMapper(undefined);
debug = (...args) => {
if (isLogWithError(args)) {
return this.logWithError(args[0], args[1], args[2], args[3], args[4] ?? {}, 'debug', args[5]);
}
return this.log(args[0], args[1] ?? {}, 'debug');
};
info = (...args) => {
if (isLogWithError(args)) {
return this.logWithError(args[0], args[1], args[2], args[3], args[4] ?? {}, 'info', args[5]);
}
return this.log(args[0], args[1] ?? {}, 'info');
};
warn = (...args) => {
if (isLogWithError(args)) {
return this.logWithError(args[0], args[1], args[2], args[3], args[4] ?? {}, 'warn', args[5]);
}
return this.log(args[0], args[1] ?? {}, 'warn');
};
error = (...args) => {
if (isLogWithError(args)) {
return this.logWithError(args[0], args[1], args[2], args[3], args[4] ?? {}, 'error', args[5], args[6]);
}
return this.log(args[0], args[1] ?? {}, 'error');
};
/**
* Since the InternalLog does not have a verbosity set yet in this case,
* we use console.warn to warn the user in dev mode.
*/
printLogDroppedSdkNotInitialized = (message, status) => {
if (__DEV__) {
console.warn(`${DATADOG_MESSAGE_PREFIX} Dropping ${status} log as the SDK is not initialized yet: "${message}"`);
}
};
printLogDroppedByMapper = (message, status) => {
InternalLog.log(`${status} log dropped by log mapper: "${message}"`, SdkVerbosity.DEBUG);
};
printLogTracked = (message, status) => {
InternalLog.log(`Tracking ${status} log "${message}"`, SdkVerbosity.DEBUG);
};
log = async (message, context, status) => {
const event = this.logEventMapper.applyEventMapper({
message,
context,
status
});
if (!event) {
this.printLogDroppedByMapper(message, status);
return generateEmptyPromise();
}
const validatedContext = validateContext(event.context);
this.printLogTracked(event.message, status);
try {
return await this.nativeLogs[status](event.message, validatedContext);
} catch (error) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (error.message === SDK_NOT_INITIALIZED_MESSAGE) {
this.printLogDroppedSdkNotInitialized(message, status);
return generateEmptyPromise();
}
throw error;
}
};
logWithError = async (message, errorKind, errorMessage, stacktrace, context, status, fingerprint = '', source) => {
const rawLogEvent = {
message,
errorKind,
errorMessage,
stacktrace,
context,
status,
fingerprint,
source
};
const mappedEvent = this.logEventMapper.applyEventMapper(rawLogEvent);
if (!mappedEvent) {
this.printLogDroppedByMapper(message, status);
return generateEmptyPromise();
}
this.printLogTracked(mappedEvent.message, status);
try {
const updatedContext = validateContext(mappedEvent.context);
updatedContext[DdAttributes.errorSourceType] = 'react-native';
if (fingerprint && fingerprint !== '') {
updatedContext[DdAttributes.errorFingerprint] = fingerprint;
}
const _debugId = debugId;
if (_debugId) {
updatedContext[DdAttributes.debugId] = _debugId;
}
return await this.nativeLogs[`${status}WithError`](mappedEvent.message, mappedEvent.errorKind, mappedEvent.errorMessage, mappedEvent.stacktrace, updatedContext);
} catch (error) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (error.message === SDK_NOT_INITIALIZED_MESSAGE) {
this.printLogDroppedSdkNotInitialized(message, status);
return generateEmptyPromise();
}
throw error;
}
};
registerLogEventMapper(logEventMapper) {
this.logEventMapper = generateEventMapper(logEventMapper);
}
unregisterLogEventMapper() {
this.logEventMapper = generateEventMapper(undefined);
}
}
export const DdLogs = new DdLogsWrapper();
//# sourceMappingURL=DdLogs.js.map