Código de muestra para scripts de valores controlados - Amazon CloudWatch

Código de muestra para scripts de valores controlados

Esta sección contiene muestras de códigos que ilustran algunas funciones posibles para los scripts valores controlados de CloudWatch Synthetics.

Muestras para Node.js y Puppeteer

Configuración de cookies

Los sitios web se basan en cookies para proporcionar funcionalidad personalizada o realizar un seguimiento de usuarios. Al configurar las cookies en scripts de CloudWatch Synthetics, puede imitar este comportamiento personalizado y validarlo.

Por ejemplo, un sitio web puede mostrar un enlace para Login (Iniciar sesión) para un usuario que vuelva a visitar la página en lugar de un enlace para Register (Registrarse).

var synthetics = require('Synthetics'); const log = require('SyntheticsLogger'); const pageLoadBlueprint = async function () { let url = "http://smile.amazon.com/"; let page = await synthetics.getPage(); // Set cookies. I found that name, value, and either url or domain are required fields. const cookies = [{ 'name': 'cookie1', 'value': 'val1', 'url': url },{ 'name': 'cookie2', 'value': 'val2', 'url': url },{ 'name': 'cookie3', 'value': 'val3', 'url': url }]; await page.setCookie(...cookies); // Navigate to the url await synthetics.executeStep('pageLoaded_home', async function (timeoutInMillis = 30000) { var response = await page.goto(url, {waitUntil: ['load', 'networkidle0'], timeout: timeoutInMillis}); // Log cookies for this page and this url const cookiesSet = await page.cookies(url); log.info("Cookies for url: " + url + " are set to: " + JSON.stringify(cookiesSet)); }); }; exports.handler = async () => { return await pageLoadBlueprint(); };

Emulación de dispositivos

Puede escribir scripts que emulan varios dispositivos para poder aproximar el aspecto y el comportamiento de una página en esos dispositivos.

El siguiente ejemplo emula un dispositivo iPhone 6. Para obtener más información acerca de la emulación, consulte page.emulate (options) en la documentación de Puppeteer.

var synthetics = require('Synthetics'); const log = require('SyntheticsLogger'); const puppeteer = require('puppeteer-core'); const pageLoadBlueprint = async function () { const iPhone = puppeteer.devices['iPhone 6']; // INSERT URL here const URL = "https://amazon.com"; let page = await synthetics.getPage(); await page.emulate(iPhone); //You can customize the wait condition here. For instance, //using 'networkidle2' may be less restrictive. const response = await page.goto(URL, {waitUntil: 'domcontentloaded', timeout: 30000}); if (!response) { throw "Failed to load page!"; } await page.waitFor(15000); await synthetics.takeScreenshot('loaded', 'loaded'); //If the response status code is not a 2xx success code if (response.status() < 200 || response.status() > 299) { throw "Failed to load page!"; } }; exports.handler = async () => { return await pageLoadBlueprint(); };

Valor controlado de la API de varios pasos

Este código de muestra demuestra un valor controlado de la API con dos pasos HTTP: prueba la misma API para casos de prueba positivos y negativos. La configuración del paso se pasa para habilitar la generación de informes de cabeceras de solicitud o de respuesta. Además, oculta el encabezado Autorización y X-Amz-Security-Token, ya que contienen credenciales de usuario.

Cuando este script se utiliza como un valor controlado, se pueden ver los detalles sobre cada paso y las solicitudes HTTP asociadas, como el paso aprobar/no aprobar, la duración y las métricas de rendimiento, como el tiempo de búsqueda del DNS y la hora del primer byte. Se puede ver el número de 2xx, 4xx y 5xx para la ejecución del valor controlado.

var synthetics = require('Synthetics'); const log = require('SyntheticsLogger'); const apiCanaryBlueprint = async function () { // Handle validation for positive scenario const validatePositiveCase = async function(res) { return new Promise((resolve, reject) => { if (res.statusCode < 200 || res.statusCode > 299) { throw res.statusCode + ' ' + res.statusMessage; } let responseBody = ''; res.on('data', (d) => { responseBody += d; }); res.on('end', () => { // Add validation on 'responseBody' here if required. For ex, your status code is 200 but data might be empty resolve(); }); }); }; // Handle validation for negative scenario const validateNegativeCase = async function(res) { return new Promise((resolve, reject) => { if (res.statusCode < 400) { throw res.statusCode + ' ' + res.statusMessage; } resolve(); }); }; let requestOptionsStep1 = { 'hostname': 'myproductsEndpoint.com', 'method': 'GET', 'path': '/test/product/validProductName', 'port': 443, 'protocol': 'https:' }; let headers = {}; headers['User-Agent'] = [synthetics.getCanaryUserAgentString(), headers['User-Agent']].join(' '); requestOptionsStep1['headers'] = headers; // By default headers, post data and response body are not included in the report for security reasons. // Change the configuration at global level or add as step configuration for individual steps let stepConfig = { includeRequestHeaders: true, includeResponseHeaders: true, restrictedHeaders: ['X-Amz-Security-Token', 'Authorization'], // Restricted header values do not appear in report generated. includeRequestBody: true, includeResponseBody: true }; await synthetics.executeHttpStep('Verify GET products API with valid name', requestOptionsStep1, validatePositiveCase, stepConfig); let requestOptionsStep2 = { 'hostname': 'myproductsEndpoint.com', 'method': 'GET', 'path': '/test/canary/InvalidName(', 'port': 443, 'protocol': 'https:' }; headers = {}; headers['User-Agent'] = [synthetics.getCanaryUserAgentString(), headers['User-Agent']].join(' '); requestOptionsStep2['headers'] = headers; // By default headers, post data and response body are not included in the report for security reasons. // Change the configuration at global level or add as step configuration for individual steps stepConfig = { includeRequestHeaders: true, includeResponseHeaders: true, restrictedHeaders: ['X-Amz-Security-Token', 'Authorization'], // Restricted header values do not appear in report generated. includeRequestBody: true, includeResponseBody: true }; await synthetics.executeHttpStep('Verify GET products API with invalid name', requestOptionsStep2, validateNegativeCase, stepConfig); }; exports.handler = async () => { return await apiCanaryBlueprint(); };

Muestras para Python y Selenium

El siguiente código de Selenium de muestra es un valor controlado que falla con un mensaje de error personalizado cuando no se carga un elemento de destino.

from aws_synthetics.selenium import synthetics_webdriver as webdriver from aws_synthetics.common import synthetics_logger as logger from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By def custom_selenium_script(): # create a browser instance browser = webdriver.Chrome() browser.get('https://www.example.com/') logger.info('navigated to home page') # set cookie browser.add_cookie({'name': 'foo', 'value': 'bar'}) browser.get('https://www.example.com/') # save screenshot browser.save_screenshot('signed.png') # expected status of an element button_condition = EC.element_to_be_clickable((By.CSS_SELECTOR, '.submit-button')) # add custom error message on failure WebDriverWait(browser, 5).until(button_condition, message='Submit button failed to load').click() logger.info('Submit button loaded successfully') # browser will be quit automatically at the end of canary run, # quit action is not necessary in the canary script browser.quit() # entry point for the canary def handler(event, context): return custom_selenium_script()