Skip to content

Commit 4cae0af

Browse files
feat: add a new reportMode configuration option (#295)
Adds the `reportMode` configuration option. The `ignoreEnvironmentCheck` configuration option is now deprecated, and the `reportMode` option should be used instead. In particular, the `reportMode` can have one of three values: * 'production' (default) - Only report errors if NODE_ENV is set to "production".: * 'always' - Always report errors regardless of the value of NODE_ENV. * 'never' - Never report errors regardless of the value of NODE_ENV. Fixes #127
1 parent b162606 commit 4cae0af

File tree

6 files changed

+551
-257
lines changed

6 files changed

+551
-257
lines changed

src/configuration.ts

Lines changed: 68 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,16 @@ export interface Logger {
3535
fatal(...args: Array<{}>): void;
3636
}
3737

38+
export type ReportMode = 'production'|'always'|'never';
39+
3840
export interface ConfigurationOptions {
3941
projectId?: string;
4042
keyFilename?: string;
4143
logLevel?: string|number;
4244
key?: string;
4345
serviceContext?: {service?: string; version?: string;};
4446
ignoreEnvironmentCheck?: boolean;
47+
reportMode?: ReportMode;
4548
credentials?: {};
4649
reportUnhandledRejections?: boolean;
4750
}
@@ -74,7 +77,7 @@ export interface ServiceContext {
7477
*/
7578
export class Configuration {
7679
_logger: Logger;
77-
_shouldReportErrorsToAPI: boolean;
80+
_reportMode: ReportMode;
7881
_projectId: string|null;
7982
_key: string|null;
8083
keyFilename: string|null;
@@ -89,23 +92,7 @@ export class Configuration {
8992
* for configuration logging purposes.
9093
*/
9194
this._logger = logger;
92-
/**
93-
* The _shouldReportErrorsToAPI property is meant to denote whether or not
94-
* the Stackdriver error reporting library will actually try to report
95-
* Errors to the Stackdriver Error API. The value of this property is
96-
* derived from the `NODE_ENV` environmental variable or the value of
97-
* ignoreEnvironmentChec property if present in the runtime configuration.
98-
* If either the `NODE_ENV` variable is set to 'production' or the
99-
* ignoreEnvironmentCheck propery on the runtime configuration is set to
100-
* true then the error reporting library attempt to send errors to the Error
101-
* API. Otherwise the value will remain false and errors will not be
102-
* reported to the API.
103-
* @memberof Configuration
104-
* @private
105-
* @type {Boolean}
106-
* @defaultvalue false
107-
*/
108-
this._shouldReportErrorsToAPI = false;
95+
this._reportMode = 'production';
10996
/**
11097
* The _projectId property is meant to contain the string project id that
11198
* the hosting application is running under. The project id is a unique
@@ -259,6 +246,12 @@ export class Configuration {
259246
}
260247
}
261248
}
249+
_determineReportMode() {
250+
if (this._givenConfiguration.reportMode) {
251+
this._reportMode =
252+
this._givenConfiguration.reportMode.toLowerCase() as ReportMode;
253+
}
254+
}
262255
/**
263256
* The _gatherLocalConfiguration function is responsible for determining
264257
* directly determing whether the properties `reportUncaughtExceptions` and
@@ -273,23 +266,56 @@ export class Configuration {
273266
* @returns {Undefined} - does not return anything
274267
*/
275268
_gatherLocalConfiguration() {
276-
if (this._givenConfiguration.ignoreEnvironmentCheck === true) {
277-
this._shouldReportErrorsToAPI = true;
278-
} else if (
279-
has(this._givenConfiguration, 'ignoreEnvironmentCheck') &&
280-
!is.boolean(this._givenConfiguration.ignoreEnvironmentCheck)) {
281-
throw new Error('config.ignoreEnvironmentCheck must be a boolean');
282-
} else {
283-
this._shouldReportErrorsToAPI = env.NODE_ENV === 'production';
269+
let isReportModeValid = true;
270+
if (has(this._givenConfiguration, 'reportMode')) {
271+
const reportMode = this._givenConfiguration.reportMode;
272+
isReportModeValid = is.string(reportMode) &&
273+
(reportMode === 'production' || reportMode === 'always' ||
274+
reportMode === 'never');
275+
}
276+
277+
if (!isReportModeValid) {
278+
throw new Error(
279+
'config.reportMode must a string that is one ' +
280+
'of "production", "always", or "never".');
284281
}
285-
if (!this._shouldReportErrorsToAPI) {
282+
283+
const hasEnvCheck = has(this._givenConfiguration, 'ignoreEnvironmentCheck');
284+
const hasReportMode = has(this._givenConfiguration, 'reportMode');
285+
if (hasEnvCheck) {
286+
this._logger.warn(
287+
'The "ignoreEnvironmentCheck" config option is deprecated. ' +
288+
'Use the "reportMode" config option instead.');
289+
}
290+
if (hasEnvCheck && hasReportMode) {
286291
this._logger.warn([
287-
'Stackdriver error reporting client has not been configured to send',
288-
'errors, please check the NODE_ENV environment variable and make sure it',
289-
'is set to "production" or the ignoreEnvironmentCheck property is set to',
290-
'true in the runtime configuration object',
292+
'Both the "ignoreEnvironmentCheck" and "reportMode" configuration options',
293+
'have been specified. The "reportMode" option will take precedence.'
291294
].join(' '));
295+
this._determineReportMode();
296+
} else if (hasEnvCheck) {
297+
if (this._givenConfiguration.ignoreEnvironmentCheck === true) {
298+
this._reportMode = 'always';
299+
} else if (
300+
has(this._givenConfiguration, 'ignoreEnvironmentCheck') &&
301+
!is.boolean(this._givenConfiguration.ignoreEnvironmentCheck)) {
302+
throw new Error('config.ignoreEnvironmentCheck must be a boolean');
303+
} else {
304+
this._reportMode = 'production';
305+
}
306+
} else if (hasReportMode) {
307+
this._determineReportMode();
292308
}
309+
310+
if (this.isReportingEnabled() && !this.getShouldReportErrorsToAPI()) {
311+
this._logger.warn([
312+
'The stackdriver error reporting client is configured to report errors',
313+
'if and only if the NODE_ENV environment variable is set to "production".',
314+
'Errors will not be reported. To have errors always reported, regardless of the',
315+
'value of NODE_ENV, set the reportMode configuration option to "always".'
316+
].join(' '));
317+
}
318+
293319
if (is.string(this._givenConfiguration.key)) {
294320
this._key = this._givenConfiguration.key!;
295321
} else if (has(this._givenConfiguration, 'key')) {
@@ -349,14 +375,22 @@ export class Configuration {
349375
return this._projectId;
350376
}
351377
/**
352-
* Returns the _shouldReportErrorsToAPI property on the instance.
378+
* Returns whether this configuration specifies that errors should be
379+
* reported to the error reporting API. That is, "reportMode" is
380+
* either set to "always" or it is set to "production" and the value
381+
* of the NODE_ENV environment variable is "production".
353382
* @memberof Configuration
354383
* @public
355384
* @function getShouldReportErrorsToAPI
356-
* @returns {Boolean} - returns the _shouldReportErrorsToAPI property
385+
* @returns {Boolean} - whether errors should be reported to the API
357386
*/
358387
getShouldReportErrorsToAPI() {
359-
return this._shouldReportErrorsToAPI;
388+
return this._reportMode === 'always' ||
389+
(this._reportMode === 'production' &&
390+
(process.env.NODE_ENV || '').toLowerCase() === 'production');
391+
}
392+
isReportingEnabled() {
393+
return this._reportMode !== 'never';
360394
}
361395
/**
362396
* Returns the _projectId property on the instance.

src/google-apis/auth-client.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,11 @@ export class RequestHandler extends Service {
159159
userCb?:
160160
(err: Error|null, response: http.ServerResponse|null,
161161
body: {}) => void) {
162-
const cb: Function = (is.function(userCb) ? userCb : RequestHandler.noOp)!;
162+
const cb: Function = (is.function(userCb) ? userCb : RequestHandler.noOp)!;
163+
if (!this._config.isReportingEnabled()) {
164+
cb(null, null, {});
165+
return;
166+
}
163167
if (this._config.getShouldReportErrorsToAPI()) {
164168
this.request(
165169
{
@@ -181,14 +185,14 @@ export class RequestHandler extends Service {
181185
});
182186
} else {
183187
cb(new Error([
184-
'Stackdriver error reporting client has not been configured to send',
185-
'errors, please check the NODE_ENV environment variable and make sure',
186-
'it is set to "production" or set the ignoreEnvironmentCheck property',
187-
'to true in the runtime configuration object',
188+
'The stackdriver error reporting client is configured to report errors',
189+
'if and only if the NODE_ENV environment variable is set to "production".',
190+
'Errors will not be reported. To have errors always reported, regardless of the',
191+
'value of NODE_ENV, set the reportMode configuration option to "always".'
188192
].join(' ')),
189193
null, null);
190194
}
191-
}
195+
}
192196
}
193197

194198
/**

src/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ export type RestifyRequestHandler = (req: any, res: any, next: Function) => any;
5555
* @property {Boolean} [ignoreEnvironmentCheck] - flag indicating whether or not
5656
* to communicate errors to the Stackdriver service even if NODE_ENV is not set
5757
* to production
58+
* @property {String} [reportMode] - flag indicating whether or not
59+
* to communicate errors to the Stackdriver service. Possible values are:
60+
* -> 'production' (default)
61+
* -> Only report errors if NODE_ENV is set to "production".
62+
* -> 'always'
63+
* -> Always report errors regardless of the value of NODE_ENV.
64+
* -> 'never'
65+
* -> Never report errors regardless of the value of NODE_ENV.
5866
*/
5967

6068
/**

system-test/error-reporting.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ describe('Request/Response lifecycle mocking', () => {
161161
.post('/events:report?');
162162
logger = createLogger({logLevel: 5});
163163
client = new RequestHandler(
164-
new Configuration({ignoreEnvironmentCheck: true}, logger), logger);
164+
new Configuration({reportMode: 'always'}, logger), logger);
165165
});
166166

167167
afterEach(() => {
@@ -207,8 +207,7 @@ describe('Request/Response lifecycle mocking', () => {
207207
const key = env.apiKey;
208208
const logger = createLogger({logLevel: 5});
209209
const client = new RequestHandler(
210-
new Configuration({key, ignoreEnvironmentCheck: true}, logger),
211-
logger);
210+
new Configuration({key, reportMode: 'always'}, logger), logger);
212211
fakeService.query({key}).reply(200, (uri: string) => {
213212
assert(uri.indexOf('key=' + key) > -1);
214213
return {};
@@ -242,7 +241,7 @@ describe('Client creation', () => {
242241
const cfg = new Configuration(
243242
{
244243
projectId: env.injected().projectId,
245-
ignoreEnvironmentCheck: true,
244+
reportMode: 'always',
246245
},
247246
logger);
248247
this.timeout(10000);
@@ -262,7 +261,7 @@ describe('Client creation', () => {
262261
function(this, done) {
263262
env.sterilizeProcess().setProjectId().setKeyFilename();
264263
const logger = createLogger({logLevel: 5});
265-
const cfg = new Configuration({ignoreEnvironmentCheck: true}, logger);
264+
const cfg = new Configuration({reportMode: 'always'}, logger);
266265
this.timeout(10000);
267266
assert.doesNotThrow(() => {
268267
new RequestHandler(cfg, logger)
@@ -283,7 +282,7 @@ describe('Client creation', () => {
283282
const cfg = new Configuration(
284283
{
285284
projectId: '' + Number(env.injected().projectNumber),
286-
ignoreEnvironmentCheck: true,
285+
reportMode: 'always',
287286
},
288287
logger);
289288
this.timeout(10000);
@@ -303,7 +302,7 @@ describe('Client creation', () => {
303302
function(this, done) {
304303
env.sterilizeProcess().setKeyFilename().setProjectNumber();
305304
const logger = createLogger({logLevel: 5});
306-
const cfg = new Configuration({ignoreEnvironmentCheck: true}, logger);
305+
const cfg = new Configuration({reportMode: 'always'}, logger);
307306
this.timeout(10000);
308307
assert.doesNotThrow(() => {
309308
new RequestHandler(cfg, logger)
@@ -319,10 +318,10 @@ describe('Client creation', () => {
319318

320319
describe('Expected Behavior', () => {
321320
const ERROR_STRING = [
322-
'Stackdriver error reporting client has not been configured to send',
323-
'errors, please check the NODE_ENV environment variable and make',
324-
'sure it is set to "production" or set the ignoreEnvironmentCheck',
325-
'property to true in the runtime configuration object',
321+
'The stackdriver error reporting client is configured to report errors',
322+
'if and only if the NODE_ENV environment variable is set to "production".',
323+
'Errors will not be reported. To have errors always reported, regardless of the',
324+
'value of NODE_ENV, set the reportMode configuration option to "always".'
326325
].join(' ');
327326

328327
const er = new Error(ERR_TOKEN);
@@ -332,11 +331,11 @@ describe('Expected Behavior', () => {
332331
env.sterilizeProcess();
333332
});
334333

335-
it('Should callback with an error with a configuration to not report errors',
334+
it('Should callback with an error with a configuration that cannot report errors',
336335
done => {
337336
env.sterilizeProcess().setKeyFilename().setProjectId();
338337
process.env.NODE_ENV = 'null';
339-
const logger = createLogger({logLevel: 5});
338+
const logger = createLogger({logLevel: 5, reportMode: 'production'});
340339
const client =
341340
new RequestHandler(new Configuration(undefined, logger), logger);
342341
client.sendError({} as ErrorMessage, (err, response) => {
@@ -353,7 +352,7 @@ describe('Expected Behavior', () => {
353352
const cfg = new Configuration(
354353
{
355354
projectId: env.injected().projectId,
356-
ignoreEnvironmentCheck: true,
355+
reportMode: 'always',
357356
},
358357
logger);
359358
const client = new RequestHandler(cfg, logger);
@@ -373,7 +372,7 @@ describe('Expected Behavior', () => {
373372
const cfg = new Configuration(
374373
{
375374
projectId: '' + Number(env.injected().projectNumber),
376-
ignoreEnvironmentCheck: true,
375+
reportMode: 'always',
377376
},
378377
logger);
379378
const client = new RequestHandler(cfg, logger);
@@ -467,7 +466,7 @@ describe('error-reporting', () => {
467466
process.removeAllListeners('unhandledRejection');
468467
const initConfiguration = Object.assign(
469468
{
470-
ignoreEnvironmentCheck: true,
469+
reportMode: 'always' as 'always',
471470
serviceContext: {
472471
service: SERVICE,
473472
version: VERSION,

0 commit comments

Comments
 (0)