diff --git a/.changeset/eighty-olives-live.md b/.changeset/eighty-olives-live.md new file mode 100644 index 0000000000..16898701f4 --- /dev/null +++ b/.changeset/eighty-olives-live.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Updated the `DatabaseManager` to include the plugin id in the Postgres application name of the database connections created for each plugin. diff --git a/packages/backend-common/src/database/DatabaseManager.test.ts b/packages/backend-common/src/database/DatabaseManager.test.ts index 336e5d499c..69386d77c5 100644 --- a/packages/backend-common/src/database/DatabaseManager.test.ts +++ b/packages/backend-common/src/database/DatabaseManager.test.ts @@ -165,6 +165,7 @@ describe('DatabaseManager', () => { user: 'foo', password: 'bar', port: '5432', + application_name: 'backstage_plugin_pluginwithoutconfig', }, }); @@ -741,5 +742,83 @@ describe('DatabaseManager', () => { expect(baseConfig.data.role).toEqual('backstage-plugin'); }); + + it('Defaults the application_name for postgres clients', async () => { + const testManager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { + client: 'pg', + connection: {}, + }, + }, + }), + ); + + await testManager.forPlugin('testplugin').getClient(); + const mockCalls = mocked(createDatabaseClient).mock.calls.splice(-1); + const [baseConfig, _] = mockCalls[0]; + expect(baseConfig.get()).toMatchObject({ + connection: { + application_name: 'backstage_plugin_testplugin', + }, + }); + }); + + it('Allows manually setting the application_name for postgres clients', async () => { + const testManager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { + client: 'pg', + connection: { + application_name: 'backstage_custom_app_name', + }, + }, + }, + }), + ); + + await testManager.forPlugin('testplugin').getClient(); + const mockCalls = mocked(createDatabaseClient).mock.calls.splice(-1); + const [baseConfig, overrides] = mockCalls[0]; + expect(baseConfig.get().connection.application_name).toBe( + 'backstage_custom_app_name', + ); + expect(overrides.connection.application_name).toBeUndefined(); + }); + + it('Allows manually setting the application_name for individual plugin client', async () => { + const testManager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { + client: 'pg', + connection: { + host: 'localhost', + user: 'foo', + password: 'bar', + database: 'foodb', + application_name: 'backstage_custom_app_name', + }, + plugin: { + overrideplugin: { + connection: { + application_name: 'custom_plugin', + }, + }, + }, + }, + }, + }), + ); + + await testManager.forPlugin('overrideplugin').getClient(); + const mockCalls = mocked(createDatabaseClient).mock.calls.splice(-1); + const [baseConfig, _] = mockCalls[0]; + expect(baseConfig.get().connection.application_name).toBe( + 'custom_plugin', + ); + }); }); }); diff --git a/packages/backend-common/src/database/DatabaseManager.ts b/packages/backend-common/src/database/DatabaseManager.ts index 02f2c6b172..db5d36afad 100644 --- a/packages/backend-common/src/database/DatabaseManager.ts +++ b/packages/backend-common/src/database/DatabaseManager.ts @@ -268,6 +268,12 @@ export class DatabaseManager { client, ); + if (client === 'pg') { + ( + baseConnection as Knex.PgConnectionConfig + ).application_name ||= `backstage_plugin_${pluginId}`; + } + return { // include base connection if client type has not been overridden ...(overridden ? {} : baseConnection),