Refactor Slack Notifications Backend Module to use MetricsApi
Signed-off-by: Gabriel Dugny <gabriel.dugny@believe.com>
This commit is contained in:
@@ -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.
|
||||
@@ -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",
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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<void>;
|
||||
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<string, Entity | undefined>;
|
||||
@@ -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,14 +165,13 @@ 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',
|
||||
},
|
||||
);
|
||||
this.messagesFailed = meter.createCounter(
|
||||
this.messagesFailed = metrics.createCounter(
|
||||
'notifications.processors.slack.error.count',
|
||||
{
|
||||
description: 'Number of messages that failed to send to Slack',
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user