📦 EqualifyEverything / equalify

📄 putMetrics.ts · 51 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51import { CloudWatchClient, PutMetricDataCommand } from '@aws-sdk/client-cloudwatch';
import { event, isStaging } from '#src/utils';

const cloudwatch = new CloudWatchClient({ region: process.env.AWS_REGION ?? 'us-east-2' });

// Separate namespaces ensure staging/production metrics never mix in CloudWatch
const NAMESPACE = isStaging ? 'Equalify/Frontend-Staging' : 'Equalify/Frontend';

// CloudWatch hard limit is 1000 datums per call; cap below the batch size used by the frontend
const MAX_DATUMS = 150;

export const putMetrics = async () => {
    const { MetricData } = event.body;

    if (!Array.isArray(MetricData) || MetricData.length === 0) {
        return { success: false, message: 'MetricData must be a non-empty array' };
    }

    const metricData = MetricData
        .slice(0, MAX_DATUMS)
        .filter((d: any) => d?.MetricName && typeof d?.Value === 'number')
        .map((d: any) => ({
            MetricName: String(d.MetricName).slice(0, 256),
            Value: d.Value,
            Unit: d.Unit ?? 'None',
            Timestamp: d.Timestamp ? new Date(d.Timestamp) : new Date(),
            Dimensions: Array.isArray(d.Dimensions)
                ? d.Dimensions.slice(0, 10).map((dim: any) => ({
                    Name: String(dim.Name ?? '').slice(0, 256),
                    Value: String(dim.Value ?? '').slice(0, 256),
                }))
                : [],
        }));

    if (metricData.length === 0) {
        return { success: false, message: 'No valid metric datums' };
    }

    try {
        await cloudwatch.send(new PutMetricDataCommand({
            Namespace: NAMESPACE,
            MetricData: metricData,
        }));
    } catch (err) {
        console.error('putMetrics: CloudWatch error', err);
        return { success: false, message: 'Failed to write metrics' };
    }

    return { success: true };
};