Codice di esempio per gli script canary - Amazon CloudWatch

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Codice di esempio per gli script canary

Questa sezione contiene esempi di codice che illustrano alcune possibili funzioni per gli script canary di CloudWatch Synthetics.

Esempi per Node.js e Playwright

Playwright canary con più passaggi

Lo script seguente è un esempio di canarino Node.js Playwright con più passaggi.

import { synthetics } from '@amzn/synthetics-playwright'; export async function handler(event, context) { try { console.log('Running Synthetics Playwright canary'); const browser = await synthetics.launch(); const browserContext = await browser.newContext(); const page = await synthetics.getPage(browserContext); // Add steps // Step 1 await synthetics.executeStep("home-page", async () => { console.log("Verify home page loads") await page.goto('https://www.amazon.com', {waitUntil: "load"}); await new Promise(r => setTimeout(r, 5000)); }); // Step 2 await synthetics.executeStep("search", async () => { console.log("Searching for a product") const searchInput = page.getByPlaceholder("Search Amazon").first(); await searchInput.click() await searchInput.fill('Amazon echo'); const btn = page.getByRole('button', { name: 'Go' }).first() await btn.click({ timeout: 15000 }) console.log("Clicked search button") }); // Step 3 await synthetics.executeStep("search-results", async () => { console.log("Verifying search results") const resultsHeading = page.getByText("Results", {exact: true}).first() await resultsHeading.highlight(); await new Promise(r => setTimeout(r, 5000)); }); } finally { // Close all browser contexts and browser await synthetics.close(); } }

Playwright canaries imposta i cookie

Lo script seguente è un esempio di un canarino Node.js Playwright che imposta tre cookie.

import { synthetics } from '@amzn/synthetics-playwright'; export const handler = async (event, context) => { try { let url = "http://smile.amazon.com/"; const browser = await synthetics.launch(); const page = await synthetics.getPage(browser); const cookies = [{ 'name': 'cookie1', 'value': 'val1', 'url': url }, { 'name': 'cookie2', 'value': 'val2', 'url': url }, { 'name': 'cookie3', 'value': 'val3', 'url': url } ]; await page.context().addCookies(cookies); await page.goto(url, {waitUntil: 'load', timeout: 30000}); await page.screenshot({ path: '/tmp/smile.png' }); } finally { await synthetics.close(); } };

Esempi per Node.js e Puppeteer

Impostazione dei cookie

I siti Web si basano sui cookie per fornire funzionalità personalizzate o tracciare gli utenti. Impostando i cookie negli script CloudWatch Synthetics, puoi imitare questo comportamento personalizzato e convalidarlo.

Ad esempio, un sito Web potrebbe visualizzare un collegamento Login (Accedi) per un utente che rivisita la pagina invece di un collegamento Register (Registrati).

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(); };

Emulazione del dispositivo

Puoi scrivere script che emulano vari dispositivi in modo da poter approssimare l'aspetto e il comportamento di una pagina su tali dispositivi.

L'esempio seguente emula un dispositivo iPhone 6. Per ulteriori informazioni sull'emulazione, consulta page.emulate (options) nella documentazione di 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(); };

Canary dell'API in più fasi

Questo codice di esempio illustra un canary dell'API con due fasi HTTP: testare la stessa API per casi di test positivi e negativi. La configurazione dei passaggi viene passata per abilitare la segnalazione delle intestazioni. request/response Inoltre, nasconde l'intestazione Authorization e X-Amz-Security-Token, poiché contiene le credenziali dell'utente.

Quando questo script viene utilizzato come canary, puoi visualizzare i dettagli di ogni fase e le richieste HTTP associate, ad esempio pass/fail, durata e parametri delle prestazioni, come il tempo di ricerca DNS e il tempo del primo byte. Puoi visualizzare il numero di 2xx, 4xx e 5xx per l'esecuzione del canary.

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(); };

Esempi per Python e Selenium

Il seguente codice di esempio Selenium è un canary che fallisce con un messaggio di errore personalizzato quando un elemento di destinazione non viene caricato.

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()