From 009ce5035b9b3df78ddcd03064971fd01952d681 Mon Sep 17 00:00:00 2001 From: franz Date: Tue, 5 Dec 2023 14:42:27 +0100 Subject: [PATCH] add cron duration metric --- .../metrics/cron-duration-metrics.client.ts | 63 +++++++++++++++++++ worker/job-handlers.ts | 7 +++ 2 files changed, 70 insertions(+) create mode 100644 modules/metrics/cron-duration-metrics.client.ts diff --git a/modules/metrics/cron-duration-metrics.client.ts b/modules/metrics/cron-duration-metrics.client.ts new file mode 100644 index 000000000..9c15793c9 --- /dev/null +++ b/modules/metrics/cron-duration-metrics.client.ts @@ -0,0 +1,63 @@ +import { + CloudWatchClient, + CloudWatchClientConfig, + MetricDatum, + PutMetricDataCommand, +} from '@aws-sdk/client-cloudwatch'; +import { env } from '../../app/env'; + +export interface NotificationsCloudwatchMetric { + merticData: MetricDatum[]; + nameSpace: string; +} + +export class CloudwatchCronDurationMetricsPublisher { + protected environment: string; + protected configuration?: CloudWatchClientConfig; + private client: CloudWatchClient; + public namespace: string; + + constructor( + namespace: string = 'default', + environment: string = env.DEPLOYMENT_ENV, + configuration?: CloudWatchClientConfig, + ) { + this.namespace = namespace; + this.environment = environment; + this.client = new CloudWatchClient({ region: env.AWS_REGION, ...configuration }); + } + + public async publish(metricName: string, count?: number): Promise { + const [major, minor, patch] = process.versions.node.split('.').map(Number); + try { + const command = new PutMetricDataCommand({ + MetricData: [ + { + MetricName: metricName, + Dimensions: [ + { + Name: 'Environment', + Value: this.environment, + }, + { + Name: 'NodeVersion', + Value: major.toString(), + }, + ], + Unit: 'None', + Timestamp: new Date(), + Value: count ? count : 1, + }, + ], + Namespace: this.namespace, + }); + + await this.client.send(command); + } catch (err) { + // Sentry.captureException(`Failed to publish "${metricName}" in "${this.environment}: ${err}`); + console.log(`Failed to publish "${metricName}" in "${this.environment}: ${err}`); + } + } +} + +export const cronsDurationMetricPublisher = new CloudwatchCronDurationMetricsPublisher('backendCronsDuration'); diff --git a/worker/job-handlers.ts b/worker/job-handlers.ts index 4da33e683..49b9e6090 100644 --- a/worker/job-handlers.ts +++ b/worker/job-handlers.ts @@ -12,6 +12,8 @@ import { networkContext } from '../modules/network/network-context.service'; import { veBalService } from '../modules/vebal/vebal.service'; import { veBalVotingListService } from '../modules/vebal/vebal-voting-list.service'; import { cronsMetricPublisher } from '../modules/metrics/metrics.client'; +import moment from 'moment'; +import { cronsDurationMetricPublisher } from '../modules/metrics/cron-duration-metrics.client'; const runningJobs: Set = new Set(); @@ -31,6 +33,7 @@ async function runIfNotAlreadyRunning( res.sendStatus(200); return; } + const startJobTime = moment(); try { runningJobs.add(jobId); @@ -44,13 +47,17 @@ async function runIfNotAlreadyRunning( await fn(); + const durationSuccess = moment.duration(moment().diff(startJobTime)).asSeconds(); if (process.env.AWS_ALERTS === 'true') { await cronsMetricPublisher.publish(`${jobId}-done`); + await cronsDurationMetricPublisher.publish(`${jobId}-done`, durationSuccess); } console.log(`Successful job ${jobId}-done`); } catch (error) { + const durationError = moment.duration(moment().diff(startJobTime)).asSeconds(); if (process.env.AWS_ALERTS === 'true') { await cronsMetricPublisher.publish(`${jobId}-error`); + await cronsDurationMetricPublisher.publish(`${jobId}-error`, durationError); } console.log(`Error job ${jobId}-error`, error); next(error);