omnis-logger-sdk
Version:
SDK для интеграции Omnis Logger в проекты
573 lines • 21.8 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getOmnisLogger = exports.initOmnisLogger = exports.getDeviceId = exports.OmnisLogger = void 0;
const axios_1 = __importDefault(require("axios"));
class OmnisLogger {
constructor(config) {
this.queue = [];
this.isProcessing = false;
this.globalContext = {};
this.deviceInfo = {};
this.config = {
environment: 'production',
enableConsole: true,
enableGlobalErrorHandlers: true,
enableNetworkErrorCapture: true,
maxRetries: 3,
timeout: 5000,
...config,
};
this.initializeDeviceInfo(config);
this.client = axios_1.default.create({
baseURL: this.config.endpoint,
timeout: this.config.timeout,
headers: {
'Content-Type': 'application/json',
'X-API-Key': this.config.apiKey,
},
});
if (this.config.enableGlobalErrorHandlers) {
this.setupGlobalErrorHandlers();
}
if (this.config.enableNetworkErrorCapture) {
this.setupNetworkErrorCapture();
}
}
initializeDeviceInfo(config) {
if (config.deviceInfo) {
this.deviceInfo = { ...config.deviceInfo };
}
else if (config.deviceInfoModule) {
this.collectDeviceInfoFromModule(config.deviceInfoModule);
}
else {
this.collectBrowserInfo();
}
}
collectDeviceInfoFromModule(DeviceInfoModule) {
try {
let Platform;
try {
Platform = require('react-native').Platform;
}
catch (e) {
console.warn('React Native Platform недоступен');
return;
}
const syncInfo = {
platform: 'react-native',
os: DeviceInfoModule.getSystemName(),
osVersion: DeviceInfoModule.getSystemVersion(),
systemName: DeviceInfoModule.getSystemName(),
systemVersion: DeviceInfoModule.getSystemVersion(),
deviceId: DeviceInfoModule.getDeviceId(),
brand: DeviceInfoModule.getBrand(),
model: DeviceInfoModule.getModel(),
deviceType: DeviceInfoModule.getDeviceType(),
bundleId: DeviceInfoModule.getBundleId(),
version: DeviceInfoModule.getVersion(),
buildNumber: DeviceInfoModule.getBuildNumber(),
readableVersion: DeviceInfoModule.getReadableVersion(),
isTablet: DeviceInfoModule.isTablet(),
};
if (Platform.OS === 'ios') {
try {
syncInfo.hasNotch = DeviceInfoModule.hasNotch();
syncInfo.hasDynamicIsland = DeviceInfoModule.hasDynamicIsland();
}
catch (e) {
}
}
this.deviceInfo = syncInfo;
this.collectAsyncDeviceInfo(DeviceInfoModule, Platform);
}
catch (error) {
console.warn('Ошибка сбора данных об устройстве из модуля:', error);
this.deviceInfo = { platform: 'react-native' };
}
}
async collectAsyncDeviceInfo(DeviceInfoModule, Platform) {
try {
const asyncInfo = {};
try {
asyncInfo.uniqueId = await DeviceInfoModule.getUniqueId();
asyncInfo.deviceName = await DeviceInfoModule.getDeviceName();
asyncInfo.manufacturer = await DeviceInfoModule.getManufacturer();
asyncInfo.applicationName = await DeviceInfoModule.getApplicationName();
asyncInfo.userAgent = await DeviceInfoModule.getUserAgent();
}
catch (e) {
}
try {
if (typeof DeviceInfoModule.isEmulatorSync === 'function') {
asyncInfo.isEmulator = DeviceInfoModule.isEmulatorSync();
}
else {
asyncInfo.isEmulator = await DeviceInfoModule.isEmulator();
}
}
catch (e) {
}
if (Platform.OS === 'android') {
try {
asyncInfo.androidId = await DeviceInfoModule.getAndroidId();
asyncInfo.apiLevel = await DeviceInfoModule.getApiLevel();
}
catch (e) {
}
}
try {
const { Dimensions } = require('react-native');
const dimensions = Dimensions.get('window');
asyncInfo.screenWidth = dimensions.width;
asyncInfo.screenHeight = dimensions.height;
asyncInfo.pixelRatio = dimensions.scale;
}
catch (e) {
}
try {
const netInfo = require('@react-native-netinfo/netinfo');
const networkState = await netInfo.fetch();
asyncInfo.isConnected = networkState.isConnected;
asyncInfo.networkType = networkState.type;
}
catch (e) {
}
this.deviceInfo = { ...this.deviceInfo, ...asyncInfo };
}
catch (error) {
console.warn('Ошибка сбора асинхронных данных об устройстве:', error);
}
}
isBrowser() {
return typeof window !== 'undefined';
}
isReactNative() {
return typeof navigator !== 'undefined' &&
navigator.product === 'ReactNative' ||
(typeof global !== 'undefined' &&
typeof global.navigator !== 'undefined' &&
global.navigator.product === 'ReactNative');
}
collectBrowserInfo() {
if (!this.isBrowser())
return;
this.deviceInfo = {
platform: 'browser',
userAgent: navigator.userAgent,
language: navigator.language,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
};
if (screen) {
this.deviceInfo.screenWidth = screen.width;
this.deviceInfo.screenHeight = screen.height;
}
if (window.devicePixelRatio) {
this.deviceInfo.pixelRatio = window.devicePixelRatio;
}
const ua = navigator.userAgent.toLowerCase();
if (ua.includes('windows')) {
this.deviceInfo.os = 'Windows';
const match = ua.match(/windows nt ([\d.]+)/);
if (match)
this.deviceInfo.osVersion = match[1];
}
else if (ua.includes('mac os')) {
this.deviceInfo.os = 'macOS';
const match = ua.match(/mac os x ([\d_]+)/);
if (match)
this.deviceInfo.osVersion = match[1].replace(/_/g, '.');
}
else if (ua.includes('linux')) {
this.deviceInfo.os = 'Linux';
}
else if (ua.includes('android')) {
this.deviceInfo.os = 'Android';
const match = ua.match(/android ([\d.]+)/);
if (match)
this.deviceInfo.osVersion = match[1];
}
else if (ua.includes('iphone') || ua.includes('ipad')) {
this.deviceInfo.os = 'iOS';
const match = ua.match(/os ([\d_]+)/);
if (match)
this.deviceInfo.osVersion = match[1].replace(/_/g, '.');
}
}
setupGlobalErrorHandlers() {
if (this.isReactNative()) {
this.setupReactNativeErrorHandlers();
}
else if (this.isBrowser()) {
this.setupBrowserErrorHandlers();
}
}
setupBrowserErrorHandlers() {
const self = this;
window.addEventListener('error', function (event) {
self.handleGlobalError(event.error || event);
});
window.addEventListener('unhandledrejection', function (event) {
self.handleGlobalRejection(event);
});
}
setupReactNativeErrorHandlers() {
const self = this;
try {
if (typeof global !== 'undefined' && global.ErrorUtils) {
const originalGlobalHandler = global.ErrorUtils.getGlobalHandler();
global.ErrorUtils.setGlobalHandler((error, isFatal) => {
self.handleGlobalError({
error,
isFatal,
type: 'react_native_js_error'
});
if (originalGlobalHandler) {
originalGlobalHandler(error, isFatal);
}
});
}
if (typeof global !== 'undefined') {
const originalRejectionHandler = global.onunhandledrejection;
global.onunhandledrejection = function (event) {
self.handleGlobalRejection(event);
if (originalRejectionHandler) {
originalRejectionHandler.call(this, event);
}
};
}
}
catch (error) {
}
}
setupNetworkErrorCapture() {
if (this.isReactNative()) {
this.setupReactNativeNetworkCapture();
}
else if (this.isBrowser()) {
this.setupBrowserNetworkCapture();
}
}
setupBrowserNetworkCapture() {
const self = this;
if (typeof window !== 'undefined' && window.fetch) {
const originalFetch = window.fetch;
window.fetch = async function (...args) {
var _a, _b;
try {
const response = await originalFetch(...args);
const url = self.extractUrlFromFetchArgs(args[0]);
const method = ((_a = args[1]) === null || _a === void 0 ? void 0 : _a.method) || 'GET';
if (!response.ok) {
self.error(`HTTP Error: ${response.status} ${response.statusText}`, {
type: 'network_error',
url,
status: response.status,
statusText: response.statusText,
method,
});
}
return response;
}
catch (error) {
const url = self.extractUrlFromFetchArgs(args[0]);
const method = ((_b = args[1]) === null || _b === void 0 ? void 0 : _b.method) || 'GET';
self.exception(error, {
type: 'network_error',
url,
method,
});
throw error;
}
};
}
if (typeof window !== 'undefined' && window.XMLHttpRequest) {
const originalXHR = window.XMLHttpRequest;
window.XMLHttpRequest = function () {
const xhr = new originalXHR();
const originalOpen = xhr.open;
const originalSend = xhr.send;
let method = '';
let url = '';
xhr.open = function (methodArg, urlArg, async, username, password) {
method = methodArg;
url = urlArg;
return originalOpen.call(this, methodArg, urlArg, async !== null && async !== void 0 ? async : true, username, password);
};
xhr.send = function (body) {
const result = originalSend.call(this, body);
xhr.addEventListener('error', function () {
self.error('XMLHttpRequest Error', {
type: 'network_error',
method,
url,
status: xhr.status,
statusText: xhr.statusText,
});
});
xhr.addEventListener('load', function () {
if (xhr.status >= 400) {
self.error(`HTTP Error: ${xhr.status} ${xhr.statusText}`, {
type: 'network_error',
method,
url,
status: xhr.status,
statusText: xhr.statusText,
});
}
});
return result;
};
return xhr;
};
}
}
setupReactNativeNetworkCapture() {
const self = this;
try {
if (typeof global !== 'undefined' && global.fetch) {
const originalFetch = global.fetch;
global.fetch = async function (...args) {
var _a, _b;
try {
const response = await originalFetch(...args);
const url = self.extractUrlFromFetchArgs(args[0]);
const method = ((_a = args[1]) === null || _a === void 0 ? void 0 : _a.method) || 'GET';
if (!response.ok) {
self.error(`HTTP Error: ${response.status} ${response.statusText}`, {
type: 'network_error',
url,
status: response.status,
statusText: response.statusText,
method,
platform: 'react-native'
});
}
return response;
}
catch (error) {
const url = self.extractUrlFromFetchArgs(args[0]);
const method = ((_b = args[1]) === null || _b === void 0 ? void 0 : _b.method) || 'GET';
self.exception(error, {
type: 'network_error',
url,
method,
platform: 'react-native'
});
throw error;
}
};
}
if (typeof global !== 'undefined' && global.XMLHttpRequest) {
const originalXHR = global.XMLHttpRequest;
global.XMLHttpRequest = function () {
const xhr = new originalXHR();
const originalOpen = xhr.open;
const originalSend = xhr.send;
let method = '';
let url = '';
xhr.open = function (methodArg, urlArg, async, username, password) {
method = methodArg;
url = urlArg;
return originalOpen.call(this, methodArg, urlArg, async !== null && async !== void 0 ? async : true, username, password);
};
xhr.send = function (body) {
const result = originalSend.call(this, body);
xhr.addEventListener('error', function () {
self.error('XMLHttpRequest Error', {
type: 'network_error',
method,
url,
status: xhr.status,
statusText: xhr.statusText,
platform: 'react-native'
});
});
xhr.addEventListener('load', function () {
if (xhr.status >= 400) {
self.error(`HTTP Error: ${xhr.status} ${xhr.statusText}`, {
type: 'network_error',
method,
url,
status: xhr.status,
statusText: xhr.statusText,
platform: 'react-native'
});
}
});
return result;
};
return xhr;
};
}
}
catch (error) {
}
}
error(message, context) {
this.log('error', message, context);
}
warn(message, context) {
this.log('warn', message, context);
}
info(message, context) {
this.log('info', message, context);
}
debug(message, context) {
this.log('debug', message, context);
}
exception(error, context) {
this.log('error', error.message, {
...context,
stack: error.stack,
name: error.name,
});
}
log(level, message, context) {
const logData = {
level,
message,
context: { ...this.globalContext, ...(context || {}) },
userAgent: this.getUserAgent(),
url: this.getCurrentUrl(),
userId: this.config.userId,
sessionId: this.config.sessionId,
platform: this.config.platform,
version: this.config.version,
environment: this.config.environment,
deviceInfo: this.deviceInfo,
};
if (this.config.enableConsole) {
console[level](`[Omnis Logger] ${message}`, { ...this.globalContext, ...(context || {}) });
}
this.queue.push(logData);
this.processQueue();
}
handleGlobalError(event) {
const error = event.error || event;
this.exception(error, {
type: 'uncaught_exception',
filename: event.filename,
lineno: event.lineno,
colno: event.colno,
});
}
handleGlobalRejection(event) {
const reason = event.reason || event;
this.error('Unhandled Promise Rejection', {
type: 'unhandled_rejection',
reason: reason.toString(),
stack: reason.stack,
});
}
getUserAgent() {
if (typeof window !== 'undefined' && window.navigator) {
return window.navigator.userAgent;
}
return undefined;
}
extractUrlFromFetchArgs(input) {
var _a;
if (typeof input === 'string') {
return input;
}
if (input && typeof input === 'object' && 'url' in input) {
return input.url;
}
if (input && typeof input === 'object' && input.toString && ((_a = input.constructor) === null || _a === void 0 ? void 0 : _a.name) === 'URL') {
return input.toString();
}
return String(input);
}
getCurrentUrl() {
if (typeof window !== 'undefined' && window.location) {
return window.location.href;
}
return undefined;
}
async processQueue() {
if (this.isProcessing || this.queue.length === 0) {
return;
}
this.isProcessing = true;
while (this.queue.length > 0) {
const logData = this.queue.shift();
if (logData) {
await this.sendLog(logData);
}
}
this.isProcessing = false;
}
async sendLog(logData, retryCount = 0) {
try {
await this.client.post('/api/logs', { data: logData });
}
catch (error) {
if (retryCount < this.config.maxRetries) {
const self = this;
setTimeout(function () {
self.sendLog(logData, retryCount + 1);
}, Math.pow(2, retryCount) * 1000);
}
}
}
async flush() {
return this.processQueue();
}
setConfig(config) {
this.config = { ...this.config, ...config };
if (config.apiKey) {
this.client.defaults.headers['X-API-Key'] = config.apiKey;
}
}
setUser(userId) {
this.config.userId = userId;
}
setSession(sessionId) {
this.config.sessionId = sessionId;
}
setGlobalContext(context) {
this.globalContext = { ...this.globalContext, ...context };
}
getGlobalContext() {
return { ...this.globalContext };
}
clearGlobalContext() {
this.globalContext = {};
}
setDeviceInfo(deviceInfo) {
this.deviceInfo = { ...deviceInfo };
}
getDeviceInfo() {
return { ...this.deviceInfo };
}
updateDeviceInfo(updates) {
this.deviceInfo = { ...this.deviceInfo, ...updates };
}
}
exports.OmnisLogger = OmnisLogger;
let globalLogger = null;
const getDeviceId = () => {
try {
const DeviceInfo = require('react-native-device-info');
return DeviceInfo.getDeviceId();
}
catch (e) {
return 'unknown-device';
}
};
exports.getDeviceId = getDeviceId;
const initOmnisLogger = (config) => {
globalLogger = new OmnisLogger(config);
return globalLogger;
};
exports.initOmnisLogger = initOmnisLogger;
const getOmnisLogger = () => {
return globalLogger;
};
exports.getOmnisLogger = getOmnisLogger;
exports.default = OmnisLogger;
//# sourceMappingURL=index.js.map