From 8aa06166989139a9a55ebfe93bf7b5d411316438 Mon Sep 17 00:00:00 2001 From: Christopher Kolstad Date: Mon, 13 May 2024 14:41:28 +0200 Subject: [PATCH] feat: expose postgres version (#7041) Adds a postgres_version gauge to allow us to see postgres_version in prometheus and to post it upstream when version checking. Depends on https://github.com/bricks-software/version-function/pull/20 to be merged first to ensure our version-function doesn't crash when given the postgres-version data. --- src/lib/db/setting-store.ts | 10 ++++++++++ src/lib/metrics.ts | 17 +++++++++++++++-- src/lib/services/version-service.ts | 8 ++++++++ src/lib/types/stores/settings-store.ts | 1 + src/test/fixtures/fake-setting-store.ts | 4 ++++ 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/lib/db/setting-store.ts b/src/lib/db/setting-store.ts index 7aa8ec284d..d73c088cd5 100644 --- a/src/lib/db/setting-store.ts +++ b/src/lib/db/setting-store.ts @@ -14,6 +14,16 @@ export default class SettingStore implements ISettingStore { this.logger = getLogger('settings-store.ts'); } + async postgresVersion(): Promise { + try { + const showResult = await this.db.raw('SHOW server_version'); + return showResult?.rows[0]?.server_version || ''; + } catch (e) { + this.logger.warn('Failed to fetch postgres version', e); + return ''; + } + } + async updateRow(name: string, content: any): Promise { return this.db(TABLE) .where('name', name) diff --git a/src/lib/metrics.ts b/src/lib/metrics.ts index b4ca918120..6273bbb60d 100644 --- a/src/lib/metrics.ts +++ b/src/lib/metrics.ts @@ -21,7 +21,7 @@ import { PROJECT_ENVIRONMENT_REMOVED, } from './types/events'; import type { IUnleashConfig } from './types/option'; -import type { IUnleashStores } from './types/stores'; +import type { ISettingStore, IUnleashStores } from './types/stores'; import { hoursToMilliseconds, minutesToMilliseconds } from 'date-fns'; import type { InstanceStatsService } from './features/instance-stats/instance-stats-service'; import type { ValidatedClientMetrics } from './features/metrics/shared/schema'; @@ -651,7 +651,12 @@ export default class MetricsMonitor { projectEnvironmentsDisabled.increment({ project_id: project }); }); - await this.configureDbMetrics(db, eventBus, schedulerService); + await this.configureDbMetrics( + db, + eventBus, + schedulerService, + stores.settingStore, + ); return Promise.resolve(); } @@ -660,6 +665,7 @@ export default class MetricsMonitor { db: Knex, eventBus: EventEmitter, schedulerService: SchedulerService, + settingStore: ISettingStore, ): Promise { if (db?.client) { const dbPoolMin = createGauge({ @@ -707,6 +713,13 @@ export default class MetricsMonitor { 'registerPoolMetrics', 0, // no jitter ); + const postgresVersion = await settingStore.postgresVersion(); + const database_version = createGauge({ + name: 'postgres_version', + help: 'Which version of postgres is running (SHOW server_version)', + labelNames: ['version'], + }); + database_version.labels({ version: postgresVersion }).set(1); } } diff --git a/src/lib/services/version-service.ts b/src/lib/services/version-service.ts index 55d7b31896..4c77a8f707 100644 --- a/src/lib/services/version-service.ts +++ b/src/lib/services/version-service.ts @@ -65,6 +65,7 @@ export interface IFeatureUsageInfo { productionChanges30: number; productionChanges60: number; productionChanges90: number; + postgresVersion: string; } export default class VersionService { @@ -260,6 +261,7 @@ export default class VersionService { featureImports, userActive, productionChanges, + postgresVersion, ] = await Promise.all([ this.featureToggleStore.count({ archived: false, @@ -282,6 +284,7 @@ export default class VersionService { this.eventStore.filteredCount({ type: FEATURES_IMPORTED }), this.userStats(), this.productionChanges(), + this.postgresVersion(), ]); const versionInfo = await this.getVersionInfo(); const customStrategies = @@ -315,6 +318,7 @@ export default class VersionService { productionChanges30: productionChanges.last30, productionChanges60: productionChanges.last60, productionChanges90: productionChanges.last90, + postgresVersion, }; return featureInfo; } @@ -336,6 +340,10 @@ export default class VersionService { return this.getProductionChanges(); } + async postgresVersion(): Promise { + return this.settingStore.postgresVersion(); + } + async hasOIDC(): Promise { const settings = await this.settingStore.get<{ enabled: boolean }>( 'unleash.enterprise.auth.oidc', diff --git a/src/lib/types/stores/settings-store.ts b/src/lib/types/stores/settings-store.ts index 67495c97c1..ae459eb244 100644 --- a/src/lib/types/stores/settings-store.ts +++ b/src/lib/types/stores/settings-store.ts @@ -8,5 +8,6 @@ export interface ISettingInsert { export interface ISettingStore extends Store { insert(name: string, content: T): Promise; updateRow(name: string, content: any): Promise; + postgresVersion(): Promise; get(name: string): Promise; } diff --git a/src/test/fixtures/fake-setting-store.ts b/src/test/fixtures/fake-setting-store.ts index f4a15467fe..837930958f 100644 --- a/src/test/fixtures/fake-setting-store.ts +++ b/src/test/fixtures/fake-setting-store.ts @@ -38,4 +38,8 @@ export default class FakeSettingStore implements ISettingStore { async updateRow(name: string, content: any): Promise { this.settings.set(name, content); } + + async postgresVersion(): Promise { + return Promise.resolve('fake-postgres-version'); + } }