Merge pull request #33349 from kurtaking/catalog-incremental-ingestion-metrics

refactor: use MetricsService in incremental catalog ingestion
This commit is contained in:
Patrik Oldsberg
2026-03-17 22:05:36 +01:00
committed by GitHub
9 changed files with 29 additions and 15 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch
---
Migrated metrics from direct `@opentelemetry/api` usage to the alpha `MetricsService`, providing plugin-scoped metric attribution. The `@opentelemetry/api` dependency has been removed.
@@ -57,7 +57,6 @@
"@backstage/plugin-events-node": "workspace:^",
"@backstage/plugin-permission-common": "workspace:^",
"@backstage/types": "workspace:^",
"@opentelemetry/api": "^1.9.0",
"express": "^4.22.0",
"express-promise-router": "^4.1.0",
"knex": "^3.0.0",
@@ -17,6 +17,7 @@
import { IncrementalIngestionEngine } from './IncrementalIngestionEngine';
import { IterationEngineOptions } from '../types';
import { performance } from 'node:perf_hooks';
import { metricsServiceMock } from '@backstage/backend-test-utils/alpha';
jest.mock('node:perf_hooks', () => ({
performance: {
@@ -76,6 +77,7 @@ describe('IncrementalIngestionEngine - Burst Length', () => {
restLength: { minutes: 1 },
logger: mockLogger,
ready: Promise.resolve(),
metrics: metricsServiceMock.mock(),
};
const engine = new IncrementalIngestionEngine(options);
@@ -132,6 +134,7 @@ describe('IncrementalIngestionEngine - Burst Length', () => {
restLength: { minutes: 1 },
logger: mockLogger,
ready: Promise.resolve(),
metrics: metricsServiceMock.mock(),
};
const engine = new IncrementalIngestionEngine(options);
@@ -177,6 +180,7 @@ describe('IncrementalIngestionEngine - Burst Length', () => {
restLength: { minutes: 1 },
logger: mockLogger,
ready: Promise.resolve(),
metrics: metricsServiceMock.mock(),
};
const engine = new IncrementalIngestionEngine(options);
@@ -15,7 +15,7 @@
*/
import type { DeferredEntity } from '@backstage/plugin-catalog-node';
import { Gauge, metrics } from '@opentelemetry/api';
import { MetricsServiceGauge } from '@backstage/backend-plugin-api/alpha';
import { IterationEngine, IterationEngineOptions } from '../types';
import { IncrementalIngestionDatabaseManager } from '../database/IncrementalIngestionDatabaseManager';
import { performance } from 'node:perf_hooks';
@@ -29,14 +29,12 @@ export class IncrementalIngestionEngine implements IterationEngine {
private readonly restLength: Duration;
private readonly burstLength: Duration;
private readonly backoff: HumanDuration[];
private readonly lastStarted: Gauge;
private readonly lastCompleted: Gauge;
private readonly lastStarted: MetricsServiceGauge;
private readonly lastCompleted: MetricsServiceGauge;
private manager: IncrementalIngestionDatabaseManager;
constructor(private options: IterationEngineOptions) {
const meter = metrics.getMeter('default');
this.manager = options.manager;
this.restLength = Duration.fromObject(options.restLength);
this.burstLength = Duration.fromObject(options.burstLength);
@@ -47,20 +45,18 @@ export class IncrementalIngestionEngine implements IterationEngine {
{ hours: 3 },
];
this.lastStarted = meter.createGauge(
this.lastStarted = options.metrics.createGauge(
'catalog_incremental.ingestions.started',
{
description:
'Epoch timestamp seconds when the ingestion was last started',
unit: 'seconds',
description: 'Epoch timestamp when the ingestion was last started',
unit: 's',
},
);
this.lastCompleted = meter.createGauge(
this.lastCompleted = options.metrics.createGauge(
'catalog_incremental.ingestions.completed',
{
description:
'Epoch timestamp seconds when the ingestion was last completed',
unit: 'seconds',
description: 'Epoch timestamp when the ingestion was last completed',
unit: 's',
},
);
}
@@ -16,6 +16,7 @@
import { SchedulerService } from '@backstage/backend-plugin-api';
import { TestDatabases, mockServices } from '@backstage/backend-test-utils';
import { metricsServiceMock } from '@backstage/backend-test-utils/alpha';
import { ConfigReader } from '@backstage/config';
import { IncrementalEntityProvider } from '../types';
import { WrapperProviders } from './WrapperProviders';
@@ -69,6 +70,7 @@ describe('WrapperProviders', () => {
scheduler: scheduler as Partial<SchedulerService> as SchedulerService,
applyDatabaseMigrations,
events: mockServices.events.mock(),
metrics: metricsServiceMock.mock(),
});
const wrapped1 = providers.wrap(provider1, {
burstInterval: { seconds: 1 },
@@ -19,6 +19,7 @@ import {
RootConfigService,
SchedulerService,
} from '@backstage/backend-plugin-api';
import { MetricsService } from '@backstage/backend-plugin-api/alpha';
import { stringifyError } from '@backstage/errors';
import {
EntityProvider,
@@ -55,6 +56,7 @@ export class WrapperProviders {
scheduler: SchedulerService;
applyDatabaseMigrations?: typeof applyDatabaseMigrations;
events: EventsService;
metrics: MetricsService;
},
) {}
@@ -117,6 +119,7 @@ export class WrapperProviders {
provider,
restLength,
connection,
metrics: this.options.metrics,
});
let frequency = Duration.isDuration(burstInterval)
@@ -19,6 +19,7 @@ import {
createBackendModule,
createExtensionPoint,
} from '@backstage/backend-plugin-api';
import { metricsServiceRef } from '@backstage/backend-plugin-api/alpha';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';
import { WrapperProviders } from './WrapperProviders';
import { eventsServiceRef } from '@backstage/plugin-events-node';
@@ -108,6 +109,7 @@ export const catalogModuleIncrementalIngestionEntityProvider =
logger: coreServices.logger,
scheduler: coreServices.scheduler,
events: eventsServiceRef,
metrics: metricsServiceRef,
},
async init({
catalog,
@@ -117,6 +119,7 @@ export const catalogModuleIncrementalIngestionEntityProvider =
logger,
scheduler,
events,
metrics,
}) {
const client = await database.getClient();
@@ -126,6 +129,7 @@ export const catalogModuleIncrementalIngestionEntityProvider =
client,
scheduler,
events,
metrics,
});
for (const entry of addedProviders) {
@@ -18,6 +18,7 @@ import {
LoggerService,
SchedulerServiceTaskFunction,
} from '@backstage/backend-plugin-api';
import { MetricsService } from '@backstage/backend-plugin-api/alpha';
import type {
DeferredEntity,
EntityProviderConnection,
@@ -184,6 +185,7 @@ export interface IterationEngine {
export interface IterationEngineOptions {
logger: LoggerService;
metrics: MetricsService;
connection: EntityProviderConnection;
manager: IncrementalIngestionDatabaseManager;
provider: IncrementalEntityProvider<unknown, unknown>;
-1
View File
@@ -4979,7 +4979,6 @@ __metadata:
"@backstage/plugin-events-node": "workspace:^"
"@backstage/plugin-permission-common": "workspace:^"
"@backstage/types": "workspace:^"
"@opentelemetry/api": "npm:^1.9.0"
"@types/express": "npm:^4.17.6"
express: "npm:^4.22.0"
express-promise-router: "npm:^4.1.0"