AWS X-Ray - это сервис AWS, который отслеживает ваше приложение. Это позволяет отслеживать ошибки и время выполнения в режиме реального времени. Итак, как вы используете его в своем бессерверном приложении JavaScript?
Сначала вам нужно установить aws-xray-sdk-core
модуль, выполнив одну из следующих команд:
yarn add aws-xray-sdk-core npm i --save aws-xray-sdk-core
Начнем с простой лямбды с одним сегментом:
import AWSXRay from 'aws-xray-sdk-core' AWSXRay.enableManualMode() const fetchData = () => { return { message: 'hello' } } export const hello = (event, context, callback) => { const segment = new AWSXRay.Segment('hello') try { const data = fetchData() callback(null, { statusCode: 200, body: data, }) } catch(err) { segment.addError(err) } finally { segment.close() } }
Запустив этот код, вы увидите что-то подобное в консоли AWS X-Ray:
Он показывает процент ошибок, среднее время выполнения и количество запросов в минуту. Но давайте займемся чем-нибудь посложнее. Допустим, у вас есть конечная точка с несколькими частями кода, которые вы хотите проанализировать отдельно:
export const slowFunction = async () => { await new Promise(resolve => setTimeout(resolve, 2000)) } export const fasterFunction = async () => { await new Promise(resolve => setTimeout(resolve, 150)) } export const unreliableFunction = async () => { if(Math.random() < 0.2) { throw new Error('Something went wrong') } }
Вот где в игру вступают подсегменты или дополнительные сегменты:
import AWSXRay from 'aws-xray-sdk-core' import { slowFunction, fasterFunction, unreliableFunction } from './functions' AWSXRay.enableManualMode() const fetchData = async (segment) => { const slowSubsegment = segment.addNewSubsegment('Slow Function') try { await slowFunction() } finally { slowSubsegment.close() } const fasterSubsegment = segment.addNewSubsegment('Faster Function') try { await fasterFunction() } finally { fasterSubsegment.close() } const unreliableSubsegment = segment.addNewSubsegment('Unreliable Function') try { await unreliableFunction() } catch (err) { unreliableSubsegment.addError(err) throw err } finally { unreliableSubsegment.close() } return { message: 'hello' } } export const hello = async (event, context, callback) => { const segment = new AWSXRay.Segment('hello function') try { const data = await fetchData(segment) callback(null, data) } catch(err) { segment.addError(err) callback(err) } finally { segment.close() } }
При успешном запуске этой функции в X-Ray появится следующий след:
Теперь вы можете анализировать время отклика с помощью производственных данных в реальном времени.
Если наша ненадежная функция выдает ошибку, трассировка также будет иметь информацию об этом:
То же самое и здесь, вы можете анализировать состояние вашего приложения и исследовать ошибки намного проще, чем просматривать мегабайты журналов.
Но этот код уродлив. Вы определенно не хотите засорять свой код всемtry
stuff. Давайте превратим его во вспомогательную функцию:
import AWSXRay from 'aws-xray-sdk-core' import { slowFunction, fasterFunction, unreliableFunction } from './functions' AWSXRay.enableManualMode() const asyncSubsegment = async (name, parent, fn) => { const subsegment = parent.addNewSubsegment(name) try { return await fn() } catch (e) { subsegment.addError(e) throw e } finally { subsegment.close() } } const fetchData = async (segment) => { await asyncSubsegment('Slow Function', segment, slowFunction) await asyncSubsegment('Faster Function', segment, fasterFunction) return asyncSubsegment('Unreliable Function', segment, unreliableFunction) } export const hello = async (event, context, callback) => { const segment = new AWSXRay.Segment('hello function') try { const data = await fetchData(segment) callback(null, data) } catch(err) { segment.addError(err) callback(err) } finally { segment.close() } }
Не идеальное решение, но выглядит намного лучше. Возможно, вам захочется создать кучу вспомогательных функций и повторно использовать их в своем приложении.
Возможно, вы захотите создать сегмент вместо подсегмента, в зависимости от ваших потребностей:
new AWSXRay.Segment('Segment Name', parentSegment.trace_id, parentSegment.id)
Использование сегментов приведет к созданию следующего вывода в консоли AWS:
Что действительно приятно, если вы хотите анализировать разные ветки кода по отдельности.
Передача сегмента при каждом вызове функции может быть немного обременительной, поэтому правильный способ справиться с этим - использовать автоматический режим. Чтобы использовать его с AWS Lambda, необходимо включить активную трассировку.
Если вы используете Serverless Framework, вам понадобится serverless-plugin-tracing
module.
Когда вы закончите с этим, пора изменить нашу asyncSubsegment
функцию, чтобы использовать текущий глобально доступный сегмент.
const asyncSubsegment = async (name, fn) => { const subsegment = AWSXRay.getSegment().addNewSubsegment(name) try { return await fn() } catch (e) { subsegment.addError(e) throw e } finally { subsegment.close() } }
После этого функция fetchData
будет выглядеть намного чище:
const fetchData = async () => { await asyncSubsegment('Slow Function', slowFunction) await asyncSubsegment('Faster Function', fasterFunction) return asyncSubsegment('Unreliable Function', unreliableFunction) }
Полный пример кода, как его использовать, также доступен в отдельной ветке.