Skip to content

WIP feat!(mongodb-log-writer): add ability to disable logging MONGOSH-1988 #500

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions packages/devtools-connect/src/log-hook.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { hookLogger } from '../';
import type { ConnectLogEmitter } from '../';
import { hookLogger } from './';
import type { ConnectLogEmitter } from './';
import { EventEmitter } from 'events';
import { MongoLogWriter } from 'mongodb-log-writer';
import { redactConnectionString } from 'mongodb-connection-string-url';
Expand All @@ -9,12 +9,12 @@ import { expect } from 'chai';
describe('Logging setup', function () {
it('logs events', async function () {
const pt = new PassThrough();
const log = new MongoLogWriter(
'logid',
null,
pt,
() => new Date('2021-12-16T14:35:08.763Z')
);
const log = new MongoLogWriter({
logId: 'logid',
logFilePath: null,
target: pt,
now: () => new Date('2021-12-16T14:35:08.763Z'),
});
const emitter: ConnectLogEmitter = new EventEmitter();

hookLogger(emitter, log, 'prefix', redactConnectionString);
Expand Down
1 change: 1 addition & 0 deletions packages/mongodb-log-writer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"lint": "eslint src/**/*.ts",
"test-only": "nyc mocha --colors -r ts-node/register src/**.spec.ts",
"test": "npm run lint && npm run build && npm run test-only",
"test-ci": "npm run test",
"build": "npm run compile-ts && gen-esm-wrapper . ./.esm-wrapper.mjs",
"prepack": "npm run build",
"compile-ts": "tsc -p tsconfig.json"
Expand Down
16 changes: 16 additions & 0 deletions packages/mongodb-log-writer/src/mongo-log-manager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,20 @@ describe('MongoLogManager', function () {
writer.end();
await once(writer, 'finish');
});

it('can create a disabled writer', async function () {
const manager = new MongoLogManager({
directory,
retentionDays,
onwarn,
onerror,
gzip: true,
});
const writer = await manager.createLogWriter({ isDisabled: true });

expect(writer.isDisabled).is.true;

writer.end();
await once(writer, 'finish');
});
});
25 changes: 19 additions & 6 deletions packages/mongodb-log-writer/src/mongo-log-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import { once } from 'events';
import { createWriteStream, promises as fs } from 'fs';
import { createGzip, constants as zlibConstants } from 'zlib';
import { Heap } from 'heap-js';
import type { MongoLogWriterOptions } from './mongo-log-writer';
import { MongoLogWriter } from './mongo-log-writer';
import { Writable } from 'stream';

/** Options used by MongoLogManager instances. */
interface MongoLogOptions {
export interface MongoLogManagerOptions {
/** A base directory in which log files are stored. */
directory: string;
/** Whether to write files as .gz files or not. */
Expand All @@ -29,9 +30,9 @@ interface MongoLogOptions {
* naming convention `${logId}_log`.
*/
export class MongoLogManager {
_options: MongoLogOptions;
_options: MongoLogManagerOptions;

constructor(options: MongoLogOptions) {
constructor(options: MongoLogManagerOptions) {
this._options = options;
}

Expand Down Expand Up @@ -97,7 +98,9 @@ export class MongoLogManager {
}

/** Create a MongoLogWriter stream for a new log file. */
async createLogWriter(): Promise<MongoLogWriter> {
async createLogWriter(
writerOptions: Pick<MongoLogWriterOptions, 'isDisabled'> = {}
): Promise<MongoLogWriter> {
const logId = new ObjectId().toString();
const doGzip = !!this._options.gzip;
const logFilePath = path.join(
Expand Down Expand Up @@ -132,10 +135,20 @@ export class MongoLogManager {
},
});
originalTarget = stream;
logWriter = new MongoLogWriter(logId, null, stream);
logWriter = new MongoLogWriter({
...writerOptions,
logId,
logFilePath: null,
target: stream,
});
}
if (!logWriter) {
logWriter = new MongoLogWriter(logId, logFilePath, stream);
logWriter = new MongoLogWriter({
...writerOptions,
logId,
logFilePath,
target: stream,
});
}

// We use 'log-finish' to give consumers an event that they can
Expand Down
131 changes: 126 additions & 5 deletions packages/mongodb-log-writer/src/mongo-log-writer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,123 @@ import type { MongoLogEntry } from '.';
import { MongoLogWriter, mongoLogId } from '.';
import { EJSON } from 'bson';
import stream from 'stream';
import { once } from 'events';
import { inspect } from 'util';
import chai, { expect } from 'chai';
import sinonChai from 'sinon-chai';
import sinon from 'sinon';
chai.use(sinonChai);

describe('MongoLogWriter', function () {
const now = new Date(1628591965386);

describe('enabling and disabling', function () {
let writer: MongoLogWriter;
let target: stream.PassThrough;
let writeSpy: sinon.SinonSpy;

const SEVERITIES_COUNT = 5;

function logAllSeverities(writer: MongoLogWriter) {
writer.info('component', mongoLogId(12345), 'context', 'message', {});
writer.warn('component', mongoLogId(12345), 'context', 'message', {});
writer.error('component', mongoLogId(12345), 'context', 'message', {});
writer.debug('component', mongoLogId(12345), 'context', 'message', {});
writer.fatal('component', mongoLogId(12345), 'context', 'message', {});
}

beforeEach(function () {
target = new stream.PassThrough().setEncoding('utf8');
writer = new MongoLogWriter({
logId: 'logid',
logFilePath: null,
target,
now: () => now,
});
writeSpy = sinon.spy(writer, 'write');
});

afterEach(async function () {
writer.end();
await once(writer, 'finish');
sinon.restore();
});

it('is enabled by default', async function () {
expect(writer.isDisabled).to.equal(false);

writer.info('component', mongoLogId(12345), 'context', 'message', {});

await writer.flush();

expect(target.read()).is.not.null;
expect(writeSpy).callCount(1);
});

it('can be disabled on initialization', async function () {
const disabledWriter = new MongoLogWriter({
logId: 'logid',
logFilePath: null,
target,
now: () => now,
isDisabled: true,
});

expect(disabledWriter.isDisabled).to.equal(true);
logAllSeverities(disabledWriter);

await disabledWriter.flush();

expect(target.read()).is.null;
expect(writeSpy).not.called;
});

it('can run disable() to disable logging across all severities', function () {
expect(writer.isDisabled).to.equal(false);

logAllSeverities(writer);

expect(writeSpy).callCount(SEVERITIES_COUNT);

writer.disable();

expect(writer.isDisabled).to.equal(true);

logAllSeverities(writer);

expect(writeSpy).callCount(SEVERITIES_COUNT);
});

it('can run enable() after being disabled', async function () {
expect(writer.isDisabled).to.equal(false);

writer.disable();
expect(writer.isDisabled).to.equal(true);

logAllSeverities(writer);

expect(writeSpy).not.called;

writer.enable();
expect(writer.isDisabled).to.equal(false);

logAllSeverities(writer);

await writer.flush();

expect(target.read()).not.null;
expect(writeSpy).callCount(SEVERITIES_COUNT);
});
});

it('allows writing log messages to a stream', async function () {
const now = new Date(1628591965386);
const target = new stream.PassThrough().setEncoding('utf8');
const writer = new MongoLogWriter('logid', null, target, () => now);
const writer = new MongoLogWriter({
logId: 'logid',
logFilePath: null,
target,
now: () => now,
});
const logEvents: MongoLogEntry[] = [];
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
writer.on('log', (entry) => logEvents.push(entry));
Expand Down Expand Up @@ -111,7 +218,12 @@ describe('MongoLogWriter', function () {
it('can log error object as data as-is', async function () {
const now = new Date(1628591965386);
const target = new stream.PassThrough().setEncoding('utf8');
const writer = new MongoLogWriter('logid', null, target, () => now);
const writer = new MongoLogWriter({
logId: 'logid',
logFilePath: null,
target,
now: () => now,
});
writer.error(
'component',
mongoLogId(12345),
Expand All @@ -137,7 +249,12 @@ describe('MongoLogWriter', function () {
it('can log non-trivial data', async function () {
const now = new Date(1628591965386);
const target = new stream.PassThrough().setEncoding('utf8');
const writer = new MongoLogWriter('logid', null, target, () => now);
const writer = new MongoLogWriter({
logId: 'logid',
logFilePath: null,
target,
now: () => now,
});

const cyclic: any = {};
cyclic.cyclic = cyclic;
Expand All @@ -160,7 +277,11 @@ describe('MongoLogWriter', function () {
const errors: Error[] = [];
function tryWrite(input: any) {
const target = new stream.PassThrough().setEncoding('utf8');
const writer = new MongoLogWriter('logid', null, target);
const writer = new MongoLogWriter({
logId: 'logid',
logFilePath: null,
target,
});
writer.on('error', (err) => errors.push(err));
writer.write(input);
}
Expand Down
Loading
Loading