Skip to content

Commit c4a0f18

Browse files
committed
enable log buffer
1 parent 942b894 commit c4a0f18

File tree

4 files changed

+72
-5
lines changed

4 files changed

+72
-5
lines changed

packages/firestore/src/api.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,11 @@ export { debugAssert as _debugAssert } from './util/assert';
238238
export { FieldPath as _FieldPath } from './model/path';
239239
export type { ResourcePath as _ResourcePath } from './model/path';
240240
export { ByteString as _ByteString } from './util/byte_string';
241-
export { logWarn as _logWarn } from './util/log';
241+
export {
242+
logWarn as _logWarn,
243+
enableLogBuffer as _enableLogBuffer,
244+
dumpLogBuffer as _dumpLogBuffer
245+
} from './util/log';
242246
export { AutoId as _AutoId } from './util/misc';
243247
export type {
244248
AuthTokenFactory,

packages/firestore/src/local/simple_db.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { getGlobal, getUA, isIndexedDBAvailable } from '@firebase/util';
2020
import { debugAssert, hardAssert } from '../util/assert';
2121
import { generateUniqueDebugId } from '../util/debug_uid';
2222
import { Code, FirestoreError } from '../util/error';
23-
import { logDebug, logError, logWarn } from '../util/log';
23+
import { logDebug, logError, logWarn, dumpLogBuffer } from '../util/log';
2424
import { Deferred } from '../util/promise';
2525

2626
import { DatabaseDeletedListener } from './persistence';
@@ -514,6 +514,8 @@ export class SimpleDb {
514514
`One possible cause is clicking the "Clear Site Data" button ` +
515515
`in a web browser.`
516516
);
517+
// TODO(dconeybe) REVERT THE NEXT LINE
518+
dumpLogBuffer();
517519
},
518520
{ passive: true }
519521
);

packages/firestore/src/util/log.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,15 @@ export function setLogLevel(logLevel: LogLevelString): void {
4747
}
4848

4949
export function logDebug(msg: string, ...obj: unknown[]): void {
50+
logBuffer?.add(LogLevel.DEBUG, msg, obj);
5051
if (logClient.logLevel <= LogLevel.DEBUG) {
5152
const args = obj.map(argToString);
5253
logClient.debug(`Firestore (${SDK_VERSION}): ${msg}`, ...args);
5354
}
5455
}
5556

5657
export function logError(msg: string, ...obj: unknown[]): void {
58+
logBuffer?.add(LogLevel.ERROR, msg, obj);
5759
if (logClient.logLevel <= LogLevel.ERROR) {
5860
const args = obj.map(argToString);
5961
logClient.error(`Firestore (${SDK_VERSION}): ${msg}`, ...args);
@@ -64,6 +66,7 @@ export function logError(msg: string, ...obj: unknown[]): void {
6466
* @internal
6567
*/
6668
export function logWarn(msg: string, ...obj: unknown[]): void {
69+
logBuffer?.add(LogLevel.WARN, msg, obj);
6770
if (logClient.logLevel <= LogLevel.WARN) {
6871
const args = obj.map(argToString);
6972
logClient.warn(`Firestore (${SDK_VERSION}): ${msg}`, ...args);
@@ -85,3 +88,61 @@ function argToString(obj: unknown): string | unknown {
8588
}
8689
}
8790
}
91+
92+
interface LogBufferMessage {
93+
level: LogLevel;
94+
msg: string;
95+
objs: unknown[];
96+
timestamp: number;
97+
}
98+
99+
class LogBuffer {
100+
private messages: Array<LogBufferMessage> = [];
101+
102+
constructor(private readonly maxLength: number) {}
103+
104+
add(level: LogLevel, msg: string, objs: unknown[]): void {
105+
const message: LogBufferMessage = {
106+
level,
107+
msg,
108+
objs: objs.map(value => structuredClone(value)),
109+
timestamp: performance.now()
110+
};
111+
if (this.messages.length == this.maxLength) {
112+
this.messages.shift();
113+
}
114+
this.messages.push(message);
115+
}
116+
117+
dump(): void {
118+
const now = performance.now();
119+
120+
while (this.messages.length > 0) {
121+
const { level, msg, objs, timestamp } = this.messages.shift();
122+
const args = obj.map(argToString);
123+
const messageString = `Firestore BUFFERED (${
124+
now - timestamp
125+
}ms ago): ${msg}`;
126+
if (level === LogLevel.WARN) {
127+
logClient.warn(messageString, ...objs);
128+
} else if (level === LogLevel.ERROR) {
129+
logClient.error(messageString, ...objs);
130+
} else {
131+
logClient.debug(messageString, ...objs);
132+
}
133+
}
134+
}
135+
}
136+
137+
let logBuffer: LogBuffer | null = null;
138+
139+
export function enableLogBuffer(maxLength: number): void {
140+
if (logBuffer) {
141+
throw new Error('log buffer has already been enabled');
142+
}
143+
logBuffer = new LogBuffer(maxLength);
144+
}
145+
146+
export function dumpLogBuffer(): void {
147+
logBuffer?.dump();
148+
}

packages/firestore/test/integration/util/firebase_export.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@
2020
// reference to the minified sources. If you change any exports in this file,
2121
// you need to also adjust "integration/firestore/firebase_export.ts".
2222

23-
import { FirebaseApp, initializeApp, setLogLevel } from '@firebase/app';
23+
import { FirebaseApp, initializeApp } from '@firebase/app';
2424

25-
import { Firestore, initializeFirestore } from '../../../src';
25+
import { Firestore, initializeFirestore, _enableLogBuffer } from '../../../src';
2626
import { PrivateSettings } from '../../../src/lite-api/settings';
2727

2828
// TODO(dimond): Right now we create a new app and Firestore instance for
2929
// every test and never clean them up. We may need to revisit.
3030
let appCount = 0;
3131

32-
setLogLevel('debug');
32+
_enableLogBuffer(1000);
3333

3434
export function newTestApp(projectId: string, appName?: string): FirebaseApp {
3535
if (appName === undefined) {

0 commit comments

Comments
 (0)