Skip to content
Merged
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
1 change: 1 addition & 0 deletions lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const defaultDispatcherOptions: PDOptions = {
healthcheckInterval: 5000,
healthcheckTimeout: 700,
suppressStatusLogs: false,
suppressHealthcheckStatusLogs: false,
beforeTerminate: () => Promise.resolve(),
topologyMode: 'primary-replica',
};
Expand Down
1 change: 1 addition & 0 deletions lib/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface CoreDBDispatcherOptions {
healthcheckInterval?: number;
healthcheckTimeout?: number;
suppressStatusLogs?: boolean;
suppressHealthcheckStatusLogs?: boolean;
beforeTerminate?: () => Promise<void>;
topologyMode?: TopologyMode;
}
Expand Down
26 changes: 14 additions & 12 deletions lib/dispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,18 +229,20 @@ export class PGDispatcher {
Promise.all(checkups).then(() => {
// Connections hold shared current state; this is not an isolated per-cycle result.
const status = this.getHealthcheckStatus();
this.logger.info({
message: 'Database current status',
data: {
...(this.isProxyMode ? {topologyMode: this.options.topologyMode} : {}),
connections: this.connections.map((connection) => ({
host: connection.host,
...(this.isProxyMode ? {} : {primary: connection.primary}),
healthy: connection.healthy,
latency: connection.latency,
})),
},
});
if (!this.options.suppressHealthcheckStatusLogs) {
this.logger.info({
message: 'Database current status',
data: {
...(this.isProxyMode ? {topologyMode: this.options.topologyMode} : {}),
connections: this.connections.map((connection) => ({
host: connection.host,
...(this.isProxyMode ? {} : {primary: connection.primary}),
healthy: connection.healthy,
latency: connection.latency,
})),
},
});
}
this.notifyHealthcheck(status);
});
};
Expand Down
4 changes: 4 additions & 0 deletions lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export interface PDOptions {
healthcheckInterval: number;
healthcheckTimeout: number;
suppressStatusLogs: boolean;
/**
* suppresses only [Database current status] logs, preserving dispatcher errors and other logs
*/
suppressHealthcheckStatusLogs?: boolean;
beforeTerminate: () => Promise<void>;
topologyMode: TopologyMode;
}
Expand Down
29 changes: 29 additions & 0 deletions tests/dispatcher.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,35 @@ describe('PGDispatcher topology modes', () => {
});
});

describe('PGDispatcher healthcheck status logging', () => {
test('logs database status by default', async () => {
const {dispatcher, logger} = createDispatcher([
createKnex(successfulCheckup({pg_is_in_recovery: false})),
]);

await dispatcher.ready();
await new Promise((resolve) => setImmediate(resolve));

expect(defaultDispatcherOptions.suppressHealthcheckStatusLogs).toBe(false);
expect(logger.info).toHaveBeenCalledWith(
'Database current status',
expect.objectContaining({connections: expect.any(Array)}),
);
});

test('suppresses database status while preserving healthcheck errors', async () => {
const {dispatcher, logger} = createDispatcher([createKnex(failedCheckup)], {
suppressHealthcheckStatusLogs: true,
});

await dispatcher.ready();
await new Promise((resolve) => setImmediate(resolve));

expect(logger.info).not.toHaveBeenCalled();
expect(loggedErrorMessages(logger)).toContain('Proxy unavailable');
});
});

describe('PGDispatcher healthcheck callback', () => {
test('reports a snapshot for every primary and replica connection', async () => {
const onHealthcheck = jest.fn();
Expand Down
Loading