Использование метрик AWS CloudWatch из AWS Lambda в синхронных функциях

#javascript #node.js #aws-lambda #amazon-cloudwatch

#javascript #node.js #aws-lambda #amazon-cloudwatch

Вопрос:

Я ищу решение, с помощью которого я мог бы безопасно (и почти надежно) генерировать метрики CW (putMetricData) в синхронном коде. Мой вариант использования выглядит следующим образом:

 // Lambda Main Handler

export const handler = async () => {
    await step1Aync();
    step2Sync();
    step3Sync();
    return {};
}

async function step1Aync() { 
    await doSomething();
    await doSomething();
    // could await this call, but dont want to since I dont need the value, nor do I want to handle failures
    cloudwatch.putMetricData();
}

function step2Sync() { 
    doSomething();
    // do not want to make this function async to use await here
    cloudwatch.putMetricData();
}

function step3Sync() { 
    doSomething();
    // do not want to make this function async to use await here
    cloudwatch.putMetricData();
}
 

Я понимаю, что, поскольку putMetricData запросы передаются в цикл событий Lambda, нет никакой гарантии, что они в конечном итоге отправят свой HTTP-запрос в CW (поскольку контекст выполнения Lambda может зависнуть до выполнения запроса). Это, конечно, если я не создаю step2Sync и step3Sync не использую асинхронно await для каждого обещания.

Часть моих рассуждений здесь заключается в том, что я хотел бы сократить время отклика лямбды, специально не обрабатывая ответы от CloudWatch. Этот лямбда-интерфейс является чувствительным ко времени API (API Gateway). Если «некоторые» запросы на CW завершаются неудачей (менее 1%), все в порядке.

Я читал, что если снова использовать тот же лямбда-контекст, он опустошит цикл событий. Однако это НЕ гарантировано. Я не знаю, что такое SLA, так сказать.

Короче говоря, я не хочу использовать асинхронные функции, когда в этом нет явной необходимости. Правильно ли я понимаю?

Ответ №1:

Возможное решение:

Определите глобальный массив, который постоянно добавляется, а затем сбросьте массив в CloudWatch одним Promise.all вызовом в конце функции. Нам все еще нужно дождаться вызовов, но это выполняется одновременно или параллельно в конце (в зависимости от базового silicon).

// массив глобальных показателей

 export const PENDING_METRICS: PutMetricDataInput[] = [];
 

// обработчик

 // Lambda Main Handler

export const handler = async () => {
    await step1Aync();
    step2Sync();
    step3Sync();
    
    // emit all of the metrics
    await Promise.all( PENDING_METRICS.map(emitMetricToCloudWatch) );
    
    // clear the global array for safety
    PENDING_METRICS.length = 0;
    return {};
}

async function step1Aync() { 
    await doSomething();
    await doSomething();
    PENDING_METRICS.push(PutMetricDataInput)
}

function step2Sync() { 
    doSomething();
    PENDING_METRICS.push(PutMetricDataInput)
}

function step3Sync() { 
    doSomething();
    PENDING_METRICS.push(PutMetricDataInput)
}
 

// Код CloudWatch

 export const emitMetricToCloudWatch = async (client, input) => client.putMetricData(input);
 

Примечание: глобальные объекты могут перетекать в другие контексты выполнения. Поэтому массив необходимо очищать после отправки каждой метрики.