Refactor scheduler to use metrics service (#32992)

* Migrate scheduler metrics to MetricsService

Signed-off-by: Kurt King <kurtaking@gmail.com>

* Add missing changeset

Signed-off-by: Kurt King <kurtaking@gmail.com>

* Update API report

Signed-off-by: Kurt King <kurtaking@gmail.com>

* Release as minor with breaking change verbiage

Signed-off-by: Kurt King <kurtaking@gmail.com>

* Apply suggestion from @aramissennyeydd

Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com>

* fix prettier

Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>

---------

Signed-off-by: Kurt King <kurtaking@gmail.com>
Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com>
Signed-off-by: aramissennyeydd <aramis.sennyey@doordash.com>
Co-authored-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com>
Co-authored-by: aramissennyeydd <aramis.sennyey@doordash.com>
This commit is contained in:
Kurt King
2026-02-28 07:14:47 -07:00
committed by GitHub
parent 0fbcf23714
commit 0e7d8f9091
7 changed files with 42 additions and 13 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-defaults': minor
---
The scheduler service now uses the metrics service to create metrics, providing plugin-scoped attribution.
@@ -6,6 +6,7 @@
import { DatabaseService } from '@backstage/backend-plugin-api';
import { HttpRouterService } from '@backstage/backend-plugin-api';
import { LoggerService } from '@backstage/backend-plugin-api';
import { MetricsService } from '@backstage/backend-plugin-api/alpha';
import { PluginMetadataService } from '@backstage/backend-plugin-api';
import { RootLifecycleService } from '@backstage/backend-plugin-api';
import { SchedulerService } from '@backstage/backend-plugin-api';
@@ -17,6 +18,7 @@ export class DefaultSchedulerService {
static create(options: {
database: DatabaseService;
logger: LoggerService;
metrics: MetricsService;
rootLifecycle: RootLifecycleService;
httpRouter: HttpRouterService;
pluginMetadata: PluginMetadataService;
@@ -20,6 +20,7 @@ import waitForExpect from 'wait-for-expect';
import { DefaultSchedulerService } from './DefaultSchedulerService';
import { createTestScopedSignal } from './__testUtils__/createTestScopedSignal';
import { PluginMetadataService } from '@backstage/backend-plugin-api';
import { metricsServiceMock } from '@backstage/backend-test-utils/alpha';
jest.setTimeout(60_000);
@@ -32,6 +33,7 @@ describe('TaskScheduler', () => {
getId: () => 'test',
} satisfies PluginMetadataService;
const testScopedSignal = createTestScopedSignal();
const metrics = metricsServiceMock.mock();
it.each(databases.eachSupportedId())(
'can return a working v1 plugin impl, %p',
@@ -42,6 +44,7 @@ describe('TaskScheduler', () => {
const manager = DefaultSchedulerService.create({
database,
logger,
metrics,
rootLifecycle,
httpRouter,
pluginMetadata,
@@ -71,6 +74,7 @@ describe('TaskScheduler', () => {
const manager = DefaultSchedulerService.create({
database,
logger,
metrics,
rootLifecycle,
httpRouter,
pluginMetadata,
@@ -27,6 +27,7 @@ import { Duration } from 'luxon';
import { migrateBackendTasks } from '../database/migrateBackendTasks';
import { PluginTaskSchedulerImpl } from './PluginTaskSchedulerImpl';
import { PluginTaskSchedulerJanitor } from './PluginTaskSchedulerJanitor';
import { MetricsService } from '@backstage/backend-plugin-api/alpha';
/**
* Default implementation of the task scheduler service.
@@ -37,6 +38,7 @@ export class DefaultSchedulerService {
static create(options: {
database: DatabaseService;
logger: LoggerService;
metrics: MetricsService;
rootLifecycle: RootLifecycleService;
httpRouter: HttpRouterService;
pluginMetadata: PluginMetadataService;
@@ -67,6 +69,7 @@ export class DefaultSchedulerService {
options.pluginMetadata.getId(),
databaseFactory,
options.logger,
options.metrics,
options.rootLifecycle,
);
@@ -27,6 +27,7 @@ import {
parseDuration,
} from './PluginTaskSchedulerImpl';
import { createDeferred } from '@backstage/types';
import { metricsServiceMock } from '@backstage/backend-test-utils/alpha';
jest.setTimeout(60_000);
@@ -56,6 +57,7 @@ describe('PluginTaskManagerImpl', () => {
'myplugin',
async () => knex,
mockServices.logger.mock(),
metricsServiceMock.mock(),
{
addShutdownHook,
addBeforeShutdownHook: jest.fn(),
@@ -24,7 +24,13 @@ import {
SchedulerServiceTaskRunner,
SchedulerServiceTaskScheduleDefinition,
} from '@backstage/backend-plugin-api';
import { Counter, Histogram, Gauge, metrics, trace } from '@opentelemetry/api';
import { trace } from '@opentelemetry/api';
import {
MetricsService,
MetricsServiceCounter,
MetricsServiceGauge,
MetricsServiceHistogram,
} from '@backstage/backend-plugin-api/alpha';
import { Knex } from 'knex';
import { Duration } from 'luxon';
import express from 'express';
@@ -45,10 +51,10 @@ export class PluginTaskSchedulerImpl implements SchedulerService {
private readonly allScheduledTasks: SchedulerServiceTaskDescriptor[] = [];
private readonly shutdownInitiated: Promise<boolean>;
private readonly counter: Counter;
private readonly duration: Histogram;
private readonly lastStarted: Gauge;
private readonly lastCompleted: Gauge;
private readonly counter: MetricsServiceCounter;
private readonly duration: MetricsServiceHistogram;
private readonly lastStarted: MetricsServiceGauge;
private readonly lastCompleted: MetricsServiceGauge;
private readonly pluginId: string;
private readonly databaseFactory: () => Promise<Knex>;
@@ -58,24 +64,27 @@ export class PluginTaskSchedulerImpl implements SchedulerService {
pluginId: string,
databaseFactory: () => Promise<Knex>,
logger: LoggerService,
metrics: MetricsService,
rootLifecycle: RootLifecycleService,
) {
this.pluginId = pluginId;
this.databaseFactory = databaseFactory;
this.logger = logger;
const meter = metrics.getMeter('default');
this.counter = meter.createCounter('backend_tasks.task.runs.count', {
this.counter = metrics.createCounter('backend_tasks.task.runs.count', {
description: 'Total number of times a task has been run',
});
this.duration = meter.createHistogram('backend_tasks.task.runs.duration', {
description: 'Histogram of task run durations',
unit: 'seconds',
});
this.lastStarted = meter.createGauge('backend_tasks.task.runs.started', {
this.duration = metrics.createHistogram(
'backend_tasks.task.runs.duration',
{
description: 'Histogram of task run durations',
unit: 'seconds',
},
);
this.lastStarted = metrics.createGauge('backend_tasks.task.runs.started', {
description: 'Epoch timestamp seconds when the task was last started',
unit: 'seconds',
});
this.lastCompleted = meter.createGauge(
this.lastCompleted = metrics.createGauge(
'backend_tasks.task.runs.completed',
{
description: 'Epoch timestamp seconds when the task was last completed',
@@ -18,6 +18,7 @@ import {
coreServices,
createServiceFactory,
} from '@backstage/backend-plugin-api';
import { metricsServiceRef } from '@backstage/backend-plugin-api/alpha';
import { DefaultSchedulerService } from './lib/DefaultSchedulerService';
/**
@@ -37,6 +38,7 @@ export const schedulerServiceFactory = createServiceFactory({
rootLifecycle: coreServices.rootLifecycle,
httpRouter: coreServices.httpRouter,
pluginMetadata: coreServices.pluginMetadata,
metrics: metricsServiceRef,
},
async factory({
database,
@@ -44,6 +46,7 @@ export const schedulerServiceFactory = createServiceFactory({
rootLifecycle,
httpRouter,
pluginMetadata,
metrics,
}) {
return DefaultSchedulerService.create({
database,
@@ -51,6 +54,7 @@ export const schedulerServiceFactory = createServiceFactory({
rootLifecycle,
httpRouter,
pluginMetadata,
metrics,
});
},
});