UNPKG

3.79 kBJavaScriptView Raw
1// @flow
2
3import RemoteLogging, { type LogLevel, type LogEntryFields } from './RemoteLogging';
4
5type Console = typeof console;
6
7/**
8 * Creates a console object that delegates calls to the specified underlying console and also sends
9 * the messages to the development environment over a remote connection.
10 */
11function createRemoteConsole(originalConsole: Console): Console {
12 let groupDepth = 0;
13
14 // $FlowIssue: Flow declares console's properties to read-only
15 const enhancedConsole = Object.create(originalConsole);
16
17 // https://console.spec.whatwg.org/#debug
18 // Don't use a level below "info" because "debug" is intended for messages that shouldn't be shown
19 // to the developer
20 _defineConsoleLogMethod('debug', 'info');
21
22 // https://console.spec.whatwg.org/#log
23 _defineConsoleLogMethod('log', 'info');
24
25 // https://console.spec.whatwg.org/#info
26 _defineConsoleLogMethod('info', 'info');
27
28 // https://console.spec.whatwg.org/#warn
29 _defineConsoleLogMethod('warn', 'warn');
30
31 // https://console.spec.whatwg.org/#error
32 _defineConsoleLogMethod('error', 'error');
33
34 // https://console.spec.whatwg.org/#assert
35 enhancedConsole.assert = function assert(condition: mixed, ...data: Array<mixed>): void {
36 if (originalConsole.assert) {
37 originalConsole.assert(condition, ...data);
38 }
39
40 if (condition) {
41 return;
42 }
43
44 const assertionMessage = 'Assertion failed';
45 if (!data.length) {
46 data.push(assertionMessage);
47 } else {
48 if (typeof data[0] !== 'string') {
49 data.unshift(assertionMessage);
50 } else {
51 data[0] = `${assertionMessage}: ${data[0]}`;
52 }
53 }
54
55 _enqueueRemoteLog('error', {}, data);
56 };
57
58 // https://console.spec.whatwg.org/#group
59 enhancedConsole.group = function group(...data: Array<mixed>): void {
60 if (originalConsole.group) {
61 originalConsole.group(...data);
62 }
63
64 _enqueueRemoteLog('info', {}, data);
65 groupDepth++;
66 };
67
68 // https://console.spec.whatwg.org/#groupcollapsed
69 enhancedConsole.groupCollapsed = function groupCollapsed(...data: Array<mixed>): void {
70 if (originalConsole.groupCollapsed) {
71 originalConsole.groupCollapsed(...data);
72 }
73
74 _enqueueRemoteLog('info', { groupCollapsed: true }, data);
75 groupDepth++;
76 };
77
78 // https://console.spec.whatwg.org/#groupend
79 enhancedConsole.groupEnd = function groupEnd(): void {
80 if (originalConsole.groupEnd) {
81 originalConsole.groupEnd();
82 }
83
84 if (groupDepth > 0) {
85 groupDepth--;
86 }
87
88 _enqueueRemoteLog('info', { shouldHide: true }, []);
89 };
90
91 /**
92 * Defines a method in the `console.log()` family on the enhanced console
93 * instance
94 */
95 function _defineConsoleLogMethod(name: string, level: LogLevel): void {
96 enhancedConsole[name] = function __expoConsoleLog(...data: Array<mixed>): void {
97 if (originalConsole[name]) {
98 originalConsole[name](...data);
99 }
100
101 _enqueueRemoteLog(level, {}, data);
102 };
103 }
104
105 /**
106 * Schedules the given log entry to be sent remotely in a safe way that handles all errors. This
107 * function is responsible for error handling because the console methods are synchronous but
108 * sending log messages is asynchronous, so this code (instead of the console methods) needs to be
109 * responsible for asynchronous errors.
110 */
111 function _enqueueRemoteLog(
112 level: LogLevel,
113 additionalFields: LogEntryFields,
114 data: Array<mixed>
115 ): void {
116 RemoteLogging.enqueueRemoteLogAsync(
117 level,
118 { groupDepth, ...additionalFields },
119 data
120 ).catch(error => {
121 originalConsole.error(
122 `There was a problem sending log messages to your development environment`,
123 error
124 );
125 });
126 }
127
128 return enhancedConsole;
129}
130
131export default {
132 createRemoteConsole,
133};