diff --git a/.changeset/solid-bats-flash.md b/.changeset/solid-bats-flash.md new file mode 100644 index 0000000000..0a4918fcc2 --- /dev/null +++ b/.changeset/solid-bats-flash.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-notifications-backend-module-slack': patch +--- + +The Slack notification processor now uses the `MetricsService` to create metrics, providing plugin-scoped attribution. `{message}` unit has also been added. diff --git a/plugins/notifications-backend-module-slack/package.json b/plugins/notifications-backend-module-slack/package.json index 7cc7b280ca..55759c0428 100644 --- a/plugins/notifications-backend-module-slack/package.json +++ b/plugins/notifications-backend-module-slack/package.json @@ -42,7 +42,6 @@ "@backstage/plugin-notifications-common": "workspace:^", "@backstage/plugin-notifications-node": "workspace:^", "@backstage/types": "workspace:^", - "@opentelemetry/api": "^1.9.0", "@slack/bolt": "^3.21.4", "@slack/types": "^2.14.0", "@slack/web-api": "^7.5.0", diff --git a/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.test.ts b/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.test.ts index ce7898566b..0393070b3f 100644 --- a/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.test.ts +++ b/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.test.ts @@ -15,6 +15,7 @@ */ import { mockServices } from '@backstage/backend-test-utils'; +import { metricsServiceMock } from '@backstage/backend-test-utils/alpha'; import { SlackNotificationProcessor } from './SlackNotificationProcessor'; import { catalogServiceMock } from '@backstage/plugin-catalog-node/testUtils'; import { KnownBlock, WebClient } from '@slack/web-api'; @@ -125,6 +126,7 @@ const DEFAULT_ENTITIES_RESPONSE = { describe('SlackNotificationProcessor', () => { const logger = mockServices.logger.mock(); const auth = mockServices.auth(); + const metrics = metricsServiceMock.mock(); const config = mockServices.rootConfig({ data: { app: { @@ -157,6 +159,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -224,6 +227,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, blockKitRenderer: () => customBlocks, })[0]; @@ -256,6 +260,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -331,6 +336,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -365,6 +371,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -410,6 +417,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -465,6 +473,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -529,6 +538,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -584,6 +594,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -639,6 +650,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -694,6 +706,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -750,6 +763,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -809,6 +823,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -863,6 +878,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -921,6 +937,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -959,6 +976,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -982,6 +1000,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: [DEFAULT_ENTITIES_RESPONSE.items[2]], }), + metrics, slack, })[0]; @@ -1021,6 +1040,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -1066,6 +1086,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -1125,6 +1146,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -1204,6 +1226,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -1298,6 +1321,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, }, )[0]; @@ -1375,6 +1399,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -1441,6 +1466,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -1481,6 +1507,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -1520,6 +1547,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, })[0]; @@ -1568,6 +1596,7 @@ describe('SlackNotificationProcessor', () => { catalog: catalogServiceMock({ entities: DEFAULT_ENTITIES_RESPONSE.items, }), + metrics, slack, }, )[0]; diff --git a/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.ts b/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.ts index de084df464..28846fcbb5 100644 --- a/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.ts +++ b/plugins/notifications-backend-module-slack/src/lib/SlackNotificationProcessor.ts @@ -15,6 +15,10 @@ */ import { AuthService, LoggerService } from '@backstage/backend-plugin-api'; +import { + MetricsService, + MetricsServiceCounter, +} from '@backstage/backend-plugin-api/alpha'; import { Entity, isUserEntity, @@ -30,7 +34,6 @@ import { NotificationSendOptions, } from '@backstage/plugin-notifications-node'; import { durationToMilliseconds } from '@backstage/types'; -import { Counter, metrics } from '@opentelemetry/api'; import { ChatPostMessageArguments, WebClient } from '@slack/web-api'; import DataLoader from 'dataloader'; import pThrottle from 'p-throttle'; @@ -48,8 +51,8 @@ export class SlackNotificationProcessor implements NotificationProcessor { private readonly sendNotifications: ( opts: ChatPostMessageArguments[], ) => Promise; - private readonly messagesSent: Counter; - private readonly messagesFailed: Counter; + private readonly messagesSent: MetricsServiceCounter; + private readonly messagesFailed: MetricsServiceCounter; private readonly broadcastChannels?: string[]; private readonly broadcastRoutes?: BroadcastRoute[]; private readonly entityLoader: DataLoader; @@ -64,6 +67,7 @@ export class SlackNotificationProcessor implements NotificationProcessor { auth: AuthService; logger: LoggerService; catalog: CatalogService; + metrics: MetricsService; slack?: WebClient; broadcastChannels?: string[]; blockKitRenderer?: SlackBlockKitRenderer; @@ -103,6 +107,7 @@ export class SlackNotificationProcessor implements NotificationProcessor { auth: AuthService; logger: LoggerService; catalog: CatalogService; + metrics: MetricsService; broadcastChannels?: string[]; broadcastRoutes?: BroadcastRoute[]; username?: string; @@ -114,6 +119,7 @@ export class SlackNotificationProcessor implements NotificationProcessor { auth, catalog, logger, + metrics, slack, broadcastChannels, broadcastRoutes, @@ -159,17 +165,18 @@ export class SlackNotificationProcessor implements NotificationProcessor { }, ); - const meter = metrics.getMeter('default'); - this.messagesSent = meter.createCounter( + this.messagesSent = metrics.createCounter( 'notifications.processors.slack.sent.count', { description: 'Number of messages sent to Slack successfully', + unit: '{message}', }, ); - this.messagesFailed = meter.createCounter( + this.messagesFailed = metrics.createCounter( 'notifications.processors.slack.error.count', { description: 'Number of messages that failed to send to Slack', + unit: '{message}', }, ); diff --git a/plugins/notifications-backend-module-slack/src/module.ts b/plugins/notifications-backend-module-slack/src/module.ts index e3d6aebee5..88f0272eb3 100644 --- a/plugins/notifications-backend-module-slack/src/module.ts +++ b/plugins/notifications-backend-module-slack/src/module.ts @@ -17,6 +17,7 @@ import { coreServices, createBackendModule, } from '@backstage/backend-plugin-api'; +import { metricsServiceRef } from '@backstage/backend-plugin-api/alpha'; import { notificationsProcessingExtensionPoint } from '@backstage/plugin-notifications-node'; import { SlackNotificationProcessor } from './lib/SlackNotificationProcessor'; import { catalogServiceRef } from '@backstage/plugin-catalog-node'; @@ -52,13 +53,15 @@ export const notificationsModuleSlack = createBackendModule({ logger: coreServices.logger, catalog: catalogServiceRef, notifications: notificationsProcessingExtensionPoint, + metrics: metricsServiceRef, }, - async init({ auth, config, logger, catalog, notifications }) { + async init({ auth, config, logger, catalog, notifications, metrics }) { notifications.addProcessor( SlackNotificationProcessor.fromConfig(config, { auth, logger, catalog, + metrics, blockKitRenderer, }), ); diff --git a/yarn.lock b/yarn.lock index 299ee9995b..fff18dbcf4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6190,7 +6190,6 @@ __metadata: "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" "@faker-js/faker": "npm:^10.0.0" - "@opentelemetry/api": "npm:^1.9.0" "@slack/bolt": "npm:^3.21.4" "@slack/types": "npm:^2.14.0" "@slack/web-api": "npm:^7.5.0"