Skip to content

Commit 37736d0

Browse files
authored
feat(compass-logging): add initial log infrastructure COMPASS-5031 (#2442)
Set up main-process logging, add a `@mongodb-js/compass-logging` package and use it to log basic information about connection attempts. Example result: ```js $ zcat ~/.mongodb/compass/6132154a13a16a1815e33f5a_log.gz {"t":{"$date":"2021-09-03T12:30:02.381Z"},"s":"I","c":"COMPASS-MAIN","id":1001000001,"ctx":"logging","msg":"Starting logging","attr":{"version":"0.0.0-dev.0","platform":"linux","arch":"x64"}} {"t":{"$date":"2021-09-03T12:30:09.134Z"},"s":"I","c":"COMPASS-CONNECT-UI","id":1001000004,"ctx":"Connection UI","msg":"Initiating connection attempt"} {"t":{"$date":"2021-09-03T12:30:09.136Z"},"s":"I","c":"COMPASS-DS-CONNECT","id":1001000009,"ctx":"Connect","msg":"Initiating connection","attr":{"url":"mongodb+srv://<credentials>@cluster0.ucdwm.mongodb.net/admin?authSource=admin&replicaSet=atlas-jt9dqp-shard-0&readPreference=primary&appname=MongoDB+Compass+Dev&ssl=true","options":{"tlsAllowInvalidHostnames":false,"sslValidate":true,"readPreference":"primary"}}} {"t":{"$date":"2021-09-03T12:30:09.137Z"},"s":"I","c":"COMPASS-DS-CONNECT","id":1001000010,"ctx":"Connect","msg":"Resolved SRV record","attr":{"from":"mongodb+srv://<credentials>@cluster0.ucdwm.mongodb.net/admin?authSource=admin&replicaSet=atlas-jt9dqp-shard-0&readPreference=primary&appname=MongoDB+Compass+Dev&ssl=true","to":"mongodb://<credentials>@cluster0-shard-00-00.ucdwm.mongodb.net,cluster0-shard-00-01.ucdwm.mongodb.net,cluster0-shard-00-02.ucdwm.mongodb.net/admin?authSource=admin&replicaSet=atlas-jt9dqp-shard-0&readPreference=primary&appname=MongoDB+Compass+Dev&ssl=true"}} {"t":{"$date":"2021-09-03T12:30:10.388Z"},"s":"I","c":"COMPASS-DS-CONNECT","id":1001000012,"ctx":"Connect","msg":"Connection established","attr":{"url":"mongodb+srv://<credentials>@cluster0.ucdwm.mongodb.net/admin?authSource=admin&replicaSet=atlas-jt9dqp-shard-0&readPreference=primary&appname=MongoDB+Compass+Dev&ssl=true"}} {"t":{"$date":"2021-09-03T12:30:17.630Z"},"s":"I","c":"COMPASS-MAIN","id":1001000003,"ctx":"app","msg":"Closing application"} ```
1 parent 1e3e69c commit 37736d0

22 files changed

+939
-11
lines changed

package-lock.json

Lines changed: 644 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/compass-connect/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@
147147
"@leafygreen-ui/leafygreen-provider": "^2.1.2",
148148
"@leafygreen-ui/toggle": "^7.0.4",
149149
"@leafygreen-ui/typography": "^8.0.2",
150+
"@mongodb-js/compass-logging": "^0.1.0",
150151
"lodash": "^4.17.15"
151152
},
152153
"homepage": "https://github.com/mongodb-js/compass",

packages/compass-connect/src/modules/connection-attempt.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import createDebug from 'debug';
2+
import createLogger from '@mongodb-js/compass-logging';
23
import { promisify } from 'util';
34

5+
const { log, mongoLogId } = createLogger('COMPASS-CONNECT-UI');
46
const debug = createDebug('mongodb-compass:compass-connect:connection-attempt');
57

68
function isConnectionAttemptTerminatedError(err) {
@@ -15,6 +17,8 @@ class ConnectionAttempt {
1517
}
1618

1719
connect(dataService) {
20+
log.info(mongoLogId(1001000004), 'Connection UI', 'Initiating connection attempt');
21+
1822
this._dataService = dataService;
1923

2024
return Promise.race([
@@ -24,6 +28,8 @@ class ConnectionAttempt {
2428
}
2529

2630
cancelConnectionAttempt() {
31+
log.info(mongoLogId(1001000005), 'Connection UI', 'Canceling connection attempt');
32+
2733
this._cancelConnectionAttempt();
2834
this._close();
2935
}

packages/compass-logging/.depcheckrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
ignores:
2+
- "@mongodb-js/prettier-config-compass"
3+
- "@mongodb-js/tsconfig-compass"
4+
- "@types/chai"
5+
- "@types/sinon-chai"
6+
- "sinon"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.nyc-output
2+
dist

packages/compass-logging/.eslintrc.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module.exports = {
2+
root: true,
3+
extends: ['@mongodb-js/eslint-config-compass'],
4+
parserOptions: {
5+
tsconfigRootDir: __dirname,
6+
project: ['./tsconfig-lint.json'],
7+
},
8+
};

packages/compass-logging/.mocharc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('@mongodb-js/mocha-config-compass');
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.nyc-output
2+
dist
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"@mongodb-js/prettier-config-compass"

packages/compass-logging/package.json

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
{
2+
"name": "@mongodb-js/compass-logging",
3+
"description": "Shared helpers for logging in Compass packages",
4+
"author": {
5+
"name": "MongoDB Inc",
6+
"email": "[email protected]"
7+
},
8+
"publishConfig": {
9+
"access": "public"
10+
},
11+
"bugs": {
12+
"url": "https://jira.mongodb.org/projects/COMPASS/issues",
13+
"email": "[email protected]"
14+
},
15+
"homepage": "https://github.com/mongodb-js/compass",
16+
"version": "0.1.0",
17+
"repository": {
18+
"type": "git",
19+
"url": "https://github.com/mongodb-js/compass.git"
20+
},
21+
"files": [
22+
"dist"
23+
],
24+
"license": "SSPL",
25+
"peerDependencies": {
26+
"hadron-ipc": "*"
27+
},
28+
"main": "dist/index.js",
29+
"types": "./dist/index.d.ts",
30+
"scripts": {
31+
"bootstrap": "npm run compile",
32+
"prepublishOnly": "npm run compile",
33+
"compile": "tsc -p tsconfig.json",
34+
"eslint": "eslint",
35+
"prettier": "prettier",
36+
"lint": "npm run eslint . && npm run prettier -- --check .",
37+
"depcheck": "depcheck",
38+
"check": "npm run lint && npm run depcheck",
39+
"check-ci": "npm run check",
40+
"test": "mocha",
41+
"test-cov": "nyc -x \"**/*.spec.*\" npm run test",
42+
"test-watch": "npm run test -- --watch",
43+
"test-ci": "npm run test-cov",
44+
"reformat": "npm run prettier -- --write ."
45+
},
46+
"dependencies": {
47+
"mongodb-log-writer": "^1.0.2"
48+
},
49+
"devDependencies": {
50+
"@mongodb-js/eslint-config-compass": "^0.2.0",
51+
"@mongodb-js/mocha-config-compass": "^0.3.0",
52+
"@mongodb-js/prettier-config-compass": "^0.2.0",
53+
"@mongodb-js/tsconfig-compass": "^0.2.0",
54+
"@types/chai": "^4.2.21",
55+
"@types/mocha": "^9.0.0",
56+
"@types/sinon-chai": "^3.2.5",
57+
"chai": "^4.3.4",
58+
"depcheck": "^1.4.1",
59+
"eslint": "^7.25.0",
60+
"hadron-ipc": "^2.4.0",
61+
"mocha": "^8.4.0",
62+
"nyc": "^15.1.0",
63+
"prettier": "2.3.2",
64+
"sinon": "^9.2.3",
65+
"typescript": "^4.3.5"
66+
}
67+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import createLogger from './';
2+
import { once } from 'events';
3+
import { expect } from 'chai';
4+
5+
describe('createLogger', function () {
6+
it('creates a logger that forwards log lines as events', async function () {
7+
const { log, mongoLogId } = createLogger('COMPONENT');
8+
const logevent = once(process, 'compass:log');
9+
10+
log.info(mongoLogId(12345), 'ctx', 'message', { attr: 42 });
11+
const [{ line }] = await logevent;
12+
const parsed = JSON.parse(line);
13+
expect(parsed.s).to.equal('I');
14+
expect(parsed.c).to.equal('COMPONENT');
15+
expect(parsed.id).to.equal(12345);
16+
expect(parsed.ctx).to.equal('ctx');
17+
expect(parsed.msg).to.equal('message');
18+
expect(parsed.attr).to.deep.equal({ attr: 42 });
19+
});
20+
});

packages/compass-logging/src/index.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { MongoLogWriter, mongoLogId } from 'mongodb-log-writer';
2+
import { Writable } from 'stream';
3+
import ipc from 'hadron-ipc';
4+
5+
function createLogger(component: string): {
6+
log: ReturnType<MongoLogWriter['bindComponent']>;
7+
mongoLogId: typeof mongoLogId;
8+
} {
9+
const target = new Writable({
10+
decodeStrings: false,
11+
write(line: string, encoding: unknown, callback: () => void) {
12+
// ipc.call is undefined outside of Electron
13+
ipc.call?.('compass:log', { line });
14+
(process as any).emit('compass:log', { line });
15+
callback();
16+
},
17+
});
18+
const writer = new MongoLogWriter('', null, target);
19+
return {
20+
log: writer.bindComponent(component),
21+
mongoLogId,
22+
};
23+
}
24+
25+
export = createLogger;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"include": ["**/*"],
4+
"exclude": ["node_modules", "dist"]
5+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "@mongodb-js/tsconfig-compass/tsconfig.common.json",
3+
"compilerOptions": {
4+
"outDir": "dist"
5+
},
6+
"include": ["src/**/*"],
7+
"exclude": ["./src/**/*.spec.*"]
8+
}

packages/compass/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@
361361
"mongodb-instance-model": "^11.12.0",
362362
"mongodb-js-metrics": "^7.4.0",
363363
"mongodb-language-model": "^2.3.0",
364+
"mongodb-log-writer": "^1.0.2",
364365
"mongodb-ns": "^2.2.0",
365366
"mongodb-query-parser": "^2.4.3",
366367
"mongodb-query-util": "^0.2.1",

packages/compass/src/main/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ if (!process.env.NODE_ENV) {
55
const pkg = require('../../package.json');
66

77
require('../setup-hadron-distribution');
8+
const setupLogging = require('./logging');
89

910
/**
1011
* Check if the distribution is defined, if not, we need to override
@@ -72,4 +73,5 @@ var ModuleCache = require('hadron-module-cache');
7273
ModuleCache.register(resourcePath);
7374
ModuleCache.add(resourcePath);
7475

76+
setupLogging(app);
7577
require('./application').main();

packages/compass/src/main/logging.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const os = require('os');
2+
const fs = require('fs').promises;
3+
const path = require('path');
4+
const ipc = require('hadron-ipc');
5+
const { mongoLogId, MongoLogManager } = require('mongodb-log-writer');
6+
const { version } = require('../../package.json');
7+
const debug = require('debug')('mongodb-compass:main:logging');
8+
9+
module.exports = async function setupLogging(app) {
10+
try {
11+
const directory = process.platform === 'win32' ?
12+
path.join(
13+
process.env.LOCALAPPDATA || process.env.APPDATA || os.homedir(),
14+
'mongodb',
15+
'compass') :
16+
path.join(os.homedir(), '.mongodb', 'compass');
17+
18+
const manager = new MongoLogManager({
19+
directory,
20+
gzip: true,
21+
alwaysFlush: true,
22+
retentionDays: 30,
23+
onerror: (err, filepath) => debug('Failed to access path', filepath, err),
24+
onwarn: (err, filepath) => debug('Failed to access path', filepath, err)
25+
});
26+
27+
await fs.mkdir(directory, { recursive: true });
28+
const writer = await manager.createLogWriter();
29+
30+
writer.info('COMPASS-MAIN', mongoLogId(1_001_000_001), 'logging', 'Starting logging', {
31+
version,
32+
platform: os.platform(),
33+
arch: os.arch()
34+
});
35+
36+
ipc.on('compass:error:fatal', (evt, meta) => {
37+
writer.fatal('COMPASS-MAIN', mongoLogId(1_001_000_002), 'app', 'Uncaught exception: ' + meta.message, meta);
38+
});
39+
40+
process.prependListener('uncaughtException', (exception) => {
41+
writer.fatal('COMPASS-MAIN', mongoLogId(1_001_000_002), 'app', 'Uncaught exception: ' + String(exception), {
42+
message: exception && exception.message,
43+
stack: exception && exception.stack
44+
});
45+
});
46+
47+
app.on('before-quit', function() {
48+
writer.info('COMPASS-MAIN', mongoLogId(1_001_000_003), 'app', 'Closing application');
49+
writer.end();
50+
});
51+
52+
process.on('compass:log', (meta) => {
53+
writer.target.write(meta.line);
54+
});
55+
56+
ipc.respondTo('compass:log', (evt, meta) => {
57+
process.emit('compass:log', meta);
58+
});
59+
60+
await manager.cleanupOldLogfiles();
61+
} catch (err) {
62+
debug('Failure setting up logging!', err);
63+
}
64+
};

packages/compass/src/main/window-manager.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ var createWindow = (module.exports.create = function(opts) {
196196
ipc.broadcast('compass:error:fatal', meta);
197197
});
198198

199+
ipc.respondTo('compass:log', (evt, meta) => {
200+
ipc.broadcast('compass:log', meta);
201+
});
202+
199203
/**
200204
* `closed` is always fired if the `BrowserWindow`
201205
* is explicity `destroy()`ed when `_window` is ready

packages/data-service/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
"mongodb-connection-model": "*"
5757
},
5858
"dependencies": {
59+
"@mongodb-js/compass-logging": "^0.1.0",
5960
"@mongodb-js/ssh-tunnel": "^1.2.0",
6061
"async": "^3.2.0",
6162
"debug": "^4.2.0",
@@ -66,6 +67,7 @@
6667
"mongodb-js-errors": "^0.5.0",
6768
"mongodb-ns": "^2.2.0",
6869
"mongodb-security": "^1.3.0",
70+
"resolve-mongodb-srv": "^1.1.0",
6971
"uuid": "^8.3.2"
7072
},
7173
"devDependencies": {

0 commit comments

Comments
 (0)