Exemplos para monitores sintéticos

Este documento descreve os modelos e o código de exemplo disponíveis para ajudar a criar monitorizações sintéticas. As funções de exemplo estão disponíveis no repositório do GitHub Google Cloud/synthetics-sdk-nodjs.

Se escrever testes e não depender de um modelo, certifique-se de que o teste é aprovado, a menos que seja gerado um Error. Recomendamos que use a biblioteca Assert para garantir que, quando ocorrem falhas, estas são atribuídas à linha de código adequada.

Modelos genéricos

Os modelos genéricos estão configurados para recolher dados de rastreio e registo para pedidos HTTP de saída. A solução tira partido do módulo auto-instrumentation-node do OpenTelemetry e do winston logger. Devido à dependência de produtos de código aberto, deve esperar alterações na estrutura dos dados de rastreio e registo. Por conseguinte, os dados de registo e rastreio recolhidos devem ser usados apenas para fins de depuração.

Pode implementar a sua própria abordagem para recolher dados de rastreio e registo para pedidos HTTP de saída. Para ver um exemplo de uma abordagem personalizada, consulte a classe SyntheticAutoInstrumentation.

Exemplo genérico de Node.js

O exemplo generic-synthetic-nodejs ilustra como consultar um URL. Este exemplo contém o mesmo que a função predefinida apresentada pela Google Cloud consola. Para ver o exemplo completo, clique em Mais e, de seguida, selecione Ver no GitHub.

const { instantiateAutoInstrumentation, runSyntheticHandler } = require('@google-cloud/synthetics-sdk-api');
// Run instantiateAutoInstrumentation before any other code runs, to get automatic logs and traces
instantiateAutoInstrumentation();
const functions = require('@google-cloud/functions-framework');
const axios = require('axios');
const assert = require('node:assert');

functions.http('SyntheticFunction', runSyntheticHandler(async ({logger, executionId}) => {
  /*
   * This function executes the synthetic code for testing purposes.
   * If the code runs without errors, the synthetic test is considered successful.
   * If an error is thrown during execution, the synthetic test is considered failed.
   */
  logger.info('Making an http request using synthetics, with execution id: ' + executionId);
  const url = 'https://www.google.com/'; // URL to send the request to
  return await assert.doesNotReject(axios.get(url));
}));

Exemplo de TypeScript

O exemplo generic-synthetic-typescript ilustra como consultar um URL. Para ver o exemplo completo, clique em Mais e, de seguida, selecione Ver no GitHub.

import {runSyntheticHandler, instantiateAutoInstrumentation} from '@google-cloud/synthetics-sdk-api'
// Run instantiateAutoInstrumentation before any other code runs, to get automatic logs and traces
instantiateAutoInstrumentation();
import * as ff from '@google-cloud/functions-framework';
import axios from 'axios';
import assert from 'node:assert';
import {Logger} from 'winston';

ff.http('SyntheticFunction', runSyntheticHandler(async ({logger, executionId}: {logger: Logger, executionId: string|undefined}) => {
  /*
   * This function executes the synthetic code for testing purposes.
   * If the code runs without errors, the synthetic test is considered successful.
   * If an error is thrown during execution, the synthetic test is considered failed.
   */
  logger.info('Making an http request using synthetics, with execution id: ' + executionId);
  const url = 'https://www.google.com/'; // URL to send the request to
  return await assert.doesNotReject(axios.get(url));
}));

Modelo do Puppeteer

Se usar o Puppeteer, considere começar com o exemplo generic-puppeteer-nodejs.

Configuração do Puppeteer necessária

Para usar o Puppeteer, certifique-se de que conclui os seguintes passos:

  1. Inclua .puppeteerrc.cjs no diretório de origem da sua função do Cloud Run:

    const { join } = require('path');
    
    /**
     * @type {import("puppeteer").Configuration}
     */
    module.exports = {
      cacheDirectory: join(__dirname, '.cache', 'puppeteer'),
    };
  2. Adicione o seguinte script ao ficheiro package.json da sua função do Cloud Run:

    "scripts": {
         "gcp-build": "node node_modules/puppeteer/install.mjs"
    },
    

Amostra de marionetista

O exemplo generic-puppeteer-nodejs ilustra como usar o Puppeteer com a sua função do Cloud Run. Para ver o exemplo completo, clique em Mais e, de seguida, selecione Ver no GitHub.

const { instantiateAutoInstrumentation, runSyntheticHandler } = require('@google-cloud/synthetics-sdk-api');
// Run instantiateAutoInstrumentation before any other code runs, to get automatic logs and traces
instantiateAutoInstrumentation();
const functions = require('@google-cloud/functions-framework');
const axios = require('axios');
const assert = require('node:assert');
const puppeteer = require('puppeteer');


functions.http('CustomPuppeteerSynthetic', runSyntheticHandler(async ({logger, executionId}) => {
 /*
  * This function executes the synthetic code for testing purposes.
  * If the code runs without errors, the synthetic test is considered successful.
  * If an error is thrown during execution, the synthetic test is considered failed.
  */

 // Launch a headless Chrome browser and open a new page
 const browser = await puppeteer.launch({ headless: 'new', timeout: 0});
 const page = await browser.newPage();

 // Navigate to the target URL
 const result = await page.goto('https://www.example.com', {waitUntil: 'load'});

 // Confirm successful navigation
 await assert.equal(result.status(), 200);

 // Print the page title to the console
 const title = await page.title();
 logger.info(`My Page title: ${title} ` + executionId);

 // Close the browser
 await browser.close();
}));

Modelo do Selenium WebDriver

Se usar o Selenium WebDriver, considere começar com o exemplo generic-selenium-nodejs. A amostra, que está disponível no GitHub, inclui um ficheiro index.js e package.json.

Para ver o exemplo completo, clique em Mais e, de seguida, selecione Ver no GitHub.

const {
  instantiateAutoInstrumentation,
  runSyntheticHandler,
} = require('@google-cloud/synthetics-sdk-api');
// Run instantiateAutoInstrumentation before any other code runs, to get automatic logs and traces
instantiateAutoInstrumentation();
const functions = require('@google-cloud/functions-framework');
const assert = require('node:assert');

const { Builder, Browser, By } = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');

/*
 * This function executes the synthetic code for testing purposes.
 * If the code runs without errors, the synthetic test is considered successful.
 * If an error is thrown during execution, the synthetic test is considered failed.
 */
functions.http(
  'CustomSeleniumSynthetic',
  runSyntheticHandler(async ({ logger, executionId }) => {
    /*
     * Construct chrome options
     * Note: `setChromeBinaryPath` must be set to '/srv/bin/chromium' when running in
     *   GCF (but will need to be changed if running on local machine).
     */
    const options = new chrome.Options();
    options.setChromeBinaryPath('/srv/bin/chromium');
    options.addArguments('--headless', '--disable-gpu', '--no-sandbox');

    // Launch headless chrome webdriver with options
    const driver = await new Builder()
      .forBrowser(Browser.CHROME)
      .setChromeOptions(options)
      .build();

    // Navigate to the target URL
    await driver.get('https://example.com');

    // Retrieve title and `a` tag of page
    const title = await driver.getTitle();
    const aTag = await driver.findElement(By.css('a')).getText();

    // assert title is as expected and print to console
    await assert.equal(title, 'Example Domain');
    logger.info(`My URL title is: ${title} ` + executionId);

    await driver.quit();
  })
);

Modelo do Mocha

Se escrever testes que dependam do modelo Mocha, considere se uma sequência de testes deve continuar ou parar quando ocorrer uma falha. Para parar uma sequência de testes após uma falha, tem de definir a flag bail.

Para ver um exemplo completo que inclui a implementação de uma API, um conjunto de testes Mocha de exemplo para os pontos finais da API e como configurar a monitorização sintética, consulte o blogue Google Cloud Tutorial de monitorização sintética.

O exemplo mocha-url-ok ilustra como uma função do Cloud Run pode invocar um conjunto de testes do Mocha e fornece um conjunto de testes de exemplo. Para ver o exemplo completo, clique em Mais e, de seguida, selecione Ver no GitHub.


const functions = require('@google-cloud/functions-framework');
const GcmSynthetics = require('@google-cloud/synthetics-sdk-mocha');

/*
 * This is the server template that is required to run a synthetic monitor in
 * Google Cloud Functions.
 */

functions.http('SyntheticMochaSuite', GcmSynthetics.runMochaHandler({
  spec: `${__dirname}/mocha_tests.spec.js`
}));

/*
 * This is the file may be interacted with to author mocha tests. To interact
 * with other GCP products or services, users should add dependencies to the
 * package.json file, and require those dependencies here A few examples:
 *  - @google-cloud/secret-manager:
 *        https://www.npmjs.com/package/@google-cloud/secret-manager
 *  - @google-cloud/spanner: https://www.npmjs.com/package/@google-cloud/spanner
 *  - Supertest: https://www.npmjs.com/package/supertest
 */

const {expect} = require('chai');
const fetch = require('node-fetch');

it('pings my website', async () => {
  const url = 'https://google.com/'; // URL to send the request to
  const externalRes = await fetch(url);
  expect(externalRes.ok).to.be.true;
});

O exemplo broken-links-ok ilustra como configurar um verificador de links quebrados. Para este modelo, especifica apenas os valores do objeto options. Este objeto especifica o URI a testar e os parâmetros do teste.

Se usar o Puppeteer, certifique-se de que conclui os passos de configuração do Puppeteer necessários.

Para ver o exemplo completo, clique em Mais e, de seguida, selecione Ver no GitHub.


const functions = require('@google-cloud/functions-framework');
const GcmSynthetics = require('@google-cloud/synthetics-sdk-broken-links');

const options = {
  origin_uri: "https://example.com",
  // link_limit: 10,
  // query_selector_all: "a", // https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
  // get_attributes: ['href'], // https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute
  // link_order: "FIRST_N", // "FIRST_N" or "RANDOM"
  // link_timeout_millis: 30000, // timeout per link
  // max_retries: 0, // number of retries per link if it failed for any reason
  // wait_for_selector: '', // https://pptr.dev/api/puppeteer.page.waitforselector
  // per_link_options: {},
    /*
    // example:
      per_link_options: {
        'http://fake-link1': { expected_status_code: "STATUS_CLASS_4XX" },
        'http://fake-link2': { expected_status_code: 304 },
        'http://fake-link3': { link_timeout_millis: 10000 },
        'http://fake-link4': {
          expected_status_code: "STATUS_CLASS_3XX",
          link_timeout_millis: 10,
        },
      },
    */
  // total_synthetic_timeout_millis: 60000 // Timeout set for the entire Synthetic Monitor
  // screenshot_options: { capture_condition: 'FAILING', storage_location: '' }
};

functions.http('BrokenLinkChecker', GcmSynthetics.runBrokenLinksHandler(options));

O que se segue?