

# Escritura de un script de valor controlado
<a name="CloudWatch_Synthetics_Canaries_WritingCanary"></a>

En las siguientes secciones, se explica cómo escribir un script de canario y cómo integrar un canario con otros servicios de AWS y con bibliotecas y dependencias externas.

**Topics**
+ [Escritura de un script de canario mediante el tiempo de ejecución de Java](Synthetics_WritingCanary_Java.md)
+ [Escritura de un script de canario de Node.js mediante el tiempo de ejecución de Playwright](Synthetics_WritingCanary_Nodejs_Playwright.md)
+ [Escritura de un script de canario de Node.js mediante el tiempo de ejecución de Puppeteer](CloudWatch_Synthetics_Canaries_WritingCanary_Nodejs_Pup.md)
+ [Escritura de un script de valor controlado Python](CloudWatch_Synthetics_Canaries_WritingCanary_Python.md)
+ [Escritura de una configuración JSON para un esquema de comprobaciones múltiples de Node.js](CloudWatch_Synthetics_WritingCanary_Multichecks.md)

# Escritura de un script de canario mediante el tiempo de ejecución de Java
<a name="Synthetics_WritingCanary_Java"></a>

**Topics**
+ [Estructura de proyecto Java para un canario](#Synthetics_canary_Java_package)
+ [Empaquetado del proyecto para un canario](#Synthetics_canary_Java_package_canary)
+ [Nombre del controlador](#Synthetics_canary_Java_handler)
+ [Configuraciones de CloudWatch Synthetics](#Synthetics_canary_Java_config)
+ [Variables de entorno de CloudWatch Synthetics](#Synthetics_canary_Java_variables)

## Estructura de proyecto Java para un canario
<a name="Synthetics_canary_Java_package"></a>

Para crear un canario en Java, debe escribir el código, compilarlo e implementar los artefactos compilados en Synthetics. Puede inicializar un proyecto de Lambda en Java de varias maneras. Por ejemplo, puede usar una configuración de proyecto Java estándar en su IDE preferido, como IntelliJ IDEA o Visual Studio Code. Si lo prefiere, puede crear la estructura de archivos necesaria de forma manual.

Un proyecto de Synthetics Java contiene la siguiente estructura general:

```
/project-root
    └ src
        └ main
            └ java
                └ canarypackage // name of package
                |    └ ExampleCanary.java // Canary code file
                |    └ other_supporting_classes
                - resources
                     └ synthetics.json // Synthetics configuration file    
     └ build.gradle OR pom.xml
```

Puede usar Maven o Gradle para crear su proyecto y administrar las dependencias.

En la estructura anterior, la clase `ExampleCanary` es el punto de entrada o el controlador del canario.

 **Ejemplo de clase de canario de Java** 

Este ejemplo es para un canario que realiza una solicitud GET a una URL almacenada en la variable de entorno *TESTING\$1URL* de Lambda. El canario no utiliza ninguno de los métodos proporcionados por el tiempo de ejecución de Synthetics.

```
package canarypackage;

import java.net.HttpURLConnection;
import java.net.URL;

// Handler value: canary.ExampleCanary::canaryCode
public class ExampleCanary { 
  public void canaryCode() throws Exception{ 
      URL url = new URL(System.getenv("TESTING_URL"));
      HttpURLConnection con=(HttpURLConnection)url.openConnection();
      con.setRequestMethod("GET");
      con.setConnectTimeout(5000);
      con.setReadTimeout(5000);
      int status=con.getResponseCode();
      if(status!=200){
        throw new Exception("Failed to load " + url + ", status code: " + status);
      }
  }
}
```

Se recomienda encarecidamente modularizar sus canarios utilizando la función `executeStep` de biblioteca proporcionada por Synthetics. El canario realiza llamadas `get` a dos URL independientes obtenidas de las variables de entorno URL1 y URL2.

**nota**  
Para utilizar la funcionalidad `executeStep`, el método de manejo del canario debe incluir un parámetro del tipo Synthetics, como se muestra a continuación. 

```
package canarypackage;

import com.amazonaws.synthetics.Synthetics;
import java.net.HttpURLConnection;
import java.net.URL;

// Handler value: canary.ExampleCanary::canaryCode
public class ExampleCanary {
  public void canaryCode(Synthetics synthetics) throws Exception {
    createStep("Step1", synthetics, System.getenv("URL1"));
    createStep("Step2", synthetics, System.getenv("URL2"));
    return;
  }
  
  private void createStep(String stepName, Synthetics synthetics, String url) throws Exception{
    synthetics.executeStep(stepName,()->{
      URL obj=new URL(url);
      HttpURLConnection con=(HttpURLConnection)obj.openConnection();
      con.setRequestMethod("GET");
      con.setConnectTimeout(5000);
      con.setReadTimeout(5000);
      int status=con.getResponseCode();
      if(status!=200){
        throw new Exception("Failed to load" + url + "status code:" + status);
      }
      return null;
    }).get();
  }
}
```

## Empaquetado del proyecto para un canario
<a name="Synthetics_canary_Java_package_canary"></a>

Synthetics acepta el código de un canario de Java en formato *zip*. El zip consta de los archivos de clases para el código del canario, los jars para cualquier dependencia de terceros y el archivo de configuración de Synthetics.

Un zip de Synthetics Java contiene la siguiente estructura general.

```
example-canary
    └ lib
    |  └ //third party dependency jars
       └ java-canary.jar
    └ synthetics.json
```

Para crear este zip a partir de la estructura de proyecto anterior, puede usar gradle (build.gradle) o maven (pom.xml). A continuación se muestra un ejemplo.

Para obtener información sobre las dependencias o interfaces en tiempo de compilación de la biblioteca de Synthetics, consulte el README en [aws-cloudwatch-synthetics-sdk-java](https://github.com/aws/aws-cloudwatch-synthetics-sdk-java/tree/main).

```
plugins {
    id 'java'
}

repositories {
    mavenCentral()
}

dependencies {
    // Third party dependencies 
    // example: implementation 'software.amazon.awssdk:s3:2.31.9'
    
    // Declares dependency on Synthetics interfaces for compiling only
    // Refer https://github.com/aws/aws-cloudwatch-synthetics-sdk-java for building from source.
    compileOnly 'software.amazon.synthetics:aws-cloudwatch-synthetics-sdk-java:1.0.0'}

test {
    useJUnitPlatform()
}

// Build the zip to be used as Canary code.
task buildZip(type: Zip) {

    archiveFileName.set("example-canary.zip")
    destinationDirectory.set(file("$buildDir"))
    
    from processResources
    into('lib') {
        from configurations.runtimeClasspath
        from(tasks.named("jar"))
    }
    from "src/main/java/resources/synthetics.json"
    
    doLast {
        println "Artifact written to: ${archiveFile.get().asFile.absolutePath}"
    }
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

tasks.named("build") {
    dependsOn "buildZip"
}
```

## Nombre del controlador
<a name="Synthetics_canary_Java_handler"></a>

El nombre del controlador es el punto de entrada para el canario. Para el tiempo de ejecución de Java, el controlador tiene el siguiente formato.

```
<<full qualified name for canary class>>::<<name of the method to start the execution from>>
// for above code: canarypackage.ExampleCanary::canaryCode
```

## Configuraciones de CloudWatch Synthetics
<a name="Synthetics_canary_Java_config"></a>

Para poder configurar el comportamiento del tiempo de ejecución de Synthetics Java, proporcione un archivo de configuración JSON opcional denominado `synthetics.json`. Este archivo debe empaquetarse en el directorio raíz del zip del paquete. Aunque un archivo de configuración es opcional, si no se proporciona uno o falta una clave de configuración, CloudWatch asume los valores predeterminados.

Los siguientes son los valores de configuración admitidos y sus valores predeterminados.

```
{
    "step": {
        "stepSuccessMetric": true,
        "stepDurationMetric": true,
        "continueOnStepFailure": false,
        "stepsReport": true
    },
    "logging": {
        "logRequest": false,
        "logResponse": false
    },
    "httpMetrics": {
        "metric_2xx": true,
        "metric_4xx": true,
        "metric_5xx": true,
        "aggregated2xxMetric": true,
        "aggregated4xxMetric": true,
        "aggregated5xxMetric": true
    },
    "canaryMetrics": {
        "failedCanaryMetric": true,
        "aggregatedFailedCanaryMetric": true
    }
}
```

 **Configuraciones de pasos** 
+ *continueOnStepFailure*: determina si un script debe continuar incluso después de que se haya producido un error en un paso. El valor predeterminado es false.
+ *stepSuccessMetric*: determina si se emite la métrica ` SuccessPercent` de un paso. La métrica `SuccessPercent` de un paso es *100* para la puesta en marcha de canarios si el paso es correcto y *0* si se produce un error en el paso. El valor predeterminado es *true*.
+ *stepDurationMetric*: determina si se emite la métrica *Duration* de un paso. La métrica *Duration* se emite como una duración (en milisegundos) de la ejecución del paso. El valor predeterminado es *true*.

 **Configuraciones de registros** 

Se aplica a los registros generados por CloudWatch Synthetics. Controla el nivel de detalle de los registros de solicitudes y respuestas.
+ *logRequest*: especifica si se debe registrar cada solicitud en los registros de canarios. El valor predeterminado es false.
+ *logResponse*: especifica si se debe registrar cada respuesta en los registros de canarios. El valor predeterminado es false.

 **Configuraciones métricas HTTP** 

Configuraciones de métricas relacionadas con el recuento de solicitudes de red con distintos códigos de estado HTTP, emitidas por CloudWatch Synthetics para este canario.
+ *metric\$12xx*: especifica si se debe emitir la métrica *2xx* (con la dimensión CanaryName) para este canario. El valor predeterminado es *true*.
+ *metric\$14xx*: especifica si se debe emitir la métrica *4xx* (con la dimensión CanaryName) para este canario. El valor predeterminado es *true*.
+ *metric\$15xx*: especifica si se debe emitir la métrica *5xx* (con la dimensión CanaryName) para este canario. El valor predeterminado es *true*.
+ *aggregated2xxMetric*: especifica si se debe emitir la métrica *2xx* (sin la dimensión CanaryName) para este canario. El valor predeterminado es *true*.
+ *aggregated4xxMetric*: especifica si se debe emitir la métrica *4xx* (sin la dimensión CanaryName) para este canario. El valor predeterminado es *true*.
+ *aggregated5xxMetric*: especifica si se debe emitir la métrica *5xx* (sin la dimensión CanaryName) para este canario. El valor predeterminado es *true*.

 **Configuraciones de métricas de canarios** 

Configuraciones para otras métricas emitidas por CloudWatch Synthetics.
+ *failedCanaryMetric*: Analizador de acceso a la red especifica si se debe emitir la métrica *Failed* (con la dimensión CanaryName) para este canario. El valor predeterminado es *true*.
+ *aggregatedFailedCanaryMetric*: especifica si se debe emitir la métrica *Failed* (sin la dimensión CanaryName) para este canario. El valor predeterminado es *true*.

## Variables de entorno de CloudWatch Synthetics
<a name="Synthetics_canary_Java_variables"></a>

Puede configurar el nivel y el formato de los registros mediante variables de entorno.

 **Formato de registro** 

El tiempo de ejecución de CloudWatch Synthetics Java crea registros de CloudWatch para cada ejecución de canarios. Los registros se escriben en formato JSON para facilitar la consulta. Si lo desea, puede cambiar el formato de registro a *TEXT*.
+ *Nombre de variable de entorno*: CW\$1SYNTHETICS\$1LOG\$1FORMAT
+ *Valores admitidos*: JSON, TEXT
+ *Predeterminado*: JSON

 **Niveles de registro** 
+ *Nombre de variable de entorno*: CW\$1SYNTHETICS\$1LOG\$1LEVEL
+ *Valores admitidos*: TRACE, DEBUG, INFO, WARN, ERROR, FATAL
+ *Predeterminado*: INFO

Además de las variables de entorno anteriores, se añade una variable de entorno predeterminada para el tiempo de ejecución de Java. Añada la variable de entorno `AWS_LAMBDA-EXEC_WRAPPER` a su función y establezca su valor en `/opt/synthetics-otel-instrument`. Esta variable de entorno modifica el comportamiento de inicio de la función para la telemetría. Si esta variable de entorno ya existe, asegúrese de que esté establecida en el valor requerido.

# Escritura de un script de canario de Node.js mediante el tiempo de ejecución de Playwright
<a name="Synthetics_WritingCanary_Nodejs_Playwright"></a>

**Topics**
+ [Empaquetado de los archivos de canarios de Node.js para el tiempo de ejecución de Playwright](#Synthetics_canary_Nodejs_Playwright_package)
+ [Cambio de un script de Playwright existente para usarlo como canario de CloudWatch Synthetics](#CloudWatch_Synthetics_canary_edit_Playwright_script)
+ [Configuraciones de CloudWatch Synthetics](#Synthetics_canary_configure_Playwright_script)

## Empaquetado de los archivos de canarios de Node.js para el tiempo de ejecución de Playwright
<a name="Synthetics_canary_Nodejs_Playwright_package"></a>

 El script de canarios incluye un archivo `.js` (sintaxis de CommonJS) o `.mjs` (sintaxis de ES) que contiene el código del controlador de Synthetics, junto con los paquetes y módulos adicionales de los que depende el código. Los scripts creados en formato ES (ECMAScript) deben usar la extensión .mjs o incluir un archivo package.json con el conjunto de campos “type”: “module”. A diferencia de otros tiempos de ejecución, como Node.js Puppeteer, no es necesario guardar los scripts en una estructura de carpetas específica. Puede empaquetar los scripts de manera directa. Utilice la utilidad de compresión de `zip` que prefiera para crear un archivo `.zip` con el archivo del controlador en la raíz. Si el script del canario depende de paquetes o módulos adicionales que no se encuentran incluidos en el tiempo de ejecución de Synthetics, puede agregar estas dependencias al archivo `.zip`. Para ello, puede instalar las bibliotecas necesarias de la función en el directorio `node_modules` mediante la ejecución del comando `npm install`. Los siguientes comandos de la CLI crean un archivo `.zip` llamado `my_deployment_package.zip`, que contiene el archivo `index.js` o `index.mjs` (controlador de Synthetics) y sus dependencias. En el ejemplo, las dependencias se instalan mediante el administrador de paquetes `npm`.

```
~/my_function
├── index.mjs
├── synthetics.json
├── myhelper-util.mjs    
└── node_modules
    ├── mydependency
```

Cree un archivo `.zip` con el contenido de la carpeta del proyecto en la raíz. Utilice la opción `r` (recursiva), como se muestra en el siguiente ejemplo, para asegurarse de que el archivo `zip` comprime las subcarpetas.

```
zip -r my_deployment_package.zip .
```

Agregue un archivo de configuración de Synthetics para configurar el comportamiento de CloudWatch Synthetics. Puede crear un archivo `synthetics.json` y guardarlo en la misma ruta que el archivo de punto de entrada o controlador.

Si lo desea, también puede almacenar el archivo de punto de entrada en la estructura de carpetas que desee. Sin embargo, asegúrese de que la ruta de la carpeta esté especificada en el nombre del controlador.

 **Nombre del controlador** 

Asegúrese de establecer el punto de entrada del script (controlador) del valor controlado como ` myCanaryFilename.functionName` para que coincida con el nombre de archivo del punto de entrada del script. También puede almacenar el canario en una carpeta independiente, como ` myFolder/my_canary_filename.mjs`. Si lo almacena en una carpeta independiente, especifique esa ruta en el punto de entrada del script, como ` myFolder/my_canary_filename.functionName`.

## Cambio de un script de Playwright existente para usarlo como canario de CloudWatch Synthetics
<a name="CloudWatch_Synthetics_canary_edit_Playwright_script"></a>

Puede editar un script existente para Node.js y Playwright para utilizarlo como canario. Para obtener más información sobre Playwight, consulte la documentación de la [biblioteca de Playwight](https://playwright.dev/docs/api/class-playwright). 

Puede utilizar el siguiente script de Playwright que está guardado en un archivo ` exampleCanary.mjs`.

```
import { chromium } from 'playwright';
import { expect } from '@playwright/test';

const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://example.com', {timeout: 30000});
await page.screenshot({path: 'example-home.png'});

const title = await page.title();
expect(title).toEqual("Example Domain");
 
await browser.close();
```

Para convertir el script, haga lo siguiente:

1. Crear y exportar una función de `handler`. El controlador es la función de punto de entrada para el script. Puede elegir cualquier nombre para la función de controlador, pero la función que se utilice en el script debe ser la misma que en el controlador del canario. Si el nombre de su script es `exampleCanary.mjs` y el nombre de la función del controlador es `myhandler`, el controlador del canario de llamará `exampleCanary.myhandler`. En el siguiente ejemplo, el nombre de la función del controlador es `handler`.

   ```
   exports.handler = async () => {
     // Your script here
     };
   ```

1. Importe `Synthetics Playwright module` como una dependencia.

   ```
   import { synthetics } from '@aws/synthetics-playwright';
   ```

1. Inicie un navegador con la función `Launch` de Synthetics.

   ```
   const browser = await synthetics.launch();
   ```

1. Cree una nueva página de Playwright mediante la función `newPage` de Synthetics.

   ```
   const page = await synthetics.newPage();
   ```

El script ya está listo para ejecutarlo como un canario de Synthetics. A continuación, se muestra el script actualizado:

 **Script actualizado en formato ES6** 

El archivo de script guardado con una extensión `.mjs`.

```
import { synthetics } from '@aws/synthetics-playwright';
import { expect } from '@playwright/test';

export const handler = async (event, context) => {
  try {
        // Launch a browser
        const browser = await synthetics.launch();
        
        // Create a new page
        const page = await synthetics.newPage(browser);
        
        // Navigate to a website
        await page.goto('https://www.example.com', {timeout: 30000});
        
        // Take screenshot
        await page.screenshot({ path: '/tmp/example.png' });
        
        // Verify the page title
        const title = await page.title();
        expect(title).toEqual("Example Domain");
    } finally {
        // Ensure browser is closed
        await synthetics.close();
    }
};
```

 **Script actualizado en formato CommonJS** 

El archivo de script guardado con una extensión `.js`.

```
const { synthetics } = require('@aws/synthetics-playwright');
const { expect } = require('@playwright/test');

exports.handler = async (event) => {
  try {
    const browser = await synthetics.launch();
    const page = await synthetics.newPage(browser);
    await page.goto('https://www.example.com', {timeout: 30000});
    await page.screenshot({ path: '/tmp/example.png' });
    const title = await page.title();
    expect(title).toEqual("Example Domain");
  } finally {
    await synthetics.close();
  }
};
```

## Configuraciones de CloudWatch Synthetics
<a name="Synthetics_canary_configure_Playwright_script"></a>

Para poder configurar el comportamiento del tiempo de ejecución de Synthetics Playwright, proporcione un archivo de configuración JSON opcional denominado `synthetics.json`. Este archivo debe empaquetarse en la misma ubicación que el archivo del controlador. Aunque un archivo de configuración es opcional, si no se proporciona un archivo de configuración o falta una clave de configuración, CloudWatch asume los valores predeterminados.

 **Empaquetado del archivo de configuración** 

Los siguientes son los valores de configuración admitidos y sus valores predeterminados.

```
{
    "step": {
        "screenshotOnStepStart": false,
        "screenshotOnStepSuccess": false,
        "screenshotOnStepFailure": false,
        "stepSuccessMetric": true,
        "stepDurationMetric": true,
        "continueOnStepFailure": true,
        "stepsReport": true
    },
    "report": {
        "includeRequestHeaders": true,
        "includeResponseHeaders": true,
        "includeUrlPassword": false,
        "includeRequestBody": true,
        "includeResponseBody": true,
        "restrictedHeaders": ['x-amz-security-token', 'Authorization'], // Value of these headers is redacted from logs and reports
        "restrictedUrlParameters": ['Session', 'SigninToken'] // Values of these url parameters are redacted from logs and reports
    },
    "logging": {
        "logRequest": false,
        "logResponse": false,
        "logResponseBody": false,
        "logRequestBody": false,
        "logRequestHeaders": false,
        "logResponseHeaders": false
    },
    "httpMetrics": {
        "metric_2xx": true,
        "metric_4xx": true,
        "metric_5xx": true,
        "failedRequestsMetric": true,
        "aggregatedFailedRequestsMetric": true,
        "aggregated2xxMetric": true,
        "aggregated4xxMetric": true,
        "aggregated5xxMetric": true
    },
    "canaryMetrics": {
        "failedCanaryMetric": true,
        "aggregatedFailedCanaryMetric": true
    },
    "userAgent": "",
    "har": true
}
```

 **Configuraciones de pasos** 
+ `screenshotOnStepStart`: determina si Synthetics debe hacer una captura de pantalla antes de que comience el paso. El valor predeterminado es `true`. 
+ `screenshotOnStepSuccess`: determina si Synthetics debe hacer una captura de pantalla después de que un paso se haya completado correctamente. El valor predeterminado es `true`. 
+ `screenshotOnStepFailure`: determina si Synthetics debe hacer una captura de pantalla después de que se haya producido un error en un paso. El valor predeterminado es `true`. 
+ `continueOnStepFailure`: determina si un script debe continuar incluso después de que se haya producido un error en un paso. El valor predeterminado es `false`. 
+ `stepSuccessMetric`: determina si se emite la métrica ` SuccessPercent` de un paso. La métrica `SuccessPercent` de un paso es `100` para la ejecución del canario si el paso es correcto y `0` si se produce un error en el paso. El valor predeterminado es `true`. 
+ `stepDurationMetric`: determina si se emite la métrica `Duration` de un paso. La métrica `Duration` se emite como una duración (en milisegundos) de la ejecución del paso. El valor predeterminado es `true`.

 **Configuraciones de informes** 

Incluye todos los informes generados por CloudWatch Synthetics, como un archivo HAR y un informe de pasos de Synthetics. Los campos de redacción de datos confidenciales `restrictedHeaders` y `restrictedUrlParameters` también se aplican a los registros generados por Synthetics. 
+ `includeRequestHeaders`: si se deben incluir encabezados de solicitud en el informe. El valor predeterminado es `false`. 
+ `includeResponseHeaders`: si se deben incluir encabezados de respuesta en el informe. El valor predeterminado es `false`.
+ `includeUrlPassword`: si se debe incluir una contraseña que aparezca en la dirección URL. De manera predeterminada, las contraseñas que aparecen en las direcciones URL se eliminan de los registros e informes para evitar la divulgación de información confidencial. El valor predeterminado es `false` . 
+ `includeRequestBody`: si se debe incluir el cuerpo de la solicitud en el informe. El valor predeterminado es `false`. 
+ `includeResponseBody`: si se debe incluir el cuerpo de respuesta en el informe. El valor predeterminado es `false`. 
+ `restrictedHeaders`: lista de valores de encabezado que se deben ignorar si se incluyen encabezados. Esto aplica a las cabeceras de solicitud y respuesta. Por ejemplo, para poder ocultar sus credenciales, pase `includeRequestHeaders` como verdadero y `restrictedHeaders` como `['Authorization']`. 
+ `restrictedUrlParameters`: lista de la ruta URL o los parámetros de consulta que se van a editar. Esto aplica a las URL que aparecen en registros, informes y errores. El parámetro no distingue entre mayúsculas y minúsculas. Puede pasar un asterisco (`*`) como un valor para editar todos los valores de ruta de URL y los parámetros de consulta. El valor predeterminado es una matriz vacía. 
+ `har`: determina si se debe generar un archivo HTTP (HAR). El valor predeterminado es `true`.

A continuación, se muestra un ejemplo de un archivo de configuraciones de informe.

```
"includeRequestHeaders": true,
"includeResponseHeaders": true,
"includeUrlPassword": false,
"includeRequestBody": true,
"includeResponseBody": true,
"restrictedHeaders": ['x-amz-security-token', 'Authorization'], // Value of these headers is redacted from logs and reports
"restrictedUrlParameters": ['Session', 'SigninToken'] // Values of these URL parameters are redacted from logs and reports
```

 **Configuraciones de registros** 

Se aplica a los registros generados por CloudWatch Synthetics. Controla el nivel de detalle de los registros de solicitudes y respuestas.
+ `logRequest`: si se debe registrar cada solicitud en los registros de canarios. Para canaries de UI, esto registra cada solicitud que el navegador envía. El valor predeterminado es ` false`. 
+ `logResponse`: si se debe registrar cada respuesta en los registros de canarios. Para canaries de UI, esto registra todas las respuestas que el navegador recibe. El valor predeterminado es ` false`. 
+ `logRequestBody`: si se deben registrar los cuerpos de la solicitud junto con las solicitudes en los registros de canarios. Esta configuración sólo aplica si `logRequest` es verdadero. El valor predeterminado es `false`. 
+ `logResponseBody`: si se deben registrar los cuerpos de respuesta junto con las solicitudes en los registros de canarios. Esta configuración sólo aplica si `logResponse` es verdadero. El valor predeterminado es `false`. 
+ `logRequestHeaders`: si se deben registrar encabezados de solicitud junto con las solicitudes en registros de canarios. Esta configuración sólo aplica si ` logRequest` es verdadero. El valor predeterminado es `false`. 
+ `logResponseHeaders`: si se deben registrar encabezados de respuesta junto con las respuestas en los registros de canarios. Esta configuración sólo aplica si ` logResponse` es verdadero. El valor predeterminado es `false`. 

 **Configuraciones métricas HTTP** 

Configuraciones de métricas relacionadas con el recuento de solicitudes de red con distintos códigos de estado HTTP, emitidas por CloudWatch Synthetics para este canario.
+ `metric_2xx`: si se debe emitir la métrica `2xx` (con la dimensión `CanaryName`) para este canario. El valor predeterminado es ` true`. 
+ `metric_4xx`: si se debe emitir la métrica `4xx` (con la dimensión `CanaryName`) para este canario. El valor predeterminado es ` true`. 
+ `metric_5xx`: si se debe emitir la métrica `5xx` (con la dimensión `CanaryName`) para este canario. El valor predeterminado es ` true`. 
+ `failedRequestsMetric`: si se debe emitir la métrica ` failedRequests` (con la dimensión `CanaryName`) para este canario. El valor predeterminado es `true`. 
+ `aggregatedFailedRequestsMetric`: si se debe emitir la métrica ` failedRequests` (sin la dimensión `CanaryName`) para este canario. El valor predeterminado es `true`. 
+ `aggregated2xxMetric`: si se debe emitir la métrica `2xx` (sin la dimensión `CanaryName`) para este canario. El valor predeterminado es `true`. 
+ `aggregated4xxMetric`: si se debe emitir la métrica `4xx` (sin la dimensión `CanaryName`) para este canario. El valor predeterminado es `true`. 
+ `aggregated5xxMetric`: si se debe emitir la métrica `5xx` (sin la dimensión `CanaryName`) para este canario. El valor predeterminado es `true`. 

 **Configuraciones de métricas de canarios** 

Configuraciones para otras métricas emitidas por CloudWatch Synthetics.
+ `failedCanaryMetric`: si se debe emitir la métrica `Failed` (con la dimensión `CanaryName`) para este canario. El valor predeterminado es ` true`. 
+ `aggregatedFailedCanaryMetric`: si se debe emitir la métrica ` Failed` (sin la dimensión `CanaryName`) para este canario. El valor predeterminado es `true`. 

 **Otras configuraciones** 
+ `userAgent`: una cadena para agregarla al agente de usuario. El agente de usuario es una cadena que se incluye en el encabezado de la solicitud e identifica el navegador en los sitios web que visita cuando se utiliza el navegador sin periféricos. CloudWatch Synthetics agrega automáticamente `CloudWatchSynthetics/canary-arn to the user agent`. La configuración especificada se adjunta al agente de usuario generado. El valor predeterminado del agente de usuario que se debe adjuntar es una cadena vacía (`""`).

### Variables de entorno de CloudWatch Synthetics
<a name="Synthetics_canary_Nodejs_Playwright_script"></a>

Configure el nivel y el formato de los registros mediante variables de entorno.

 **Formato de registro** 

El tiempo de ejecución de CloudWatch Synthetics Playwright crea registros de CloudWatch para cada ejecución de canarios. Los registros se escriben en formato JSON para facilitar la consulta. Si lo desea, puede cambiar el formato de registro a `TEXT`.
+ `Environment variable name`: CW\$1SYNTHETICS\$1LOG\$1FORMAT 
+ `Supported values`: JSON, TEXT 
+ `Default`: JSON 

 **Niveles de registro** 

Si bien habilitar el modo `Debug` aumenta el nivel de detalle, puede resultar útil para solucionar problemas.
+ `Environment variable name`: CW\$1SYNTHETICS\$1LOG\$1LEVEL
+ `Supported values`: TRACE, DEBUG, INFO, WARN, ERROR, FATAL 
+ `Default`: INFO

# Escritura de un script de canario de Node.js mediante el tiempo de ejecución de Puppeteer
<a name="CloudWatch_Synthetics_Canaries_WritingCanary_Nodejs_Pup"></a>

**Topics**
+ [Creación de un valor controlado de CloudWatch Synthetics desde cero](#CloudWatch_Synthetics_Canaries_write_from_scratch)
+ [Empaquetado de los archivos de valores controlados de Node.js](#CloudWatch_Synthetics_Canaries_package)
+ [Cambio de un script de Puppeteer existente para usarlo como valor controlado de Synthetics](#CloudWatch_Synthetics_Canaries_modify_puppeteer_script)
+ [Variables de entorno](#CloudWatch_Synthetics_Environment_Variables)
+ [Integración del valor controlado con otros servicios de AWS](#CloudWatch_Synthetics_Canaries_AWS_integrate)
+ [Forzar al valor controlado para que utilice una dirección IP estática](#CloudWatch_Synthetics_Canaries_staticIP)

## Creación de un valor controlado de CloudWatch Synthetics desde cero
<a name="CloudWatch_Synthetics_Canaries_write_from_scratch"></a>

Aquí hay un ejemplo de script mínimo de valor controlado de Synthetics. Este script pasa como una ejecución correcta y devuelve una cadena. Para ver el aspecto de un valor controlado erróneo, cambie `let fail = false;` a `let fail = true;`. 

Debe definir una función de punto de entrada para el script de valor controlado. Para ver cómo se cargan los archivos en la ubicación de Amazon S3 especificada como `ArtifactS3Location` del canario, cree estos archivos en la carpeta `/tmp`. Todos los artefactos de canarios deben almacenarse en el directorio `/tmp`, ya que es el único en el que se puede escribir. Asegúrese de que la ruta de la captura de pantalla esté establecida en `/tmp` para todas las capturas de pantalla u otros archivos creados por el script. Synthetics carga los archivos automáticamente de ` /tmp` en un bucket de S3.

```
/tmp/<name>
```

Después de que el script se ejecuta, el estado superado o no superado y las métricas de duración se ejecutan en CloudWatch y los archivos bajo `/tmp` se cargan en un bucket de S3.

```
const basicCustomEntryPoint = async function () {

    // Insert your code here

    // Perform multi-step pass/fail check

    // Log decisions made and results to /tmp

    // Be sure to wait for all your code paths to complete 
    // before returning control back to Synthetics.
    // In that way, your canary will not finish and report success
    // before your code has finished executing

    // Throw to fail, return to succeed
    let fail = false;
    if (fail) {
        throw "Failed basicCanary check.";
    }

    return "Successfully completed basicCanary checks.";
};

exports.handler = async () => {
    return await basicCustomEntryPoint();
};
```

A continuación, expandiremos el script para usar el registro de Synthetics y realizar una llamada usando el SDK de AWS. A modo de demostración, este script creará un cliente de Amazon DynamoDB y realizará una llamada a las listTables DynamoDB de la API. Registra la respuesta a la solicitud y los registros se superan o no en función de si la solicitud se realizó correctamente.

```
const log = require('@aws/synthetics-logger');
const AWS = require('aws-sdk');
// Require any dependencies that your script needs
// Bundle additional files and dependencies into a .zip file with folder structure
// nodejs/node_modules/additional files and folders

const basicCustomEntryPoint = async function () {

    log.info("Starting DynamoDB:listTables canary.");
    
    let dynamodb = new AWS.DynamoDB();
    var params = {};
    let request = await dynamodb.listTables(params);
    try {
        let response = await request.promise();
        log.info("listTables response: " + JSON.stringify(response));
    } catch (err) {
        log.error("listTables error: " + JSON.stringify(err), err.stack);
        throw err;
    }

    return "Successfully completed DynamoDB:listTables canary.";
};

exports.handler = async () => {
    return await basicCustomEntryPoint();
};
```

## Empaquetado de los archivos de valores controlados de Node.js
<a name="CloudWatch_Synthetics_Canaries_package"></a>

 **Para syn-nodejs-puppeteer-11.0 y versiones posteriores** 

 La estructura de empaquetado anterior (para syn-nodejs-puppeteer-10.0 y versiones anteriores) sigue siendo compatible con las versiones más recientes.

Cree un script utilizando una de las siguientes opciones:
+ Archivo .js (sintaxis de CommonJS)
+ Archivo .mjs (sintaxis de los módulos de ES)

Para los módulos de ES, utilice una de las siguientes opciones:
+ Archivo .js (sintaxis de CommonJS)
+ Archivo .mjs (sintaxis de los módulos de ES)

La estructura de los paquetes se define a continuación:
+ Archivo de controlador a nivel raíz (index.js/index.mjs)
+ Archivo de configuración opcional (synthetics.json)
+ Dependencias adicionales en node\$1modules (de ser necesarias)

Ejemplo de estructura de empaquetado:

```
  my_function/
├── index.mjs
├── synthetics.json
├── helper-utils.mjs
└── node_modules/
    └── dependencies
```

Para empaquetar, siga los pasos que se indican a continuación:

1. Instale las dependencias (si las hay).

   ```
   npm install
   ```

1. Cree un paquete .zip.

   ```
   zip -r my_deployment_package.zip
   ```

 **Para syn-nodejs-puppeteer-11.0 y versiones anteriores** 

Cuando se usa Amazon S3, se requiere la siguiente estructura:

```
  nodejs/
└── node_modules/
    └── myCanaryFilename.js
```

 **Para añadir compatibilidad opcional para subcarpetas en syn-nodejs-puppeteer-3.4\$1:** 

```
nodejs/
└── node_modules/
    └── myFolder/
        └── myCanaryFilename.js
```

**nota**  
La ruta del controlador en la configuración debe coincidir con la ubicación del archivo.

 **Nombre del controlador** 

Asegúrese de establecer el punto de entrada del script (controlador) del valor controlado como ` myCanaryFilename.functionName` para que coincida con el nombre de archivo del punto de entrada del script. Si utiliza un tiempo de ejecución anterior a `syn-nodejs-puppeteer-3.4`, el `functionName` debe ser `handler`. Si utiliza ` syn-nodejs-puppeteer-3.4` o uno posterior, puede elegir cualquier nombre de función como el controlador. Si utiliza `syn-nodejs-puppeteer-3.4` o uno posterior, también puede almacenar el valor controlado en una carpeta independiente, como ` nodejs/node_modules/myFolder/my_canary_filename`. Si lo almacena en una carpeta independiente, especifique esa ruta en el punto de entrada del script, como ` myFolder/my_canary_filename.functionName`.

## Cambio de un script de Puppeteer existente para usarlo como valor controlado de Synthetics
<a name="CloudWatch_Synthetics_Canaries_modify_puppeteer_script"></a>

En esta sección se explica cómo tomar scripts de Puppeteer y modificarlos para que se ejecuten como scripts de valor controlado de Synthetics. Para obtener más información acerca de Puppeteer, consulte [Puppeteer API v1.14.0](https://github.com/puppeteer/puppeteer/blob/v1.14.0/docs/api.md). 

Comenzaremos con este ejemplo de script de Puppeteer:

```
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'example.png'});

  await browser.close();
})();
```

Los pasos de conversión son los siguientes:
+ Crear y exportar una función de `handler`. El controlador es la función de punto de entrada para el script. Si utiliza un tiempo de ejecución anterior a ` syn-nodejs-puppeteer-3.4`, la función del controlador debe denominarse `handler`. Si utiliza `syn-nodejs-puppeteer-3.4` o uno posterior, la función puede tener cualquier nombre, pero debe ser el mismo nombre que se usa en el script. Además, si utiliza `syn-nodejs-puppeteer-3.4` o uno posterior, puede almacenar los scripts en cualquier carpeta y especificar dicha carpeta como parte del nombre del controlador.

  ```
  const basicPuppeteerExample = async function () {};
  
  exports.handler = async () => {
      return await basicPuppeteerExample();
  };
  ```
+ Use la dependencia de `Synthetics`.

  ```
  var synthetics = require('@aws/synthetics-puppeteer');
  ```
+ Utilice la función de `Synthetics.getPage` para obtener un objeto `Page` de Puppeteer.

  ```
  const page = await synthetics.getPage();
  ```

  El objeto de página devuelto por la función Synthetics.getPage tiene instrumentados para el registro los eventos `request`, `response` y ` requestfailed` de **page.on**. Synthetics también configura la generación de archivos HAR para las solicitudes y respuestas en la página y agrega el ARN del valor controlado a los encabezados del agente de usuario de las solicitudes salientes en la página.

El script ya está listo para ser ejecutado como un valor controlado de Synthetics. Aquí está el script actualizado:

```
var synthetics = require('@aws/synthetics-puppeteer');  // Synthetics dependency

const basicPuppeteerExample = async function () {
    const page = await synthetics.getPage(); // Get instrumented page from Synthetics
    await page.goto('https://example.com');
    await page.screenshot({path: '/tmp/example.png'}); // Write screenshot to /tmp folder
};

exports.handler = async () => {  // Exported handler function 
    return await basicPuppeteerExample();
};
```

## Variables de entorno
<a name="CloudWatch_Synthetics_Environment_Variables"></a>

Puede utilizar variables de entorno al crear canaries. Esto le permite escribir un único script de valor controlado y luego usar ese script con diferentes valores para crear rápidamente varios valores controlados que tengan una tarea similar.

Suponga, por ejemplo, que su organización tiene puntos de enlaces como `prod`, ` dev`, y `pre-release` para las diferentes etapas del desarrollo del software, y que necesita crear canaries para probar cada uno de estos puntos de enlace. Puede escribir un único script de valor controlado que pruebe el software y, a continuación, especificar los valores diferentes para la variable de entorno de punto de conexión cuando cree cada uno de los tres valores controlados. A continuación, cuando se crea un valor controlado, se especifica el script y los valores que se van a utilizar para las variables de entorno.

Los nombres de las variables de entorno pueden contener letras, números y guiones bajos. Deben comenzar con una letra y tener al menos dos caracteres. El tamaño total de las variables de entorno no puede superar los 4 KB. No es posible especificar variables de entorno reservadas de Lambda como claves para sus variables de entorno. Para obtener más información acerca de las variables de entorno reservadas, consulte [Runtime environment variables](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime) (Variables de entorno en tiempo de ejecución).

**importante**  
Las claves y valores de las variables de entorno se cifran en reposo utilizando claves AWS KMS propiedad de AWS. Sin embargo, las variables de entorno no se cifran del lado del cliente. No guarde información confidencial en ellos.

En el siguiente ejemplo el script utiliza dos variables de entorno. Este script es para un valor controlado que verifica si hay una página web disponible. Utiliza variables de entorno para parametrizar tanto la URL que verifica como el nivel de registro de CloudWatch Synthetics que utiliza. 

La siguiente función establece `LogLevel` al valor de la variable de entorno ` LOG_LEVEL`.

```
 synthetics.setLogLevel(process.env.LOG_LEVEL);
```

La función establece `URL` al valor de la variable de entorno `URL`.

```
const URL = process.env.URL;
```

Este es el script completo. Cuando se crea un valor controlado con este script, se especifican los valores para las variables de entorno `LOG_LEVEL` y `URL`.

```
var synthetics = require('@aws/synthetics-puppeteer');
const log = require('@aws/synthetics-logger');

const pageLoadEnvironmentVariable = async function () {

    // Setting the log level (0-3)
    synthetics.setLogLevel(process.env.LOG_LEVEL);
    // INSERT URL here
    const URL = process.env.URL;

    let page = await synthetics.getPage();
    //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!";
    }
    //Wait for page to render.
    //Increase or decrease wait time based on endpoint being monitored.
    await page.waitFor(15000);
    await synthetics.takeScreenshot('loaded', 'loaded');
    let pageTitle = await page.title();
    log.info('Page title: ' + pageTitle);
    log.debug('Environment variable:' + process.env.URL);

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

### Traspaso de las variables de entorno al script
<a name="CloudWatch_Synthetics_Canaries_pass_variables"></a>

Para pasar variables de entorno al script cuando cree un valor controlado en la consola, especifique las claves y los valores de las variables de entorno en la sección **Variables de entorno** en la consola. Para obtener más información, consulte [Creación de un valor controlado](CloudWatch_Synthetics_Canaries_Create.md).

Para pasar variables de entorno a través de la API o AWS CLI, utilice el parámetro ` EnvironmentVariables` en la sección `RunConfig`. A continuación, se observa un ejemplo del comando de AWS CLI que crea un valor controlado que utiliza dos variables de entorno con claves de `Environment` y `Region`.

```
aws synthetics create-canary --cli-input-json '{
   "Name":"nameofCanary",
   "ExecutionRoleArn":"roleArn",
   "ArtifactS3Location":"s3://amzn-s3-demo-bucket-123456789012-us-west-2",
   "Schedule":{
      "Expression":"rate(0 minute)",
      "DurationInSeconds":604800
   },
   "Code":{
      "S3Bucket": "canarycreation",
      "S3Key": "cwsyn-mycanaryheartbeat-12345678-d1bd-1234-abcd-123456789012-12345678-6a1f-47c3-b291-123456789012.zip",
      "Handler":"pageLoadBlueprint.handler"
   },
   "RunConfig": {
      "TimeoutInSeconds":60,
      "EnvironmentVariables": {
         "Environment":"Production",
         "Region": "us-west-1"
      }
   },
   "SuccessRetentionPeriodInDays":13,
   "FailureRetentionPeriodInDays":13,
   "RuntimeVersion":"syn-nodejs-2.0"
}'
```

## Integración del valor controlado con otros servicios de AWS
<a name="CloudWatch_Synthetics_Canaries_AWS_integrate"></a>

Todos los canaries pueden utilizar la biblioteca de AWS SDK. Puede utilizar esta biblioteca cuando escriba su valor controlado para integrarlo con otros servicios de AWS.

Para ello, debe agregar el siguiente código al valor controlado. Para estos ejemplos, AWS Secrets Manager se utiliza como servicio para la integración del valor controlado.
+ Importar el SDK de AWS.

  ```
  const AWS = require('aws-sdk');
  ```
+ Cree un cliente para el servicio de AWS con el que se está integrando.

  ```
  const secretsManager = new AWS.SecretsManager();
  ```
+ Use el cliente para realizar llamadas a la API a ese servicio.

  ```
  var params = {
    SecretId: secretName
  };
  return await secretsManager.getSecretValue(params).promise();
  ```

El siguiente fragmento de código de script de valor controlado muestra un ejemplo de integración con Secrets Manager con más detalle.

```
var synthetics = require('@aws/synthetics-puppeteer');
const log = require('@aws/synthetics-logger');
 
const AWS = require('aws-sdk');
const secretsManager = new AWS.SecretsManager();
 
const getSecrets = async (secretName) => {
    var params = {
        SecretId: secretName
    };
    return await secretsManager.getSecretValue(params).promise();
}
 
const secretsExample = async function () {
    let URL = "<URL>";
    let page = await synthetics.getPage();
    
    log.info(`Navigating to URL: ${URL}`);
    const response = await page.goto(URL, {waitUntil: 'domcontentloaded', timeout: 30000});
    
    // Fetch secrets
    let secrets = await getSecrets("secretname")
   
    /**
    * Use secrets to login. 
    *
    * Assuming secrets are stored in a JSON format like:
    * {
    *   "username": "<USERNAME>",
    *   "password": "<PASSWORD>"
    * }
    **/
    let secretsObj = JSON.parse(secrets.SecretString);
    await synthetics.executeStep('login', async function () {
        await page.type(">USERNAME-INPUT-SELECTOR<", secretsObj.username);
        await page.type(">PASSWORD-INPUT-SELECTOR<", secretsObj.password);
        
        await Promise.all([
          page.waitForNavigation({ timeout: 30000 }),
          await page.click(">SUBMIT-BUTTON-SELECTOR<")
        ]);
    });
   
    // Verify login was successful
    await synthetics.executeStep('verify', async function () {
        await page.waitForXPath(">SELECTOR<", { timeout: 30000 });
    });
};

exports.handler = async () => {
    return await secretsExample();
};
```

## Forzar al valor controlado para que utilice una dirección IP estática
<a name="CloudWatch_Synthetics_Canaries_staticIP"></a>

Se puede configurar un valor controlado para que utilice una dirección IP estática.

**Para forzar a un valor controlado a utilizar una dirección IP estática**

1. Cree una nueva VPC Para obtener más información, consulte [Utilización de DNS con su VPC](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html).

1. Cree una gateway de Internet. Para obtener más información, consulte [Adding an internet gateway to your VPC](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html#working-with-igw) (Cómo añadir una gateway de Internet a la VPC).

1. Cree una subred pública en la nueva VPC.

1. Agregue una nueva tabla de enrutamiento a la VPC.

1. Agregue una ruta en la nueva tabla de enrutamiento, que va desde `0.0.0.0/0` a la gateway de Internet.

1. Asocie la nueva tabla de enrutamiento con la subred pública.

1. Cree una dirección IP elástica Para obtener más información, consulte [Elastic IP addresses](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html) (Direcciones IP elásticas).

1. Cree una nueva gateway NAT y asígnela a la subred pública y a la dirección IP elástica.

1. Cree las subredes privadas en la VPC

1. Agregue una ruta a la tabla de enrutamiento predeterminada de la VPC, que va desde `0.0.0.0/0` a la gateway NAT

1. Cree el valor controlado. 

# Escritura de un script de valor controlado Python
<a name="CloudWatch_Synthetics_Canaries_WritingCanary_Python"></a>

Este script pasa como una ejecución correcta y devuelve una cadena. Cómo ver el aspecto de un valor controlado erróneo, cambie error = Falso a error = verdadero

```
def basic_custom_script():
    # Insert your code here
    # Perform multi-step pass/fail check
    # Log decisions made and results to /tmp
    # Be sure to wait for all your code paths to complete 
    # before returning control back to Synthetics.
    # In that way, your canary will not finish and report success
    # before your code has finished executing
    fail = False
    if fail:
        raise Exception("Failed basicCanary check.")
    return "Successfully completed basicCanary checks."
def handler(event, context):
    return basic_custom_script()
```

## Empaquetado de los archivos de valores controlados de Python
<a name="CloudWatch_Synthetics_Canaries_WritingCanary_Python_package"></a>

Si tiene más de un archivo .py o el script tiene una dependencia, puede agruparlos todos en un único archivo ZIP. Si utiliza el tiempo de ejecución `syn-python-selenium-1.1`, el archivo ZIP debe contener el archivo .py principal del valor controlado dentro de una carpeta `python`, como `python/my_canary_filename.py`. Si utiliza ` syn-python-selenium-1.1` o uno posterior, puede utilizar una carpeta diferente, como `python/myFolder/my_canary_filename.py`.

Este archivo ZIP debe contener todas las carpetas y archivos necesarios, pero los demás archivos no necesitan estar en la carpeta `python`.

Asegúrese de establecer el punto de entrada del script del valor controlado como ` my_canary_filename.functionName` para que coincida con el nombre del archivo y el nombre de la función del punto de entrada de su script. Si utiliza el tiempo de ejecución `syn-python-selenium-1.0`, el `functionName` debe ser `handler`. Si utiliza ` syn-python-selenium-1.1` o uno posterior, no se aplica esta restricción para el nombre del controlador y, además, usted puede optar por almacenar el valor controlado en una carpeta independiente, como ` python/myFolder/my_canary_filename.py`. Si lo almacena en una carpeta independiente, especifique esa ruta en el punto de entrada del script, como ` myFolder/my_canary_filename.functionName`. 

## Cambio de un script de Puppeteer existente para usarlo como un valor controlado de Synthetics
<a name="CloudWatch_Synthetics_Canaries_WritingCanary_Python_Selenium"></a>

Se puede modificar rápidamente un script existente para Python y Selenium para ser utilizado como un valor controlado. Para obtener más información acerca de Selenium, consulte [www.selenium.dev/](https://www.selenium.dev/).

Para este ejemplo comenzaremos con el siguiente script de Selenium:

```
from selenium import webdriver

def basic_selenium_script():
    browser = webdriver.Chrome()
    browser.get('https://example.com')
    browser.save_screenshot('loaded.png')

basic_selenium_script()
```

Los pasos de conversión son los siguientes:

**Para convertir un script de Selenio para ser utilizado como un valor controlado**

1. Cambie la instrucción `import` para usar Selenium del módulo ` aws_synthetics`:

   ```
   from aws_synthetics.selenium import synthetics_webdriver as webdriver
   ```

   El módulo Selenium de `aws_synthetics` garantiza que el valor controlado pueda emitir métricas y registros, generar un archivo HAR y trabajar con otras características de CloudWatch Synthetics.

1. Cree una función de controlador y llame al método de Selenium. El controlador es la función de punto de entrada para el script.

   Si utiliza `syn-python-selenium-1.0`, la función del controlador debe denominarse `handler`. Si utiliza `syn-python-selenium-1.1` o uno posterior, la función puede tener cualquier nombre, pero debe ser el mismo nombre que se usa en el script. Además, si utiliza `syn-python-selenium-1.1` o uno posterior, puede almacenar los scripts en cualquier carpeta y especificar dicha carpeta como parte del nombre del controlador.

   ```
   def handler(event, context):
       basic_selenium_script()
   ```

El script ahora se ha actualizado para ser un valor controlado de CloudWatch Synthetics. Aquí está el script actualizado:

El `webdriver` es una instancia de la clase [SyntheticsWebDriver](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_Library_Python.html#CloudWatch_Synthetics_Library_Python_SyntheticsWebDriver), y el navegador devuelto por `webdriver.Chrome()` es una instancia de [SyntheticsBrowser](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Synthetics_Canaries_Library_Python.html#CloudWatch_Synthetics_Library_Python_SyntheticsBrowser).

```
from aws_synthetics.selenium import synthetics_webdriver as webdriver

def basic_selenium_script():
    browser = webdriver.Chrome()
    browser.get('https://example.com')
    browser.save_screenshot('loaded.png')

def handler(event, context):
    basic_selenium_script()
```

## Cambio de un script existente de Puppeteer Synthetics para autenticar certificados no estándar
<a name="Canaries_Non-Standard_Certificates"></a>

Un caso de uso importante de canarios de Synthetics es poder supervisar sus propios puntos de conexión. Si quiere supervisar un punto de conexión que no está preparado para el tráfico externo, esta supervisión puede significar a veces que no dispone de un certificado adecuado firmado por una autoridad de certificación externa de confianza.

Dos posibles soluciones para este escenario son las siguientes:
+ Para autenticar un certificado de cliente, consulte [How to validate authentication using Amazon CloudWatch Synthetics – Part 2](https://aws.amazon.com/blogs/mt/how-to-validate-authentication-using-amazon-cloudwatch-synthetics-part-2/).
+ Para autenticar un certificado autofirmado, consulte [How to validate authentication with self-signed certificates in Amazon CloudWatch Synthetics](https://aws.amazon.com/blogs/mt/how-to-validate-authentication-with-self-signed-certificates-in-amazon-cloudwatch-synthetics/).

No solo tiene estas dos opciones cuando utiliza canarios de CloudWatch Synthetics. Puede ampliar estas características y agregar su lógica empresarial mediante la ampliación del código del canario.

**nota**  
Los canarios de Synthetics que se ejecutan en tiempos de ejecución de Python tienen la marca ` --ignore-certificate-errors` habilitada de forma innata, por lo que esos canarios no deberían tener problemas para llegar a sitios con configuraciones de certificados no estándar.

# Escritura de una configuración JSON para un esquema de comprobaciones múltiples de Node.js
<a name="CloudWatch_Synthetics_WritingCanary_Multichecks"></a>

El esquema de comprobaciones múltiples de Node.js le permite crear canarios que lleven a cabo múltiples comprobaciones de validación en una sola ejecución de canario. Este esquema resulta útil cuando se desean probar varios puntos de conexión, validar diferentes aspectos de la aplicación o llevar a cabo una serie de comprobaciones relacionadas de forma secuencial. 

**Topics**
+ [Estructura de configuración raíz](#root-configuration-structure)
+ [Configuración global](#global-settings)
+ [Administración de datos y variables](#variables-data-management)
+ [Definiciones de pasos](#step-definitions)
+ [Tipos de comprobación](#check-types)
+ [Métodos de autenticación](#authentication-methods)
+ [Aserciones y validación](#assertions-validation)
+ [Extracción de datos](#data-extraction)

## Estructura de configuración raíz
<a name="root-configuration-structure"></a>

La configuración raíz define la estructura general del canario de esquema avanzado de la API.


**Propiedades del esquema**  

| Propiedad | Tipo | Obligatorio | Descripción | 
| --- | --- | --- | --- | 
|  globalSettings  | Objeto | No | Configuraciones predeterminadas aplicadas a todos los pasos | 
|  variables  | Objeto | No | Valores reutilizables en todos los pasos (máximo 10) | 
|  steps  | Objeto |  Sí  | Recopilación de pasos de supervisión (de 1 a 10 pasos) | 

 **Ejemplo** 

```
{
  "globalSettings": {
    "stepTimeout": 30000,
    "userAgent": "CloudWatch-Synthetics-Advanced/1.0"
  },
  "variables": {
    "baseUrl": "https://api.example.com",
    "apiVersion": "v1"
  },
  "steps": {
    "1": {
      "stepName": "healthCheck",
      "checkerType": "HTTP",
      "url": "${baseUrl}/health",
      "httpMethod": "GET"
    }
  }
}
```

 **Reglas de validación** 
+ Debe contener un paso como mínimo.
+ Se permiten 10 pasos como máximo.
+ No se permiten propiedades adicionales que no sean `globalSettings`, ` variables` y `steps`.

## Configuración global
<a name="global-settings"></a>

La configuración global proporciona configuraciones predeterminadas que se aplican a todos los pasos, a menos que se anulen por paso.

 **Propiedades de** 


**Propiedades de la configuración global**  

| Propiedad | Tipo | Predeterminado | Range | Descripción | 
| --- | --- | --- | --- | --- | 
|  stepTimeout  | entero | 30000 | 5000-300000 | Tiempo de espera predeterminado para todos los pasos (milisegundos) | 

 **Ejemplo** 

```
{
  "globalSettings": {
    "stepTimeout": 60000,
            
  }
}
```

## Administración de datos y variables
<a name="variables-data-management"></a>

Las variables le permiten definir valores reutilizables a los que se puede hacer referencia en toda la configuración mediante la sintaxis `${variableName}`.

 **Propiedades de variables** 


| Propiedad | Tipo | Descripción | 
| --- | --- | --- | 
| Nombres de variable | cadena | Debe coincidir con el patrón ^[a-zA-Z][a-zA-Z0-9\$1]\$1\$1 | 
| Valores de variable | cadena | Cualquier valor de cadena | 

 **Limitaciones** 
+ Se permiten 10 variables por configuración como máximo.
+ Los nombres de variable deben comenzar por una letra.
+ Los nombres de variable solo pueden contener letras, números y guiones bajos.
+ La longitud máxima no se especifica en el esquema.

 **Ejemplo** 

```
{
  "variables": {
    "baseUrl": "https://api.example.com",
    "apiKey": "${AWS_SECRET:my-api-key}",
    "timeout": "30000",
    "userEmail": "test@example.com"
  }
}
```

 **Uso de la configuración** 

```
{
  "steps": {
    "1": {
      "url": "${baseUrl}/users",
      "timeout": "${timeout}",
      "headers": {
        "Authorization": "Bearer ${apiKey}"
      }
    }
  }
}
```

## Definiciones de pasos
<a name="step-definitions"></a>

Los pasos definen las operaciones de supervisión individuales. Cada paso está numerado del 1 al 10 y contiene un tipo específico de comprobación.

 *Propiedades comunes de los pasos* 


| Propiedad | Tipo | Obligatorio | Descripción | 
| --- | --- | --- | --- | 
|  stepName  | string |  Sí  | Identificador único del paso | 
|  checkerType  | cadena |  Sí  | Tipo de comprobación: HTTP, DNS, SSL,  TCP | 
|  extractors  | matriz | No | Configuración de la extracción de datos | 

 *Validación del nombre del paso* 
+ Patrón: ^[a-zA-Z][a-zA-Z0-9\$1-]\$1\$1
+ Longitud máxima: 64 caracteres
+ Letra como carácter inicial

 *Numeración de los pasos* 
+ Los pasos se numeran como claves de cadena: “1”, “2”,..., “10”
+ Patrón: ^([1-9]\$110)\$1
+ Se requiere 1 paso como mínimo.
+ Se permiten 10 pasos como máximo.

 *Ejemplo* 

```
{
  "steps": {
    "1": {
      "stepName": "loginAPI",
      "checkerType": "HTTP",
      "url": "https://api.example.com/login",
      "httpMethod": "POST"
    },
    "2": {
      "stepName": "dnsCheck",
      "checkerType": "DNS",
      "domain": "example.com"
    }
  }
}
```

## Tipos de comprobación
<a name="check-types"></a>

### Comprobaciones HTTP
<a name="http-types"></a>

Supervise los puntos de conexión y las API web con una validación exhaustiva de las solicitudes y las respuestas.

 **Propiedades necesarias** 


| Propiedad | Tipo | Descripción | 
| --- | --- | --- | 
|  url  | cadena | URL de destino (debe tener un formato de URI válido) | 
|  httpMethod  | cadena | Método HTTP: GET, POST, PUT,  PATCH, DELETE, HEAD, OPTIONS | 

 **Propiedades opcionales** 


| Propiedad | Tipo | Predeterminado | Range | Descripción | 
| --- | --- | --- | --- | --- | 
|  timeout  | entero | 30000 | 5000-300000 | Tiempo de espera de la solicitud (milisegundos) | 
|  waitTime  | entero | 0 | 0-60 | Retraso antes de la solicitud (segundos) | 
|  headers  | objeto | - | - | Encabezados HTTP personalizados | 
|  body  | cadena | - | - | Cuerpo de la solicitud para operaciones POST y PUT | 
|  authentication  | objeto | - | - | Configuración de la autenticación | 
|  assertions  | matriz | - | - | Reglas de validación de respuestas | 

 **Ejemplo** 

```
{
  "stepName": "createUser",
  "checkerType": "HTTP",
  "url": "https://api.example.com/users",
  "httpMethod": "POST",
  "timeout": 15000,
  "headers": {
    "Content-Type": "application/json",
    "X-API-Version": "v1"
  },
  "body": "{\"name\":\"John Doe\",\"email\":\"john@example.com\"}",
  "authentication": {
    "type": "API_KEY",
    "apiKey": "${AWS_SECRET:api-credentials}",
    "headerName": "X-API-Key"
  },
  "assertions": [
    {
      "type": "STATUS_CODE",
      "operator": "EQUALS",
      "value": 201
    }
  ]
}
```

### Comprobaciones de DNS
<a name="dns-types"></a>

Valide la resolución de DNS y registre la información.

 **Propiedades necesarias** 


| Propiedad | Tipo | Descripción | 
| --- | --- | --- | 
|  domain  | cadena | Nombre del dominio que se consultará (formato de nombre de host) | 

 **Propiedades opcionales** 


| Propiedad | Tipo | Predeterminado | Descripción | 
| --- | --- | --- | --- | 
|  recordType  | cadena | “A” | Tipo de registro de DNS: A, CNAME, MX,  TXT, NS | 
|  nameserver  | cadena | - | Servidor de DNS específico que se consultará | 
|  timeout  | entero | 30000 | Tiempo de espera de la consulta (5000-300000 ms) | 
|  port  | entero | 53 | Puerto de servidor de DNS (1-65535) | 
|  protocol  | cadena | “UDP” | Protocolo: UDP o TCP | 
|  assertions  | matriz | - | Reglas de validación de respuestas de DNS | 

 **Ejemplo** 

```
{
  "stepName": "dnsResolution",
  "checkerType": "DNS",
  "domain": "example.com",
  "recordType": "A",
  "nameserver": "8.8.8.8",
  "timeout": 10000,
  "assertions": [
    {
      "type": "RECORD_VALUE",
      "operator": "CONTAINS",
      "value": "192.168"
    }
  ]
}
```

### Comprobaciones de SSL
<a name="ssl-types"></a>

Supervise el estado y la configuración de los certificados SSL.

 **Propiedades necesarias** 


| Propiedad | Tipo | Descripción | 
| --- | --- | --- | 
|  hostname  | cadena | Nombre de host de destino (formato de nombre de host) | 

 **Propiedades opcionales** 


| Propiedad | Tipo | Predeterminado | Descripción | 
| --- | --- | --- | --- | 
|  port  | entero | 443 | Puerto SSL (1-65535) | 
|  timeout  | entero | 30000 | Tiempo de espera de conexión (5000-300000 ms) | 
|  sni  | booleano | TRUE | Indicación del nombre del servidor | 
|  verifyHostname  | booleano | TRUE | Verificación de nombres de host | 
|  allowSelfSigned  | valor booleano | FALSO | Aceptación de certificados autofirmados | 
|  assertions  | matriz | - | Reglas de validación de certificados | 

 **Ejemplo** 

```
{
  "stepName": "sslCertCheck",
  "checkerType": "SSL",
  "hostname": "secure.example.com",
  "port": 443,
  "sni": true,
  "verifyHostname": true,
  "assertions": [
    {
      "type": "CERTIFICATE_EXPIRY",
      "operator": "GREATER_THAN",
      "value": 30,
      "unit": "DAYS"
    }
  ]
}
```

### Comprobaciones de TCP
<a name="tcp-types"></a>

Pruebe la conectividad de los puertos TCP y la validación de respuestas.

 **Propiedades necesarias** 


| Propiedad | Tipo | Descripción | 
| --- | --- | --- | 
|  hostname  | cadena | Nombre de host de destino (formato de nombre de host) | 
|  port  | entero | Puerto de destino (1-65535) | 

 **Propiedades opcionales** 


| Propiedad | Tipo | Predeterminado | Descripción | 
| --- | --- | --- | --- | 
|  timeout  | entero | 30000 | Tiempo de espera general (5000-300000 ms) | 
|  connectionTimeout  | entero | 3 000 | Tiempo de espera de conexión (5000-300000 ms) | 
|  readTimeout  | entero | 2000 | Tiempo de espera de lectura de datos (5000-300000 ms) | 
|  sendData  | cadena | - | Datos que se enviarán después de la conexión | 
|  expectedResponse  | cadena | - | Datos de respuesta esperados | 
|  encoding  | cadena | “UTF-8” | Codificación de datos: UTF-8, ASCII, HEX | 
|  assertions  | matriz | - | Validación de respuestas y conexiones | 

 **Ejemplo** 

```
{
  "stepName": "databaseConnection",
  "checkerType": "TCP",
  "hostname": "db.example.com",
  "port": 3306,
  "connectionTimeout": 5000,
  "sendData": "SELECT 1",
  "expectedResponse": "1",
  "assertions": [
    {
      "type": "CONNECTION_SUCCESSFUL",
      "value": true
    }
  ]
}
```

## Métodos de autenticación
<a name="authentication-methods"></a>

 **Sin autenticación** 

```
{
  "type": "NONE"
}
```

 **Autenticación básica** 


| Propiedad | Tipo | Obligatorio | Descripción | 
| --- | --- | --- | --- | 
|  type  | string |  Sí  | Debe ser "BASIC" | 
|  username  | cadena |  Sí  | Nombre de usuario para la autenticación | 
|  password  | cadena |  Sí  | Contraseña para la autenticación | 

 **Ejemplo** 

```
{
  "type": "BASIC",
  "username": "admin",
  "password": "${AWS_SECRET:basic-auth:password}"
}
```

 **Autenticación de la clave de API** 


| Propiedad | Tipo | Obligatorio/a | Predeterminado | Descripción | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Sí  | - | Debe ser "API\$1KEY" | 
|  apiKey  | cadena |  Sí  | - | Valor de la clave de API | 
|  headerName  | cadena | No | “X-API-Key” | Nombre del encabezado para la clave de API | 

 **Ejemplo** 

```
{
  "type": "API_KEY",
  "apiKey": "${AWS_SECRET:api-credentials}",
  "headerName": "Authorization"
}
```

 **Credenciales del cliente OAuth** 


| Propiedad | Tipo | Obligatorio/a | Predeterminado | Descripción | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Sí  | - | Debe ser "OAUTH\$1CLIENT\$1CREDENTIALS" | 
|  tokenUrl  | cadena |  Sí  | - | URL del punto de conexión del token de OAuth | 
|  clientId  | cadena |  Sí  | - | ID de cliente de OAuth | 
|  clientSecret  | cadena |  Sí  | - | Secreto de cliente de OAuth | 
|  scope  | cadena | No | - | Ámbito de OAuth | 
|  audience  | cadena | No | - | Audiencia de OAuth | 
|  resource  | cadena | No | - | Recurso de OAuth | 
|  tokenApiAuth  | matriz | No | - | Métodos de autenticación de la API del token: BASIC\$1AUTH\$1HEADER, REQUEST\$1BODY | 
|  tokenCacheTtl  | entero | No | 3600 | TTL de caché de token (mínimo 60 segundos) | 

 **Ejemplo** 

```
{
  "type": "OAUTH_CLIENT_CREDENTIALS",
  "tokenUrl": "https://auth.example.com/oauth/token",
  "clientId": "${AWS_SECRET:oauth-creds:client_id}",
  "clientSecret": "${AWS_SECRET:oauth-creds:client_secret}",
  "scope": "read write",
  "tokenCacheTtl": 7200
}
```

 **AWS Signature (Versión 4)** 


| Propiedad | Tipo | Obligatorio | Descripción | 
| --- | --- | --- | --- | 
|  type  | string |  Sí  | Debe ser "SIGV4" | 
|  service  | cadena |  Sí  | Nombre del servicio de AWS (por ejemplo, “execute-api”») | 
|  region  | cadena |  Sí  | AWS región | 
|  roleArn  | cadena |  Sí  | ARN del rol de IAM para la firma | 

 **Ejemplo** 

```
{
  "type": "SIGV4",
  "service": "execute-api",
  "region": "us-east-1",
  "roleArn": "arn:aws:iam::123456789012:role/SyntheticsRole"
}
```

## Aserciones y validación
<a name="assertions-validation"></a>

### Aserciones HTTP
<a name="http-assertions"></a>

 **Aserciones de código de estado** 


| Propiedad | Tipo | Obligatorio | Descripción | 
| --- | --- | --- | --- | 
|  type  | string |  Sí  | Debe ser "STATUS\$1CODE" | 
|  operator  | cadena |  Sí  | EQUALS, NOT\$1EQUALS, GREATER\$1THAN,  LESS\$1THAN, IN\$1RANGE | 
|  value  | entero | Condicional | Código de estado HTTP (100-599) | 
|  rangeMin  | entero | Condicional | Valor de intervalo mínimo (para IN\$1RANGE) | 
|  rangeMax  | entero | Condicional | Valor de intervalo máximo (para IN\$1RANGE) | 

```
{
  "type": "STATUS_CODE",
  "operator": "EQUALS",
  "value": 200
}
```

 **Aserciones de tiempo de respuesta** 


| Propiedad | Tipo | Obligatorio/a | Predeterminado | Descripción | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Sí  | - | Debe ser "RESPONSE\$1TIME" | 
|  operator  | cadena |  Sí  | - | LESS\$1THAN, GREATER\$1THAN, EQUALS | 
|  value  | número |  Sí  | - | Valor de tiempo (mínimo 0) | 
|  unit  | cadena | No | “MILLISECONDS” | Debe ser "MILLISECONDS" | 

```
{
  "type": "RESPONSE_TIME",
  "operator": "LESS_THAN",
  "value": 500,
  "unit": "MILLISECONDS"
}
```

 **Aserciones de encabezado** 


| Propiedad | Tipo | Obligatorio | Descripción | 
| --- | --- | --- | --- | 
|  type  | string |  Sí  | Debe ser "HEADER" | 
|  headerName  | cadena |  Sí  | Nombre del encabezado que se validará | 
|  operator  | cadena |  Sí  | EQUALS, NOT\$1EQUALS, CONTAINS,  NOT\$1CONTAINS, REGEX\$1MATCH, EXIST | 
|  value  | Cadena o booleano | Condicional | Valor esperado (booleano para el operador EXIST) | 

```
{
  "type": "HEADER",
  "headerName": "Content-Type",
  "operator": "CONTAINS",
  "value": "application/json"
}
```

 **Aserciones de cuerpo** 


| Propiedad | Tipo | Obligatorio/a | Predeterminado | Descripción | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Sí  | - | Debe ser "BODY" | 
|  target  | cadena | No | “JSON” | JSON o TEXT | 
|  path  | cadena | Condicional | - | JSONPath (obligatorio para el destino JSON) | 
|  operator  | cadena |  Sí  | - | CONTAINS, NOT\$1CONTAINS, EQUALS,  NOT\$1EQUALS, EXISTS | 
|  value  | Cadena o booleano |  Sí  | - | Valor esperado (booleano para el operador EXISTS) | 

```
{
  "type": "BODY",
  "target": "JSON",
  "path": "$.users[0].name",
  "operator": "EQUALS",
  "value": "John Doe"
}
```

### Aserciones de DNS
<a name="dns-assertions"></a>

 **Aserciones de valor de registro** 


| Propiedad | Tipo | Obligatorio/a | Range | Descripción | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Sí  | - | Debe ser "RECORD\$1VALUE" | 
|  operator  | cadena |  Sí  | - | EQUALS, NOT\$1EQUALS, CONTAINS,  NOT\$1CONTAINS, REGEX\$1MATCH | 
|  value  | cadena |  Sí  | - | Valor de registro esperado | 

 **Aserciones de recuento de registros** 


| Propiedad | Tipo | Obligatorio/a | Range | Descripción | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Sí  | - | Debe ser "RECORD\$1COUNT" | 
|  operator  | cadena |  Sí  | - | EQUALS, GREATER\$1THAN, LESS\$1THAN | 
|  value  | entero |  Sí  | ≥ 0 | Recuento esperado (mínimo 0) | 

 **Aserciones autoritarias** 


| Propiedad | Tipo | Obligatorio/a | Range | Descripción | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Sí  | - | Debe ser "AUTHORITATIVE" | 
|  value  | booleano |  Sí  | - | Estado autoritario esperado | 

 **Aserciones TTL** 


| Propiedad | Tipo | Obligatorio/a | Range | Descripción | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Sí  | - | Debe ser "TTL" | 
|  operator  | cadena |  Sí  | - | EQUALS, GREATER\$1THAN, LESS\$1THAN | 
|  value  | entero |  Sí  | ≥ 0 | TTL esperado (mínimo 0) | 

### Aserciones SSL
<a name="ssl-assertions"></a>

 **Aserciones de expiración de certificados** 


| Propiedad | Tipo | Obligatorio/a | Predeterminado | Descripción | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Sí  | - | Debe ser "CERTIFICATE\$1EXPIRY" | 
|  operator  | cadena |  Sí  | - | GREATER\$1THAN, LESS\$1THAN | 
|  value  | entero |  Sí  | - | Valor de tiempo (mínimo 0) | 
|  unit  | cadena | No | “DAYS” | DAYS, HOURS | 

 **Aserciones de asunto de certificado** 


| Propiedad | Tipo | Obligatorio/a | Predeterminado | Descripción | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Sí  | - | Debe ser "CERTIFICATE\$1SUBJECT" | 
|  field  | cadena |  Sí  | - | Campo de asunto: CN, O, OU, C, ST, L | 
|  operator  | cadena |  Sí  | - | CONTAINS, EQUALS, REGEX\$1MATCH | 
|  value  | cadena |  Sí  | - | Valor de campo esperado | 

 **Aserciones de emisor de certificado** 


| Propiedad | Tipo | Obligatorio/a | Predeterminado | Descripción | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Sí  | - | Debe ser "CERTIFICATE\$1ISSUER" | 
|  field  | cadena |  Sí  | - | Campo emisor: CN, O | 
|  operator  | cadena |  Sí  | - | CONTAINS, EQUALS | 
|  value  | cadena |  Sí  | - | Valor de campo esperado | 

### Aserciones TCP
<a name="tcp-assertions"></a>

 **Aserciones de éxito de conexión** 


| Propiedad | Tipo | Obligatorio/a | Predeterminado | Descripción | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Sí  | - | Debe ser "CONNECTION\$1SUCCESSFUL" | 
|  value  | booleano |  Sí  | - | Estado de conexión esperado | 

 **Aserciones de datos de respuesta** 


| Propiedad | Tipo | Obligatorio/a | Predeterminado | Descripción | 
| --- | --- | --- | --- | --- | 
|  type  | string |  Sí  | - | Debe ser "RESPONSE\$1DATA" | 
|  operator  | cadena |  Sí  | - | CONTAINS, EQUALS, NOT\$1CONTAINS,  REGEX\$1MATCH, STARTS\$1WITH, ENDS\$1WITH | 
|  value  | cadena |  Sí  | - | Datos de respuesta esperados | 
|  encoding  | cadena | No | “UTF-8” | UTF-8, ASCII, HEX | 

## Extracción de datos
<a name="data-extraction"></a>

Los extractores permiten capturar datos de las respuestas para usarlos en pasos posteriores o con fines de elaboración de informes.

 **Propiedades de extracción** 


| Propiedad | Tipo | Obligatorio/a | Predeterminado | Descripción | 
| --- | --- | --- | --- | --- | 
|  name  | string |  Sí  | - | Nombre de variable para datos extraídos | 
|  type  | cadena |  Sí  | - | Tipo de extracción: BODY | 
|  path  | cadena | No | - | JSONPath para la extracción de cuerpo | 
|  regex  | cadena | No | - | Patrón de expresión regular | 
|  regexGroup  | entero | No | 0 | Grupo de captura de expresión regular (mínimo 0) | 

 **Validación de nombre de extracción** 
+ Patrón: `^[a-zA-Z][a-zA-Z0-9_]*$`
+ Letra como carácter inicial
+ Pueden contener letras, números y guiones bajos.

**Limitación**: la sustitución no se aplica a los campos del esquema que tengan valores ENUM específicos.

 **Tipos de extracción** 

```
{
  "name": "userId",
  "type": "BODY",
  "path": "$.user.id"
}
```

```
{
  "stepName": "loginAndExtract",
  "checkerType": "HTTP",
  "url": "https://api.example.com/login",
  "httpMethod": "POST",
  "body": "{\"username\":\"test\",\"password\":\"pass\"}",
  "extractors": [
    {
      "name": "textVariable",
      "type": "BODY",
      "path": "$.myvalue"
    }
  ]
},
{
  "stepName": "substituteVariable",
  "checkerType": "HTTP",
  "url": "https://api.example.com/get/${textVariable}",
  "httpMethod": "GET",
  "assertions": [
    {
    "type": "BODY",
    "target": "JSON",
    "path": "$.users[0].name",
    "operator": "EQUALS",
    "value": "${textVariable}"
    }
  ]
}
```