

# 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.