UNPKG

@rockpack/logger

Version:

This module can help you build error tracking & crash reporting system for your React application.

133 lines (132 loc) 4.93 kB
import React, { Component, createContext, isValidElement, useContext } from 'react'; import { isString, isNumber, isFunction } from 'valid-types'; import BSOD from './BSOD'; import { getStackData, onCriticalError } from './stack'; import { getCurrentDate } from './utils'; import { logger } from './logger'; export const LoggerContext = createContext(null); const isBackend = () => typeof window === 'undefined'; export const useLoggerApi = () => { const ctx = useContext(LoggerContext); return { getStackData: ctx.getStackData, triggerError: ctx.onError }; }; export default class LoggerContainer extends Component { constructor(props) { super(props); this.__hasCriticalError = false; this.handlerError = (errorMsg, url, lineNumber, lineCount, trace) => { this.unbindActions(); if (!this.__hasCriticalError) { this.__hasCriticalError = true; const stackData = onCriticalError(this.stack, logger.getStackCollection(), { getCurrentDate: this.props.getCurrentDate, onPrepareStack: this.props.onPrepareStack, }, trace, lineNumber); this.onError(stackData); this.setState({ bsod: true }); } }; this._onMouseDown = (e) => { this.stack.mousePressed = e && e.button; }; this._onKeyDown = (e) => { this.stack.keyboardPressed = e && e.code; }; this._onKeyUp = () => { setTimeout(() => { this.stack.keyboardPressed = null; }); }; this._onMouseUp = () => { setTimeout(() => { this.stack.mousePressed = null; }); }; this.getStackData = () => getStackData(this.stack, logger.getStackCollection(), { getCurrentDate: this.props.getCurrentDate, onPrepareStack: this.props.onPrepareStack, }); this.onError = (stackData) => { if (isFunction(this.props.onError)) { this.props.onError(stackData); } }; this.closeBsod = () => { this.setState({ bsod: false }); }; this.state = { bsod: false }; this.stack = { keyboardPressed: null, mousePressed: null, session: {}, env: {}, actions: logger.getStackCollection().data }; const LIMIT = isNumber(this.props.limit) ? this.props.limit : 25; logger.setUp({ active: props.active }); logger.getStackCollection().setLimit(LIMIT); if (isFunction(this.props.onPrepareStack)) { this.stack.onPrepareStack = this.props.onPrepareStack; } if (isFunction(this.props.stdout)) { logger.setUp({ stdout: this.props.stdout }); } this.stack.session.start = isFunction(this.props.getCurrentDate) ? this.props.getCurrentDate() : getCurrentDate(); if (isString(this.props.sessionID) || isNumber(this.props.sessionID)) { this.stack.sessionId = this.props.sessionID; } } componentDidMount() { if (this.props.active && !isBackend()) { this.bindActions(); window.onerror = this.handlerError; } } componentWillUnmount() { this.unbindActions(); } bindActions() { document.addEventListener('mousedown', this._onMouseDown); document.addEventListener('mouseup', this._onMouseUp); document.addEventListener('keydown', this._onKeyDown); document.addEventListener('keyup', this._onKeyUp); } unbindActions() { window.onerror = null; document.removeEventListener('keydown', this._onKeyDown); document.removeEventListener('keyup', this._onKeyUp); document.removeEventListener('mousedown', this._onMouseDown); document.removeEventListener('mouseup', this._onMouseUp); } render() { const Bsod = isValidElement(this.props.bsod) ? this.props.bsod : BSOD; return (React.createElement(LoggerContext.Provider, { value: { getStackData: this.getStackData, onError: this.onError } }, this.props.children, this.props.bsodActive && this.state.bsod && (React.createElement(Bsod, { count: logger.getCounter(), onClose: this.closeBsod, stackData: this.getStackData() })))); } } LoggerContainer.defaultProps = { logger, active: true, bsodActive: true, sessionID: false, limit: 25, getCurrentDate };