@mongosh/logging 3.2.0 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AUTHORS +1 -0
- package/lib/analytics-helpers.d.ts +1 -1
- package/lib/helpers.d.ts +7 -0
- package/lib/helpers.js +31 -0
- package/lib/helpers.js.map +1 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +3 -3
- package/lib/index.js.map +1 -1
- package/lib/logging-and-telemetry.d.ts +2 -0
- package/lib/logging-and-telemetry.js +429 -0
- package/lib/logging-and-telemetry.js.map +1 -0
- package/lib/types.d.ts +33 -0
- package/lib/types.js +3 -0
- package/lib/types.js.map +1 -0
- package/package.json +5 -5
- package/src/analytics-helpers.ts +1 -1
- package/src/helpers.spec.ts +26 -0
- package/src/helpers.ts +49 -0
- package/src/index.ts +2 -1
- package/src/{setup-logger-and-telemetry.spec.ts → logging-and-telemetry.spec.ts} +193 -94
- package/src/logging-and-telemetry.ts +871 -0
- package/src/types.ts +35 -0
- package/lib/setup-logger-and-telemetry.d.ts +0 -5
- package/lib/setup-logger-and-telemetry.js +0 -364
- package/lib/setup-logger-and-telemetry.js.map +0 -1
- package/src/setup-logger-and-telemetry.ts +0 -795
|
@@ -0,0 +1,871 @@
|
|
|
1
|
+
import redactInfo from 'mongodb-redact';
|
|
2
|
+
import { redactURICredentials } from '@mongosh/history';
|
|
3
|
+
import type {
|
|
4
|
+
MongoshBus,
|
|
5
|
+
ApiEventWithArguments,
|
|
6
|
+
ApiEvent,
|
|
7
|
+
UseEvent,
|
|
8
|
+
EvaluateInputEvent,
|
|
9
|
+
ShowEvent,
|
|
10
|
+
ConnectEvent,
|
|
11
|
+
ScriptLoadFileEvent,
|
|
12
|
+
StartLoadingCliScriptsEvent,
|
|
13
|
+
StartMongoshReplEvent,
|
|
14
|
+
GlobalConfigFileLoadEvent,
|
|
15
|
+
CryptLibrarySkipEvent,
|
|
16
|
+
CryptLibraryFoundEvent,
|
|
17
|
+
SnippetsCommandEvent,
|
|
18
|
+
SnippetsErrorEvent,
|
|
19
|
+
SnippetsFetchIndexErrorEvent,
|
|
20
|
+
SnippetsFetchIndexEvent,
|
|
21
|
+
SnippetsLoadedEvent,
|
|
22
|
+
SnippetsLoadSnippetEvent,
|
|
23
|
+
SnippetsNpmDownloadActiveEvent,
|
|
24
|
+
SnippetsNpmDownloadFailedEvent,
|
|
25
|
+
SnippetsNpmLookupEvent,
|
|
26
|
+
SnippetsRunNpmEvent,
|
|
27
|
+
SnippetsTransformErrorEvent,
|
|
28
|
+
EditorRunEditCommandEvent,
|
|
29
|
+
EditorReadVscodeExtensionsDoneEvent,
|
|
30
|
+
EditorReadVscodeExtensionsFailedEvent,
|
|
31
|
+
FetchingUpdateMetadataEvent,
|
|
32
|
+
FetchingUpdateMetadataCompleteEvent,
|
|
33
|
+
SessionStartedEvent,
|
|
34
|
+
MongoshBusEventsMap,
|
|
35
|
+
WriteCustomLogEvent,
|
|
36
|
+
} from '@mongosh/types';
|
|
37
|
+
import { inspect } from 'util';
|
|
38
|
+
import { MongoLogWriter } from 'mongodb-log-writer';
|
|
39
|
+
import { mongoLogId } from 'mongodb-log-writer';
|
|
40
|
+
import type {
|
|
41
|
+
AnalyticsIdentifyMessage,
|
|
42
|
+
MongoshAnalytics,
|
|
43
|
+
MongoshAnalyticsIdentity,
|
|
44
|
+
} from './analytics-helpers';
|
|
45
|
+
import type { ConnectEventMap } from '@mongodb-js/devtools-connect';
|
|
46
|
+
import { hookLogger } from '@mongodb-js/devtools-connect';
|
|
47
|
+
import { MultiSet, toSnakeCase } from './helpers';
|
|
48
|
+
import { Writable } from 'stream';
|
|
49
|
+
import type {
|
|
50
|
+
LoggingAndTelemetryBusEventState,
|
|
51
|
+
MongoshLoggingAndTelemetry,
|
|
52
|
+
MongoshLoggingAndTelemetryArguments,
|
|
53
|
+
MongoshTrackingProperties,
|
|
54
|
+
} from './types';
|
|
55
|
+
|
|
56
|
+
export function setupLoggingAndTelemetry(
|
|
57
|
+
props: MongoshLoggingAndTelemetryArguments
|
|
58
|
+
): MongoshLoggingAndTelemetry {
|
|
59
|
+
const loggingAndTelemetry = new LoggingAndTelemetry(props);
|
|
60
|
+
|
|
61
|
+
loggingAndTelemetry.setup();
|
|
62
|
+
return loggingAndTelemetry;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
class LoggingAndTelemetry implements MongoshLoggingAndTelemetry {
|
|
66
|
+
private static dummyLogger = new MongoLogWriter(
|
|
67
|
+
'',
|
|
68
|
+
null,
|
|
69
|
+
new Writable({
|
|
70
|
+
write(chunk, encoding, callback) {
|
|
71
|
+
callback();
|
|
72
|
+
},
|
|
73
|
+
})
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
private readonly bus: MongoshBus;
|
|
77
|
+
private readonly analytics: MongoshAnalytics;
|
|
78
|
+
private readonly userTraits: {
|
|
79
|
+
platform: string;
|
|
80
|
+
[key: string]: unknown;
|
|
81
|
+
};
|
|
82
|
+
private readonly mongoshVersion: string;
|
|
83
|
+
|
|
84
|
+
private log: MongoLogWriter;
|
|
85
|
+
private pendingLogEvents: CallableFunction[] = [];
|
|
86
|
+
private isSetup = false;
|
|
87
|
+
private isBufferingEvents = false;
|
|
88
|
+
|
|
89
|
+
constructor({
|
|
90
|
+
bus,
|
|
91
|
+
analytics,
|
|
92
|
+
userTraits,
|
|
93
|
+
mongoshVersion,
|
|
94
|
+
}: MongoshLoggingAndTelemetryArguments) {
|
|
95
|
+
this.bus = bus;
|
|
96
|
+
this.analytics = analytics;
|
|
97
|
+
this.log = LoggingAndTelemetry.dummyLogger;
|
|
98
|
+
this.userTraits = userTraits;
|
|
99
|
+
this.mongoshVersion = mongoshVersion;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
public setup(): void {
|
|
103
|
+
if (this.isSetup) {
|
|
104
|
+
throw new Error('Setup can only be called once.');
|
|
105
|
+
}
|
|
106
|
+
this.setupBusEventListeners();
|
|
107
|
+
this.isSetup = true;
|
|
108
|
+
this.isBufferingEvents = true;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public attachLogger(logger: MongoLogWriter): void {
|
|
112
|
+
if (!this.isSetup) {
|
|
113
|
+
throw new Error('Run setup() before setting up the log writer.');
|
|
114
|
+
}
|
|
115
|
+
/** Setup can only be run when overriding a dummy log or a null log. */
|
|
116
|
+
if (this.log !== LoggingAndTelemetry.dummyLogger) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
'Previously set logger has not been detached. Run detachLogger() before setting.'
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
this.log = logger;
|
|
122
|
+
this.isBufferingEvents = false;
|
|
123
|
+
|
|
124
|
+
this.runAndClearPendingEvents();
|
|
125
|
+
|
|
126
|
+
this.bus.emit('mongosh:log-initialized');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public detachLogger() {
|
|
130
|
+
this.log = LoggingAndTelemetry.dummyLogger;
|
|
131
|
+
// Still run any remaining pending events with the dummy log for telemetry purposes.
|
|
132
|
+
this.runAndClearPendingEvents();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private runAndClearPendingEvents() {
|
|
136
|
+
let pendingEvent: CallableFunction | undefined;
|
|
137
|
+
while ((pendingEvent = this.pendingLogEvents.shift())) {
|
|
138
|
+
pendingEvent();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** Information used and set by different bus events. */
|
|
143
|
+
private busEventState: LoggingAndTelemetryBusEventState = {
|
|
144
|
+
/** We emit different analytics events for loading files and evaluating scripts
|
|
145
|
+
* depending on whether we're already in the REPL or not yet. We store the
|
|
146
|
+
* state here so that the places where the events are emitted don't have to
|
|
147
|
+
* be aware of this distinction. */
|
|
148
|
+
hasStartedMongoshRepl: false,
|
|
149
|
+
apiCallTracking: {
|
|
150
|
+
isEnabled: false,
|
|
151
|
+
apiCalls: new MultiSet<Pick<ApiEvent, 'class' | 'method'>>(),
|
|
152
|
+
deprecatedApiCalls: new MultiSet<Pick<ApiEvent, 'class' | 'method'>>(),
|
|
153
|
+
},
|
|
154
|
+
usesShellOption: false,
|
|
155
|
+
telemetryAnonymousId: undefined,
|
|
156
|
+
userId: undefined,
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
private setupBusEventListeners(): void {
|
|
160
|
+
const onBus = <
|
|
161
|
+
EventsMap extends Record<
|
|
162
|
+
keyof MongoshBusEventsMap | keyof ConnectEventMap,
|
|
163
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
164
|
+
(...args: any[]) => unknown
|
|
165
|
+
> = MongoshBusEventsMap,
|
|
166
|
+
K extends
|
|
167
|
+
| keyof MongoshBusEventsMap
|
|
168
|
+
| keyof ConnectEventMap = keyof MongoshBusEventsMap
|
|
169
|
+
>(
|
|
170
|
+
event: K,
|
|
171
|
+
listener: (...args: Parameters<EventsMap[K]>) => void
|
|
172
|
+
) => {
|
|
173
|
+
this.bus.on(event, ((...args: Parameters<EventsMap[K]>) => {
|
|
174
|
+
if (this.isBufferingEvents) {
|
|
175
|
+
this.pendingLogEvents.push(() => listener(...args));
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
listener(...args);
|
|
180
|
+
}) as MongoshBusEventsMap[K]);
|
|
181
|
+
return this.bus;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const getUserTraits = (): AnalyticsIdentifyMessage['traits'] => ({
|
|
185
|
+
...this.userTraits,
|
|
186
|
+
session_id: this.log.logId,
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const getTrackingProperties = (): MongoshTrackingProperties => ({
|
|
190
|
+
mongosh_version: this.mongoshVersion,
|
|
191
|
+
session_id: this.log.logId,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const getTelemetryUserIdentity = (): MongoshAnalyticsIdentity => {
|
|
195
|
+
return {
|
|
196
|
+
anonymousId:
|
|
197
|
+
this.busEventState.telemetryAnonymousId ??
|
|
198
|
+
(this.busEventState.userId as string),
|
|
199
|
+
};
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
onBus('mongosh:start-mongosh-repl', (ev: StartMongoshReplEvent) => {
|
|
203
|
+
this.log.info(
|
|
204
|
+
'MONGOSH',
|
|
205
|
+
mongoLogId(1_000_000_002),
|
|
206
|
+
'repl',
|
|
207
|
+
'Started REPL',
|
|
208
|
+
ev
|
|
209
|
+
);
|
|
210
|
+
this.busEventState.hasStartedMongoshRepl = true;
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
onBus(
|
|
214
|
+
'mongosh:start-loading-cli-scripts',
|
|
215
|
+
(event: StartLoadingCliScriptsEvent) => {
|
|
216
|
+
this.log.info(
|
|
217
|
+
'MONGOSH',
|
|
218
|
+
mongoLogId(1_000_000_003),
|
|
219
|
+
'repl',
|
|
220
|
+
'Start loading CLI scripts'
|
|
221
|
+
);
|
|
222
|
+
this.busEventState.usesShellOption = event.usesShellOption;
|
|
223
|
+
}
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
onBus('mongosh:connect', (args: ConnectEvent) => {
|
|
227
|
+
const { uri, resolved_hostname, ...argsWithoutUriAndHostname } = args;
|
|
228
|
+
const connectionUri = uri && redactURICredentials(uri);
|
|
229
|
+
const atlasHostname = {
|
|
230
|
+
atlas_hostname: args.is_atlas ? resolved_hostname : null,
|
|
231
|
+
};
|
|
232
|
+
const properties = {
|
|
233
|
+
...getTrackingProperties(),
|
|
234
|
+
...argsWithoutUriAndHostname,
|
|
235
|
+
...atlasHostname,
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
this.log.info(
|
|
239
|
+
'MONGOSH',
|
|
240
|
+
mongoLogId(1_000_000_004),
|
|
241
|
+
'connect',
|
|
242
|
+
'Connecting to server',
|
|
243
|
+
{
|
|
244
|
+
userId: this.busEventState.userId,
|
|
245
|
+
telemetryAnonymousId: this.busEventState.telemetryAnonymousId,
|
|
246
|
+
connectionUri,
|
|
247
|
+
...properties,
|
|
248
|
+
}
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
this.analytics.track({
|
|
252
|
+
...getTelemetryUserIdentity(),
|
|
253
|
+
event: 'New Connection',
|
|
254
|
+
properties,
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
onBus('mongosh:start-session', (args: SessionStartedEvent) => {
|
|
259
|
+
const normalizedTimingsArray = Object.entries(args.timings).map(
|
|
260
|
+
([key, duration]) => {
|
|
261
|
+
const snakeCaseKey = toSnakeCase(key);
|
|
262
|
+
return [snakeCaseKey, duration];
|
|
263
|
+
}
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
const normalizedTimings = Object.fromEntries(normalizedTimingsArray);
|
|
267
|
+
this.analytics.track({
|
|
268
|
+
...getTelemetryUserIdentity(),
|
|
269
|
+
event: 'Startup Time',
|
|
270
|
+
properties: {
|
|
271
|
+
...getTrackingProperties(),
|
|
272
|
+
is_interactive: args.isInteractive,
|
|
273
|
+
js_context: args.jsContext,
|
|
274
|
+
...normalizedTimings,
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
onBus(
|
|
280
|
+
'mongosh:new-user',
|
|
281
|
+
(newTelemetryUserIdentity: { userId: string; anonymousId: string }) => {
|
|
282
|
+
if (!newTelemetryUserIdentity.anonymousId) {
|
|
283
|
+
this.busEventState.userId = newTelemetryUserIdentity.userId;
|
|
284
|
+
}
|
|
285
|
+
this.busEventState.telemetryAnonymousId =
|
|
286
|
+
newTelemetryUserIdentity.anonymousId;
|
|
287
|
+
this.analytics.identify({
|
|
288
|
+
anonymousId: newTelemetryUserIdentity.anonymousId,
|
|
289
|
+
traits: getUserTraits(),
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
onBus(
|
|
295
|
+
'mongosh:update-user',
|
|
296
|
+
(updatedTelemetryUserIdentity: {
|
|
297
|
+
userId: string;
|
|
298
|
+
anonymousId?: string;
|
|
299
|
+
}) => {
|
|
300
|
+
if (updatedTelemetryUserIdentity.anonymousId) {
|
|
301
|
+
this.busEventState.telemetryAnonymousId =
|
|
302
|
+
updatedTelemetryUserIdentity.anonymousId;
|
|
303
|
+
} else {
|
|
304
|
+
this.busEventState.userId = updatedTelemetryUserIdentity.userId;
|
|
305
|
+
}
|
|
306
|
+
this.analytics.identify({
|
|
307
|
+
...getTelemetryUserIdentity(),
|
|
308
|
+
traits: getUserTraits(),
|
|
309
|
+
});
|
|
310
|
+
this.log.info(
|
|
311
|
+
'MONGOSH',
|
|
312
|
+
mongoLogId(1_000_000_005),
|
|
313
|
+
'config',
|
|
314
|
+
'User updated'
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
onBus('mongosh:error', (error: Error, context: string) => {
|
|
320
|
+
const mongoshError = error as {
|
|
321
|
+
name: string;
|
|
322
|
+
message: string;
|
|
323
|
+
code: unknown;
|
|
324
|
+
scope: unknown;
|
|
325
|
+
metadata: unknown;
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
this.log[context === 'fatal' ? 'fatal' : 'error'](
|
|
329
|
+
'MONGOSH',
|
|
330
|
+
mongoLogId(1_000_000_006),
|
|
331
|
+
context,
|
|
332
|
+
`${mongoshError.name}: ${mongoshError.message}`,
|
|
333
|
+
error
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
if (error.name.includes('Mongosh')) {
|
|
337
|
+
this.analytics.track({
|
|
338
|
+
...getTelemetryUserIdentity(),
|
|
339
|
+
event: 'Error',
|
|
340
|
+
properties: {
|
|
341
|
+
...getTrackingProperties(),
|
|
342
|
+
name: mongoshError.name,
|
|
343
|
+
code: mongoshError.code,
|
|
344
|
+
scope: mongoshError.scope,
|
|
345
|
+
metadata: mongoshError.metadata,
|
|
346
|
+
},
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
onBus('mongosh:write-custom-log', (event: WriteCustomLogEvent) => {
|
|
352
|
+
this.log[event.method](
|
|
353
|
+
'MONGOSH-SCRIPTS',
|
|
354
|
+
mongoLogId(1_000_000_054),
|
|
355
|
+
'custom-log',
|
|
356
|
+
event.message,
|
|
357
|
+
event.attr,
|
|
358
|
+
event.level
|
|
359
|
+
);
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
onBus('mongosh:globalconfig-load', (args: GlobalConfigFileLoadEvent) => {
|
|
363
|
+
this.log.info(
|
|
364
|
+
'MONGOSH',
|
|
365
|
+
mongoLogId(1_000_000_048),
|
|
366
|
+
'config',
|
|
367
|
+
'Loading global configuration file',
|
|
368
|
+
args
|
|
369
|
+
);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
onBus('mongosh:evaluate-input', (args: EvaluateInputEvent) => {
|
|
373
|
+
this.log.info(
|
|
374
|
+
'MONGOSH',
|
|
375
|
+
mongoLogId(1_000_000_007),
|
|
376
|
+
'repl',
|
|
377
|
+
'Evaluating input',
|
|
378
|
+
args
|
|
379
|
+
);
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
onBus('mongosh:use', (args: UseEvent) => {
|
|
383
|
+
this.log.info(
|
|
384
|
+
'MONGOSH',
|
|
385
|
+
mongoLogId(1_000_000_008),
|
|
386
|
+
'shell-api',
|
|
387
|
+
'Used "use" command',
|
|
388
|
+
args
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
this.analytics.track({
|
|
392
|
+
...getTelemetryUserIdentity(),
|
|
393
|
+
event: 'Use',
|
|
394
|
+
properties: {
|
|
395
|
+
...getTrackingProperties(),
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
onBus('mongosh:show', (args: ShowEvent) => {
|
|
401
|
+
this.log.info(
|
|
402
|
+
'MONGOSH',
|
|
403
|
+
mongoLogId(1_000_000_009),
|
|
404
|
+
'shell-api',
|
|
405
|
+
'Used "show" command',
|
|
406
|
+
args
|
|
407
|
+
);
|
|
408
|
+
|
|
409
|
+
this.analytics.track({
|
|
410
|
+
...getTelemetryUserIdentity(),
|
|
411
|
+
event: 'Show',
|
|
412
|
+
properties: {
|
|
413
|
+
...getTrackingProperties(),
|
|
414
|
+
method: args.method,
|
|
415
|
+
},
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
onBus('mongosh:setCtx', (args: ApiEventWithArguments) => {
|
|
420
|
+
this.log.info(
|
|
421
|
+
'MONGOSH',
|
|
422
|
+
mongoLogId(1_000_000_010),
|
|
423
|
+
'shell-api',
|
|
424
|
+
'Initialized context',
|
|
425
|
+
args
|
|
426
|
+
);
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
onBus('mongosh:api-call-with-arguments', (args: ApiEventWithArguments) => {
|
|
430
|
+
// TODO: redactInfo cannot handle circular or otherwise nontrivial input
|
|
431
|
+
let arg;
|
|
432
|
+
try {
|
|
433
|
+
arg = JSON.parse(JSON.stringify(args));
|
|
434
|
+
} catch {
|
|
435
|
+
arg = { _inspected: inspect(args) };
|
|
436
|
+
}
|
|
437
|
+
this.log.info(
|
|
438
|
+
'MONGOSH',
|
|
439
|
+
mongoLogId(1_000_000_011),
|
|
440
|
+
'shell-api',
|
|
441
|
+
'Performed API call',
|
|
442
|
+
redactInfo(arg)
|
|
443
|
+
);
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
onBus('mongosh:api-load-file', (args: ScriptLoadFileEvent) => {
|
|
447
|
+
this.log.info(
|
|
448
|
+
'MONGOSH',
|
|
449
|
+
mongoLogId(1_000_000_012),
|
|
450
|
+
'shell-api',
|
|
451
|
+
'Loading file via load()',
|
|
452
|
+
args
|
|
453
|
+
);
|
|
454
|
+
|
|
455
|
+
this.analytics.track({
|
|
456
|
+
...getTelemetryUserIdentity(),
|
|
457
|
+
event: this.busEventState.hasStartedMongoshRepl
|
|
458
|
+
? 'Script Loaded'
|
|
459
|
+
: 'Script Loaded CLI',
|
|
460
|
+
properties: {
|
|
461
|
+
...getTrackingProperties(),
|
|
462
|
+
nested: args.nested,
|
|
463
|
+
...(this.busEventState.hasStartedMongoshRepl
|
|
464
|
+
? {}
|
|
465
|
+
: { shell: this.busEventState.usesShellOption }),
|
|
466
|
+
},
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
onBus('mongosh:eval-cli-script', () => {
|
|
471
|
+
this.log.info(
|
|
472
|
+
'MONGOSH',
|
|
473
|
+
mongoLogId(1_000_000_013),
|
|
474
|
+
'repl',
|
|
475
|
+
'Evaluating script passed on the command line'
|
|
476
|
+
);
|
|
477
|
+
|
|
478
|
+
this.analytics.track({
|
|
479
|
+
...getTelemetryUserIdentity(),
|
|
480
|
+
event: 'Script Evaluated',
|
|
481
|
+
properties: {
|
|
482
|
+
...getTrackingProperties(),
|
|
483
|
+
shell: this.busEventState.usesShellOption,
|
|
484
|
+
},
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
onBus('mongosh:mongoshrc-load', () => {
|
|
489
|
+
this.log.info(
|
|
490
|
+
'MONGOSH',
|
|
491
|
+
mongoLogId(1_000_000_014),
|
|
492
|
+
'repl',
|
|
493
|
+
'Loading .mongoshrc.js'
|
|
494
|
+
);
|
|
495
|
+
|
|
496
|
+
this.analytics.track({
|
|
497
|
+
...getTelemetryUserIdentity(),
|
|
498
|
+
event: 'Mongoshrc Loaded',
|
|
499
|
+
properties: {
|
|
500
|
+
...getTrackingProperties(),
|
|
501
|
+
},
|
|
502
|
+
});
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
onBus('mongosh:mongoshrc-mongorc-warn', () => {
|
|
506
|
+
this.log.info(
|
|
507
|
+
'MONGOSH',
|
|
508
|
+
mongoLogId(1_000_000_015),
|
|
509
|
+
'repl',
|
|
510
|
+
'Warning about .mongorc.js/.mongoshrc.js mismatch'
|
|
511
|
+
);
|
|
512
|
+
|
|
513
|
+
this.analytics.track({
|
|
514
|
+
...getTelemetryUserIdentity(),
|
|
515
|
+
event: 'Mongorc Warning',
|
|
516
|
+
properties: {
|
|
517
|
+
...getTrackingProperties(),
|
|
518
|
+
},
|
|
519
|
+
});
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
onBus('mongosh:crypt-library-load-skip', (ev: CryptLibrarySkipEvent) => {
|
|
523
|
+
this.log.info(
|
|
524
|
+
'AUTO-ENCRYPTION',
|
|
525
|
+
mongoLogId(1_000_000_050),
|
|
526
|
+
'crypt-library',
|
|
527
|
+
'Skipping shared library candidate',
|
|
528
|
+
ev
|
|
529
|
+
);
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
onBus('mongosh:crypt-library-load-found', (ev: CryptLibraryFoundEvent) => {
|
|
533
|
+
this.log.warn(
|
|
534
|
+
'AUTO-ENCRYPTION',
|
|
535
|
+
mongoLogId(1_000_000_051),
|
|
536
|
+
'crypt-library',
|
|
537
|
+
'Accepted shared library candidate',
|
|
538
|
+
{
|
|
539
|
+
cryptSharedLibPath: ev.cryptSharedLibPath,
|
|
540
|
+
expectedVersion: ev.expectedVersion.versionStr,
|
|
541
|
+
}
|
|
542
|
+
);
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
onBus('mongosh-snippets:loaded', (ev: SnippetsLoadedEvent) => {
|
|
546
|
+
this.log.info(
|
|
547
|
+
'MONGOSH-SNIPPETS',
|
|
548
|
+
mongoLogId(1_000_000_019),
|
|
549
|
+
'snippets',
|
|
550
|
+
'Loaded snippets',
|
|
551
|
+
ev
|
|
552
|
+
);
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
onBus('mongosh-snippets:npm-lookup', (ev: SnippetsNpmLookupEvent) => {
|
|
556
|
+
this.log.info(
|
|
557
|
+
'MONGOSH-SNIPPETS',
|
|
558
|
+
mongoLogId(1_000_000_020),
|
|
559
|
+
'snippets',
|
|
560
|
+
'Performing npm lookup',
|
|
561
|
+
ev
|
|
562
|
+
);
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
onBus('mongosh-snippets:npm-lookup-stopped', () => {
|
|
566
|
+
this.log.info(
|
|
567
|
+
'MONGOSH-SNIPPETS',
|
|
568
|
+
mongoLogId(1_000_000_021),
|
|
569
|
+
'snippets',
|
|
570
|
+
'npm lookup stopped'
|
|
571
|
+
);
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
onBus(
|
|
575
|
+
'mongosh-snippets:npm-download-failed',
|
|
576
|
+
(ev: SnippetsNpmDownloadFailedEvent) => {
|
|
577
|
+
this.log.info(
|
|
578
|
+
'MONGOSH-SNIPPETS',
|
|
579
|
+
mongoLogId(1_000_000_022),
|
|
580
|
+
'snippets',
|
|
581
|
+
'npm download failed',
|
|
582
|
+
ev
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
onBus(
|
|
588
|
+
'mongosh-snippets:npm-download-active',
|
|
589
|
+
(ev: SnippetsNpmDownloadActiveEvent) => {
|
|
590
|
+
this.log.info(
|
|
591
|
+
'MONGOSH-SNIPPETS',
|
|
592
|
+
mongoLogId(1_000_000_023),
|
|
593
|
+
'snippets',
|
|
594
|
+
'npm download active',
|
|
595
|
+
ev
|
|
596
|
+
);
|
|
597
|
+
}
|
|
598
|
+
);
|
|
599
|
+
|
|
600
|
+
onBus('mongosh-snippets:fetch-index', (ev: SnippetsFetchIndexEvent) => {
|
|
601
|
+
this.log.info(
|
|
602
|
+
'MONGOSH-SNIPPETS',
|
|
603
|
+
mongoLogId(1_000_000_024),
|
|
604
|
+
'snippets',
|
|
605
|
+
'Fetching snippet index',
|
|
606
|
+
ev
|
|
607
|
+
);
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
onBus('mongosh-snippets:fetch-cache-invalid', () => {
|
|
611
|
+
this.log.info(
|
|
612
|
+
'MONGOSH-SNIPPETS',
|
|
613
|
+
mongoLogId(1_000_000_025),
|
|
614
|
+
'snippets',
|
|
615
|
+
'Snippet cache invalid'
|
|
616
|
+
);
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
onBus(
|
|
620
|
+
'mongosh-snippets:fetch-index-error',
|
|
621
|
+
(ev: SnippetsFetchIndexErrorEvent) => {
|
|
622
|
+
this.log.info(
|
|
623
|
+
'MONGOSH-SNIPPETS',
|
|
624
|
+
mongoLogId(1_000_000_026),
|
|
625
|
+
'snippets',
|
|
626
|
+
'Fetching snippet index failed',
|
|
627
|
+
ev
|
|
628
|
+
);
|
|
629
|
+
}
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
onBus('mongosh-snippets:fetch-index-done', () => {
|
|
633
|
+
this.log.info(
|
|
634
|
+
'MONGOSH-SNIPPETS',
|
|
635
|
+
mongoLogId(1_000_000_027),
|
|
636
|
+
'snippets',
|
|
637
|
+
'Fetching snippet index done'
|
|
638
|
+
);
|
|
639
|
+
});
|
|
640
|
+
onBus(
|
|
641
|
+
'mongosh-snippets:package-json-edit-error',
|
|
642
|
+
(ev: SnippetsErrorEvent) => {
|
|
643
|
+
this.log.info(
|
|
644
|
+
'MONGOSH-SNIPPETS',
|
|
645
|
+
mongoLogId(1_000_000_028),
|
|
646
|
+
'snippets',
|
|
647
|
+
'Modifying snippets package.json failed',
|
|
648
|
+
ev
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
);
|
|
652
|
+
|
|
653
|
+
onBus('mongosh-snippets:spawn-child', (ev: SnippetsRunNpmEvent) => {
|
|
654
|
+
this.log.info(
|
|
655
|
+
'MONGOSH-SNIPPETS',
|
|
656
|
+
mongoLogId(1_000_000_029),
|
|
657
|
+
'snippets',
|
|
658
|
+
'Spawning helper',
|
|
659
|
+
ev
|
|
660
|
+
);
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
onBus('mongosh-snippets:load-snippet', (ev: SnippetsLoadSnippetEvent) => {
|
|
664
|
+
this.log.info(
|
|
665
|
+
'MONGOSH-SNIPPETS',
|
|
666
|
+
mongoLogId(1_000_000_030),
|
|
667
|
+
'snippets',
|
|
668
|
+
'Loading snippet',
|
|
669
|
+
ev
|
|
670
|
+
);
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
onBus('mongosh-snippets:snippet-command', (ev: SnippetsCommandEvent) => {
|
|
674
|
+
this.log.info(
|
|
675
|
+
'MONGOSH-SNIPPETS',
|
|
676
|
+
mongoLogId(1_000_000_031),
|
|
677
|
+
'snippets',
|
|
678
|
+
'Running snippet command',
|
|
679
|
+
ev
|
|
680
|
+
);
|
|
681
|
+
|
|
682
|
+
if (ev.args[0] === 'install') {
|
|
683
|
+
this.analytics.track({
|
|
684
|
+
...getTelemetryUserIdentity(),
|
|
685
|
+
event: 'Snippet Install',
|
|
686
|
+
properties: {
|
|
687
|
+
...getTrackingProperties(),
|
|
688
|
+
},
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
onBus(
|
|
694
|
+
'mongosh-snippets:transform-error',
|
|
695
|
+
(ev: SnippetsTransformErrorEvent) => {
|
|
696
|
+
this.log.info(
|
|
697
|
+
'MONGOSH-SNIPPETS',
|
|
698
|
+
mongoLogId(1_000_000_032),
|
|
699
|
+
'snippets',
|
|
700
|
+
'Rewrote error message',
|
|
701
|
+
ev
|
|
702
|
+
);
|
|
703
|
+
}
|
|
704
|
+
);
|
|
705
|
+
|
|
706
|
+
onBus('mongosh:api-call', (ev: ApiEvent) => {
|
|
707
|
+
// Only track if we have previously seen a mongosh:evaluate-started call
|
|
708
|
+
if (!this.busEventState.apiCallTracking.isEnabled) return;
|
|
709
|
+
const { apiCalls, deprecatedApiCalls } =
|
|
710
|
+
this.busEventState.apiCallTracking;
|
|
711
|
+
if (ev.deprecated) {
|
|
712
|
+
deprecatedApiCalls.add({ class: ev.class, method: ev.method });
|
|
713
|
+
}
|
|
714
|
+
if (ev.callDepth === 0 && ev.isAsync) {
|
|
715
|
+
apiCalls.add({ class: ev.class, method: ev.method });
|
|
716
|
+
}
|
|
717
|
+
});
|
|
718
|
+
onBus('mongosh:evaluate-started', () => {
|
|
719
|
+
const { apiCalls, deprecatedApiCalls } =
|
|
720
|
+
this.busEventState.apiCallTracking;
|
|
721
|
+
this.busEventState.apiCallTracking.isEnabled = true;
|
|
722
|
+
// Clear API calls before evaluation starts. This is important because
|
|
723
|
+
// some API calls are also emitted by mongosh CLI repl internals,
|
|
724
|
+
// but we only care about those emitted from user code (i.e. during
|
|
725
|
+
// evaluation).
|
|
726
|
+
deprecatedApiCalls.clear();
|
|
727
|
+
apiCalls.clear();
|
|
728
|
+
});
|
|
729
|
+
onBus('mongosh:evaluate-finished', () => {
|
|
730
|
+
const { apiCalls, deprecatedApiCalls } =
|
|
731
|
+
this.busEventState.apiCallTracking;
|
|
732
|
+
for (const [entry] of deprecatedApiCalls) {
|
|
733
|
+
this.log.warn(
|
|
734
|
+
'MONGOSH',
|
|
735
|
+
mongoLogId(1_000_000_033),
|
|
736
|
+
'shell-api',
|
|
737
|
+
'Deprecated API call',
|
|
738
|
+
entry
|
|
739
|
+
);
|
|
740
|
+
|
|
741
|
+
this.analytics.track({
|
|
742
|
+
...getTelemetryUserIdentity(),
|
|
743
|
+
event: 'Deprecated Method',
|
|
744
|
+
properties: {
|
|
745
|
+
...getTrackingProperties(),
|
|
746
|
+
...entry,
|
|
747
|
+
},
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
for (const [entry, count] of apiCalls) {
|
|
751
|
+
this.analytics.track({
|
|
752
|
+
...getTelemetryUserIdentity(),
|
|
753
|
+
event: 'API Call',
|
|
754
|
+
properties: {
|
|
755
|
+
...getTrackingProperties(),
|
|
756
|
+
...entry,
|
|
757
|
+
count,
|
|
758
|
+
},
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
deprecatedApiCalls.clear();
|
|
762
|
+
apiCalls.clear();
|
|
763
|
+
this.busEventState.apiCallTracking.isEnabled = false;
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
// Log ids 1_000_000_034 through 1_000_000_042 are reserved for the
|
|
767
|
+
// devtools-connect package which was split out from mongosh.
|
|
768
|
+
// 'mongodb' is not supported in startup snapshots yet.
|
|
769
|
+
|
|
770
|
+
onBus('mongosh-sp:reset-connection-options', () => {
|
|
771
|
+
this.log.info(
|
|
772
|
+
'MONGOSH-SP',
|
|
773
|
+
mongoLogId(1_000_000_040),
|
|
774
|
+
'connect',
|
|
775
|
+
'Reconnect because of changed connection options'
|
|
776
|
+
);
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
onBus(
|
|
780
|
+
'mongosh-editor:run-edit-command',
|
|
781
|
+
(ev: EditorRunEditCommandEvent) => {
|
|
782
|
+
this.log.error(
|
|
783
|
+
'MONGOSH-EDITOR',
|
|
784
|
+
mongoLogId(1_000_000_047),
|
|
785
|
+
'editor',
|
|
786
|
+
'Open external editor',
|
|
787
|
+
redactInfo(ev)
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
);
|
|
791
|
+
|
|
792
|
+
onBus(
|
|
793
|
+
'mongosh-editor:read-vscode-extensions-done',
|
|
794
|
+
(ev: EditorReadVscodeExtensionsDoneEvent) => {
|
|
795
|
+
this.log.error(
|
|
796
|
+
'MONGOSH-EDITOR',
|
|
797
|
+
mongoLogId(1_000_000_043),
|
|
798
|
+
'editor',
|
|
799
|
+
'Reading vscode extensions from file system succeeded',
|
|
800
|
+
ev
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
);
|
|
804
|
+
|
|
805
|
+
onBus(
|
|
806
|
+
'mongosh-editor:read-vscode-extensions-failed',
|
|
807
|
+
(ev: EditorReadVscodeExtensionsFailedEvent) => {
|
|
808
|
+
this.log.error(
|
|
809
|
+
'MONGOSH-EDITOR',
|
|
810
|
+
mongoLogId(1_000_000_044),
|
|
811
|
+
'editor',
|
|
812
|
+
'Reading vscode extensions from file system failed',
|
|
813
|
+
{
|
|
814
|
+
...ev,
|
|
815
|
+
error: ev.error.message,
|
|
816
|
+
}
|
|
817
|
+
);
|
|
818
|
+
}
|
|
819
|
+
);
|
|
820
|
+
|
|
821
|
+
onBus(
|
|
822
|
+
'mongosh:fetching-update-metadata',
|
|
823
|
+
(ev: FetchingUpdateMetadataEvent) => {
|
|
824
|
+
this.log.info(
|
|
825
|
+
'MONGOSH',
|
|
826
|
+
mongoLogId(1_000_000_052),
|
|
827
|
+
'startup',
|
|
828
|
+
'Fetching update metadata',
|
|
829
|
+
{
|
|
830
|
+
...ev,
|
|
831
|
+
}
|
|
832
|
+
);
|
|
833
|
+
}
|
|
834
|
+
);
|
|
835
|
+
|
|
836
|
+
onBus(
|
|
837
|
+
'mongosh:fetching-update-metadata-complete',
|
|
838
|
+
(ev: FetchingUpdateMetadataCompleteEvent) => {
|
|
839
|
+
this.log.info(
|
|
840
|
+
'MONGOSH',
|
|
841
|
+
mongoLogId(1_000_000_053),
|
|
842
|
+
'startup',
|
|
843
|
+
'Fetching update metadata complete',
|
|
844
|
+
{
|
|
845
|
+
...ev,
|
|
846
|
+
}
|
|
847
|
+
);
|
|
848
|
+
}
|
|
849
|
+
);
|
|
850
|
+
|
|
851
|
+
hookLogger(
|
|
852
|
+
this.bus,
|
|
853
|
+
{
|
|
854
|
+
info: (...args: Parameters<typeof this.log.info>) => {
|
|
855
|
+
return this.log.info(...args);
|
|
856
|
+
},
|
|
857
|
+
warn: (...args: Parameters<typeof this.log.warn>) => {
|
|
858
|
+
return this.log.warn(...args);
|
|
859
|
+
},
|
|
860
|
+
error: (...args: Parameters<typeof this.log.error>) => {
|
|
861
|
+
return this.log.error(...args);
|
|
862
|
+
},
|
|
863
|
+
mongoLogId: (...args: Parameters<typeof this.log.mongoLogId>) => {
|
|
864
|
+
return this.log.mongoLogId(...args);
|
|
865
|
+
},
|
|
866
|
+
},
|
|
867
|
+
'mongosh',
|
|
868
|
+
(uri) => redactURICredentials(uri)
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
}
|