Skip to content

Commit 2eb3d4a

Browse files
committed
feat(mongodb-log-writer): add ability to specify a prefix for log files
This is needed for mongosh to use a `mongosh_` prefix for custom log directories.
1 parent 821875d commit 2eb3d4a

File tree

2 files changed

+79
-7
lines changed

2 files changed

+79
-7
lines changed

packages/mongodb-log-writer/src/mongo-log-manager.spec.ts

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,19 @@ describe('MongoLogManager', function () {
6161
expect(log[0].t.$date).to.be.a('string');
6262
});
6363

64+
it('can take a custom prefix for log files', async function () {
65+
const manager = new MongoLogManager({
66+
directory,
67+
retentionDays,
68+
prefix: 'custom_',
69+
onwarn,
70+
onerror,
71+
});
72+
73+
const writer = await manager.createLogWriter();
74+
expect(writer.logFilePath as string).to.match(/custom_/);
75+
});
76+
6477
it('cleans up old log files when requested', async function () {
6578
retentionDays = 0.000001; // 86.4 ms
6679
const manager = new MongoLogManager({
@@ -131,8 +144,8 @@ describe('MongoLogManager', function () {
131144
directory,
132145
retentionDays,
133146
retentionGB: 3,
134-
onwarn,
135147
onerror,
148+
onwarn,
136149
});
137150

138151
const offset = Math.floor(Date.now() / 1000);
@@ -178,7 +191,57 @@ describe('MongoLogManager', function () {
178191
expect(leftoverFiles).deep.equals([faultyFile, ...validFiles.slice(3)]);
179192
});
180193

181-
it('cleans up least recent log files when over a storage limit', async function () {
194+
it('cleanup only applies to files with the prefix, if set', async function () {
195+
const manager = new MongoLogManager({
196+
directory,
197+
retentionDays,
198+
maxLogFileCount: 7,
199+
prefix: 'custom_',
200+
onwarn,
201+
onerror,
202+
});
203+
204+
const paths: string[] = [];
205+
const offset = Math.floor(Date.now() / 1000);
206+
207+
// Create 4 files: 2 with a different prefix and 2 with no prefix
208+
for (let i = 1; i >= 0; i--) {
209+
const withoutPrefix = path.join(
210+
directory,
211+
ObjectId.createFromTime(offset - i).toHexString() + '_log'
212+
);
213+
await fs.writeFile(withoutPrefix, '');
214+
paths.push(withoutPrefix);
215+
216+
const withDifferentPrefix = path.join(
217+
directory,
218+
'different_' +
219+
ObjectId.createFromTime(offset - i).toHexString() +
220+
'_log'
221+
);
222+
await fs.writeFile(withDifferentPrefix, '');
223+
paths.push(withDifferentPrefix);
224+
}
225+
226+
// Create 10 files with the prefix
227+
for (let i = 9; i >= 0; i--) {
228+
const filename = path.join(
229+
directory,
230+
`custom_${ObjectId.createFromTime(offset - i).toHexString()}_log`
231+
);
232+
await fs.writeFile(filename, '');
233+
paths.push(filename);
234+
}
235+
236+
expect(await getFilesState(paths)).to.equal('11111111111111');
237+
await manager.cleanupOldLogFiles();
238+
239+
// The first 4 files without the right prefix should still be there.
240+
// The next (oldest) 3 files with the prefix should be deleted.
241+
expect(await getFilesState(paths)).to.equal('11110001111111');
242+
});
243+
244+
it('cleans up least recent log files when requested with a storage limit', async function () {
182245
const manager = new MongoLogManager({
183246
directory,
184247
retentionDays,

packages/mongodb-log-writer/src/mongo-log-manager.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ interface MongoLogOptions {
1919
maxLogFileCount?: number;
2020
/** The maximal size of log files which are kept. */
2121
retentionGB?: number;
22+
/** Prefix to use for the log files */
23+
prefix?: string;
24+
/** A handler for warnings related to a specific filesystem path. */
25+
onerror: (err: Error, path: string) => unknown | Promise<void>;
2226
/** A handler for errors related to a specific filesystem path. */
2327
onerror: (err: Error, path: string) => unknown | Promise<void>;
24-
/** A handler for warnings related to a specific filesystem path. */
25-
onwarn: (err: Error, path: string) => unknown | Promise<void>;
2628
}
2729

2830
/**
@@ -48,6 +50,10 @@ export class MongoLogManager {
4850
}
4951
}
5052

53+
private get prefix() {
54+
return this._options.prefix ?? '';
55+
}
56+
5157
/** Clean up log files older than `retentionDays`. */
5258
async cleanupOldLogFiles(maxDurationMs = 5_000): Promise<void> {
5359
const dir = this._options.directory;
@@ -80,8 +86,11 @@ export class MongoLogManager {
8086
if (Date.now() - deletionStartTimestamp > maxDurationMs) break;
8187

8288
if (!dirent.isFile()) continue;
83-
const { id } =
84-
/^(?<id>[a-f0-9]{24})_log(\.gz)?$/i.exec(dirent.name)?.groups ?? {};
89+
const logRegExp = new RegExp(
90+
`^${this.prefix}(?<id>[a-f0-9]{24})_log(\\.gz)?$`,
91+
'i'
92+
);
93+
const { id } = logRegExp.exec(dirent.name)?.groups ?? {};
8594
if (!id) continue;
8695

8796
const fileTimestamp = +new ObjectId(id).getTimestamp();
@@ -143,7 +152,7 @@ export class MongoLogManager {
143152
const doGzip = !!this._options.gzip;
144153
const logFilePath = path.join(
145154
this._options.directory,
146-
`${logId}_log${doGzip ? '.gz' : ''}`
155+
`${this.prefix}${logId}_log${doGzip ? '.gz' : ''}`
147156
);
148157

149158
let originalTarget: Writable;

0 commit comments

Comments
 (0)