

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 Java 執行時期撰寫 Canary 指令碼
<a name="Synthetics_WritingCanary_Java"></a>

**Topics**
+ [

## Canary 的 Java 專案結構
](#Synthetics_canary_Java_package)
+ [

## 封裝 Canary 的專案
](#Synthetics_canary_Java_package_canary)
+ [

## 處理常式名稱
](#Synthetics_canary_Java_handler)
+ [

## CloudWatch Synthetics 組態
](#Synthetics_canary_Java_config)
+ [

## CloudWatch Synthetics 環境變數
](#Synthetics_canary_Java_variables)

## Canary 的 Java 專案結構
<a name="Synthetics_canary_Java_package"></a>

若要在 Java 中建立 Canary，需要撰寫程式碼、編譯程式碼，然後將編譯的成品部署到 Synthetics。可以透過各種方式初始化 Java Lambda 專案。舉例來說，您可以在偏好的 IDE 中使用標準 Java 專案設定，例如 IntelliJ IDEA 或 Visual Studio Code。或者，您可以手動建立所需的檔案結構。

Synthetics Java 專案包含下列一般結構：

```
/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
```

可以使用 Maven 或 Gradle 建置專案並管理相依項。

在上述結構中，`ExampleCanary` 類別是 Canary 的進入點或處理常式。

 **Java Canary 類別範例** 

此範例可讓 Canary 對存放在 *TESTING\$1URL* Lambda 環境變數中的 URL 提出取得請求。Canary 不會使用 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);
      }
  }
}
```

強烈建議您使用 Synthetics 提供的程式庫函式 `executeStep` 模組化您的 Canary。Canary 會向從環境變數 URL1 和 URL2 取得的兩個獨立 URL 發起 `get` 呼叫。

**注意**  
若要使用 `executeStep` 功能，Canary 的處理常式方法應採用 Synthetics 類型的參數，如下所示。

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

## 封裝 Canary 的專案
<a name="Synthetics_canary_Java_package_canary"></a>

Synthetics 接受 *zip* 格式的 Java Canary 程式碼。zip 包含 Canary 程式碼的類別檔案、任何第三方相依項的 jar 以及 Synthetics 設定檔。

Synthetics Java zip 包含下列一般結構。

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

若要從上述專案結構建置此 zip，可以使用 gradle (build.gradle) 或 maven (pom.xml)。請見此處範例。

如需有關編譯 Synthetics 程式庫的時間相依性或界面的資訊，請參閱 [ aws-cloudwatch-synthetics-sdk-java ](https://github.com/aws/aws-cloudwatch-synthetics-sdk-java/tree/main)下的 README。

```
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"
}
```

## 處理常式名稱
<a name="Synthetics_canary_Java_handler"></a>

處理常式名稱是 Canary 的進入點。對於 Java 執行時期，處理常式的格式如下。

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

## CloudWatch Synthetics 組態
<a name="Synthetics_canary_Java_config"></a>

您可以提供名為 `synthetics.json` 的選用 JSON 設定檔，設定 Synthetics Java 執行時期的行為。此檔案應該封裝在套件 zip 的根目錄中。雖然設定檔是選用的，但如果您未提供設定檔，或者設定金鑰缺失，CloudWatch 會使用預設值。

以下是支援的組態值及其預設值。

```
{
    "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
    }
}
```

 **步驟組態** 
+ *continueOnStepFailure*：確定指令碼是否應在步驟失敗後繼續。預設值為 false。
+ *stepSuccessMetric*：確定是否發出步驟的 ` SuccessPercent` 指標。如果步驟成功，步驟的`SuccessPercent`指標為 *100*，如果步驟失敗，則為 * 0*。預設值為 *true*。
+ *stepDurationMetric* – 判斷是否發出步驟的*持續時間*指標。*持續時間*指標以步驟執行的持續時間發出，以毫秒為單位。預設值為 * true*。

 **記錄組態** 

適用於 CloudWatch Synthetics 產生的日誌。控制請求和回應日誌的詳盡程度。
+ *logRequest*：指定是否要在 Canary 日誌中記錄每個請求。預設值為 false。
+ *logResponse*：指定是否要在 Canary 日誌中記錄每個回應。預設值為 false。

 **HTTP 指標組態** 

與具有不同 HTTP 狀態碼之網路請求計數相關的指標組態，由 CloudWatch Synthetics 針對此 Canary 發出。
+ *metric\$12xx* – 指定是否要為此 Canary 發出 * 2xx* 指標 （使用 CanaryName 維度）。預設值為 *true*。
+ *metric\$14xx* – 指定是否要為此 Canary 發出 * 4xx* 指標 （使用 CanaryName 維度）。預設值為 *true*。
+ *metric\$15xx* – 指定是否要為此 Canary 發出 * 5xx* 指標 （使用 CanaryName 維度）。預設值為 *true*。
+ *aggregated2xxMetric* – 指定是否要為此 Canary 發出 * 2xx* 指標 （不含 CanaryName 維度）。預設值為 *true*。
+ *aggregated4xxMetric* – 指定是否要為此 Canary 發出 * 4xx* 指標 （不含 CanaryName 維度）。預設值為 *true*。
+ *aggregated5xxMetric* – 指定是否要為此 Canary 發出 * 5xx* 指標 （不含 CanaryName 維度）。預設值為 *true*。

 **Canary 指標組態** 

CloudWatch Synthetics 發出之其他指標的組態。
+ *failedCanaryMetric* Network Access Analyzer 指定是否要為此 Canary 發出*失敗*指標 （使用 CanaryName 維度）。預設值為 *true*。
+ *aggregatedFailedCanaryMetric*：指定是否要為此 Canary 發出*失敗*指標 (不含 CanaryName 維度)。預設值為 *true*。

## CloudWatch Synthetics 環境變數
<a name="Synthetics_canary_Java_variables"></a>

您可以使用環境變數來設定記錄層級和格式。

 **日誌格式** 

CloudWatch Synthetics Java 執行時期會為每個 Canary 執行建立 CloudWatch 日誌。日誌以 JSON 格式撰寫，方便查詢。或者，您可以將日誌格式變更為 *TEXT*。
+ *環境變數名稱* – CW\$1SYNTHETICS\$1LOG\$1FORMAT
+ *支援的值* – JSON、TEXT
+ *預設值* – JSON

 **日誌層級** 
+ *環境變數名稱* – CW\$1SYNTHETICS\$1LOG\$1LEVEL
+ *支援的值* – TRACE、DEBUG、INFO、WARN、ERROR、FATAL
+ *預設值* – INFO

除了上述環境變數之外，還會為 Java 執行時期新增預設環境變數、將 `AWS_LAMBDA-EXEC_WRAPPER` 環境變數新增至函式，並將其值設定為 `/opt/synthetics-otel-instrument`。此環境變數會修改函式的啟動行為以進行遙測。如果此環境變數已存在，請確定已將其設定為所需的值。