From 790b5800e868004ad0ea66b1ed843e8e701f7ea5 Mon Sep 17 00:00:00 2001 From: Scott Macdonald <57190223+scmacdon@users.noreply.github.com> Date: Thu, 3 Oct 2024 09:48:34 -0400 Subject: [PATCH] Update the CloudWatch scenario to meet Java standards (#6898) --- .doc_gen/metadata/cloudwatch_metadata.yaml | 12 +- javav2/example_code/cloudwatch/README.md | 34 +- javav2/example_code/cloudwatch/pom.xml | 38 +- .../cloudwatch/CloudWatchScenario.java | 945 -------------- .../com/example/cloudwatch/DeleteAlarm.java | 64 - .../example/cloudwatch/DescribeAlarms.java | 69 -- .../com/example/cloudwatch/GetMetricData.java | 87 -- .../com/example/cloudwatch/ListMetrics.java | 91 -- .../example/cloudwatch/PutMetricAlarm.java | 84 -- .../com/example/cloudwatch/PutMetricData.java | 86 -- .../scenario/CloudWatchActions.java | 1082 +++++++++++++++++ .../scenario/CloudWatchScenario.java | 614 ++++++++++ .../cloudwatch/src/main/resources/log4j2.xml | 15 + .../src/test/java/CloudWatchTest.java | 398 +++--- 14 files changed, 1964 insertions(+), 1655 deletions(-) delete mode 100644 javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/CloudWatchScenario.java delete mode 100644 javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/DeleteAlarm.java delete mode 100644 javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/DescribeAlarms.java delete mode 100644 javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/GetMetricData.java delete mode 100644 javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/ListMetrics.java delete mode 100644 javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutMetricAlarm.java delete mode 100644 javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutMetricData.java create mode 100644 javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java create mode 100644 javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/scenario/CloudWatchScenario.java create mode 100644 javav2/example_code/cloudwatch/src/main/resources/log4j2.xml diff --git a/.doc_gen/metadata/cloudwatch_metadata.yaml b/.doc_gen/metadata/cloudwatch_metadata.yaml index e79cea8f9c0..326d0b3c015 100644 --- a/.doc_gen/metadata/cloudwatch_metadata.yaml +++ b/.doc_gen/metadata/cloudwatch_metadata.yaml @@ -61,7 +61,7 @@ cloudwatch_DeleteAlarms: excerpts: - description: snippet_tags: - - cloudwatch.java2.delete_metrics.main + - cloudwatch.java2.delete_alarm.main Python: versions: - sdk_version: 3 @@ -227,7 +227,7 @@ cloudwatch_DescribeAlarms: excerpts: - description: snippet_tags: - - cloudwatch.java2.scenario.describe.alarm.main + - cloudwatch.java2.describe_alarms.main .NET: versions: - sdk_version: 3 @@ -1026,6 +1026,7 @@ cloudwatch_PutMetricData: services: cloudwatch: {PutMetricData} cloudwatch_GetStartedMetricsDashboardsAlarms: + title: Learn core operations for &CW; using an &AWS; SDK synopsis_list: - List &CW; namespaces and metrics. - Get statistics for a metric and for estimated billing. @@ -1042,7 +1043,7 @@ cloudwatch_GetStartedMetricsDashboardsAlarms: github: kotlin/services/cloudwatch sdkguide: excerpts: - - description: + - description: Run an interactive scenario demonstrating &CW; features. snippet_tags: - cloudwatch.kotlin.scenario.main Java: @@ -1051,9 +1052,12 @@ cloudwatch_GetStartedMetricsDashboardsAlarms: github: javav2/example_code/cloudwatch sdkguide: excerpts: - - description: + - description: Run an interactive scenario demonstrating &CW; features. snippet_tags: - cloudwatch.java2.scenario.main + - description: A wrapper class for &CW; SDK methods. + snippet_tags: + - cloudwatch.java2.actions.main .NET: versions: - sdk_version: 3 diff --git a/javav2/example_code/cloudwatch/README.md b/javav2/example_code/cloudwatch/README.md index 05909e57cda..d04e4bcb3a1 100644 --- a/javav2/example_code/cloudwatch/README.md +++ b/javav2/example_code/cloudwatch/README.md @@ -38,31 +38,31 @@ For prerequisites, see the [README](../../README.md#Prerequisites) in the `javav Code examples that show you how to perform the essential operations within a service. -- [Learn the basics](src/main/java/com/example/cloudwatch/CloudWatchScenario.java) +- [Learn the basics](src/main/java/com/example/cloudwatch/scenario/CloudWatchScenario.java) ### Single actions Code excerpts that show you how to call individual service functions. -- [DeleteAlarms](src/main/java/com/example/cloudwatch/DeleteAlarm.java#L6) -- [DeleteAnomalyDetector](src/main/java/com/example/cloudwatch/CloudWatchScenario.java#L299) -- [DeleteDashboards](src/main/java/com/example/cloudwatch/CloudWatchScenario.java#L347) -- [DescribeAlarmHistory](src/main/java/com/example/cloudwatch/CloudWatchScenario.java#L460) -- [DescribeAlarms](src/main/java/com/example/cloudwatch/CloudWatchScenario.java#L635) -- [DescribeAlarmsForMetric](src/main/java/com/example/cloudwatch/CloudWatchScenario.java#L495) -- [DescribeAnomalyDetectors](src/main/java/com/example/cloudwatch/CloudWatchScenario.java#L403) +- [DeleteAlarms](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L169) +- [DeleteAnomalyDetector](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L127) +- [DeleteDashboards](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L194) +- [DescribeAlarmHistory](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L372) +- [DescribeAlarms](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L658) +- [DescribeAlarmsForMetric](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L433) +- [DescribeAnomalyDetectors](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L276) - [DisableAlarmActions](src/main/java/com/example/cloudwatch/DisableAlarmActions.java#L6) - [EnableAlarmActions](src/main/java/com/example/cloudwatch/EnableAlarmActions.java#L6) -- [GetMetricData](src/main/java/com/example/cloudwatch/CloudWatchScenario.java#L576) -- [GetMetricStatistics](src/main/java/com/example/cloudwatch/CloudWatchScenario.java#L843) -- [GetMetricWidgetImage](src/main/java/com/example/cloudwatch/CloudWatchScenario.java#L363) -- [ListDashboards](src/main/java/com/example/cloudwatch/CloudWatchScenario.java#L755) -- [ListMetrics](src/main/java/com/example/cloudwatch/ListMetrics.java#L6) -- [PutAnomalyDetector](src/main/java/com/example/cloudwatch/CloudWatchScenario.java#L431) -- [PutDashboard](src/main/java/com/example/cloudwatch/CloudWatchScenario.java#L773) -- [PutMetricAlarm](src/main/java/com/example/cloudwatch/CloudWatchScenario.java#L659) -- [PutMetricData](src/main/java/com/example/cloudwatch/CloudWatchScenario.java#L530) +- [GetMetricData](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L579) +- [GetMetricStatistics](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L940) +- [GetMetricWidgetImage](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L218) +- [ListDashboards](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L828) +- [ListMetrics](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L990) +- [PutAnomalyDetector](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L325) +- [PutDashboard](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L850) +- [PutMetricAlarm](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L693) +- [PutMetricData](src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java#L510) diff --git a/javav2/example_code/cloudwatch/pom.xml b/javav2/example_code/cloudwatch/pom.xml index 9b4ec469207..4a906a73557 100755 --- a/javav2/example_code/cloudwatch/pom.xml +++ b/javav2/example_code/cloudwatch/pom.xml @@ -29,7 +29,14 @@ software.amazon.awssdk bom - 2.21.20 + 2.26.15 + pom + import + + + org.apache.logging.log4j + log4j-bom + 2.23.1 pom import @@ -90,5 +97,34 @@ software.amazon.awssdk cloudwatchlogs + + software.amazon.awssdk + sso + + + software.amazon.awssdk + ssooidc + + + org.apache.logging.log4j + log4j-core + + + software.amazon.awssdk + netty-nio-client + + + org.slf4j + slf4j-api + 2.0.13 + + + org.apache.logging.log4j + log4j-slf4j2-impl + + + org.apache.logging.log4j + log4j-1.2-api + \ No newline at end of file diff --git a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/CloudWatchScenario.java b/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/CloudWatchScenario.java deleted file mode 100644 index dece8a435af..00000000000 --- a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/CloudWatchScenario.java +++ /dev/null @@ -1,945 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.example.cloudwatch; - -// snippet-start:[cloudwatch.java2.scenario.main] -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.ObjectMapper; -import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; -import software.amazon.awssdk.core.SdkBytes; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.cloudwatch.CloudWatchClient; -import software.amazon.awssdk.services.cloudwatch.model.AlarmHistoryItem; -import software.amazon.awssdk.services.cloudwatch.model.AlarmType; -import software.amazon.awssdk.services.cloudwatch.model.AnomalyDetector; -import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException; -import software.amazon.awssdk.services.cloudwatch.model.ComparisonOperator; -import software.amazon.awssdk.services.cloudwatch.model.DashboardValidationMessage; -import software.amazon.awssdk.services.cloudwatch.model.Datapoint; -import software.amazon.awssdk.services.cloudwatch.model.DeleteAlarmsRequest; -import software.amazon.awssdk.services.cloudwatch.model.DeleteAnomalyDetectorRequest; -import software.amazon.awssdk.services.cloudwatch.model.DeleteDashboardsRequest; -import software.amazon.awssdk.services.cloudwatch.model.DescribeAlarmHistoryRequest; -import software.amazon.awssdk.services.cloudwatch.model.DescribeAlarmHistoryResponse; -import software.amazon.awssdk.services.cloudwatch.model.DescribeAlarmsForMetricRequest; -import software.amazon.awssdk.services.cloudwatch.model.DescribeAlarmsForMetricResponse; -import software.amazon.awssdk.services.cloudwatch.model.DescribeAlarmsRequest; -import software.amazon.awssdk.services.cloudwatch.model.DescribeAlarmsResponse; -import software.amazon.awssdk.services.cloudwatch.model.DescribeAnomalyDetectorsRequest; -import software.amazon.awssdk.services.cloudwatch.model.DescribeAnomalyDetectorsResponse; -import software.amazon.awssdk.services.cloudwatch.model.Dimension; -import software.amazon.awssdk.services.cloudwatch.model.GetMetricDataRequest; -import software.amazon.awssdk.services.cloudwatch.model.GetMetricDataResponse; -import software.amazon.awssdk.services.cloudwatch.model.GetMetricStatisticsRequest; -import software.amazon.awssdk.services.cloudwatch.model.GetMetricStatisticsResponse; -import software.amazon.awssdk.services.cloudwatch.model.GetMetricWidgetImageRequest; -import software.amazon.awssdk.services.cloudwatch.model.GetMetricWidgetImageResponse; -import software.amazon.awssdk.services.cloudwatch.model.HistoryItemType; -import software.amazon.awssdk.services.cloudwatch.model.ListMetricsRequest; -import software.amazon.awssdk.services.cloudwatch.model.ListMetricsResponse; -import software.amazon.awssdk.services.cloudwatch.model.Metric; -import software.amazon.awssdk.services.cloudwatch.model.MetricAlarm; -import software.amazon.awssdk.services.cloudwatch.model.MetricDataQuery; -import software.amazon.awssdk.services.cloudwatch.model.MetricDataResult; -import software.amazon.awssdk.services.cloudwatch.model.MetricDatum; -import software.amazon.awssdk.services.cloudwatch.model.MetricStat; -import software.amazon.awssdk.services.cloudwatch.model.PutAnomalyDetectorRequest; -import software.amazon.awssdk.services.cloudwatch.model.PutDashboardRequest; -import software.amazon.awssdk.services.cloudwatch.model.PutDashboardResponse; -import software.amazon.awssdk.services.cloudwatch.model.PutMetricAlarmRequest; -import software.amazon.awssdk.services.cloudwatch.model.PutMetricDataRequest; -import software.amazon.awssdk.services.cloudwatch.model.ScanBy; -import software.amazon.awssdk.services.cloudwatch.model.SingleMetricAnomalyDetector; -import software.amazon.awssdk.services.cloudwatch.model.StandardUnit; -import software.amazon.awssdk.services.cloudwatch.model.Statistic; -import software.amazon.awssdk.services.cloudwatch.paginators.ListDashboardsIterable; -import software.amazon.awssdk.services.cloudwatch.paginators.ListMetricsIterable; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoUnit; -import java.util.ArrayList; -import java.util.List; -import java.util.Scanner; - -/** - * Before running this Java V2 code example, set up your development - * environment, including your credentials. - * - * For more information, see the following documentation topic: - * - * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html - * - * To enable billing metrics and statistics for this example, make sure billing - * alerts are enabled for your account: - * https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html#turning_on_billing_metrics - * - * This Java code example performs the following tasks: - * - * 1. List available namespaces from Amazon CloudWatch. - * 2. List available metrics within the selected Namespace. - * 3. Get statistics for the selected metric over the last day. - * 4. Get CloudWatch estimated billing for the last week. - * 5. Create a new CloudWatch dashboard with metrics. - * 6. List dashboards using a paginator. - * 7. Create a new custom metric by adding data for it. - * 8. Add the custom metric to the dashboard. - * 9. Create an alarm for the custom metric. - * 10. Describe current alarms. - * 11. Get current data for the new custom metric. - * 12. Push data into the custom metric to trigger the alarm. - * 13. Check the alarm state using the action DescribeAlarmsForMetric. - * 14. Get alarm history for the new alarm. - * 15. Add an anomaly detector for the custom metric. - * 16. Describe current anomaly detectors. - * 17. Get a metric image for the custom metric. - * 18. Clean up the Amazon CloudWatch resources. - */ -public class CloudWatchScenario { - public static final String DASHES = new String(new char[80]).replace("\0", "-"); - - public static void main(String[] args) throws IOException { - final String usage = """ - - Usage: - \s - - Where: - myDate - The start date to use to get metric statistics. (For example, 2023-01-11T18:35:24.00Z.)\s - costDateWeek - The start date to use to get AWS/Billinget statistics. (For example, 2023-01-11T18:35:24.00Z.)\s - dashboardName - The name of the dashboard to create.\s - dashboardJson - The location of a JSON file to use to create a dashboard. (See Readme file.)\s - dashboardAdd - The location of a JSON file to use to update a dashboard. (See Readme file.)\s - settings - The location of a JSON file from which various values are read. (See Readme file.)\s - metricImage - The location of a BMP file that is used to create a graph.\s - """; - - if (args.length != 7) { - System.out.println(usage); - System.exit(1); - } - - Region region = Region.US_EAST_1; - String myDate = args[0]; - String costDateWeek = args[1]; - String dashboardName = args[2]; - String dashboardJson = args[3]; - String dashboardAdd = args[4]; - String settings = args[5]; - String metricImage = args[6]; - - Double dataPoint = Double.parseDouble("10.0"); - Scanner sc = new Scanner(System.in); - CloudWatchClient cw = CloudWatchClient.builder() - .region(region) - .credentialsProvider(ProfileCredentialsProvider.create()) - .build(); - - System.out.println(DASHES); - System.out.println("Welcome to the Amazon CloudWatch example scenario."); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println( - "1. List at least five available unique namespaces from Amazon CloudWatch. Select one from the list."); - ArrayList list = listNameSpaces(cw); - for (int z = 0; z < 5; z++) { - int index = z + 1; - System.out.println(" " + index + ". " + list.get(z)); - } - - String selectedNamespace = ""; - String selectedMetrics = ""; - int num = Integer.parseInt(sc.nextLine()); - if (1 <= num && num <= 5) { - selectedNamespace = list.get(num - 1); - } else { - System.out.println("You did not select a valid option."); - System.exit(1); - } - System.out.println("You selected " + selectedNamespace); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("2. List available metrics within the selected namespace and select one from the list."); - ArrayList metList = listMets(cw, selectedNamespace); - for (int z = 0; z < 5; z++) { - int index = z + 1; - System.out.println(" " + index + ". " + metList.get(z)); - } - num = Integer.parseInt(sc.nextLine()); - if (1 <= num && num <= 5) { - selectedMetrics = metList.get(num - 1); - } else { - System.out.println("You did not select a valid option."); - System.exit(1); - } - System.out.println("You selected " + selectedMetrics); - Dimension myDimension = getSpecificMet(cw, selectedNamespace); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("3. Get statistics for the selected metric over the last day."); - String metricOption = ""; - ArrayList statTypes = new ArrayList<>(); - statTypes.add("SampleCount"); - statTypes.add("Average"); - statTypes.add("Sum"); - statTypes.add("Minimum"); - statTypes.add("Maximum"); - - for (int t = 0; t < 5; t++) { - System.out.println(" " + (t + 1) + ". " + statTypes.get(t)); - } - System.out.println("Select a metric statistic by entering a number from the preceding list:"); - num = Integer.parseInt(sc.nextLine()); - if (1 <= num && num <= 5) { - metricOption = statTypes.get(num - 1); - } else { - System.out.println("You did not select a valid option."); - System.exit(1); - } - System.out.println("You selected " + metricOption); - getAndDisplayMetricStatistics(cw, selectedNamespace, selectedMetrics, metricOption, myDate, myDimension); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("4. Get CloudWatch estimated billing for the last week."); - getMetricStatistics(cw, costDateWeek); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("5. Create a new CloudWatch dashboard with metrics."); - createDashboardWithMetrics(cw, dashboardName, dashboardJson); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("6. List dashboards using a paginator."); - listDashboards(cw); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("7. Create a new custom metric by adding data to it."); - createNewCustomMetric(cw, dataPoint); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("8. Add an additional metric to the dashboard."); - addMetricToDashboard(cw, dashboardAdd, dashboardName); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("9. Create an alarm for the custom metric."); - String alarmName = createAlarm(cw, settings); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("10. Describe ten current alarms."); - describeAlarms(cw); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("11. Get current data for new custom metric."); - getCustomMetricData(cw, settings); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("12. Push data into the custom metric to trigger the alarm."); - addMetricDataForAlarm(cw, settings); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("13. Check the alarm state using the action DescribeAlarmsForMetric."); - checkForMetricAlarm(cw, settings); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("14. Get alarm history for the new alarm."); - getAlarmHistory(cw, settings, myDate); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("15. Add an anomaly detector for the custom metric."); - addAnomalyDetector(cw, settings); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("16. Describe current anomaly detectors."); - describeAnomalyDetectors(cw, settings); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("17. Get a metric image for the custom metric."); - getAndOpenMetricImage(cw, metricImage); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("18. Clean up the Amazon CloudWatch resources."); - deleteDashboard(cw, dashboardName); - deleteCWAlarm(cw, alarmName); - deleteAnomalyDetector(cw, settings); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("The Amazon CloudWatch example scenario is complete."); - System.out.println(DASHES); - cw.close(); - } - - // snippet-start:[cloudwatch.java2.scenario.del.anomalydetector.main] - public static void deleteAnomalyDetector(CloudWatchClient cw, String fileName) { - try { - // Read values from the JSON file. - JsonParser parser = new JsonFactory().createParser(new File(fileName)); - com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(parser); - String customMetricNamespace = rootNode.findValue("customMetricNamespace").asText(); - String customMetricName = rootNode.findValue("customMetricName").asText(); - - SingleMetricAnomalyDetector singleMetricAnomalyDetector = SingleMetricAnomalyDetector.builder() - .metricName(customMetricName) - .namespace(customMetricNamespace) - .stat("Maximum") - .build(); - - DeleteAnomalyDetectorRequest request = DeleteAnomalyDetectorRequest.builder() - .singleMetricAnomalyDetector(singleMetricAnomalyDetector) - .build(); - - cw.deleteAnomalyDetector(request); - System.out.println("Successfully deleted the Anomaly Detector."); - - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } catch (IOException e) { - e.printStackTrace(); - } - } - // snippet-end:[cloudwatch.java2.scenario.del.anomalydetector.main] - - // snippet-start:[cloudwatch.java2.scenario.del.alarm.main] - public static void deleteCWAlarm(CloudWatchClient cw, String alarmName) { - try { - DeleteAlarmsRequest request = DeleteAlarmsRequest.builder() - .alarmNames(alarmName) - .build(); - - cw.deleteAlarms(request); - System.out.println("Successfully deleted alarm " + alarmName); - - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.del.alarm.main] - - // snippet-start:[cloudwatch.java2.scenario.del.dashboard.main] - public static void deleteDashboard(CloudWatchClient cw, String dashboardName) { - try { - DeleteDashboardsRequest dashboardsRequest = DeleteDashboardsRequest.builder() - .dashboardNames(dashboardName) - .build(); - cw.deleteDashboards(dashboardsRequest); - System.out.println(dashboardName + " was successfully deleted."); - - } catch (CloudWatchException e) { - System.err.println(e.getMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.del.dashboard.main] - - // snippet-start:[cloudwatch.java2.scenario.get.metric.image.main] - public static void getAndOpenMetricImage(CloudWatchClient cw, String fileName) { - System.out.println("Getting Image data for custom metric."); - try { - String myJSON = "{\n" + - " \"title\": \"Example Metric Graph\",\n" + - " \"view\": \"timeSeries\",\n" + - " \"stacked \": false,\n" + - " \"period\": 10,\n" + - " \"width\": 1400,\n" + - " \"height\": 600,\n" + - " \"metrics\": [\n" + - " [\n" + - " \"AWS/Billing\",\n" + - " \"EstimatedCharges\",\n" + - " \"Currency\",\n" + - " \"USD\"\n" + - " ]\n" + - " ]\n" + - "}"; - - GetMetricWidgetImageRequest imageRequest = GetMetricWidgetImageRequest.builder() - .metricWidget(myJSON) - .build(); - - GetMetricWidgetImageResponse response = cw.getMetricWidgetImage(imageRequest); - SdkBytes sdkBytes = response.metricWidgetImage(); - byte[] bytes = sdkBytes.asByteArray(); - File outputFile = new File(fileName); - try (FileOutputStream outputStream = new FileOutputStream(outputFile)) { - outputStream.write(bytes); - } - - } catch (CloudWatchException | IOException e) { - System.err.println(e.getMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.get.metric.image.main] - - // snippet-start:[cloudwatch.java2.scenario.describe.anomalydetector.main] - public static void describeAnomalyDetectors(CloudWatchClient cw, String fileName) { - try { - // Read values from the JSON file. - JsonParser parser = new JsonFactory().createParser(new File(fileName)); - com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(parser); - String customMetricNamespace = rootNode.findValue("customMetricNamespace").asText(); - String customMetricName = rootNode.findValue("customMetricName").asText(); - DescribeAnomalyDetectorsRequest detectorsRequest = DescribeAnomalyDetectorsRequest.builder() - .maxResults(10) - .metricName(customMetricName) - .namespace(customMetricNamespace) - .build(); - - DescribeAnomalyDetectorsResponse response = cw.describeAnomalyDetectors(detectorsRequest); - List anomalyDetectorList = response.anomalyDetectors(); - for (AnomalyDetector detector : anomalyDetectorList) { - System.out.println("Metric name: " + detector.singleMetricAnomalyDetector().metricName()); - System.out.println("State: " + detector.stateValue()); - } - - } catch (CloudWatchException | IOException e) { - System.err.println(e.getMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.describe.anomalydetector.main] - - // snippet-start:[cloudwatch.java2.scenario.add.anomalydetector.main] - public static void addAnomalyDetector(CloudWatchClient cw, String fileName) { - try { - // Read values from the JSON file. - JsonParser parser = new JsonFactory().createParser(new File(fileName)); - com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(parser); - String customMetricNamespace = rootNode.findValue("customMetricNamespace").asText(); - String customMetricName = rootNode.findValue("customMetricName").asText(); - - SingleMetricAnomalyDetector singleMetricAnomalyDetector = SingleMetricAnomalyDetector.builder() - .metricName(customMetricName) - .namespace(customMetricNamespace) - .stat("Maximum") - .build(); - - PutAnomalyDetectorRequest anomalyDetectorRequest = PutAnomalyDetectorRequest.builder() - .singleMetricAnomalyDetector(singleMetricAnomalyDetector) - .build(); - - cw.putAnomalyDetector(anomalyDetectorRequest); - System.out.println("Added anomaly detector for metric " + customMetricName + "."); - - } catch (CloudWatchException | IOException e) { - System.err.println(e.getMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.add.anomalydetector.main] - - // snippet-start:[cloudwatch.java2.scenario.get.alarm.history.main] - public static void getAlarmHistory(CloudWatchClient cw, String fileName, String date) { - try { - // Read values from the JSON file. - JsonParser parser = new JsonFactory().createParser(new File(fileName)); - com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(parser); - String alarmName = rootNode.findValue("exampleAlarmName").asText(); - - Instant start = Instant.parse(date); - Instant endDate = Instant.now(); - DescribeAlarmHistoryRequest historyRequest = DescribeAlarmHistoryRequest.builder() - .startDate(start) - .endDate(endDate) - .alarmName(alarmName) - .historyItemType(HistoryItemType.ACTION) - .build(); - - DescribeAlarmHistoryResponse response = cw.describeAlarmHistory(historyRequest); - List historyItems = response.alarmHistoryItems(); - if (historyItems.isEmpty()) { - System.out.println("No alarm history data found for " + alarmName + "."); - } else { - for (AlarmHistoryItem item : historyItems) { - System.out.println("History summary: " + item.historySummary()); - System.out.println("Time stamp: " + item.timestamp()); - } - } - - } catch (CloudWatchException | IOException e) { - System.err.println(e.getMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.get.alarm.history.main] - - // snippet-start:[cloudwatch.java2.scenario.check.met.alarm.main] - public static void checkForMetricAlarm(CloudWatchClient cw, String fileName) { - try { - // Read values from the JSON file. - JsonParser parser = new JsonFactory().createParser(new File(fileName)); - com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(parser); - String customMetricNamespace = rootNode.findValue("customMetricNamespace").asText(); - String customMetricName = rootNode.findValue("customMetricName").asText(); - boolean hasAlarm = false; - int retries = 10; - - DescribeAlarmsForMetricRequest metricRequest = DescribeAlarmsForMetricRequest.builder() - .metricName(customMetricName) - .namespace(customMetricNamespace) - .build(); - - while (!hasAlarm && retries > 0) { - DescribeAlarmsForMetricResponse response = cw.describeAlarmsForMetric(metricRequest); - hasAlarm = response.hasMetricAlarms(); - retries--; - Thread.sleep(20000); - System.out.println("."); - } - if (!hasAlarm) - System.out.println("No Alarm state found for " + customMetricName + " after 10 retries."); - else - System.out.println("Alarm state found for " + customMetricName + "."); - - } catch (CloudWatchException | IOException | InterruptedException e) { - System.err.println(e.getMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.check.met.alarm.main] - - // snippet-start:[cloudwatch.java2.scenario.add.met.alarm.main] - public static void addMetricDataForAlarm(CloudWatchClient cw, String fileName) { - try { - // Read values from the JSON file. - JsonParser parser = new JsonFactory().createParser(new File(fileName)); - com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(parser); - String customMetricNamespace = rootNode.findValue("customMetricNamespace").asText(); - String customMetricName = rootNode.findValue("customMetricName").asText(); - - // Set an Instant object. - String time = ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT); - Instant instant = Instant.parse(time); - - MetricDatum datum = MetricDatum.builder() - .metricName(customMetricName) - .unit(StandardUnit.NONE) - .value(1001.00) - .timestamp(instant) - .build(); - - MetricDatum datum2 = MetricDatum.builder() - .metricName(customMetricName) - .unit(StandardUnit.NONE) - .value(1002.00) - .timestamp(instant) - .build(); - - List metricDataList = new ArrayList<>(); - metricDataList.add(datum); - metricDataList.add(datum2); - - PutMetricDataRequest request = PutMetricDataRequest.builder() - .namespace(customMetricNamespace) - .metricData(metricDataList) - .build(); - - cw.putMetricData(request); - System.out.println("Added metric values for for metric " + customMetricName); - - } catch (CloudWatchException | IOException e) { - System.err.println(e.getMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.add.met.alarm.main] - - // snippet-start:[cloudwatch.java2.scenario.get.met.data.main] - public static void getCustomMetricData(CloudWatchClient cw, String fileName) { - try { - // Read values from the JSON file. - JsonParser parser = new JsonFactory().createParser(new File(fileName)); - com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(parser); - String customMetricNamespace = rootNode.findValue("customMetricNamespace").asText(); - String customMetricName = rootNode.findValue("customMetricName").asText(); - - // Set the date. - Instant nowDate = Instant.now(); - - long hours = 1; - long minutes = 30; - Instant date2 = nowDate.plus(hours, ChronoUnit.HOURS).plus(minutes, - ChronoUnit.MINUTES); - - Metric met = Metric.builder() - .metricName(customMetricName) - .namespace(customMetricNamespace) - .build(); - - MetricStat metStat = MetricStat.builder() - .stat("Maximum") - .period(1) - .metric(met) - .build(); - - MetricDataQuery dataQUery = MetricDataQuery.builder() - .metricStat(metStat) - .id("foo2") - .returnData(true) - .build(); - - List dq = new ArrayList<>(); - dq.add(dataQUery); - - GetMetricDataRequest getMetReq = GetMetricDataRequest.builder() - .maxDatapoints(10) - .scanBy(ScanBy.TIMESTAMP_DESCENDING) - .startTime(nowDate) - .endTime(date2) - .metricDataQueries(dq) - .build(); - - GetMetricDataResponse response = cw.getMetricData(getMetReq); - List data = response.metricDataResults(); - for (MetricDataResult item : data) { - System.out.println("The label is " + item.label()); - System.out.println("The status code is " + item.statusCode().toString()); - } - - } catch (CloudWatchException | IOException e) { - System.err.println(e.getMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.get.met.data.main] - - // snippet-start:[cloudwatch.java2.scenario.describe.alarm.main] - public static void describeAlarms(CloudWatchClient cw) { - try { - List typeList = new ArrayList<>(); - typeList.add(AlarmType.METRIC_ALARM); - - DescribeAlarmsRequest alarmsRequest = DescribeAlarmsRequest.builder() - .alarmTypes(typeList) - .maxRecords(10) - .build(); - - DescribeAlarmsResponse response = cw.describeAlarms(alarmsRequest); - List alarmList = response.metricAlarms(); - for (MetricAlarm alarm : alarmList) { - System.out.println("Alarm name: " + alarm.alarmName()); - System.out.println("Alarm description: " + alarm.alarmDescription()); - } - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.describe.alarm.main] - - // snippet-start:[cloudwatch.java2.scenario.create.alarm.main] - public static String createAlarm(CloudWatchClient cw, String fileName) { - try { - // Read values from the JSON file. - JsonParser parser = new JsonFactory().createParser(new File(fileName)); - com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(parser); - String customMetricNamespace = rootNode.findValue("customMetricNamespace").asText(); - String customMetricName = rootNode.findValue("customMetricName").asText(); - String alarmName = rootNode.findValue("exampleAlarmName").asText(); - String emailTopic = rootNode.findValue("emailTopic").asText(); - String accountId = rootNode.findValue("accountId").asText(); - String region = rootNode.findValue("region").asText(); - - // Create a List for alarm actions. - List alarmActions = new ArrayList<>(); - alarmActions.add("arn:aws:sns:" + region + ":" + accountId + ":" + emailTopic); - PutMetricAlarmRequest alarmRequest = PutMetricAlarmRequest.builder() - .alarmActions(alarmActions) - .alarmDescription("Example metric alarm") - .alarmName(alarmName) - .comparisonOperator(ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD) - .threshold(100.00) - .metricName(customMetricName) - .namespace(customMetricNamespace) - .evaluationPeriods(1) - .period(10) - .statistic("Maximum") - .datapointsToAlarm(1) - .treatMissingData("ignore") - .build(); - - cw.putMetricAlarm(alarmRequest); - System.out.println(alarmName + " was successfully created!"); - return alarmName; - - } catch (CloudWatchException | IOException e) { - System.err.println(e.getMessage()); - System.exit(1); - } - return ""; - } - // snippet-end:[cloudwatch.java2.scenario.create.alarm.main] - - // snippet-start:[cloudwatch.java2.scenario.add.metric.dashboard.main] - public static void addMetricToDashboard(CloudWatchClient cw, String fileName, String dashboardName) { - try { - PutDashboardRequest dashboardRequest = PutDashboardRequest.builder() - .dashboardName(dashboardName) - .dashboardBody(readFileAsString(fileName)) - .build(); - - cw.putDashboard(dashboardRequest); - System.out.println(dashboardName + " was successfully updated."); - - } catch (CloudWatchException | IOException e) { - System.err.println(e.getMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.add.metric.dashboard.main] - - // snippet-start:[cloudwatch.java2.scenario.create.metric.main] - public static void createNewCustomMetric(CloudWatchClient cw, Double dataPoint) { - try { - Dimension dimension = Dimension.builder() - .name("UNIQUE_PAGES") - .value("URLS") - .build(); - - // Set an Instant object. - String time = ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT); - Instant instant = Instant.parse(time); - - MetricDatum datum = MetricDatum.builder() - .metricName("PAGES_VISITED") - .unit(StandardUnit.NONE) - .value(dataPoint) - .timestamp(instant) - .dimensions(dimension) - .build(); - - PutMetricDataRequest request = PutMetricDataRequest.builder() - .namespace("SITE/TRAFFIC") - .metricData(datum) - .build(); - - cw.putMetricData(request); - System.out.println("Added metric values for for metric PAGES_VISITED"); - - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.create.metric.main] - - // snippet-start:[cloudwatch.java2.scenario.list.dashboard.main] - public static void listDashboards(CloudWatchClient cw) { - try { - ListDashboardsIterable listRes = cw.listDashboardsPaginator(); - listRes.stream() - .flatMap(r -> r.dashboardEntries().stream()) - .forEach(entry -> { - System.out.println("Dashboard name is: " + entry.dashboardName()); - System.out.println("Dashboard ARN is: " + entry.dashboardArn()); - }); - - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.list.dashboard.main] - - // snippet-start:[cloudwatch.java2.scenario.create.dashboard.main] - public static void createDashboardWithMetrics(CloudWatchClient cw, String dashboardName, String fileName) { - try { - PutDashboardRequest dashboardRequest = PutDashboardRequest.builder() - .dashboardName(dashboardName) - .dashboardBody(readFileAsString(fileName)) - .build(); - - PutDashboardResponse response = cw.putDashboard(dashboardRequest); - System.out.println(dashboardName + " was successfully created."); - List messages = response.dashboardValidationMessages(); - if (messages.isEmpty()) { - System.out.println("There are no messages in the new Dashboard"); - } else { - for (DashboardValidationMessage message : messages) { - System.out.println("Message is: " + message.message()); - } - } - - } catch (CloudWatchException | IOException e) { - System.err.println(e.getMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.create.dashboard.main] - - public static String readFileAsString(String file) throws IOException { - return new String(Files.readAllBytes(Paths.get(file))); - } - - // snippet-start:[cloudwatch.java2.scenario.get.metrics.main] - public static void getMetricStatistics(CloudWatchClient cw, String costDateWeek) { - try { - Instant start = Instant.parse(costDateWeek); - Instant endDate = Instant.now(); - Dimension dimension = Dimension.builder() - .name("Currency") - .value("USD") - .build(); - - List dimensionList = new ArrayList<>(); - dimensionList.add(dimension); - GetMetricStatisticsRequest statisticsRequest = GetMetricStatisticsRequest.builder() - .metricName("EstimatedCharges") - .namespace("AWS/Billing") - .dimensions(dimensionList) - .statistics(Statistic.MAXIMUM) - .startTime(start) - .endTime(endDate) - .period(86400) - .build(); - - GetMetricStatisticsResponse response = cw.getMetricStatistics(statisticsRequest); - List data = response.datapoints(); - if (!data.isEmpty()) { - for (Datapoint datapoint : data) { - System.out - .println("Timestamp: " + datapoint.timestamp() + " Maximum value: " + datapoint.maximum()); - } - } else { - System.out.println("The returned data list is empty"); - } - - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.get.metrics.main] - - // snippet-start:[cloudwatch.java2.scenario.display.metrics.main] - public static void getAndDisplayMetricStatistics(CloudWatchClient cw, String nameSpace, String metVal, - String metricOption, String date, Dimension myDimension) { - try { - Instant start = Instant.parse(date); - Instant endDate = Instant.now(); - - GetMetricStatisticsRequest statisticsRequest = GetMetricStatisticsRequest.builder() - .endTime(endDate) - .startTime(start) - .dimensions(myDimension) - .metricName(metVal) - .namespace(nameSpace) - .period(86400) - .statistics(Statistic.fromValue(metricOption)) - .build(); - - GetMetricStatisticsResponse response = cw.getMetricStatistics(statisticsRequest); - List data = response.datapoints(); - if (!data.isEmpty()) { - for (Datapoint datapoint : data) { - System.out - .println("Timestamp: " + datapoint.timestamp() + " Maximum value: " + datapoint.maximum()); - } - } else { - System.out.println("The returned data list is empty"); - } - - } catch (CloudWatchException e) { - System.err.println(e.getMessage()); - System.exit(1); - } - } - // snippet-end:[cloudwatch.java2.scenario.display.metrics.main] - - public static Dimension getSpecificMet(CloudWatchClient cw, String namespace) { - try { - ListMetricsRequest request = ListMetricsRequest.builder() - .namespace(namespace) - .build(); - - ListMetricsResponse response = cw.listMetrics(request); - List myList = response.metrics(); - Metric metric = myList.get(0); - return metric.dimensions().get(0); - - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - return null; - } - - // snippet-start:[cloudwatch.java2.scenario.list.metrics.main] - public static ArrayList listMets(CloudWatchClient cw, String namespace) { - try { - ArrayList metList = new ArrayList<>(); - ListMetricsRequest request = ListMetricsRequest.builder() - .namespace(namespace) - .build(); - - ListMetricsIterable listRes = cw.listMetricsPaginator(request); - listRes.stream() - .flatMap(r -> r.metrics().stream()) - .forEach(metrics -> metList.add(metrics.metricName())); - - return metList; - - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - return null; - } - // snippet-end:[cloudwatch.java2.scenario.list.metrics.main] - - // snippet-start:[cloudwatch.java2.scenario.list.namespaces.main] - public static ArrayList listNameSpaces(CloudWatchClient cw) { - try { - ArrayList nameSpaceList = new ArrayList<>(); - ListMetricsRequest request = ListMetricsRequest.builder() - .build(); - - ListMetricsIterable listRes = cw.listMetricsPaginator(request); - listRes.stream() - .flatMap(r -> r.metrics().stream()) - .forEach(metrics -> { - String data = metrics.namespace(); - if (!nameSpaceList.contains(data)) { - nameSpaceList.add(data); - } - }); - - return nameSpaceList; - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - return null; - } - // snippet-end:[cloudwatch.java2.scenario.list.namespaces.main] -} -// snippet-end:[cloudwatch.java2.scenario.main] \ No newline at end of file diff --git a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/DeleteAlarm.java b/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/DeleteAlarm.java deleted file mode 100644 index 0beb6381456..00000000000 --- a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/DeleteAlarm.java +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.example.cloudwatch; - -// snippet-start:[cloudwatch.java2.delete_metrics.main] -// snippet-start:[cloudwatch.java2.delete_metrics.import] -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.cloudwatch.CloudWatchClient; -import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException; -import software.amazon.awssdk.services.cloudwatch.model.DeleteAlarmsRequest; -// snippet-end:[cloudwatch.java2.delete_metrics.import] - -/** - * Before running this Java V2 code example, set up your development - * environment, including your credentials. - * - * For more information, see the following documentation topic: - * - * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html - */ - -public class DeleteAlarm { - public static void main(String[] args) { - final String usage = """ - - Usage: - - - Where: - alarmName - An alarm name to delete (for example, MyAlarm). - """; - - if (args.length != 1) { - System.out.println(usage); - System.exit(1); - } - - String alarmName = args[0]; - Region region = Region.US_EAST_2; - CloudWatchClient cw = CloudWatchClient.builder() - .region(region) - .build(); - - deleteCWAlarm(cw, alarmName); - cw.close(); - } - - public static void deleteCWAlarm(CloudWatchClient cw, String alarmName) { - try { - DeleteAlarmsRequest request = DeleteAlarmsRequest.builder() - .alarmNames(alarmName) - .build(); - - cw.deleteAlarms(request); - System.out.printf("Successfully deleted alarm %s", alarmName); - - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - } -} -// snippet-end:[cloudwatch.java2.delete_metrics.main] diff --git a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/DescribeAlarms.java b/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/DescribeAlarms.java deleted file mode 100644 index 60b334d8d6e..00000000000 --- a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/DescribeAlarms.java +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.example.cloudwatch; - -// snippet-start:[cloudwatch.java2.describe_alarms.main] -// snippet-start:[cloudwatch.java2.describe_alarms.import] -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.cloudwatch.CloudWatchClient; -import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException; -import software.amazon.awssdk.services.cloudwatch.model.DescribeAlarmsRequest; -import software.amazon.awssdk.services.cloudwatch.model.DescribeAlarmsResponse; -import software.amazon.awssdk.services.cloudwatch.model.MetricAlarm; -// snippet-end:[cloudwatch.java2.describe_alarms.import] - -/** - * Before running this Java V2 code example, set up your development - * environment, including your credentials. - * - * For more information, see the following documentation topic: - * - * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html - */ -public class DescribeAlarms { - public static void main(String[] args) { - Region region = Region.US_EAST_1; - CloudWatchClient cw = CloudWatchClient.builder() - .region(region) - .build(); - - desCWAlarms(cw); - cw.close(); - } - - public static void desCWAlarms(CloudWatchClient cw) { - try { - boolean done = false; - String newToken = null; - while (!done) { - DescribeAlarmsResponse response; - if (newToken == null) { - DescribeAlarmsRequest request = DescribeAlarmsRequest.builder().build(); - response = cw.describeAlarms(request); - } else { - DescribeAlarmsRequest request = DescribeAlarmsRequest.builder() - .nextToken(newToken) - .build(); - response = cw.describeAlarms(request); - } - - for (MetricAlarm alarm : response.metricAlarms()) { - System.out.printf("\n Retrieved alarm %s", alarm.alarmName()); - } - - if (response.nextToken() == null) { - done = true; - } else { - newToken = response.nextToken(); - } - } - - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - System.out.print("Done"); - } -} -// snippet-end:[cloudwatch.java2.describe_alarms.main] diff --git a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/GetMetricData.java b/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/GetMetricData.java deleted file mode 100644 index 5a4b6d66d06..00000000000 --- a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/GetMetricData.java +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.example.cloudwatch; - -// snippet-start:[cloudwatch.java2.get_metric_alarm.main] -// snippet-start:[cloudwatch.java2.get_metric_data.import] -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.cloudwatch.CloudWatchClient; -import software.amazon.awssdk.services.cloudwatch.model.GetMetricDataResponse; -import software.amazon.awssdk.services.cloudwatch.model.Metric; -import software.amazon.awssdk.services.cloudwatch.model.MetricStat; -import software.amazon.awssdk.services.cloudwatch.model.MetricDataQuery; -import software.amazon.awssdk.services.cloudwatch.model.GetMetricDataRequest; -import software.amazon.awssdk.services.cloudwatch.model.MetricDataResult; -import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException; -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; -// snippet-end:[cloudwatch.java2.get_metric_data.import] - -/** - * Before running this Java V2 code example, set up your development - * environment, including your credentials. - * - * For more information, see the following documentation topic: - * - * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html - */ -public class GetMetricData { - public static void main(String[] args) { - Region region = Region.US_EAST_1; - CloudWatchClient cw = CloudWatchClient.builder() - .region(region) - .build(); - - getMetData(cw); - cw.close(); - } - - public static void getMetData(CloudWatchClient cw) { - try { - // Set the date. - Instant start = Instant.parse("2019-10-23T10:12:35Z"); - Instant endDate = Instant.now(); - Metric met = Metric.builder() - .metricName("DiskReadBytes") - .namespace("AWS/EC2") - .build(); - - MetricStat metStat = MetricStat.builder() - .stat("Minimum") - .period(60) - .metric(met) - .build(); - - MetricDataQuery dataQUery = MetricDataQuery.builder() - .metricStat(metStat) - .id("foo2") - .returnData(true) - .build(); - - List dq = new ArrayList<>(); - dq.add(dataQUery); - - GetMetricDataRequest getMetReq = GetMetricDataRequest.builder() - .maxDatapoints(100) - .startTime(start) - .endTime(endDate) - .metricDataQueries(dq) - .build(); - - GetMetricDataResponse response = cw.getMetricData(getMetReq); - List data = response.metricDataResults(); - - for (MetricDataResult item : data) { - System.out.println("The label is " + item.label()); - System.out.println("The status code is " + item.statusCode().toString()); - } - - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - } -} -// snippet-end:[cloudwatch.java2.get_metric_alarm.main] diff --git a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/ListMetrics.java b/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/ListMetrics.java deleted file mode 100644 index e00f6d952db..00000000000 --- a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/ListMetrics.java +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.example.cloudwatch; - -// snippet-start:[cloudwatch.java2.list_metrics.main] -// snippet-start:[cloudwatch.java2.list_metrics.import] -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.cloudwatch.CloudWatchClient; -import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException; -import software.amazon.awssdk.services.cloudwatch.model.ListMetricsRequest; -import software.amazon.awssdk.services.cloudwatch.model.ListMetricsResponse; -import software.amazon.awssdk.services.cloudwatch.model.Metric; -// snippet-end:[cloudwatch.java2.list_metrics.import] - -/** - * Before running this Java V2 code example, set up your development - * environment, including your credentials. - * - * For more information, see the following documentation topic: - * - * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html - */ -public class ListMetrics { - public static void main(String[] args) { - final String usage = """ - - Usage: - \s - - Where: - namespace - The namespace to filter against (for example, AWS/EC2).\s - """; - - if (args.length != 1) { - System.out.println(usage); - System.exit(1); - } - - String namespace = args[0]; - Region region = Region.US_EAST_1; - CloudWatchClient cw = CloudWatchClient.builder() - .region(region) - .build(); - - listMets(cw, namespace); - cw.close(); - } - - public static void listMets(CloudWatchClient cw, String namespace) { - boolean done = false; - String nextToken = null; - - try { - while (!done) { - - ListMetricsResponse response; - if (nextToken == null) { - ListMetricsRequest request = ListMetricsRequest.builder() - .namespace(namespace) - .build(); - - response = cw.listMetrics(request); - } else { - ListMetricsRequest request = ListMetricsRequest.builder() - .namespace(namespace) - .nextToken(nextToken) - .build(); - - response = cw.listMetrics(request); - } - - for (Metric metric : response.metrics()) { - System.out.printf("Retrieved metric %s", metric.metricName()); - System.out.println(); - } - - if (response.nextToken() == null) { - done = true; - } else { - nextToken = response.nextToken(); - } - } - - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - } -} -// snippet-end:[cloudwatch.java2.list_metrics.main] diff --git a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutMetricAlarm.java b/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutMetricAlarm.java deleted file mode 100644 index 1fd43ff7ae2..00000000000 --- a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutMetricAlarm.java +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.example.cloudwatch; - -// snippet-start:[cloudwatch.java2.put_metric_alarm.main] -// snippet-start:[cloudwatch.java2.put_metric_alarm.import] -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.cloudwatch.CloudWatchClient; -import software.amazon.awssdk.services.cloudwatch.model.Dimension; -import software.amazon.awssdk.services.cloudwatch.model.PutMetricAlarmRequest; -import software.amazon.awssdk.services.cloudwatch.model.ComparisonOperator; -import software.amazon.awssdk.services.cloudwatch.model.Statistic; -import software.amazon.awssdk.services.cloudwatch.model.StandardUnit; -import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException; -// snippet-end:[cloudwatch.java2.put_metric_alarm.import] - -/** - * Before running this Java V2 code example, set up your development - * environment, including your credentials. - * - * For more information, see the following documentation topic: - * - * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html - */ -public class PutMetricAlarm { - public static void main(String[] args) { - - final String usage = """ - - Usage: - \s - - Where: - alarmName - An alarm name to use. - instanceId - An instance Id value . - """; - - if (args.length != 2) { - System.out.println(usage); - System.exit(1); - } - - String alarmName = args[0]; - String instanceId = args[1]; - CloudWatchClient cw = CloudWatchClient.builder() - .region(Region.US_EAST_1) - .build(); - - putMetricAlarm(cw, alarmName, instanceId); - cw.close(); - } - - public static void putMetricAlarm(CloudWatchClient cw, String alarmName, String instanceId) { - try { - Dimension dimension = Dimension.builder() - .name("InstanceId") - .value(instanceId).build(); - - PutMetricAlarmRequest request = PutMetricAlarmRequest.builder() - .alarmName(alarmName) - .comparisonOperator(ComparisonOperator.GREATER_THAN_THRESHOLD) - .evaluationPeriods(1) - .metricName("CPUUtilization") - .namespace("AWS/EC2") - .period(60) - .statistic(Statistic.AVERAGE) - .threshold(70.0) - .actionsEnabled(false) - .alarmDescription("Alarm when server CPU utilization exceeds 70%") - .unit(StandardUnit.SECONDS) - .dimensions(dimension) - .build(); - - cw.putMetricAlarm(request); - System.out.printf("Successfully created alarm with name %s", alarmName); - - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - } -} -// snippet-end:[cloudwatch.java2.put_metric_alarm.main] diff --git a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutMetricData.java b/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutMetricData.java deleted file mode 100644 index 6cf60518e97..00000000000 --- a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/PutMetricData.java +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.example.cloudwatch; - -// snippet-start:[cloudwatch.java2.put_metric_data.main] -// snippet-start:[cloudwatch.java2.put_metric_data.import] -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.cloudwatch.CloudWatchClient; -import software.amazon.awssdk.services.cloudwatch.model.Dimension; -import software.amazon.awssdk.services.cloudwatch.model.MetricDatum; -import software.amazon.awssdk.services.cloudwatch.model.StandardUnit; -import software.amazon.awssdk.services.cloudwatch.model.PutMetricDataRequest; -import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -// snippet-end:[cloudwatch.java2.put_metric_data.import] - -/** - * Before running this Java V2 code example, set up your development - * environment, including your credentials. - * - * For more information, see the following documentation topic: - * - * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html - */ -public class PutMetricData { - public static void main(String[] args) { - final String usage = """ - - Usage: - \s - - Where: - dataPoint - The value for the metric. - """; - - if (args.length != 1) { - System.out.println(usage); - System.exit(1); - } - - Double dataPoint = Double.parseDouble(args[0]); - Region region = Region.US_WEST_2; - CloudWatchClient cw = CloudWatchClient.builder() - .region(region) - .build(); - - putMetData(cw, dataPoint); - cw.close(); - } - - public static void putMetData(CloudWatchClient cw, Double dataPoint) { - try { - Dimension dimension = Dimension.builder() - .name("UNIQUE_PAGES") - .value("URLS") - .build(); - - // Set an Instant object. - String time = ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT); - Instant instant = Instant.parse(time); - - MetricDatum datum = MetricDatum.builder() - .metricName("PAGES_VISITED") - .unit(StandardUnit.NONE) - .value(dataPoint) - .timestamp(instant) - .dimensions(dimension).build(); - - PutMetricDataRequest request = PutMetricDataRequest.builder() - .namespace("SITE/TRAFFIC") - .metricData(datum).build(); - - cw.putMetricData(request); - - } catch (CloudWatchException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - System.out.printf("Successfully put data point %f", dataPoint); - } -} -// snippet-end:[cloudwatch.java2.put_metric_data.main] diff --git a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java b/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java new file mode 100644 index 00000000000..786bf2152be --- /dev/null +++ b/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/scenario/CloudWatchActions.java @@ -0,0 +1,1082 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.cloudwatch.scenario; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; +import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; +import software.amazon.awssdk.services.cloudwatch.model.AlarmHistoryItem; +import software.amazon.awssdk.services.cloudwatch.model.AlarmType; +import software.amazon.awssdk.services.cloudwatch.model.AnomalyDetector; +import software.amazon.awssdk.services.cloudwatch.model.ComparisonOperator; +import software.amazon.awssdk.services.cloudwatch.model.DashboardValidationMessage; +import software.amazon.awssdk.services.cloudwatch.model.Datapoint; +import software.amazon.awssdk.services.cloudwatch.model.DeleteAlarmsRequest; +import software.amazon.awssdk.services.cloudwatch.model.DeleteAlarmsResponse; +import software.amazon.awssdk.services.cloudwatch.model.DeleteAnomalyDetectorRequest; +import software.amazon.awssdk.services.cloudwatch.model.DeleteAnomalyDetectorResponse; +import software.amazon.awssdk.services.cloudwatch.model.DeleteDashboardsRequest; +import software.amazon.awssdk.services.cloudwatch.model.DeleteDashboardsResponse; +import software.amazon.awssdk.services.cloudwatch.model.DescribeAlarmHistoryRequest; +import software.amazon.awssdk.services.cloudwatch.model.DescribeAlarmsForMetricRequest; +import software.amazon.awssdk.services.cloudwatch.model.DescribeAlarmsRequest; +import software.amazon.awssdk.services.cloudwatch.model.DescribeAnomalyDetectorsRequest; +import software.amazon.awssdk.services.cloudwatch.model.Dimension; +import software.amazon.awssdk.services.cloudwatch.model.GetMetricDataRequest; +import software.amazon.awssdk.services.cloudwatch.model.GetMetricStatisticsRequest; +import software.amazon.awssdk.services.cloudwatch.model.GetMetricStatisticsResponse; +import software.amazon.awssdk.services.cloudwatch.model.GetMetricWidgetImageRequest; +import software.amazon.awssdk.services.cloudwatch.model.HistoryItemType; +import software.amazon.awssdk.services.cloudwatch.model.ListDashboardsRequest; +import software.amazon.awssdk.services.cloudwatch.model.ListMetricsRequest; +import software.amazon.awssdk.services.cloudwatch.model.Metric; +import software.amazon.awssdk.services.cloudwatch.model.MetricAlarm; +import software.amazon.awssdk.services.cloudwatch.model.MetricDataQuery; +import software.amazon.awssdk.services.cloudwatch.model.MetricDataResult; +import software.amazon.awssdk.services.cloudwatch.model.MetricDatum; +import software.amazon.awssdk.services.cloudwatch.model.MetricStat; +import software.amazon.awssdk.services.cloudwatch.model.PutAnomalyDetectorRequest; +import software.amazon.awssdk.services.cloudwatch.model.PutDashboardRequest; +import software.amazon.awssdk.services.cloudwatch.model.PutDashboardResponse; +import software.amazon.awssdk.services.cloudwatch.model.PutMetricAlarmRequest; +import software.amazon.awssdk.services.cloudwatch.model.PutMetricDataRequest; +import software.amazon.awssdk.services.cloudwatch.model.PutMetricDataResponse; +import software.amazon.awssdk.services.cloudwatch.model.ScanBy; +import software.amazon.awssdk.services.cloudwatch.model.SingleMetricAnomalyDetector; +import software.amazon.awssdk.services.cloudwatch.model.StandardUnit; +import software.amazon.awssdk.services.cloudwatch.model.Statistic; +import software.amazon.awssdk.services.cloudwatch.paginators.DescribeAlarmHistoryPublisher; +import software.amazon.awssdk.services.cloudwatch.paginators.ListDashboardsPublisher; +import software.amazon.awssdk.services.cloudwatch.paginators.ListMetricsPublisher; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.Duration; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletableFuture; + +// snippet-start:[cloudwatch.java2.actions.main] +public class CloudWatchActions { + + private static CloudWatchAsyncClient cloudWatchAsyncClient; + + private static final Logger logger = LoggerFactory.getLogger(CloudWatchActions.class); + + /** + * Retrieves an asynchronous CloudWatch client instance. + * + *

+ * This method ensures that the CloudWatch client is initialized with the following configurations: + *

    + *
  • Maximum concurrency: 100
  • + *
  • Connection timeout: 60 seconds
  • + *
  • Read timeout: 60 seconds
  • + *
  • Write timeout: 60 seconds
  • + *
  • API call timeout: 2 minutes
  • + *
  • API call attempt timeout: 90 seconds
  • + *
  • Retry strategy: STANDARD
  • + *
+ *

+ * + * @return the asynchronous CloudWatch client instance + */ + private static CloudWatchAsyncClient getAsyncClient() { + if (cloudWatchAsyncClient == null) { + SdkAsyncHttpClient httpClient = NettyNioAsyncHttpClient.builder() + .maxConcurrency(100) + .connectionTimeout(Duration.ofSeconds(60)) + .readTimeout(Duration.ofSeconds(60)) + .writeTimeout(Duration.ofSeconds(60)) + .build(); + + ClientOverrideConfiguration overrideConfig = ClientOverrideConfiguration.builder() + .apiCallTimeout(Duration.ofMinutes(2)) + .apiCallAttemptTimeout(Duration.ofSeconds(90)) + .retryStrategy(RetryMode.STANDARD) + .build(); + + cloudWatchAsyncClient = CloudWatchAsyncClient.builder() + .httpClient(httpClient) + .overrideConfiguration(overrideConfig) + .build(); + } + return cloudWatchAsyncClient; + } + + // snippet-start:[cloudwatch.java2.scenario.del.anomalydetector.main] + /** + * Deletes an Anomaly Detector. + * + * @param fileName the name of the file containing the Anomaly Detector configuration + * @return a CompletableFuture that represents the asynchronous deletion of the Anomaly Detector + */ + public CompletableFuture deleteAnomalyDetectorAsync(String fileName) { + CompletableFuture readFileFuture = CompletableFuture.supplyAsync(() -> { + try { + JsonParser parser = new JsonFactory().createParser(new File(fileName)); + return new ObjectMapper().readTree(parser); // Return the root node + } catch (IOException e) { + throw new RuntimeException("Failed to read or parse the file", e); + } + }); + + return readFileFuture.thenCompose(rootNode -> { + String customMetricNamespace = rootNode.findValue("customMetricNamespace").asText(); + String customMetricName = rootNode.findValue("customMetricName").asText(); + + SingleMetricAnomalyDetector singleMetricAnomalyDetector = SingleMetricAnomalyDetector.builder() + .metricName(customMetricName) + .namespace(customMetricNamespace) + .stat("Maximum") + .build(); + + DeleteAnomalyDetectorRequest request = DeleteAnomalyDetectorRequest.builder() + .singleMetricAnomalyDetector(singleMetricAnomalyDetector) + .build(); + + return getAsyncClient().deleteAnomalyDetector(request); + }).whenComplete((result, exception) -> { + if (exception != null) { + throw new RuntimeException("Failed to delete the Anomaly Detector", exception); + } else { + logger.info("Successfully deleted the Anomaly Detector."); + } + }); + } + // snippet-end:[cloudwatch.java2.scenario.del.anomalydetector.main] + + // snippet-start:[cloudwatch.java2.delete_alarm.main] + /** + * Deletes a CloudWatch alarm. + * + * @param alarmName the name of the alarm to be deleted + * @return a {@link CompletableFuture} representing the asynchronous operation to delete the alarm + * the {@link DeleteAlarmsResponse} is returned when the operation completes successfully, + * or a {@link RuntimeException} is thrown if the operation fails + */ + public CompletableFuture deleteCWAlarmAsync(String alarmName) { + DeleteAlarmsRequest request = DeleteAlarmsRequest.builder() + .alarmNames(alarmName) + .build(); + + return getAsyncClient().deleteAlarms(request) + .whenComplete((response, exception) -> { + if (exception != null) { + throw new RuntimeException("Failed to delete the alarm:{} " + alarmName, exception); + } else { + logger.info("Successfully deleted alarm {} ", alarmName); + } + }); + } + // snippet-end:[cloudwatch.java2.delete_alarm.main] + + // snippet-start:[cloudwatch.java2.scenario.del.dashboard.main] + /** + * Deletes the specified dashboard. + * + * @param dashboardName the name of the dashboard to be deleted + * @return a {@link CompletableFuture} representing the asynchronous operation of deleting the dashboard + * @throws RuntimeException if the dashboard deletion fails + */ + public CompletableFuture deleteDashboardAsync(String dashboardName) { + DeleteDashboardsRequest dashboardsRequest = DeleteDashboardsRequest.builder() + .dashboardNames(dashboardName) + .build(); + + return getAsyncClient().deleteDashboards(dashboardsRequest) + .whenComplete((response, exception) -> { + if (exception != null) { + throw new RuntimeException("Failed to delete the dashboard: " + dashboardName, exception); + } else { + logger.info("{} was successfully deleted.", dashboardName); + } + }); + } + // snippet-end:[cloudwatch.java2.scenario.del.dashboard.main] + + // snippet-start:[cloudwatch.java2.scenario.get.metric.image.main] + + /** + * Retrieves and saves a custom metric image to a file. + * + * @param fileName the name of the file to save the metric image to + * @return a {@link CompletableFuture} that completes when the image has been saved to the file + */ + public CompletableFuture downloadAndSaveMetricImageAsync(String fileName) { + logger.info("Getting Image data for custom metric."); + String myJSON = """ + { + "title": "Example Metric Graph", + "view": "timeSeries", + "stacked ": false, + "period": 10, + "width": 1400, + "height": 600, + "metrics": [ + [ + "AWS/Billing", + "EstimatedCharges", + "Currency", + "USD" + ] + ] + } + """; + + GetMetricWidgetImageRequest imageRequest = GetMetricWidgetImageRequest.builder() + .metricWidget(myJSON) + .build(); + + return getAsyncClient().getMetricWidgetImage(imageRequest) + .thenCompose(response -> { + SdkBytes sdkBytes = response.metricWidgetImage(); + byte[] bytes = sdkBytes.asByteArray(); + return CompletableFuture.runAsync(() -> { + try { + File outputFile = new File(fileName); + try (FileOutputStream outputStream = new FileOutputStream(outputFile)) { + outputStream.write(bytes); + } + } catch (IOException e) { + throw new RuntimeException("Failed to write image to file", e); + } + }); + }) + .whenComplete((result, exception) -> { + if (exception != null) { + throw new RuntimeException("Error getting and saving metric image", exception); + } else { + logger.info("Image data saved successfully to {}", fileName); + } + }); + } + // snippet-end:[cloudwatch.java2.scenario.get.metric.image.main] + + // snippet-start:[cloudwatch.java2.scenario.describe.anomalydetector.main] + + /** + * Describes the anomaly detectors based on the specified JSON file. + * + * @param fileName the name of the JSON file containing the custom metric namespace and name + * @return a {@link CompletableFuture} that completes when the anomaly detectors have been described + * @throws RuntimeException if there is a failure during the operation, such as when reading or parsing the JSON file, + * or when describing the anomaly detectors + */ + public CompletableFuture describeAnomalyDetectorsAsync(String fileName) { + CompletableFuture readFileFuture = CompletableFuture.supplyAsync(() -> { + try { + JsonParser parser = new JsonFactory().createParser(new File(fileName)); + return new ObjectMapper().readTree(parser); + } catch (IOException e) { + throw new RuntimeException("Failed to read or parse the file", e); + } + }); + + return readFileFuture.thenCompose(rootNode -> { + try { + String customMetricNamespace = rootNode.findValue("customMetricNamespace").asText(); + String customMetricName = rootNode.findValue("customMetricName").asText(); + + DescribeAnomalyDetectorsRequest detectorsRequest = DescribeAnomalyDetectorsRequest.builder() + .maxResults(10) + .metricName(customMetricName) + .namespace(customMetricNamespace) + .build(); + + return getAsyncClient().describeAnomalyDetectors(detectorsRequest).thenAccept(response -> { + List anomalyDetectorList = response.anomalyDetectors(); + for (AnomalyDetector detector : anomalyDetectorList) { + logger.info("Metric name: {} ", detector.singleMetricAnomalyDetector().metricName()); + logger.info("State: {} ", detector.stateValue()); + } + }); + } catch (RuntimeException e) { + throw new RuntimeException("Failed to describe anomaly detectors", e); + } + }).whenComplete((result, exception) -> { + if (exception != null) { + throw new RuntimeException("Error describing anomaly detectors", exception); + } + }); + } + // snippet-end:[cloudwatch.java2.scenario.describe.anomalydetector.main] + + // snippet-start:[cloudwatch.java2.scenario.add.anomalydetector.main] + + /** + * Adds an anomaly detector for the given file. + * + * @param fileName the name of the file containing the anomaly detector configuration + * @return a {@link CompletableFuture} that completes when the anomaly detector has been added + */ + public CompletableFuture addAnomalyDetectorAsync(String fileName) { + CompletableFuture readFileFuture = CompletableFuture.supplyAsync(() -> { + try { + JsonParser parser = new JsonFactory().createParser(new File(fileName)); + return new ObjectMapper().readTree(parser); // Return the root node + } catch (IOException e) { + throw new RuntimeException("Failed to read or parse the file", e); + } + }); + + return readFileFuture.thenCompose(rootNode -> { + try { + String customMetricNamespace = rootNode.findValue("customMetricNamespace").asText(); + String customMetricName = rootNode.findValue("customMetricName").asText(); + + SingleMetricAnomalyDetector singleMetricAnomalyDetector = SingleMetricAnomalyDetector.builder() + .metricName(customMetricName) + .namespace(customMetricNamespace) + .stat("Maximum") + .build(); + + PutAnomalyDetectorRequest anomalyDetectorRequest = PutAnomalyDetectorRequest.builder() + .singleMetricAnomalyDetector(singleMetricAnomalyDetector) + .build(); + + return getAsyncClient().putAnomalyDetector(anomalyDetectorRequest).thenAccept(response -> { + logger.info("Added anomaly detector for metric {}", customMetricName); + }); + } catch (Exception e) { + throw new RuntimeException("Failed to create anomaly detector", e); + } + }).whenComplete((result, exception) -> { + if (exception != null) { + throw new RuntimeException("Error adding anomaly detector", exception); + } + }); + } + // snippet-end:[cloudwatch.java2.scenario.add.anomalydetector.main] + + // snippet-start:[cloudwatch.java2.scenario.get.alarm.history.main] + + /** + * Retrieves the alarm history for a given alarm name and date range. + * + * @param fileName the path to the JSON file containing the alarm name + * @param date the date to start the alarm history search (in the format "yyyy-MM-dd'T'HH:mm:ss'Z'") + * @return a {@code CompletableFuture} that completes when the alarm history has been retrieved and processed + */ + public CompletableFuture getAlarmHistoryAsync(String fileName, String date) { + CompletableFuture readFileFuture = CompletableFuture.supplyAsync(() -> { + try { + JsonParser parser = new JsonFactory().createParser(new File(fileName)); + com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(parser); + return rootNode.findValue("exampleAlarmName").asText(); // Return alarmName from the JSON file + } catch (IOException e) { + throw new RuntimeException("Failed to read or parse the file", e); + } + }); + + // Use the alarm name to describe alarm history with a paginator. + return readFileFuture.thenCompose(alarmName -> { + try { + Instant start = Instant.parse(date); + Instant endDate = Instant.now(); + DescribeAlarmHistoryRequest historyRequest = DescribeAlarmHistoryRequest.builder() + .startDate(start) + .endDate(endDate) + .alarmName(alarmName) + .historyItemType(HistoryItemType.ACTION) + .build(); + + // Use the paginator to paginate through alarm history pages. + DescribeAlarmHistoryPublisher historyPublisher = getAsyncClient().describeAlarmHistoryPaginator(historyRequest); + CompletableFuture future = historyPublisher + .subscribe(response -> response.alarmHistoryItems().forEach(item -> { + logger.info("History summary: {}", item.historySummary()); + logger.info("Timestamp: {}", item.timestamp()); + })) + .whenComplete((result, exception) -> { + if (exception != null) { + logger.error("Error occurred while getting alarm history: " + exception.getMessage(), exception); + } else { + logger.info("Successfully retrieved all alarm history."); + } + }); + + // Return the future to the calling code for further handling + return future; + } catch (Exception e) { + throw new RuntimeException("Failed to process alarm history", e); + } + }).whenComplete((result, exception) -> { + if (exception != null) { + throw new RuntimeException("Error completing alarm history processing", exception); + } + }); + } + + // snippet-end:[cloudwatch.java2.scenario.get.alarm.history.main] + + // snippet-start:[cloudwatch.java2.scenario.check.met.alarm.main] + + /** + * Checks for a metric alarm in AWS CloudWatch. + * + * @param fileName the name of the file containing the JSON configuration for the custom metric + * @return a {@link CompletableFuture} that completes when the check for the metric alarm is complete + */ + public CompletableFuture checkForMetricAlarmAsync(String fileName) { + CompletableFuture readFileFuture = CompletableFuture.supplyAsync(() -> { + try { + JsonParser parser = new JsonFactory().createParser(new File(fileName)); + com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(parser); + return rootNode.toString(); // Return JSON as a string for further processing + } catch (IOException e) { + throw new RuntimeException("Failed to read file", e); + } + }); + + return readFileFuture.thenCompose(jsonContent -> { + try { + com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(jsonContent); + String customMetricNamespace = rootNode.findValue("customMetricNamespace").asText(); + String customMetricName = rootNode.findValue("customMetricName").asText(); + + DescribeAlarmsForMetricRequest metricRequest = DescribeAlarmsForMetricRequest.builder() + .metricName(customMetricName) + .namespace(customMetricNamespace) + .build(); + + return checkForAlarmAsync(metricRequest, customMetricName, 10); + + } catch (IOException e) { + throw new RuntimeException("Failed to parse JSON content", e); + } + }).whenComplete((result, exception) -> { + if (exception != null) { + throw new RuntimeException("Error checking metric alarm", exception); + } + }); + } + + // Recursive method to check for the alarm. + + /** + * Checks for the existence of an alarm asynchronously for the specified metric. + * + * @param metricRequest the request to describe the alarms for the specified metric + * @param customMetricName the name of the custom metric to check for an alarm + * @param retries the number of retries to perform if no alarm is found + * @return a {@link CompletableFuture} that completes when an alarm is found or the maximum number of retries has been reached + */ + private static CompletableFuture checkForAlarmAsync(DescribeAlarmsForMetricRequest metricRequest, String customMetricName, int retries) { + if (retries == 0) { + return CompletableFuture.completedFuture(null).thenRun(() -> + logger.info("No Alarm state found for {} after 10 retries.", customMetricName) + ); + } + + return (getAsyncClient().describeAlarmsForMetric(metricRequest).thenCompose(response -> { + if (response.hasMetricAlarms()) { + logger.info("Alarm state found for {}", customMetricName); + return CompletableFuture.completedFuture(null); // Alarm found, complete the future + } else { + return CompletableFuture.runAsync(() -> { + try { + Thread.sleep(20000); + logger.info("."); + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted while waiting to retry", e); + } + }).thenCompose(v -> checkForAlarmAsync(metricRequest, customMetricName, retries - 1)); // Recursive call + } + })); + } + // snippet-end:[cloudwatch.java2.scenario.check.met.alarm.main] + + // snippet-start:[cloudwatch.java2.scenario.add.met.alarm.main] + + /** + * Adds metric data for an alarm asynchronously. + * + * @param fileName the name of the JSON file containing the metric data + * @return a CompletableFuture that asynchronously returns the PutMetricDataResponse + */ + public CompletableFuture addMetricDataForAlarmAsync(String fileName) { + CompletableFuture readFileFuture = CompletableFuture.supplyAsync(() -> { + try { + JsonParser parser = new JsonFactory().createParser(new File(fileName)); + com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(parser); + return rootNode.toString(); // Return JSON as a string for further processing + } catch (IOException e) { + throw new RuntimeException("Failed to read file", e); + } + }); + + return readFileFuture.thenCompose(jsonContent -> { + try { + com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(jsonContent); + String customMetricNamespace = rootNode.findValue("customMetricNamespace").asText(); + String customMetricName = rootNode.findValue("customMetricName").asText(); + Instant instant = Instant.now(); + + // Create MetricDatum objects. + MetricDatum datum1 = MetricDatum.builder() + .metricName(customMetricName) + .unit(StandardUnit.NONE) + .value(1001.00) + .timestamp(instant) + .build(); + + MetricDatum datum2 = MetricDatum.builder() + .metricName(customMetricName) + .unit(StandardUnit.NONE) + .value(1002.00) + .timestamp(instant) + .build(); + + List metricDataList = new ArrayList<>(); + metricDataList.add(datum1); + metricDataList.add(datum2); + + // Build the PutMetricData request. + PutMetricDataRequest request = PutMetricDataRequest.builder() + .namespace(customMetricNamespace) + .metricData(metricDataList) + .build(); + + // Send the request asynchronously. + return getAsyncClient().putMetricData(request); + + } catch (IOException e) { + CompletableFuture failedFuture = new CompletableFuture<>(); + failedFuture.completeExceptionally(new RuntimeException("Failed to parse JSON content", e)); + return failedFuture; + } + }).whenComplete((response, exception) -> { + if (exception != null) { + logger.error("Failed to put metric data: " + exception.getMessage(), exception); + } else { + logger.info("Added metric values for metric."); + } + }); + } + // snippet-end:[cloudwatch.java2.scenario.add.met.alarm.main] + + // snippet-start:[cloudwatch.java2.scenario.get.met.data.main] + + /** + * Retrieves custom metric data from the AWS CloudWatch service. + * + * @param fileName the name of the file containing the custom metric information + * @return a {@link CompletableFuture} that completes when the metric data has been retrieved + */ + public CompletableFuture getCustomMetricDataAsync(String fileName) { + CompletableFuture readFileFuture = CompletableFuture.supplyAsync(() -> { + try { + // Read values from the JSON file. + JsonParser parser = new JsonFactory().createParser(new File(fileName)); + com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(parser); + return rootNode.toString(); // Return JSON as a string for further processing + } catch (IOException e) { + throw new RuntimeException("Failed to read file", e); + } + }); + + return readFileFuture.thenCompose(jsonContent -> { + try { + // Parse the JSON string to extract relevant values. + com.fasterxml.jackson.databind.JsonNode rootNode = new ObjectMapper().readTree(jsonContent); + String customMetricNamespace = rootNode.findValue("customMetricNamespace").asText(); + String customMetricName = rootNode.findValue("customMetricName").asText(); + + // Set the current time and date range for metric query. + Instant nowDate = Instant.now(); + long hours = 1; + long minutes = 30; + Instant endTime = nowDate.plus(hours, ChronoUnit.HOURS).plus(minutes, ChronoUnit.MINUTES); + + Metric met = Metric.builder() + .metricName(customMetricName) + .namespace(customMetricNamespace) + .build(); + + MetricStat metStat = MetricStat.builder() + .stat("Maximum") + .period(60) // Assuming period in seconds + .metric(met) + .build(); + + MetricDataQuery dataQuery = MetricDataQuery.builder() + .metricStat(metStat) + .id("foo2") + .returnData(true) + .build(); + + List dq = new ArrayList<>(); + dq.add(dataQuery); + + GetMetricDataRequest getMetricDataRequest = GetMetricDataRequest.builder() + .maxDatapoints(10) + .scanBy(ScanBy.TIMESTAMP_DESCENDING) + .startTime(nowDate) + .endTime(endTime) + .metricDataQueries(dq) + .build(); + + // Call the async method for CloudWatch data retrieval. + return getAsyncClient().getMetricData(getMetricDataRequest); + + } catch (IOException e) { + throw new RuntimeException("Failed to parse JSON content", e); + } + }).thenAccept(response -> { + List data = response.metricDataResults(); + for (MetricDataResult item : data) { + logger.info("The label is: {}", item.label()); + logger.info("The status code is: {}", item.statusCode().toString()); + } + }).exceptionally(exception -> { + throw new RuntimeException("Failed to get metric data", exception); + }); + } + // snippet-end:[cloudwatch.java2.scenario.get.met.data.main] + + // snippet-start:[cloudwatch.java2.describe_alarms.main] + + /** + * Describes the CloudWatch alarms of the 'METRIC_ALARM' type. + * + * @return a {@link CompletableFuture} that represents the asynchronous operation + * of describing the CloudWatch alarms. The future completes when the + * operation is finished, either successfully or with an error. + */ + public CompletableFuture describeAlarmsAsync() { + List typeList = new ArrayList<>(); + typeList.add(AlarmType.METRIC_ALARM); + DescribeAlarmsRequest alarmsRequest = DescribeAlarmsRequest.builder() + .alarmTypes(typeList) + .maxRecords(10) + .build(); + + return getAsyncClient().describeAlarms(alarmsRequest) + .thenAccept(response -> { + List alarmList = response.metricAlarms(); + for (MetricAlarm alarm : alarmList) { + logger.info("Alarm name: {}", alarm.alarmName()); + logger.info("Alarm description: {} ", alarm.alarmDescription()); + } + }) + .whenComplete((response, ex) -> { + if (ex != null) { + logger.info("Failed to describe alarms: {}", ex.getMessage()); + } else { + logger.info("Successfully described alarms."); + } + }); + } + // snippet-end:[cloudwatch.java2.describe_alarms.main] + + // snippet-start:[cloudwatch.java2.scenario.create.alarm.main] + /** + * Creates an alarm based on the configuration provided in a JSON file. + * + * @param fileName the name of the JSON file containing the alarm configuration + * @return a CompletableFuture that represents the asynchronous operation of creating the alarm + * @throws RuntimeException if an exception occurs while reading the JSON file or creating the alarm + */ + public CompletableFuture createAlarmAsync(String fileName) { + com.fasterxml.jackson.databind.JsonNode rootNode; + try { + JsonParser parser = new JsonFactory().createParser(new File(fileName)); + rootNode = new ObjectMapper().readTree(parser); + } catch (IOException e) { + throw new RuntimeException("Failed to read the alarm configuration file", e); + } + + // Extract values from the JSON node. + String customMetricNamespace = rootNode.findValue("customMetricNamespace").asText(); + String customMetricName = rootNode.findValue("customMetricName").asText(); + String alarmName = rootNode.findValue("exampleAlarmName").asText(); + String emailTopic = rootNode.findValue("emailTopic").asText(); + String accountId = rootNode.findValue("accountId").asText(); + String region = rootNode.findValue("region").asText(); + + // Create a List for alarm actions. + List alarmActions = new ArrayList<>(); + alarmActions.add("arn:aws:sns:" + region + ":" + accountId + ":" + emailTopic); + + PutMetricAlarmRequest alarmRequest = PutMetricAlarmRequest.builder() + .alarmActions(alarmActions) + .alarmDescription("Example metric alarm") + .alarmName(alarmName) + .comparisonOperator(ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD) + .threshold(100.00) + .metricName(customMetricName) + .namespace(customMetricNamespace) + .evaluationPeriods(1) + .period(10) + .statistic("Maximum") + .datapointsToAlarm(1) + .treatMissingData("ignore") + .build(); + + // Call the putMetricAlarm asynchronously and handle the result. + return getAsyncClient().putMetricAlarm(alarmRequest) + .handle((response, ex) -> { + if (ex != null) { + logger.info("Failed to create alarm: {}", ex.getMessage()); + throw new RuntimeException("Failed to create alarm", ex); + } else { + logger.info("{} was successfully created!", alarmName); + return alarmName; + } + }); + } + // snippet-end:[cloudwatch.java2.scenario.create.alarm.main] + + // snippet-start:[cloudwatch.java2.scenario.add.metric.dashboard.main] + /** + * Adds a metric to a dashboard asynchronously. + * + * @param fileName the name of the file containing the dashboard content + * @param dashboardName the name of the dashboard to be updated + * @return a {@link CompletableFuture} representing the asynchronous operation, which will complete with a + * {@link PutDashboardResponse} when the dashboard is successfully updated + */ + public CompletableFuture addMetricToDashboardAsync(String fileName, String dashboardName) { + String dashboardBody; + try { + dashboardBody = readFileAsString(fileName); + } catch (IOException e) { + throw new RuntimeException("Failed to read the dashboard file", e); + } + + PutDashboardRequest dashboardRequest = PutDashboardRequest.builder() + .dashboardName(dashboardName) + .dashboardBody(dashboardBody) + .build(); + + return getAsyncClient().putDashboard(dashboardRequest) + .handle((response, ex) -> { + if (ex != null) { + logger.info("Failed to update dashboard: {}", ex.getMessage()); + throw new RuntimeException("Error updating dashboard", ex); + } else { + logger.info("{} was successfully updated.", dashboardName); + return response; + } + }); + } + // snippet-end:[cloudwatch.java2.scenario.add.metric.dashboard.main] + + // snippet-start:[cloudwatch.java2.scenario.create.metric.main] + /** + * Creates a new custom metric. + * + * @param dataPoint the data point to be added to the custom metric + * @return a {@link CompletableFuture} representing the asynchronous operation of adding the custom metric + */ + public CompletableFuture createNewCustomMetricAsync(Double dataPoint) { + Dimension dimension = Dimension.builder() + .name("UNIQUE_PAGES") + .value("URLS") + .build(); + + // Set an Instant object for the current time in UTC. + String time = ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT); + Instant instant = Instant.parse(time); + + // Create the MetricDatum. + MetricDatum datum = MetricDatum.builder() + .metricName("PAGES_VISITED") + .unit(StandardUnit.NONE) + .value(dataPoint) + .timestamp(instant) + .dimensions(dimension) + .build(); + + PutMetricDataRequest request = PutMetricDataRequest.builder() + .namespace("SITE/TRAFFIC") + .metricData(datum) + .build(); + + return getAsyncClient().putMetricData(request) + .whenComplete((response, ex) -> { + if (ex != null) { + throw new RuntimeException("Error adding custom metric", ex); + } else { + logger.info("Successfully added metric values for PAGES_VISITED."); + } + }); + } + // snippet-end:[cloudwatch.java2.scenario.create.metric.main] + + // snippet-start:[cloudwatch.java2.scenario.list.dashboard.main] + /** + * Lists the available dashboards. + * + * @return a {@link CompletableFuture} that completes when the operation is finished. + * The future will complete exceptionally if an error occurs while listing the dashboards. + */ + public CompletableFuture listDashboardsAsync() { + ListDashboardsRequest listDashboardsRequest = ListDashboardsRequest.builder().build(); + ListDashboardsPublisher paginator = getAsyncClient().listDashboardsPaginator(listDashboardsRequest); + return paginator.subscribe(response -> { + response.dashboardEntries().forEach(entry -> { + logger.info("Dashboard name is: {} ", entry.dashboardName()); + logger.info("Dashboard ARN is: {} ", entry.dashboardArn()); + }); + }).exceptionally(ex -> { + logger.info("Failed to list dashboards: {} ", ex.getMessage()); + throw new RuntimeException("Error occurred while listing dashboards", ex); + }); + } + // snippet-end:[cloudwatch.java2.scenario.list.dashboard.main] + + // snippet-start:[cloudwatch.java2.scenario.create.dashboard.main] + + /** + * Creates a new dashboard with the specified name and metrics from the given file. + * + * @param dashboardName the name of the dashboard to be created + * @param fileName the name of the file containing the dashboard body + * @return a {@link CompletableFuture} representing the asynchronous operation of creating the dashboard + * @throws IOException if there is an error reading the dashboard body from the file + */ + public CompletableFuture createDashboardWithMetricsAsync(String dashboardName, String fileName) throws IOException { + String dashboardBody = readFileAsString(fileName); + PutDashboardRequest dashboardRequest = PutDashboardRequest.builder() + .dashboardName(dashboardName) + .dashboardBody(dashboardBody) + .build(); + + return getAsyncClient().putDashboard(dashboardRequest) + .handle((response, ex) -> { + if (ex != null) { + logger.info("Failed to create dashboard: {}", ex.getMessage()); + throw new RuntimeException("Dashboard creation failed", ex); + } else { + // Handle the normal response case + logger.info("{} was successfully created.", dashboardName); + List messages = response.dashboardValidationMessages(); + if (messages.isEmpty()) { + logger.info("There are no messages in the new Dashboard."); + } else { + for (DashboardValidationMessage message : messages) { + logger.info("Message: {}", message.message()); + } + } + return response; // Return the response for further use + } + }); + } + // snippet-end:[cloudwatch.java2.scenario.create.dashboard.main] + + // snippet-start:[cloudwatch.java2.scenario.get.metrics.main] + + /** + * Retrieves the metric statistics for the "EstimatedCharges" metric in the "AWS/Billing" namespace. + * + * @param costDateWeek the start date for the metric statistics, in the format of an ISO-8601 date string (e.g., "2023-04-05") + * @return a {@link CompletableFuture} that, when completed, contains the {@link GetMetricStatisticsResponse} with the retrieved metric statistics + * @throws RuntimeException if the metric statistics cannot be retrieved successfully + */ + public CompletableFuture getMetricStatisticsAsync(String costDateWeek) { + Instant start = Instant.parse(costDateWeek); + Instant endDate = Instant.now(); + + // Define dimension + Dimension dimension = Dimension.builder() + .name("Currency") + .value("USD") + .build(); + + List dimensionList = new ArrayList<>(); + dimensionList.add(dimension); + + GetMetricStatisticsRequest statisticsRequest = GetMetricStatisticsRequest.builder() + .metricName("EstimatedCharges") + .namespace("AWS/Billing") + .dimensions(dimensionList) + .statistics(Statistic.MAXIMUM) + .startTime(start) + .endTime(endDate) + .period(86400) // One day period + .build(); + + return getAsyncClient().getMetricStatistics(statisticsRequest) + .whenComplete((response, exception) -> { + if (response != null) { + List data = response.datapoints(); + if (!data.isEmpty()) { + for (Datapoint datapoint : data) { + logger.info("Timestamp: {} Maximum value: {})", datapoint.timestamp(), datapoint.maximum()); + } + } else { + logger.info("The returned data list is empty"); + } + } else { + throw new RuntimeException("Failed to get metric statistics: " + exception.getMessage(), exception); + } + }); + } + // snippet-end:[cloudwatch.java2.scenario.get.metrics.main] + + + // snippet-start:[cloudwatch.java2.scenario.display.metrics.main] + /** + * Retrieves and displays metric statistics for the specified parameters. + * + * @param nameSpace the namespace for the metric + * @param metVal the name of the metric + * @param metricOption the statistic to retrieve for the metric (e.g., "Maximum", "Average") + * @param date the date for which to retrieve the metric statistics, in the format "yyyy-MM-dd'T'HH:mm:ss'Z'" + * @param myDimension the dimension(s) to filter the metric statistics by + * @return a {@link CompletableFuture} that completes when the metric statistics have been retrieved and displayed + */ + public CompletableFuture getAndDisplayMetricStatisticsAsync(String nameSpace, String metVal, + String metricOption, String date, Dimension myDimension) { + + Instant start = Instant.parse(date); + Instant endDate = Instant.now(); + + // Building the request for metric statistics. + GetMetricStatisticsRequest statisticsRequest = GetMetricStatisticsRequest.builder() + .endTime(endDate) + .startTime(start) + .dimensions(myDimension) + .metricName(metVal) + .namespace(nameSpace) + .period(86400) // 1 day period + .statistics(Statistic.fromValue(metricOption)) + .build(); + + return getAsyncClient().getMetricStatistics(statisticsRequest) + .whenComplete((response, exception) -> { + if (response != null) { + List data = response.datapoints(); + if (!data.isEmpty()) { + for (Datapoint datapoint : data) { + logger.info("Timestamp: {} Maximum value: {}", datapoint.timestamp(), datapoint.maximum()); + } + } else { + logger.info("The returned data list is empty"); + } + } else { + logger.info("Failed to get metric statistics: {} ", exception.getMessage()); + } + }) + .exceptionally(exception -> { + throw new RuntimeException("Error while getting metric statistics: " + exception.getMessage(), exception); + }); + } + + // snippet-end:[cloudwatch.java2.scenario.display.metrics.main] + + // snippet-start:[cloudwatch.java2.list_metrics.main] + /** + * Retrieves a list of metric names for the specified namespace. + * + * @param namespace the namespace for which to retrieve the metric names + * @return a {@link CompletableFuture} that, when completed, contains an {@link ArrayList} of + * the metric names in the specified namespace + * @throws RuntimeException if an error occurs while listing the metrics + */ + public CompletableFuture> listMetsAsync(String namespace) { + ListMetricsRequest request = ListMetricsRequest.builder() + .namespace(namespace) + .build(); + + ListMetricsPublisher metricsPaginator = getAsyncClient().listMetricsPaginator(request); + Set metSet = new HashSet<>(); + CompletableFuture future = metricsPaginator.subscribe(response -> { + response.metrics().forEach(metric -> { + String metricName = metric.metricName(); + metSet.add(metricName); + }); + }); + + return future + .thenApply(ignored -> new ArrayList<>(metSet)) + .exceptionally(exception -> { + throw new RuntimeException("Failed to list metrics: " + exception.getMessage(), exception); + }); + } + // snippet-end:[cloudwatch.java2.list_metrics.main] + + // snippet-start:[cloudwatch.java2.scenario.list.namespaces.main] + /** + * Lists the available namespaces for the current AWS account. + * + * @return a {@link CompletableFuture} that, when completed, contains an {@link ArrayList} of the available namespace names. + * @throws RuntimeException if an error occurs while listing the namespaces. + */ + public CompletableFuture> listNameSpacesAsync() { + ArrayList nameSpaceList = new ArrayList<>(); + ListMetricsRequest request = ListMetricsRequest.builder().build(); + + ListMetricsPublisher metricsPaginator = getAsyncClient().listMetricsPaginator(request); + CompletableFuture future = metricsPaginator.subscribe(response -> { + response.metrics().forEach(metric -> { + String namespace = metric.namespace(); + if (!nameSpaceList.contains(namespace)) { + nameSpaceList.add(namespace); + } + }); + }); + + return future + .thenApply(ignored -> nameSpaceList) + .exceptionally(exception -> { + throw new RuntimeException("Failed to list namespaces: " + exception.getMessage(), exception); + }); + } + // snippet-end:[cloudwatch.java2.scenario.list.namespaces.main] + /** + * Retrieves the specific metric asynchronously. + * + * @param namespace the namespace of the metric to retrieve + * @return a CompletableFuture that completes with the first dimension of the first metric found in the specified namespace, + * or throws a RuntimeException if an error occurs or no metrics or dimensions are found + */ + public CompletableFuture getSpecificMetAsync(String namespace) { + ListMetricsRequest request = ListMetricsRequest.builder() + .namespace(namespace) + .build(); + + return getAsyncClient().listMetrics(request).handle((response, exception) -> { + if (exception != null) { + logger.info("Error occurred while listing metrics: {} ", exception.getMessage()); + throw new RuntimeException("Failed to retrieve specific metric dimension", exception); + } else { + List myList = response.metrics(); + if (!myList.isEmpty()) { + Metric metric = myList.get(0); + if (!metric.dimensions().isEmpty()) { + return metric.dimensions().get(0); // Return the first dimension + } + } + throw new RuntimeException("No metrics or dimensions found"); + } + }); + } + + public static String readFileAsString(String file) throws IOException { + return new String(Files.readAllBytes(Paths.get(file))); + } +} +// snippet-end:[cloudwatch.java2.actions.main] \ No newline at end of file diff --git a/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/scenario/CloudWatchScenario.java b/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/scenario/CloudWatchScenario.java new file mode 100644 index 00000000000..96c36f5105c --- /dev/null +++ b/javav2/example_code/cloudwatch/src/main/java/com/example/cloudwatch/scenario/CloudWatchScenario.java @@ -0,0 +1,614 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.cloudwatch.scenario; + +// snippet-start:[cloudwatch.java2.scenario.main] +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.services.cloudwatch.model.CloudWatchException; +import software.amazon.awssdk.services.cloudwatch.model.DashboardInvalidInputErrorException; +import software.amazon.awssdk.services.cloudwatch.model.DeleteAlarmsResponse; +import software.amazon.awssdk.services.cloudwatch.model.DeleteAnomalyDetectorResponse; +import software.amazon.awssdk.services.cloudwatch.model.DeleteDashboardsResponse; +import software.amazon.awssdk.services.cloudwatch.model.Dimension; +import software.amazon.awssdk.services.cloudwatch.model.GetMetricStatisticsResponse; +import software.amazon.awssdk.services.cloudwatch.model.LimitExceededException; +import software.amazon.awssdk.services.cloudwatch.model.PutDashboardResponse; +import software.amazon.awssdk.services.cloudwatch.model.PutMetricDataResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Scanner; +import java.util.concurrent.CompletableFuture; + +/** + * Before running this Java V2 code example, set up your development + * environment, including your credentials. + * + * For more information, see the following documentation topic: + * + * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html + * + * To enable billing metrics and statistics for this example, make sure billing + * alerts are enabled for your account: + * https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html#turning_on_billing_metrics + * + * This Java code example performs the following tasks: + * + * 1. List available namespaces from Amazon CloudWatch. + * 2. List available metrics within the selected Namespace. + * 3. Get statistics for the selected metric over the last day. + * 4. Get CloudWatch estimated billing for the last week. + * 5. Create a new CloudWatch dashboard with metrics. + * 6. List dashboards using a paginator. + * 7. Create a new custom metric by adding data for it. + * 8. Add the custom metric to the dashboard. + * 9. Create an alarm for the custom metric. + * 10. Describe current alarms. + * 11. Get current data for the new custom metric. + * 12. Push data into the custom metric to trigger the alarm. + * 13. Check the alarm state using the action DescribeAlarmsForMetric. + * 14. Get alarm history for the new alarm. + * 15. Add an anomaly detector for the custom metric. + * 16. Describe current anomaly detectors. + * 17. Get a metric image for the custom metric. + * 18. Clean up the Amazon CloudWatch resources. + */ +public class CloudWatchScenario { + public static final String DASHES = new String(new char[80]).replace("\0", "-"); + + static CloudWatchActions cwActions = new CloudWatchActions(); + + private static final Logger logger = LoggerFactory.getLogger(CloudWatchScenario.class); + static Scanner scanner = new Scanner(System.in); + public static void main(String[] args) throws Throwable { + + final String usage = """ + + Usage: + \s + + Where: + myDate - The start date to use to get metric statistics. (For example, 2023-01-11T18:35:24.00Z.)\s + costDateWeek - The start date to use to get AWS/Billing statistics. (For example, 2023-01-11T18:35:24.00Z.)\s + dashboardName - The name of the dashboard to create.\s + dashboardJson - The location of a JSON file to use to create a dashboard. (See jsonWidgets.json in javav2/example_code/cloudwatch.)\s + dashboardAdd - The location of a JSON file to use to update a dashboard. (See CloudDashboard.json in javav2/example_code/cloudwatch.)\s + settings - The location of a JSON file from which various values are read. (See settings.json in javav2/example_code/cloudwatch.)\s + metricImage - The location of a BMP file that is used to create a graph.\s + """; + + if (args.length != 7) { + logger.info(usage); + return; + } + String myDate = args[0]; + String costDateWeek = args[1]; + String dashboardName = args[2]; + String dashboardJson = args[3]; + String dashboardAdd = args[4]; + String settings = args[5]; + String metricImage = args[6]; + + logger.info(DASHES); + logger.info("Welcome to the Amazon CloudWatch Basics scenario."); + logger.info(""" + Amazon CloudWatch is a comprehensive monitoring and observability service + provided by Amazon Web Services (AWS). It is designed to help you monitor your + AWS resources, applications, and services, as well as on-premises resources, + in real-time. + + CloudWatch collects and tracks various types of data, including metrics, + logs, and events, from your AWS and on-premises resources. It allows you to set + alarms and automatically respond to changes in your environment, + enabling you to quickly identify and address issues before they impact your + applications or services. + + With CloudWatch, you can gain visibility into your entire infrastructure, from the cloud + to the edge, and use this information to make informed decisions and optimize your + resource utilization. + + This scenario guides you through how to perform Amazon CloudWatch tasks by using the + AWS SDK for Java v2. Let's get started... + """); + waitForInputToContinue(scanner); + + try { + runScenario(myDate, costDateWeek, dashboardName, dashboardJson, dashboardAdd, settings, metricImage); + } catch (RuntimeException e) { + e.printStackTrace(); + } + logger.info(DASHES); + } + + private static void runScenario(String myDate, String costDateWeek, String dashboardName, String dashboardJson, String dashboardAdd, String settings, String metricImage ) throws Throwable { + Double dataPoint = Double.parseDouble("10.0"); + logger.info(DASHES); + logger.info(""" + 1. List at least five available unique namespaces from Amazon CloudWatch. + Select one from the list. + """); + String selectedNamespace; + String selectedMetrics; + int num; + try { + CompletableFuture> future = cwActions.listNameSpacesAsync(); + ArrayList list = future.join(); + for (int z = 0; z < 5; z++) { + int index = z + 1; + logger.info(" " + index + ". {}", list.get(z)); + } + + num = Integer.parseInt(scanner.nextLine()); + if (1 <= num && num <= 5) { + selectedNamespace = list.get(num - 1); + } else { + logger.info("You did not select a valid option."); + return; + } + logger.info("You selected {}", selectedNamespace); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: " + rt.getMessage()); + } + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("2. List available metrics within the selected namespace."); + logger.info(""" + A metric is a measure of the performance or health of your AWS resources, + applications, or custom resources. Metrics are the basic building blocks of CloudWatch + and provide data points that represent a specific aspect of your system or application over time. + + Select a metric from the list. + """); + + Dimension myDimension = null; + try { + CompletableFuture> future = cwActions.listMetsAsync(selectedNamespace); + ArrayList metList = future.join(); + logger.info("Metrics successfully retrieved. Total metrics: {}", metList.size()); + for (int z = 0; z < 5; z++) { + int index = z + 1; + logger.info(" " + index + ". " + metList.get(z)); + } + num = Integer.parseInt(scanner.nextLine()); + if (1 <= num && num <= 5) { + selectedMetrics = metList.get(num - 1); + } else { + logger.info("You did not select a valid option."); + return; + } + logger.info("You selected {}", selectedMetrics); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + + try { + myDimension = cwActions.getSpecificMetAsync(selectedNamespace).join(); + logger.info("Metric statistics successfully retrieved and displayed."); + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("3. Get statistics for the selected metric over the last day."); + logger.info(""" + Statistics refer to the various mathematical calculations that can be performed on the + collected metrics to derive meaningful insights. Statistics provide a way to summarize and + analyze the data collected for a specific metric over a specified time period. + """); + waitForInputToContinue(scanner); + String metricOption = ""; + ArrayList statTypes = new ArrayList<>(); + statTypes.add("SampleCount"); + statTypes.add("Average"); + statTypes.add("Sum"); + statTypes.add("Minimum"); + statTypes.add("Maximum"); + + for (int t = 0; t < 5; t++) { + logger.info(" " + (t + 1) + ". {}", statTypes.get(t)); + } + logger.info("Select a metric statistic by entering a number from the preceding list:"); + num = Integer.parseInt(scanner.nextLine()); + if (1 <= num && num <= 5) { + metricOption = statTypes.get(num - 1); + } else { + logger.info("You did not select a valid option."); + return; + } + logger.info("You selected " + metricOption); + waitForInputToContinue(scanner); + try { + CompletableFuture future = cwActions.getAndDisplayMetricStatisticsAsync(selectedNamespace, selectedMetrics, metricOption, myDate, myDimension); + future.join(); + logger.info("Metric statistics retrieved successfully."); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("4. Get CloudWatch estimated billing for the last week."); + waitForInputToContinue(scanner); + try { + CompletableFuture future = cwActions.getMetricStatisticsAsync(costDateWeek); + future.join(); + + logger.info("Metric statistics successfully retrieved and displayed."); + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("5. Create a new CloudWatch dashboard with metrics."); + waitForInputToContinue(scanner); + try { + CompletableFuture future = cwActions.createDashboardWithMetricsAsync(dashboardName, dashboardJson); + future.join(); + + } catch (RuntimeException | IOException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof DashboardInvalidInputErrorException cwEx) { + logger.info("Invalid CloudWatch data. Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("6. List dashboards using a paginator."); + waitForInputToContinue(scanner); + try { + CompletableFuture future = cwActions.listDashboardsAsync(); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("7. Create a new custom metric by adding data to it."); + logger.info(""" + The primary benefit of using a custom metric in Amazon CloudWatch is the ability to + monitor and collect data that is specific to your application or infrastructure. + """); + waitForInputToContinue(scanner); + try { + CompletableFuture future = cwActions.createNewCustomMetricAsync(dataPoint); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("8. Add an additional metric to the dashboard."); + waitForInputToContinue(scanner); + try { + CompletableFuture future = cwActions.addMetricToDashboardAsync(dashboardAdd, dashboardName); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof DashboardInvalidInputErrorException cwEx) { + logger.info("Invalid CloudWatch data. Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + logger.info(DASHES); + + logger.info(DASHES); + logger.info("9. Create an alarm for the custom metric."); + waitForInputToContinue(scanner); + String alarmName = "" ; + try { + CompletableFuture future = cwActions.createAlarmAsync(settings); + alarmName = future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof LimitExceededException cwEx) { + logger.info("The quota for alarms has been reached: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("10. Describe ten current alarms."); + waitForInputToContinue(scanner); + try { + CompletableFuture future = cwActions.describeAlarmsAsync(); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("11. Get current data for new custom metric."); + try { + CompletableFuture future = cwActions.getCustomMetricDataAsync(settings); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("12. Push data into the custom metric to trigger the alarm."); + waitForInputToContinue(scanner); + try { + CompletableFuture future = cwActions.addMetricDataForAlarmAsync(settings); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("13. Check the alarm state using the action DescribeAlarmsForMetric."); + waitForInputToContinue(scanner); + try { + CompletableFuture future = cwActions.checkForMetricAlarmAsync(settings); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("14. Get alarm history for the new alarm."); + waitForInputToContinue(scanner); + try { + CompletableFuture future = cwActions.getAlarmHistoryAsync(settings, myDate); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + logger.info(DASHES); + + logger.info(DASHES); + logger.info("15. Add an anomaly detector for the custom metric."); + logger.info(""" + An anomaly detector is a feature that automatically detects unusual patterns or deviations in your + monitored metrics. It uses machine learning algorithms to analyze the historical behavior + of your metrics and establish a baseline. + + The anomaly detector then compares the current metric values against this baseline and + identifies any anomalies or outliers that may indicate potential issues or unexpected changes + in your system's performance or behavior. + + """); + waitForInputToContinue(scanner); + try { + CompletableFuture future = cwActions.addAnomalyDetectorAsync(settings); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("16. Describe current anomaly detectors."); + waitForInputToContinue(scanner); + try { + CompletableFuture future = cwActions.describeAnomalyDetectorsAsync(settings); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("17. Get a metric image for the custom metric."); + try { + CompletableFuture future = cwActions.downloadAndSaveMetricImageAsync(metricImage); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + logger.info(DASHES); + + logger.info(DASHES); + logger.info("18. Clean up the Amazon CloudWatch resources."); + + try { + logger.info(". Delete the Dashboard."); + waitForInputToContinue(scanner); + CompletableFuture future = cwActions.deleteDashboardAsync(dashboardName); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + + try { + logger.info("Delete the alarm."); + waitForInputToContinue(scanner); + CompletableFuture future = cwActions.deleteCWAlarmAsync(alarmName); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + + try { + logger.info("Delete the anomaly detector."); + waitForInputToContinue(scanner); + CompletableFuture future = cwActions.deleteAnomalyDetectorAsync(settings); + future.join(); + + } catch (RuntimeException rt) { + Throwable cause = rt.getCause(); + if (cause instanceof CloudWatchException cwEx) { + logger.info("CloudWatch error occurred: Error message: {}, Error code {}", cwEx.getMessage(), cwEx.awsErrorDetails().errorCode()); + } else { + logger.info("An unexpected error occurred: {}", rt.getMessage()); + } + throw cause; + } + waitForInputToContinue(scanner); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("The Amazon CloudWatch example scenario is complete."); + logger.info(DASHES); + } + + private static void waitForInputToContinue(Scanner scanner) { + while (true) { + logger.info(""); + logger.info("Enter 'c' followed by to continue:"); + String input = scanner.nextLine(); + if (input.trim().equalsIgnoreCase("c")) { + logger.info("Continuing with the program..."); + logger.info(""); + break; + } else { + // Handle invalid input. + logger.info("Invalid input. Please try again."); + } + } + } +} +// snippet-end:[cloudwatch.java2.scenario.main] \ No newline at end of file diff --git a/javav2/example_code/cloudwatch/src/main/resources/log4j2.xml b/javav2/example_code/cloudwatch/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..4d900326937 --- /dev/null +++ b/javav2/example_code/cloudwatch/src/main/resources/log4j2.xml @@ -0,0 +1,15 @@ + + + + + + %msg%n + + + + + + + + + \ No newline at end of file diff --git a/javav2/example_code/cloudwatch/src/test/java/CloudWatchTest.java b/javav2/example_code/cloudwatch/src/test/java/CloudWatchTest.java index dce37ebdf93..601b651ec02 100644 --- a/javav2/example_code/cloudwatch/src/test/java/CloudWatchTest.java +++ b/javav2/example_code/cloudwatch/src/test/java/CloudWatchTest.java @@ -1,22 +1,33 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -import com.example.cloudwatch.DeleteAlarm; +import com.example.cloudwatch.scenario.CloudWatchActions; import com.google.gson.Gson; import org.junit.jupiter.api.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.cloudwatch.CloudWatchClient; +import software.amazon.awssdk.services.cloudwatch.model.DeleteAlarmsResponse; +import software.amazon.awssdk.services.cloudwatch.model.DeleteAnomalyDetectorResponse; +import software.amazon.awssdk.services.cloudwatch.model.DeleteDashboardsResponse; import software.amazon.awssdk.services.cloudwatch.model.Dimension; -import software.amazon.awssdk.services.cloudwatchevents.CloudWatchEventsClient; -import software.amazon.awssdk.services.cloudwatchlogs.CloudWatchLogsClient; +import software.amazon.awssdk.services.cloudwatch.model.GetMetricStatisticsResponse; +import software.amazon.awssdk.services.cloudwatch.model.PutDashboardResponse; +import software.amazon.awssdk.services.cloudwatch.model.PutMetricDataResponse; import com.example.cloudwatch.*; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueResponse; import java.io.*; import java.util.ArrayList; +import java.util.concurrent.CompletableFuture; + import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; + /** * To run these integration tests, you must set the required values @@ -26,29 +37,21 @@ @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class CloudWatchTest { private static CloudWatchClient cw; - private static CloudWatchLogsClient cloudWatchLogsClient; - private static CloudWatchEventsClient cwe; - private static String logGroup = ""; - private static String alarmName = ""; - private static String streamName = ""; - private static String metricId = ""; - private static String instanceId = ""; - private static String ruleResource = ""; - private static String filterName = ""; - private static String destinationArn = ""; - private static String roleArn = ""; - private static String ruleArn = ""; private static String namespace = ""; - private static String filterPattern = ""; - private static String ruleName = ""; private static String myDateSc = ""; private static String costDateWeekSc = ""; private static String dashboardNameSc = ""; private static String dashboardJsonSc = ""; private static String dashboardAddSc = ""; private static String settingsSc = ""; - private static String metricImageSc = ""; + private static String alarmName = ""; + + private static final CloudWatchActions cwActions = new CloudWatchActions(); + + private static Dimension myDimension = null; + + private static final Logger logger = LoggerFactory.getLogger(CloudWatchTest.class); @BeforeAll public static void setUp() throws IOException { cw = CloudWatchClient.builder() @@ -56,261 +59,242 @@ public static void setUp() throws IOException { .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) .build(); - cloudWatchLogsClient = CloudWatchLogsClient.builder() - .region(Region.US_EAST_1) - .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) - .build(); - - cwe = CloudWatchEventsClient.builder() - .region(Region.US_EAST_1) - .credentialsProvider(EnvironmentVariableCredentialsProvider.create()) - .build(); - // Get the values to run these tests from AWS Secrets Manager. Gson gson = new Gson(); String json = getSecretValues(); SecretValues values = gson.fromJson(json, SecretValues.class); - logGroup = values.getLogGroup(); - alarmName = values.getAlarmName(); - streamName = values.getStreamName(); - ruleResource = values.getRuleResource(); - metricId = values.getMetricId(); - filterName = values.getFilterName(); - destinationArn = values.getDestinationArn(); - roleArn = values.getRoleArn(); - filterPattern = values.getFilterPattern(); - instanceId = values.getInstanceId(); - ruleName = values.getRuleName(); - ruleArn = values.getRuleArn(); namespace = values.getNamespace(); - myDateSc = values.myDateSc; + myDateSc = values.getMyDateSc(); costDateWeekSc = values.getCostDateWeekSc(); dashboardNameSc = values.getDashboardNameSc(); dashboardJsonSc = values.getDashboardJsonSc(); dashboardAddSc = values.getDashboardAddSc(); settingsSc = values.getSettingsSc(); - metricImageSc = values.getMetricImageSc(); - - // Uncomment this code block if you prefer using a config.properties file to - // retrieve AWS values required for these tests. - /* - * try (InputStream input = - * CloudWatchTest.class.getClassLoader().getResourceAsStream("config.properties" - * )) { - * Properties prop = new Properties(); - * if (input == null) { - * System.out.println("Sorry, unable to find config.properties"); - * return; - * } - * - * // Populate the data members required for all tests - * prop.load(input); - * logGroup = prop.getProperty("logGroup"); - * alarmName = prop.getProperty("alarmName"); - * streamName = prop.getProperty("streamName"); - * ruleResource = prop.getProperty("ruleResource"); - * metricId = prop.getProperty("metricId"); - * filterName = prop.getProperty("filterName"); - * destinationArn = prop.getProperty("destinationArn"); - * roleArn= prop.getProperty("roleArn"); - * filterPattern= prop.getProperty("filterPattern"); - * instanceId= prop.getProperty("instanceId"); - * ruleName= prop.getProperty("ruleName"); - * ruleArn= prop.getProperty("ruleArn"); - * namespace= prop.getProperty("namespace"); - * myDateSc= prop.getProperty("myDateSc"); - * costDateWeekSc= prop.getProperty("costDateWeekSc"); - * dashboardNameSc= prop.getProperty("dashboardNameSc"); - * dashboardJsonSc= prop.getProperty("dashboardJsonSc"); - * dashboardAddSc= prop.getProperty("dashboardAddSc"); - * settingsSc= prop.getProperty("settingsSc"); - * metricImageSc= prop.getProperty("metricImageSc"); - * - * } catch (IOException ex) { - * ex.printStackTrace(); - * } - */ } @Test @Tag("IntegrationTest") @Order(1) - public void CreateAlarm() { - assertDoesNotThrow(() -> PutMetricAlarm.putMetricAlarm(cw, alarmName, instanceId)); - System.out.println(" Test 1 passed"); + public void testHelloService() { + assertDoesNotThrow(() -> HelloService.listMets(cw, namespace)); + logger.info(" Test 1 passed"); } @Test @Tag("IntegrationTest") @Order(2) - public void DescribeAlarms() { - assertDoesNotThrow(() -> DescribeAlarms.desCWAlarms(cw)); + public void testListNameSpaces() { + assertDoesNotThrow(() -> { + CompletableFuture> future = cwActions.listNameSpacesAsync(); + ArrayList list = future.join(); + assertFalse(list.isEmpty()); + }); System.out.println("Test 2 passed"); } + @Test @Tag("IntegrationTest") @Order(3) - public void DescribeSubscriptionFilters() { - assertDoesNotThrow(() -> DescribeSubscriptionFilters.describeFilters(cloudWatchLogsClient, logGroup)); - System.out.println(" Test 3 passed"); + public void testListMets() { + assertDoesNotThrow(() -> { + CompletableFuture> future = cwActions.listMetsAsync(namespace); + ArrayList metList = future.join(); + assertFalse(metList.isEmpty()); + + }); + logger.info("Test 3 passed"); } - @Test @Tag("IntegrationTest") @Order(4) - public void DisableAlarmActions() { - assertDoesNotThrow(() -> DisableAlarmActions.disableActions(cw, alarmName)); - System.out.println("\n Test 4 passed"); + public void testGetSpecificMet() { + assertDoesNotThrow(() -> { + myDimension = cwActions.getSpecificMetAsync(namespace).join(); + assertNotNull(myDimension, "The retrieved metric dimension should not be null"); + }); + logger.info("Test 4 passed"); } @Test @Tag("IntegrationTest") @Order(5) - public void EnableAlarmActions() { - assertDoesNotThrow(() -> EnableAlarmActions.enableActions(cw, alarmName)); - System.out.println("\n Test 6 passed"); + public void testGetAndDisplayMetric() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.getAndDisplayMetricStatisticsAsync("AWS/MemoryDB","ActiveDefragHits", "Maximum", myDateSc, myDimension); + future.join(); + }); + logger.info("Test 5 passed"); } @Test @Tag("IntegrationTest") @Order(6) - void PutCloudWatchEvent() { - assertDoesNotThrow(() -> PutEvents.putCWEvents(cwe, ruleResource)); - System.out.println("\n Test 6 passed"); + void testCreateDashboard() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.createDashboardWithMetricsAsync(dashboardNameSc, dashboardJsonSc); + future.join(); + }); + logger.info("\n Test 6 passed"); } @Test @Tag("IntegrationTest") @Order(7) - public void GetMetricData() { - assertDoesNotThrow(() -> GetMetricData.getMetData(cw)); - System.out.println("\n Test 7 passed"); + public void testGetMetricData() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.getMetricStatisticsAsync(costDateWeekSc); + future.join(); + }); + logger.info("\n Test 7 passed"); } @Test @Tag("IntegrationTest") @Order(8) - public void PutRule() { - assertDoesNotThrow(() -> PutRule.putCWRule(cwe, ruleName, ruleArn)); - System.out.println("\n Test 8 passed"); + public void testListDashboards() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.listDashboardsAsync(); + future.join(); + }); + logger.info("\n Test 8 passed"); } @Test @Tag("IntegrationTest") @Order(9) - public void ListMetrics() { - assertDoesNotThrow(() -> ListMetrics.listMets(cw, namespace)); - System.out.println("\n Test 9 passed"); + public void testListMetrics() { + Double dataPoint = Double.parseDouble("10.0"); + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.createNewCustomMetricAsync(dataPoint); + future.join(); + }); + logger.info("\n Test 9 passed"); } @Test @Tag("IntegrationTest") @Order(10) - public void DeleteAlarm() { - assertDoesNotThrow(() -> DeleteAlarm.deleteCWAlarm(cw, alarmName)); - System.out.println("\n Test 10 passed"); - } + public void testMetricToDashboard() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.addMetricToDashboardAsync(dashboardAddSc, dashboardNameSc); + future.join(); + }); + logger.info("\n Test 10 passed"); + } @Test @Tag("IntegrationTest") @Order(11) - public void CloudWatchScenarioTest() { - Double dataPoint = Double.parseDouble("10.0"); - System.out.println( - "1. List at least five available unique namespaces from Amazon CloudWatch. Select one from the list."); - ArrayList list = CloudWatchScenario.listNameSpaces(cw); - for (int z = 0; z < 5; z++) { - int index = z + 1; - System.out.println(" " + index + ". " + list.get(z)); - } + public void testCreateAlarm() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.createAlarmAsync(settingsSc); + alarmName = future.join(); + assertFalse(alarmName.isEmpty()); + }); + logger.info("\n Test 11 passed"); + } - String selectedNamespace = ""; - String selectedMetrics = ""; - int num = 2; - if (1 <= num && num <= 5) { - selectedNamespace = list.get(num - 1); - } else { - System.out.println("You did not select a valid option."); - System.exit(1); - } - System.out.println("You selected " + selectedNamespace); + @Test + @Tag("IntegrationTest") + @Order(12) + public void testDescribeAlarms() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.describeAlarmsAsync(); + future.join(); + }); + logger.info("\n Test 12 passed"); + } - System.out.println("2. List available metrics within the selected namespace and select one from the list."); - ArrayList metList = CloudWatchScenario.listMets(cw, selectedNamespace); - for (int z = 0; z < 5; z++) { - int index = z + 1; - System.out.println(" " + index + ". " + metList.get(z)); - } - num = 1; - if (1 <= num && num <= 5) { - selectedMetrics = metList.get(num - 1); - } else { - System.out.println("You did not select a valid option."); - System.exit(1); - } - System.out.println("You selected " + selectedMetrics); - Dimension myDimension = CloudWatchScenario.getSpecificMet(cw, selectedNamespace); - - System.out.println("3. Get statistics for the selected metric over the last day."); - String metricOption = ""; - ArrayList statTypes = new ArrayList<>(); - statTypes.add("SampleCount"); - statTypes.add("Average"); - statTypes.add("Sum"); - statTypes.add("Minimum"); - statTypes.add("Maximum"); - - for (int t = 0; t < 5; t++) { - System.out.println(" " + (t + 1) + ". " + statTypes.get(t)); - } - System.out.println("Select a metric statistic by entering a number from the preceding list:"); - num = Integer.parseInt("2"); - if (1 <= num && num <= 5) { - metricOption = statTypes.get(num - 1); - } else { - System.out.println("You did not select a valid option."); - System.exit(1); - } - System.out.println("You selected " + metricOption); - CloudWatchScenario.getAndDisplayMetricStatistics(cw, selectedNamespace, selectedMetrics, metricOption, myDateSc, - myDimension); - System.out.println("4. Get CloudWatch estimated billing for the last week."); - CloudWatchScenario.getMetricStatistics(cw, costDateWeekSc); - - System.out.println("5. Create a new CloudWatch dashboard with metrics."); - CloudWatchScenario.createDashboardWithMetrics(cw, dashboardNameSc, dashboardJsonSc); - System.out.println("6. List dashboards using a paginator."); - CloudWatchScenario.listDashboards(cw); - - System.out.println("7. Create a new custom metric by adding data to it."); - CloudWatchScenario.createNewCustomMetric(cw, dataPoint); - - System.out.println("8. Add an additional metric to the dashboard."); - CloudWatchScenario.addMetricToDashboard(cw, dashboardAddSc, dashboardNameSc); - System.out.println("9. Create an alarm for the custom metric."); - String alarmName = CloudWatchScenario.createAlarm(cw, settingsSc); - System.out.println("10. Describe ten current alarms."); - CloudWatchScenario.describeAlarms(cw); - System.out.println("11. Get current data for new custom metric."); - CloudWatchScenario.getCustomMetricData(cw, settingsSc); - System.out.println("12. Push data into the custom metric to trigger the alarm."); - CloudWatchScenario.addMetricDataForAlarm(cw, settingsSc); - System.out.println("13. Check the alarm state using the action DescribeAlarmsForMetric."); - CloudWatchScenario.checkForMetricAlarm(cw, settingsSc); - System.out.println("14. Get alarm history for the new alarm."); - CloudWatchScenario.getAlarmHistory(cw, settingsSc, myDateSc); - System.out.println("15. Add an anomaly detector for the custom metric."); - CloudWatchScenario.addAnomalyDetector(cw, settingsSc); - System.out.println("16. Describe current anomaly detectors."); - CloudWatchScenario.describeAnomalyDetectors(cw, settingsSc); - System.out.println("17. Get a metric image for the custom metric."); - CloudWatchScenario.getAndOpenMetricImage(cw, metricImageSc); - System.out.println("18. Clean up the Amazon CloudWatch resources."); - CloudWatchScenario.deleteDashboard(cw, dashboardNameSc); - CloudWatchScenario.deleteCWAlarm(cw, alarmName); - CloudWatchScenario.deleteAnomalyDetector(cw, settingsSc); - System.out.println("The Amazon CloudWatch example scenario is complete."); + @Test + @Tag("IntegrationTest") + @Order(13) + public void testCustomMetricData() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.getCustomMetricDataAsync(settingsSc); + future.join(); + }); + logger.info("\n Test 13 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(14) + public void testMetricDataForAlarm() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.addMetricDataForAlarmAsync(settingsSc); + future.join(); + }); + logger.info("\n Test 14 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(15) + public void testMetricAlarmAsync() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.checkForMetricAlarmAsync(settingsSc); + future.join(); + }); + logger.info("\n Test 15 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(16) + public void testAlarmHistory() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.getAlarmHistoryAsync(settingsSc, myDateSc); + future.join(); + }); + logger.info("\n Test 16 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(17) + public void testAnomalyDetector() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.addAnomalyDetectorAsync(settingsSc); + future.join(); + }); + logger.info("\n Test 17 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(18) + public void testDeleteDashboard() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.deleteDashboardAsync(dashboardNameSc); + future.join(); + + }); + logger.info("\n Test 18 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(19) + public void testCWAlarmAsync() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.deleteCWAlarmAsync(alarmName); + future.join(); + + }); + logger.info("\n Test 19 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(20) + public void testDeleteAnomalyDetector() { + assertDoesNotThrow(() -> { + CompletableFuture future = cwActions.deleteAnomalyDetectorAsync(settingsSc); + future.join(); + + }); + logger.info("\n Test 20 passed"); } private static String getSecretValues() {