Skip to content

Commit 27d3e3f

Browse files
committed
Feedback from @mikelehen and @schmidt-sebastian
Refactor to also log fatal issues Refactor to not attempt to log if the level is invalid Adding docs and more feedback
1 parent ba95331 commit 27d3e3f

File tree

9 files changed

+109
-90
lines changed

9 files changed

+109
-90
lines changed

packages/database/src/core/PersistentConnection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,7 @@ export class PersistentConnection extends ServerActions {
936936
this.securityDebugCallback_(body);
937937
} else {
938938
if ('msg' in body) {
939-
log('FIREBASE: ' + body['msg'].replace('\n', '\nFIREBASE: '));
939+
console.log('FIREBASE: ' + body['msg'].replace('\n', '\nFIREBASE: '));
940940
}
941941
}
942942
}

packages/database/src/core/Repo.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ export class Repo {
653653
forEach(stats, (stat: string, value: any) => {
654654
// pad stat names to be the same length (plus 2 extra spaces).
655655
for (let i = stat.length; i < longestName + 2; i++) stat += ' ';
656-
log(stat + value);
656+
console.log(stat + value);
657657
});
658658
}
659659

packages/database/src/core/util/util.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import { SessionStorage } from '../storage/storage';
2929
import { isNodeSdk } from '@firebase/util';
3030
import { Logger } from '@firebase/logger';
3131

32-
const logClient = new Logger();
32+
const logClient = new Logger('@firebase/database');
3333

3434
/**
3535
* Returns a locally-unique ID (generated by just incrementing up from 0 each time its called).
@@ -159,8 +159,9 @@ export const error = function(...var_args: string[]) {
159159
* @param {...string} var_args
160160
*/
161161
export const fatal = function(...var_args: string[]) {
162-
const message = buildLogMessage_(...var_args);
163-
throw new Error('FIREBASE FATAL ERROR: ' + message);
162+
const message = `FIREBASE FATAL ERROR: ${buildLogMessage_(...var_args)}`;
163+
logClient.error(message);
164+
throw new Error(message);
164165
};
165166

166167
/**

packages/firestore/src/util/log.ts

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
import { SDK_VERSION } from '../core/version';
2020
import { AnyJs } from './misc';
2121
import { PlatformSupport } from '../platform/platform';
22-
import { Logger, LogLevel as _LogLevel } from '@firebase/logger';
22+
import { Logger, LogLevel as FirebaseLogLevel } from '@firebase/logger';
2323

24-
const client = new Logger();
24+
const logClient = new Logger('@firebase/firestore');
2525

2626
export enum LogLevel {
2727
DEBUG,
@@ -31,30 +31,36 @@ export enum LogLevel {
3131

3232
// Helper methods are needed because variables can't be exported as read/write
3333
export function getLogLevel(): LogLevel {
34-
if (client.logLevel === _LogLevel.DEBUG) {
34+
if (logClient.logLevel === FirebaseLogLevel.DEBUG) {
3535
return LogLevel.DEBUG;
36-
}
37-
38-
if (client.logLevel === _LogLevel.SILENT) {
36+
} else if (logClient.logLevel === FirebaseLogLevel.SILENT) {
3937
return LogLevel.SILENT;
38+
} else {
39+
return LogLevel.ERROR;
4040
}
41-
42-
return LogLevel.ERROR;
4341
}
4442
export function setLogLevel(newLevel: LogLevel): void {
45-
client.logLevel = newLevel;
43+
/**
44+
* Since Firestore's LogLevel enum is a pure subset of Firebase's LogLevel, we
45+
* can return it directly.
46+
*/
47+
logClient.logLevel = newLevel;
4648
}
4749

4850
export function debug(tag: string, msg: string, ...obj: AnyJs[]): void {
49-
const time = new Date().toISOString();
50-
const args = obj.map(argToString);
51-
client.log(`Firestore (${SDK_VERSION}) ${time} [${tag}]: ${msg}`, ...args);
51+
if (logClient.logLevel <= FirebaseLogLevel.DEBUG) {
52+
const time = new Date().toISOString();
53+
const args = obj.map(argToString);
54+
logClient.log(`Firestore (${SDK_VERSION}) ${time} [${tag}]: ${msg}`, ...args);
55+
}
5256
}
5357

5458
export function error(msg: string, ...obj: AnyJs[]): void {
55-
const time = new Date().toISOString();
56-
const args = obj.map(argToString);
57-
client.error(`Firestore (${SDK_VERSION}) ${time}: ${msg}`, ...args);
59+
if (logClient.logLevel <= FirebaseLogLevel.ERROR) {
60+
const time = new Date().toISOString();
61+
const args = obj.map(argToString);
62+
logClient.error(`Firestore (${SDK_VERSION}) ${time}: ${msg}`, ...args);
63+
}
5864
}
5965

6066
/**

packages/logger/README.md

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,39 @@
1-
# @firebase/template
2-
3-
This package can be used as a template for anyone creating new packages in the
4-
Firebase JS SDK. It will give you a couple things OOTB:
5-
6-
- **Typescript Support:** Your code should be written in TS to be consistent
7-
with the rest of the SDK.
8-
- **Isomorphic Testing/Coverage:** Your tests will be run in both Node.js and
9-
Browser environments and coverage from both, collected.
10-
- **Links to all of the other packages:** Should your new package need to take
11-
a dependency on any of the other packages in this monorepo (e.g.
12-
`@firebase/app`, `@firebase/util`, etc), all those dependencies are already
13-
set up, you can just remove the ones you don't need.
1+
# @firebase/logger
2+
3+
This package serves as the base of all logging in the JS SDK. Any logging that
4+
is intended to be for firebase end developers, should go through this module.
5+
6+
## Basic Usage
7+
8+
Firebase components should import the `Logger` class and instantiate a new
9+
instance by passing a component name (e.g. `@firebase/<COMPONENT>`) to the
10+
constructor.
11+
12+
_e.g._
13+
14+
```typescript
15+
import { Logger } from '@firebase/logger';
16+
17+
const logClient = new Logger(`@firebase/<COMPONENT>`);
18+
```
19+
20+
Each `Logger` instance supports 5 log functions each to be used in a specific
21+
instance:
22+
23+
- `debug`: Internal logs; use this to allow developers to send us their debug
24+
logs for us to be able to diagnose an issue.
25+
- `log`: Use to inform your user about things they may need to know.
26+
- `info`: Use if you have to inform the user about something that they need to
27+
take a concrete action on. Once they take that action, the log should go away.
28+
- `warn`: Use when a product feature may stop functioning correctly; unexpected
29+
scenario. Majority of user-facing logs.
30+
- `error`: Only use when user App would stop functioning correctly - super rare!
31+
32+
## Log Format
33+
34+
Each log will be formatted in the following manner:
35+
36+
```typescript
37+
`[${new Date()}] ${this.name}: ${...args}`
38+
```
39+

packages/logger/gulpfile.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const buildModule = gulp.parallel([
2323
]);
2424

2525
const setupWatcher = () => {
26-
gulp.watch('src/**/*', buildModule);
26+
gulp.watch(['index.ts', 'src/**/*'], buildModule);
2727
};
2828

2929
gulp.task('build', buildModule);

packages/logger/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,12 @@
2121
* just use index.ts
2222
*/
2323

24-
import { instances, setDefaultLogLevel, LogLevel } from './src/logger';
24+
import { instances, LogLevel } from './src/logger';
2525

2626
export function setLogLevel(level: LogLevel) {
2727
instances.forEach(inst => {
2828
inst.logLevel = level;
2929
});
30-
setDefaultLogLevel(level);
3130
}
3231

3332
export { Logger, LogLevel, LogHandler } from './src/logger';

packages/logger/src/logger.ts

Lines changed: 31 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,6 @@
1414
* limitations under the License.
1515
*/
1616

17-
/**
18-
* This is the file that people using Node.js will actually import. You should
19-
* only include this file if you have something specific about your
20-
* implementation that mandates having a separate entrypoint. Otherwise you can
21-
* just use index.ts
22-
*/
23-
2417
/**
2518
* A container for all of the Logger instances
2619
*/
@@ -31,15 +24,15 @@ export const instances: Logger[] = [];
3124
* silence the logs altogether.
3225
*
3326
* The order is a follows:
34-
* DEBUG < VERBOSE < INFO < WARN < ERROR < SILENT
27+
* DEBUG < LOG < INFO < WARN < ERROR < SILENT
3528
*
3629
* All of the log types above the current log level will be captured (i.e. if
3730
* I set the log level to `INFO`, errors will still be logged, but `DEBUG` and
38-
* `VERBOSE` logs will not)
31+
* `LOG` logs will not)
3932
*/
4033
export enum LogLevel {
4134
DEBUG,
42-
VERBOSE,
35+
LOG,
4336
INFO,
4437
WARN,
4538
ERROR,
@@ -49,71 +42,67 @@ export enum LogLevel {
4942
/**
5043
* A container for the default log level
5144
*/
52-
let defaultLogLevel: LogLevel = LogLevel.WARN;
53-
54-
/**
55-
* A function to set the default log level externally
56-
*/
57-
export function setDefaultLogLevel(val: LogLevel) {
58-
if (!(val in LogLevel)) {
59-
throw new TypeError('Attempted to Invalid value assigned to `logLevel`');
60-
}
61-
defaultLogLevel = val;
62-
}
45+
const defaultLogLevel: LogLevel = LogLevel.WARN;
6346

6447
/**
6548
* We allow users the ability to pass their own log handler. We will pass the
6649
* type of log, the current log level, and any other arguments passed (i.e. the
6750
* messages that the user wants to log) to this function.
6851
*/
6952
export type LogHandler = (
53+
loggerInstance: Logger,
7054
logType: LogLevel,
71-
currentLogLevel: LogLevel,
7255
...args: any[]
7356
) => void;
7457

7558
/**
76-
* The default log handler will forward DEBUG, VERBOSE, INFO, WARN, and ERROR
59+
* The default log handler will forward DEBUG, LOG, INFO, WARN, and ERROR
7760
* messages on to their corresponding console counterparts (if the log method
7861
* is supported by the current log level)
7962
*/
8063
const defaultLogHandler: LogHandler = (
81-
logType: LogLevel,
82-
currentLevel: LogLevel,
83-
...args: any[]
64+
instance,
65+
logType,
66+
...args
8467
) => {
85-
if (logType < currentLevel) return;
68+
if (logType < instance.logLevel) return;
69+
const now = new Date();
8670
switch (logType) {
8771
case LogLevel.SILENT:
8872
return;
89-
case LogLevel.VERBOSE:
90-
console.log(...args);
73+
case LogLevel.LOG:
74+
console.log(`[${now}] ${instance.name}:`, ...args);
9175
break;
9276
case LogLevel.INFO:
93-
console.info(...args);
77+
console.info(`[${now}] ${instance.name}:`, ...args);
9478
break;
9579
case LogLevel.WARN:
96-
console.warn(...args);
80+
console.warn(`[${now}] ${instance.name}:`, ...args);
9781
break;
9882
case LogLevel.ERROR:
99-
console.error(...args);
83+
console.error(`[${now}] ${instance.name}:`, ...args);
10084
break;
10185
default:
102-
console.debug(...args);
86+
console.log(`[${now}] ${instance.name}:`, ...args);
10387
}
10488
};
10589

10690
export class Logger {
107-
constructor() {
91+
/**
92+
* Gives you an instance of a Logger to capture messages according to
93+
* Firebase's logging scheme.
94+
*
95+
* @param name The name that the logs will be associated with
96+
*/
97+
constructor(public name: string) {
10898
/**
10999
* Capture the current instance for later use
110100
*/
111101
instances.push(this);
112102
}
113103

114104
/**
115-
* The log level of the given logger. Though all of the log levels can be
116-
* centrally set, each logger can be set individually if it desires.
105+
* The log level of the given Logger instance.
117106
*/
118107
private _logLevel = defaultLogLevel;
119108
get logLevel() {
@@ -127,9 +116,7 @@ export class Logger {
127116
}
128117

129118
/**
130-
* The log handler for the current logger instance. This can be set to any
131-
* function value, though this should not be needed the vast majority of the
132-
* time
119+
* The log handler for the Logger instance.
133120
*/
134121
private _logHandler: LogHandler = defaultLogHandler;
135122
get logHandler() {
@@ -147,18 +134,18 @@ export class Logger {
147134
*/
148135

149136
debug(...args) {
150-
this._logHandler(LogLevel.DEBUG, this._logLevel, ...args);
137+
this._logHandler(this, LogLevel.DEBUG, ...args);
151138
}
152139
log(...args) {
153-
this._logHandler(LogLevel.VERBOSE, this._logLevel, ...args);
140+
this._logHandler(this, LogLevel.LOG, ...args);
154141
}
155142
info(...args) {
156-
this._logHandler(LogLevel.INFO, this._logLevel, ...args);
143+
this._logHandler(this, LogLevel.INFO, ...args);
157144
}
158145
warn(...args) {
159-
this._logHandler(LogLevel.WARN, this._logLevel, ...args);
146+
this._logHandler(this, LogLevel.WARN, ...args);
160147
}
161148
error(...args) {
162-
this._logHandler(LogLevel.ERROR, this._logLevel, ...args);
149+
this._logHandler(this, LogLevel.ERROR, ...args);
163150
}
164151
}

packages/logger/test/logger.test.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,31 +31,31 @@ describe('@firebase/logger', () => {
3131
errorSpy: null
3232
};
3333
/**
34-
* Before each test, instantiate a new instance of Logger and set the log
35-
* level so that all
36-
*
37-
* Also spy on all of the console methods so we can assert against them as
38-
* needed
34+
* Before each test, instantiate a new instance of Logger and establish spies
35+
* on all of the console methods so we can assert against them as needed
3936
*/
4037
beforeEach(() => {
41-
client = new Logger();
38+
client = new Logger('@firebase/test-logger');
4239

43-
spies.debugSpy = Spy(console, 'debug');
4440
spies.logSpy = Spy(console, 'log');
4541
spies.infoSpy = Spy(console, 'info');
4642
spies.warnSpy = Spy(console, 'warn');
4743
spies.errorSpy = Spy(console, 'error');
4844
});
4945

5046
afterEach(() => {
51-
spies.debugSpy.restore();
5247
spies.logSpy.restore();
5348
spies.infoSpy.restore();
5449
spies.warnSpy.restore();
5550
spies.errorSpy.restore();
5651
});
5752

5853
function testLog(message, channel, shouldLog) {
54+
/**
55+
* `debug` logs also go through log channel
56+
*/
57+
channel = channel === 'debug' ? 'log' : channel;
58+
5959
it(`Should ${shouldLog ? '' : 'not'} call \`console.${channel}\` if \`.${
6060
channel
6161
}\` is called`, () => {
@@ -71,7 +71,7 @@ describe('@firebase/logger', () => {
7171
/**
7272
* Allow all logs to be exported for this block of tests
7373
*/
74-
before(() => {
74+
beforeEach(() => {
7575
setLogLevel(LogLevel.DEBUG);
7676
});
7777
testLog(message, 'debug', true);
@@ -82,7 +82,7 @@ describe('@firebase/logger', () => {
8282
});
8383

8484
describe('Defaults', () => {
85-
before(() => {
85+
beforeEach(() => {
8686
setLogLevel(LogLevel.WARN);
8787
});
8888
testLog(message, 'debug', false);

0 commit comments

Comments
 (0)