Track connected account webhook subscription lifecycle metrics (#23710)
Emits created/renewed/deleted counters and their failure counterparts from the messaging and calendar webhook subscription services. Each counter carries channel_type and provider attributes so the Grafana panels can break them down. Infra side: twentyhq/twenty-infra#841 Co-authored-by: neo773 <huzef@twenty.com>
This commit is contained in:
@@ -77,4 +77,10 @@ export enum MetricsKeys {
|
||||
SdkClientGenerationDurationMs = 'sdk-client-generation/duration-ms',
|
||||
ConnectedAccountSyncWebhookReceivedMessaging = 'connected-account-sync-webhook/received/messaging',
|
||||
ConnectedAccountSyncWebhookReceivedCalendar = 'connected-account-sync-webhook/received/calendar',
|
||||
ConnectedAccountWebhookSubscriptionCreated = 'connected-account-webhook-subscription/created',
|
||||
ConnectedAccountWebhookSubscriptionCreationFailed = 'connected-account-webhook-subscription/creation-failed',
|
||||
ConnectedAccountWebhookSubscriptionRenewed = 'connected-account-webhook-subscription/renewed',
|
||||
ConnectedAccountWebhookSubscriptionRenewalFailed = 'connected-account-webhook-subscription/renewal-failed',
|
||||
ConnectedAccountWebhookSubscriptionDeleted = 'connected-account-webhook-subscription/deleted',
|
||||
ConnectedAccountWebhookSubscriptionDeletionFailed = 'connected-account-webhook-subscription/deletion-failed',
|
||||
}
|
||||
|
||||
+46
@@ -10,6 +10,8 @@ import { Repository } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
|
||||
import { MetricsService } from 'src/engine/core-modules/metrics/metrics.service';
|
||||
import { MetricsKeys } from 'src/engine/core-modules/metrics/types/metrics-keys.type';
|
||||
import { CalendarChannelEntity } from 'src/engine/metadata-modules/calendar-channel/entities/calendar-channel.entity';
|
||||
import { ConnectedAccountEntity } from 'src/engine/metadata-modules/connected-account/entities/connected-account.entity';
|
||||
import { WebhookSubscriptionDriverFactory } from 'src/modules/connected-account/webhook-subscription-manager/services/webhook-subscription-driver-factory.service';
|
||||
@@ -24,6 +26,7 @@ export class CalendarWebhookSubscriptionService {
|
||||
private readonly calendarChannelRepository: Repository<CalendarChannelEntity>,
|
||||
private readonly webhookSubscriptionDriverFactory: WebhookSubscriptionDriverFactory,
|
||||
private readonly exceptionHandlerService: ExceptionHandlerService,
|
||||
private readonly metricsService: MetricsService,
|
||||
) {}
|
||||
|
||||
async createSubscription(
|
||||
@@ -82,6 +85,12 @@ export class CalendarWebhookSubscriptionService {
|
||||
webhookSubscriptionStatus: WebhookSubscriptionStatus.ACTIVE,
|
||||
webhookSubscriptionExpiresAt: result.expiresAt,
|
||||
});
|
||||
|
||||
this.metricsService.incrementCounterBy({
|
||||
key: MetricsKeys.ConnectedAccountWebhookSubscriptionCreated,
|
||||
amount: 1,
|
||||
attributes: this.buildMetricAttributes(connectedAccount.provider),
|
||||
});
|
||||
} catch (error) {
|
||||
await this.calendarChannelRepository.update(calendarChannel.id, {
|
||||
webhookSubscriptionClientState: clientState,
|
||||
@@ -89,6 +98,12 @@ export class CalendarWebhookSubscriptionService {
|
||||
webhookSubscriptionExpiresAt: null,
|
||||
});
|
||||
|
||||
this.metricsService.incrementCounterBy({
|
||||
key: MetricsKeys.ConnectedAccountWebhookSubscriptionCreationFailed,
|
||||
amount: 1,
|
||||
attributes: this.buildMetricAttributes(connectedAccount.provider),
|
||||
});
|
||||
|
||||
this.exceptionHandlerService.captureExceptions([error], {
|
||||
workspace: { id: workspaceId },
|
||||
});
|
||||
@@ -149,11 +164,23 @@ export class CalendarWebhookSubscriptionService {
|
||||
webhookSubscriptionStatus: WebhookSubscriptionStatus.ACTIVE,
|
||||
webhookSubscriptionExpiresAt: result.expiresAt,
|
||||
});
|
||||
|
||||
this.metricsService.incrementCounterBy({
|
||||
key: MetricsKeys.ConnectedAccountWebhookSubscriptionRenewed,
|
||||
amount: 1,
|
||||
attributes: this.buildMetricAttributes(connectedAccount.provider),
|
||||
});
|
||||
} catch (error) {
|
||||
await this.calendarChannelRepository.update(calendarChannel.id, {
|
||||
webhookSubscriptionStatus: WebhookSubscriptionStatus.FAILED,
|
||||
});
|
||||
|
||||
this.metricsService.incrementCounterBy({
|
||||
key: MetricsKeys.ConnectedAccountWebhookSubscriptionRenewalFailed,
|
||||
amount: 1,
|
||||
attributes: this.buildMetricAttributes(connectedAccount.provider),
|
||||
});
|
||||
|
||||
this.exceptionHandlerService.captureExceptions([error], {
|
||||
workspace: { id: calendarChannel.workspaceId },
|
||||
});
|
||||
@@ -191,13 +218,32 @@ export class CalendarWebhookSubscriptionService {
|
||||
|
||||
try {
|
||||
await driver.deleteSubscription(this.toContext(calendarChannel));
|
||||
|
||||
this.metricsService.incrementCounterBy({
|
||||
key: MetricsKeys.ConnectedAccountWebhookSubscriptionDeleted,
|
||||
amount: 1,
|
||||
attributes: this.buildMetricAttributes(connectedAccount.provider),
|
||||
});
|
||||
} catch (error) {
|
||||
this.metricsService.incrementCounterBy({
|
||||
key: MetricsKeys.ConnectedAccountWebhookSubscriptionDeletionFailed,
|
||||
amount: 1,
|
||||
attributes: this.buildMetricAttributes(connectedAccount.provider),
|
||||
});
|
||||
|
||||
this.exceptionHandlerService.captureExceptions([error], {
|
||||
workspace: { id: calendarChannel.workspaceId },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private buildMetricAttributes(provider: string) {
|
||||
return {
|
||||
channel_type: WebhookSubscriptionChannelType.CALENDAR,
|
||||
provider,
|
||||
};
|
||||
}
|
||||
|
||||
private toContext(
|
||||
calendarChannel: CalendarChannelEntity,
|
||||
): WebhookSubscriptionContext {
|
||||
|
||||
+46
@@ -10,6 +10,8 @@ import { Repository } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
|
||||
import { MetricsService } from 'src/engine/core-modules/metrics/metrics.service';
|
||||
import { MetricsKeys } from 'src/engine/core-modules/metrics/types/metrics-keys.type';
|
||||
import { ConnectedAccountEntity } from 'src/engine/metadata-modules/connected-account/entities/connected-account.entity';
|
||||
import { MessageChannelEntity } from 'src/engine/metadata-modules/message-channel/entities/message-channel.entity';
|
||||
import { WebhookSubscriptionDriverFactory } from 'src/modules/connected-account/webhook-subscription-manager/services/webhook-subscription-driver-factory.service';
|
||||
@@ -24,6 +26,7 @@ export class MessagingWebhookSubscriptionService {
|
||||
private readonly messageChannelRepository: Repository<MessageChannelEntity>,
|
||||
private readonly webhookSubscriptionDriverFactory: WebhookSubscriptionDriverFactory,
|
||||
private readonly exceptionHandlerService: ExceptionHandlerService,
|
||||
private readonly metricsService: MetricsService,
|
||||
) {}
|
||||
|
||||
async createSubscription(
|
||||
@@ -81,6 +84,12 @@ export class MessagingWebhookSubscriptionService {
|
||||
webhookSubscriptionStatus: WebhookSubscriptionStatus.ACTIVE,
|
||||
webhookSubscriptionExpiresAt: result.expiresAt,
|
||||
});
|
||||
|
||||
this.metricsService.incrementCounterBy({
|
||||
key: MetricsKeys.ConnectedAccountWebhookSubscriptionCreated,
|
||||
amount: 1,
|
||||
attributes: this.buildMetricAttributes(connectedAccount.provider),
|
||||
});
|
||||
} catch (error) {
|
||||
await this.messageChannelRepository.update(messageChannel.id, {
|
||||
webhookSubscriptionClientState: clientState,
|
||||
@@ -88,6 +97,12 @@ export class MessagingWebhookSubscriptionService {
|
||||
webhookSubscriptionExpiresAt: null,
|
||||
});
|
||||
|
||||
this.metricsService.incrementCounterBy({
|
||||
key: MetricsKeys.ConnectedAccountWebhookSubscriptionCreationFailed,
|
||||
amount: 1,
|
||||
attributes: this.buildMetricAttributes(connectedAccount.provider),
|
||||
});
|
||||
|
||||
this.exceptionHandlerService.captureExceptions([error], {
|
||||
workspace: { id: workspaceId },
|
||||
});
|
||||
@@ -147,11 +162,23 @@ export class MessagingWebhookSubscriptionService {
|
||||
webhookSubscriptionStatus: WebhookSubscriptionStatus.ACTIVE,
|
||||
webhookSubscriptionExpiresAt: result.expiresAt,
|
||||
});
|
||||
|
||||
this.metricsService.incrementCounterBy({
|
||||
key: MetricsKeys.ConnectedAccountWebhookSubscriptionRenewed,
|
||||
amount: 1,
|
||||
attributes: this.buildMetricAttributes(connectedAccount.provider),
|
||||
});
|
||||
} catch (error) {
|
||||
await this.messageChannelRepository.update(messageChannel.id, {
|
||||
webhookSubscriptionStatus: WebhookSubscriptionStatus.FAILED,
|
||||
});
|
||||
|
||||
this.metricsService.incrementCounterBy({
|
||||
key: MetricsKeys.ConnectedAccountWebhookSubscriptionRenewalFailed,
|
||||
amount: 1,
|
||||
attributes: this.buildMetricAttributes(connectedAccount.provider),
|
||||
});
|
||||
|
||||
this.exceptionHandlerService.captureExceptions([error], {
|
||||
workspace: { id: messageChannel.workspaceId },
|
||||
});
|
||||
@@ -189,13 +216,32 @@ export class MessagingWebhookSubscriptionService {
|
||||
|
||||
try {
|
||||
await driver.deleteSubscription(this.toContext(messageChannel));
|
||||
|
||||
this.metricsService.incrementCounterBy({
|
||||
key: MetricsKeys.ConnectedAccountWebhookSubscriptionDeleted,
|
||||
amount: 1,
|
||||
attributes: this.buildMetricAttributes(connectedAccount.provider),
|
||||
});
|
||||
} catch (error) {
|
||||
this.metricsService.incrementCounterBy({
|
||||
key: MetricsKeys.ConnectedAccountWebhookSubscriptionDeletionFailed,
|
||||
amount: 1,
|
||||
attributes: this.buildMetricAttributes(connectedAccount.provider),
|
||||
});
|
||||
|
||||
this.exceptionHandlerService.captureExceptions([error], {
|
||||
workspace: { id: messageChannel.workspaceId },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private buildMetricAttributes(provider: string) {
|
||||
return {
|
||||
channel_type: WebhookSubscriptionChannelType.MESSAGING,
|
||||
provider,
|
||||
};
|
||||
}
|
||||
|
||||
private toContext(
|
||||
messageChannel: MessageChannelEntity,
|
||||
): WebhookSubscriptionContext {
|
||||
|
||||
+2
@@ -3,6 +3,7 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { WorkspaceIteratorModule } from 'src/database/commands/command-runners/workspace-iterator.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { MetricsModule } from 'src/engine/core-modules/metrics/metrics.module';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { ConnectedAccountEntity } from 'src/engine/metadata-modules/connected-account/entities/connected-account.entity';
|
||||
import { CalendarChannelEntity } from 'src/engine/metadata-modules/calendar-channel/entities/calendar-channel.entity';
|
||||
@@ -21,6 +22,7 @@ import { WebhookSubscriptionManagerModule } from 'src/modules/connected-account/
|
||||
imports: [
|
||||
WebhookSubscriptionManagerModule,
|
||||
FeatureFlagModule,
|
||||
MetricsModule,
|
||||
WorkspaceIteratorModule,
|
||||
TypeOrmModule.forFeature([
|
||||
WorkspaceEntity,
|
||||
|
||||
Reference in New Issue
Block a user