├── .circleci
└── config.yml
├── .dockerignore
├── .github
├── ISSUE_TEMPLATE
│ ├── bug.md
│ ├── config.yml
│ ├── metrics.md
│ └── request.md
├── dependabot.yaml
└── workflows
│ ├── container_description.yml
│ └── maven.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── MAINTAINERS.md
├── Makefile
├── NOTICE
├── README.md
├── RELEASING.md
├── SECURITY.md
├── example.yml
├── examples
├── AmazonMQ.yml
├── ApiGateway.yml
├── AppRunner.yml
├── ApplicationELB.yml
├── Athena.yml
├── AuroraServerless.yml
├── AutoScaling.yml
├── Backup.yml
├── CloudFront.yml
├── DDoSProtection.yml
├── DMS.yml
├── DocumentDB.yml
├── DynamoDB.yml
├── EBS.yml
├── EC2.yml
├── ECS.yml
├── EFS.yml
├── ELB.yml
├── ElastiCache.yml
├── Fargate.yml
├── Firehose.yml
├── Kafka.yml
├── Kinesis.yml
├── Lambda.yml
├── NATGateway.yml
├── NetworkELB.yml
├── RDS.yml
├── Redshift.yml
├── Route53.yml
├── S3.yml
├── SES.yml
├── SNS.yml
├── SQS.yml
├── Sagemaker.yml
├── VPN.yml
├── WAF.yml
├── WAFV2.yml
└── dashboards
│ └── DocumentDB.yml
├── pom.xml
└── src
├── main
├── java
│ └── io
│ │ └── prometheus
│ │ └── cloudwatch
│ │ ├── BuildInfoCollector.java
│ │ ├── CachingDimensionSource.java
│ │ ├── CloudWatchCollector.java
│ │ ├── DataGetter.java
│ │ ├── DefaultDimensionSource.java
│ │ ├── DimensionSource.java
│ │ ├── DisallowHttpMethods.java
│ │ ├── DynamicReloadServlet.java
│ │ ├── GetMetricDataDataGetter.java
│ │ ├── GetMetricStatisticsDataGetter.java
│ │ ├── HealthServlet.java
│ │ ├── HomePageServlet.java
│ │ ├── MetricRule.java
│ │ ├── ReloadSignalHandler.java
│ │ └── WebServer.java
└── resources
│ └── .properties
└── test
└── java
└── io
└── prometheus
└── cloudwatch
├── CachingDimensionExpiryTest.java
├── CachingDimensionSourceTest.java
├── CloudWatchCollectorTest.java
├── GetMetricDataGetterTest.java
└── RequestsMatchers.java
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | ---
2 | version: 2.1
3 |
4 | orbs:
5 | prometheus: prometheus/prometheus@0.17.1
6 |
7 | executors:
8 | java:
9 | docker:
10 | - image: cimg/openjdk:21.0
11 |
12 | jobs:
13 | build:
14 | working_directory: ~/circleci-java
15 | executor: java
16 | steps:
17 | - checkout
18 | - restore_cache: # restore the saved cache after the first run or if `pom.xml` has changed
19 | key: circleci-demo-java-spring-{{ checksum "pom.xml" }}
20 | - run: mvn dependency:go-offline # gets the project dependencies
21 | - save_cache:
22 | paths:
23 | - ~/.m2
24 | key: circleci-demo-java-spring-{{ checksum "pom.xml" }}
25 | - run:
26 | name: Check formatting
27 | command: |
28 | if (mvn fmt:check);
29 | then
30 | echo "Code is well formatted"
31 | else
32 | echo "Code is not formatted well. Please run 'mvn fmt:format' and commit changes"
33 | exit 1
34 | fi
35 | - run: mvn package
36 | publish_image:
37 | executor: java
38 | environment:
39 | DOCKER_BUILDKIT: 1
40 | BUILDX_PLATFORMS: linux/amd64,linux/arm64
41 | steps:
42 | - checkout
43 | - setup_remote_docker
44 | - run:
45 | name: Install buildx
46 | command: |
47 | BUILDX_BINARY_URL="https://github.com/docker/buildx/releases/download/v0.7.0/buildx-v0.7.0.linux-amd64"
48 |
49 | curl --output docker-buildx \
50 | --silent --show-error --location --fail --retry 3 \
51 | "$BUILDX_BINARY_URL"
52 |
53 | mkdir -p ~/.docker/cli-plugins
54 |
55 | mv docker-buildx ~/.docker/cli-plugins/
56 | chmod a+x ~/.docker/cli-plugins/docker-buildx
57 |
58 | docker buildx install
59 | # Run binfmt
60 | docker run --rm --privileged tonistiigi/binfmt:latest --install "$BUILDX_PLATFORMS"
61 | - run: docker context create buildx
62 | - run: docker buildx create --name buildx --use buildx
63 | - run: docker login -u "$QUAY_LOGIN" -p "$QUAY_PASSWORD" quay.io
64 | - run: docker login -u "$DOCKER_LOGIN" -p "$DOCKER_PASSWORD"
65 | - run: |
66 | tags=(master main)
67 | if [[ -n "$CIRCLE_TAG" ]]; then
68 | tags+=("${CIRCLE_TAG}" latest)
69 | fi
70 |
71 | set -x
72 | docker buildx build \
73 | --progress plain \
74 | --platform "$BUILDX_PLATFORMS" \
75 | "${tags[@]/#/--tag=quay.io/prometheus/cloudwatch-exporter:}" \
76 | "${tags[@]/#/--tag=prom/cloudwatch-exporter:}" \
77 | --push .
78 | - run: docker images
79 | build_image:
80 | executor: java
81 | environment:
82 | DOCKER_BUILDKIT: 1
83 | BUILDX_PLATFORMS: linux/amd64,linux/arm64
84 | steps:
85 | - checkout
86 | - setup_remote_docker
87 | - run:
88 | name: Install buildx
89 | command: |
90 | BUILDX_BINARY_URL="https://github.com/docker/buildx/releases/download/v0.7.0/buildx-v0.7.0.linux-amd64"
91 |
92 | curl --output docker-buildx \
93 | --silent --show-error --location --fail --retry 3 \
94 | "$BUILDX_BINARY_URL"
95 |
96 | mkdir -p ~/.docker/cli-plugins
97 |
98 | mv docker-buildx ~/.docker/cli-plugins/
99 | chmod a+x ~/.docker/cli-plugins/docker-buildx
100 |
101 | docker buildx install
102 | # Run binfmt
103 | docker run --rm --privileged tonistiigi/binfmt:latest --install "$BUILDX_PLATFORMS"
104 | - run: docker context create buildx
105 | - run: docker buildx create --name buildx --use buildx
106 | - run: |
107 | docker buildx build \
108 | --progress plain \
109 | --platform "$BUILDX_PLATFORMS" \
110 | .
111 |
112 | workflows:
113 | version: 2
114 | cloudwatch_exporter:
115 | jobs:
116 | - build:
117 | filters:
118 | tags:
119 | only: /.*/
120 | - build_image:
121 | requires:
122 | - build
123 | filters:
124 | branches:
125 | ignore: master
126 | - publish_image:
127 | context: org-context
128 | requires:
129 | - build
130 | filters:
131 | tags:
132 | only: /.*/
133 | branches:
134 | only: master
135 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | ### Maven template
2 | target/
3 | pom.xml.tag
4 | pom.xml.releaseBackup
5 | pom.xml.versionsBackup
6 | pom.xml.next
7 | release.properties
8 | dependency-reduced-pom.xml
9 | buildNumber.properties
10 | .mvn/timing.properties
11 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar
12 | .mvn/wrapper/maven-wrapper.jar
13 |
14 | ### Java template
15 | # Compiled class file
16 | *.class
17 |
18 | # Log file
19 | *.log
20 |
21 | # BlueJ files
22 | *.ctxt
23 |
24 | # Mobile Tools for Java (J2ME)
25 | .mtj.tmp/
26 |
27 | # Package Files #
28 | *.jar
29 | *.war
30 | *.nar
31 | *.ear
32 | *.zip
33 | *.tar.gz
34 | *.rar
35 |
36 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
37 | hs_err_pid*
38 |
39 | ### JetBrains template
40 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
41 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
42 |
43 | # User-specific stuff
44 | .idea/
45 |
46 | # CMake
47 | cmake-build-*/
48 |
49 | # File-based project format
50 | *.iws
51 |
52 | # IntelliJ
53 | out/
54 |
55 | # mpeltonen/sbt-idea plugin
56 | .idea_modules/
57 |
58 | # JIRA plugin
59 | atlassian-ide-plugin.xml
60 |
61 | # Crashlytics plugin (for Android Studio and IntelliJ)
62 | com_crashlytics_export_strings.xml
63 | crashlytics.properties
64 | crashlytics-build.properties
65 | fabric.properties
66 |
67 | # local additions
68 | .circleci/
69 | example*
70 | .git*
71 |
72 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 'Report a bug'
3 | about: Report a bug 🪲
4 | title: "[bug]: bug title here"
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | ### What did you do
11 |
12 |
13 |
14 | ### What did you expect to see?
15 |
16 | ### What did you see instead? Under which circumstances?
17 |
18 | ### Are you currently working around this issue?
19 |
20 |
21 |
22 | ### Additional context
23 |
24 |
25 |
26 |
27 |
28 | ### Environment
29 |
30 | * Exporter version: `X.X.X`
31 | * Operating system & architecture: `XX`
32 | * Running in containers? y/n
33 | * Using the official image? y/n
34 |
35 |
36 | ### Exporter configuration file
37 |
38 |
39 | expand
40 |
41 | ```yaml
42 |
43 | ```
44 |
45 |
46 |
47 | ### Logs
48 |
49 |
50 |
51 | expand
52 |
53 | ```log
54 | (paste log lines here)
55 | ```
56 |
57 |
58 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Prometheus community channels
4 | url: https://prometheus.io/community
5 | about: For general prometheus questions ❓❓
6 | - name: Cloudwatch Service quotas
7 | url: https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_limits.html
8 | about: Read about Cloudwatch quotas
9 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/metrics.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 'Metrics issue'
3 | about: Request help getting metrics out of CloudWatch 📈
4 | title: "[metrics]: short description here"
5 | labels: metrics-configuration
6 | assignees: ''
7 |
8 | ---
9 |
10 | ### Context information
11 |
12 |
13 |
14 | * AWS service:
15 | * CloudWatch namespace:
16 | * Link to metrics documentation for this service:
17 | * AWS region of the exporter:
18 | * AWS region of the service:
19 |
20 |
21 |
22 | Exporter configuration
23 |
24 |
25 |
26 | ```yaml
27 |
28 |
29 |
30 |
31 | ```
32 |
33 |
34 |
35 |
36 |
37 | Exporter logs
38 |
39 |
40 |
41 | ```log
42 |
43 | ```
44 |
45 | ### What do you expect to happen?
46 |
47 |
48 |
49 | ### What happened instead?
50 |
51 |
52 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 'Suggest a feature'
3 | about: Suggest an idea to make the tool better! 🌟
4 | title: "[request]: describe request here"
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 | ## Use case. Why is this important?
10 |
11 |
12 |
13 | ## How do you think the new configuration should look like?
14 |
15 |
16 | Example:
17 |
18 | ```yaml
19 |
20 | ```
21 |
--------------------------------------------------------------------------------
/.github/dependabot.yaml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "maven" # See documentation for possible values
4 | directory: "/" # Location of package manifests
5 | schedule:
6 | interval: "weekly"
7 | day: "thursday"
8 | open-pull-requests-limit: 100
9 | - package-ecosystem: "github-actions"
10 | directory: "/"
11 | schedule:
12 | interval: "weekly"
13 | day: "thursday"
14 |
--------------------------------------------------------------------------------
/.github/workflows/container_description.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Push README to Docker Hub
3 | on:
4 | push:
5 | paths:
6 | - "README.md"
7 | - "README-containers.md"
8 | - ".github/workflows/container_description.yml"
9 | branches: [ main, master ]
10 |
11 | permissions:
12 | contents: read
13 |
14 | jobs:
15 | PushDockerHubReadme:
16 | runs-on: ubuntu-latest
17 | name: Push README to Docker Hub
18 | if: github.repository_owner == 'prometheus' || github.repository_owner == 'prometheus-community' # Don't run this workflow on forks.
19 | steps:
20 | - name: git checkout
21 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
22 | - name: Set docker hub repo name
23 | run: echo "DOCKER_REPO_NAME=$(make docker-repo-name)" >> $GITHUB_ENV
24 | - name: Push README to Dockerhub
25 | uses: christian-korneck/update-container-description-action@d36005551adeaba9698d8d67a296bd16fa91f8e8 # v1
26 | env:
27 | DOCKER_USER: ${{ secrets.DOCKER_HUB_LOGIN }}
28 | DOCKER_PASS: ${{ secrets.DOCKER_HUB_PASSWORD }}
29 | with:
30 | destination_container_repo: ${{ env.DOCKER_REPO_NAME }}
31 | provider: dockerhub
32 | short_description: ${{ env.DOCKER_REPO_NAME }}
33 | # Empty string results in README-containers.md being pushed if it
34 | # exists. Otherwise, README.md is pushed.
35 | readme_file: ''
36 |
37 | PushQuayIoReadme:
38 | runs-on: ubuntu-latest
39 | name: Push README to quay.io
40 | if: github.repository_owner == 'prometheus' || github.repository_owner == 'prometheus-community' # Don't run this workflow on forks.
41 | steps:
42 | - name: git checkout
43 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
44 | - name: Set quay.io org name
45 | run: echo "DOCKER_REPO=$(echo quay.io/${GITHUB_REPOSITORY_OWNER} | tr -d '-')" >> $GITHUB_ENV
46 | - name: Set quay.io repo name
47 | run: echo "DOCKER_REPO_NAME=$(make docker-repo-name)" >> $GITHUB_ENV
48 | - name: Push README to quay.io
49 | uses: christian-korneck/update-container-description-action@d36005551adeaba9698d8d67a296bd16fa91f8e8 # v1
50 | env:
51 | DOCKER_APIKEY: ${{ secrets.QUAY_IO_API_TOKEN }}
52 | with:
53 | destination_container_repo: ${{ env.DOCKER_REPO_NAME }}
54 | provider: quay
55 | # Empty string results in README-containers.md being pushed if it
56 | # exists. Otherwise, README.md is pushed.
57 | readme_file: ''
58 |
--------------------------------------------------------------------------------
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
3 |
4 | # This workflow uses actions that are not certified by GitHub.
5 | # They are provided by a third-party and are governed by
6 | # separate terms of service, privacy policy, and support
7 | # documentation.
8 |
9 | name: Java CI with Maven
10 |
11 | on:
12 | push:
13 | branches: [ "master" ]
14 |
15 | jobs:
16 | build:
17 |
18 | runs-on: ubuntu-latest
19 |
20 | steps:
21 | - uses: actions/checkout@v4
22 | - name: Set up JDK 21
23 | uses: actions/setup-java@v4
24 | with:
25 | java-version: '21'
26 | distribution: 'temurin'
27 | cache: maven
28 | - name: test
29 | run: mvn -B test --file pom.xml
30 | - name: build
31 | run: mvn -B package --file pom.xml
32 |
33 | # Upload the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive
34 | - name: Update dependency graph
35 | uses: advanced-security/maven-dependency-submission-action@v4.1.1
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /targetpom.xml.releaseBackup
2 | release.properties
3 | target/
4 | /pom.xml.releaseBackup
5 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Prometheus Community Code of Conduct
2 |
3 | Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md).
4 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Prometheus uses GitHub to manage reviews of pull requests.
4 |
5 | * If you have a trivial fix or improvement, go ahead and create a pull request,
6 | addressing (with `@...`) the maintainer of this repository (see
7 | [MAINTAINERS.md](MAINTAINERS.md)) in the description of the pull request.
8 |
9 | * If you plan to do something more involved, first discuss your ideas
10 | on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers).
11 | This will avoid unnecessary work and surely give you and us a good deal
12 | of inspiration.
13 |
14 | ### Formatting
15 | - IDEs differ in how they format Java code. This can generate a lot of unrelated code change. To avoid this - we enforce specific formatting.
16 | - Code is automatically formatted with [Spotify fmt maven-plugin](https://github.com/spotify/fmt-maven-plugin) whenever you run standard `mvn install`.
17 | - CI builds will fail if code is not formatted that way.
18 | - To simply run the formatter you can always run: `mvn fmt:format` (requires JVM > 11)
19 | # Releasing
20 |
21 | For release instructions, see [RELEASING](RELEASING.md).
22 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM eclipse-temurin:21-jdk-noble as builder
2 |
3 | SHELL ["/bin/bash", "-xe", "-o", "pipefail", "-c"]
4 |
5 | ARG MAVEN_VERSION=3.8.5
6 | ARG MAVEN_SHA512=89ab8ece99292476447ef6a6800d9842bbb60787b9b8a45c103aa61d2f205a971d8c3ddfb8b03e514455b4173602bd015e82958c0b3ddc1728a57126f773c743
7 |
8 | ADD https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz /opt/maven.tar.gz
9 | RUN mkdir -p /opt/maven \
10 | && echo "${MAVEN_SHA512} /opt/maven.tar.gz" | sha512sum -c \
11 | && tar -x --strip-components=1 -C /opt/maven -f /opt/maven.tar.gz
12 | ENV PATH /opt/maven/bin:${PATH}
13 |
14 | WORKDIR /cloudwatch_exporter
15 | COPY . /cloudwatch_exporter
16 |
17 | RUN mvn package \
18 | && mv target/cloudwatch_exporter-*-with-dependencies.jar /cloudwatch_exporter.jar
19 |
20 | FROM eclipse-temurin:21-jre-noble as runner
21 | LABEL maintainer="The Prometheus Authors "
22 | EXPOSE 9106
23 |
24 | WORKDIR /
25 | RUN mkdir /config
26 | COPY --from=builder /cloudwatch_exporter.jar /cloudwatch_exporter.jar
27 | ENTRYPOINT [ "java", "-jar", "/cloudwatch_exporter.jar", "9106"]
28 | CMD ["/config/config.yml"]
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/MAINTAINERS.md:
--------------------------------------------------------------------------------
1 | * Matthias Rampke @matthiasr
2 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # This is a dummy Makefile to satisfy expectations from common workflows.
2 | # Since this is not a Go project, we do not import Makefile.common from
3 | # github.com/prometheus/prometheus, but some common workflows depend on targets
4 | # there.
5 |
6 | DOCKER_IMAGE_NAME = cloudwatch-exporter
7 | DOCKER_REPO ?= prom
8 |
9 | .PHONY: docker-repo-name
10 | docker-repo-name: common-docker-repo-name
11 |
12 | .PHONY: common-docker-repo-name
13 | common-docker-repo-name:
14 | @echo "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)"
15 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | Metrics exporter for Amazon AWS CloudWatch
2 | Copyright 2015 The Prometheus Authors
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | CloudWatch Exporter
2 | =====
3 |
4 | A Prometheus exporter for [Amazon CloudWatch](http://aws.amazon.com/cloudwatch/).
5 |
6 | ## Alternatives
7 |
8 | For ECS workloads, there is also an [ECS exporter](https://github.com/prometheus-community/ecs_exporter).
9 |
10 | For a different approach to CloudWatch metrics, with automatic discovery, consider [Yet Another CloudWatch Exporter (YACE)](https://github.com/nerdswords/yet-another-cloudwatch-exporter).
11 |
12 | ## Building and running
13 |
14 | Cloudwatch Exporter requires at least Java 11.
15 |
16 | `mvn package` to build.
17 |
18 | `java -jar target/cloudwatch_exporter-*-SNAPSHOT-jar-with-dependencies.jar 9106 example.yml` to run.
19 |
20 | The most recent pre-built JAR can be found at http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22cloudwatch_exporter%22
21 |
22 | ## Credentials and permissions
23 |
24 | The CloudWatch Exporter uses the
25 | [AWS Java SDK](http://docs.aws.amazon.com/AWSSdkDocsJava/latest/DeveloperGuide/welcome.html),
26 | which offers [a variety of ways to provide credentials](http://docs.aws.amazon.com/AWSSdkDocsJava/latest/DeveloperGuide/credentials.html).
27 | This includes the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment
28 | variables.
29 |
30 | The `cloudwatch:ListMetrics`, `cloudwatch:GetMetricStatistics` and `cloudwatch:GetMetricData` IAM permissions are required.
31 | The `tag:GetResources` IAM permission is also required to use the `aws_tag_select` feature.
32 |
33 | ## Configuration
34 | The configuration is in YAML.
35 |
36 | An example with common options and `aws_dimension_select`:
37 | ```
38 | ---
39 | region: eu-west-1
40 | metrics:
41 | - aws_namespace: AWS/ELB
42 | aws_metric_name: RequestCount
43 | aws_dimensions: [AvailabilityZone, LoadBalancerName]
44 | aws_dimension_select:
45 | LoadBalancerName: [myLB]
46 | aws_statistics: [Sum]
47 | ```
48 |
49 | A similar example with common options and `aws_tag_select`:
50 | ```
51 | ---
52 | region: eu-west-1
53 | metrics:
54 | - aws_namespace: AWS/ELB
55 | aws_metric_name: RequestCount
56 | aws_dimensions: [AvailabilityZone, LoadBalancerName]
57 | aws_tag_select:
58 | tag_selections:
59 | Monitoring: ["enabled"]
60 | resource_type_selection: "elasticloadbalancing:loadbalancer"
61 | resource_id_dimension: LoadBalancerName
62 | aws_statistics: [Sum]
63 | ```
64 | **Note:** configuration examples for different namespaces can be found in [examples](./examples) directory
65 |
66 | **Note:** A configuration builder can be found [here](https://github.com/djloude/cloudwatch_exporter_metrics_config_builder).
67 |
68 | Name | Description
69 | ---------|------------
70 | region | Optional. The AWS region to connect to. If none is provided, an attempt will be made to determine the region from the [default region provider chain](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/java-dg-region-selection.html#default-region-provider-chain).
71 | role_arn | Optional. The AWS role to assume. Useful for retrieving cross account metrics.
72 | metrics | Required. A list of CloudWatch metrics to retrieve and export
73 | aws_namespace | Required. Namespace of the CloudWatch metric.
74 | aws_metric_name | Required. Metric name of the CloudWatch metric.
75 | aws_dimensions | Required. This should contain exactly all the dimensions available for a metric. Run `aws cloudwatch list-metrics` to find out which dimensions you need to include for your metric.
76 | aws_dimension_select | Optional. Which dimension values to filter. Specify a map from the dimension name to a list of values to select from that dimension.
77 | aws_dimension_select_regex | Optional. Which dimension values to filter on with a regular expression. Specify a map from the dimension name to a list of regexes that will be applied to select from that dimension.
78 | aws_tag_select | Optional. A tag configuration to filter on, based on mapping from the tagged resource ID to a CloudWatch dimension.
79 | tag_selections | Optional, under `aws_tag_select`. Specify a map from a tag key to a list of tag values to apply [tag filtering](https://docs.aws.amazon.com/resourcegroupstagging/latest/APIReference/API_GetResources.html#resourcegrouptagging-GetResources-request-TagFilters) on resources from which metrics will be gathered.
80 | resource_type_selection | Required, under `aws_tag_select`. Specify the [resource type](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#genref-aws-service-namesspaces) to filter on. `resource_type_selection` should be comprised as `service:resource_type`, as per the [resource group tagging API](https://docs.aws.amazon.com/resourcegroupstagging/latest/APIReference/API_GetResources.html#resourcegrouptagging-GetResources-request-TagFilters). Where `resource_type` could be an empty string, like in S3 case: `resource_type_selection: "s3:"`.
81 | resource_id_dimension | Required, under `aws_tag_select`. For the current metric, specify which CloudWatch dimension maps to the ARN [resource ID](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arns-syntax).
82 | arn_resource_id_regexp | If the Cloudwatch dimension specified in `resource_id_dimension` doesn't conform to the convention for resource ID an alternative regular expression to extract the resource ID from the ARN can be given here. The default is `(?:([^:/]+)|[^:/]+/([^:]+))$`. The first non empty match group will be used.
83 | aws_statistics | Optional. A list of statistics to retrieve, values can include Sum, SampleCount, Minimum, Maximum, Average. Defaults to all statistics unless extended statistics are requested.
84 | aws_extended_statistics | Optional. A list of extended statistics to retrieve. Extended statistics currently include percentiles in the form `pN` or `pN.N`.
85 | delay_seconds | Optional. The newest data to request. Used to avoid collecting data that has not fully converged. Defaults to 600s. Can be set globally and per metric.
86 | range_seconds | Optional. How far back to request data for. Useful for cases such as Billing metrics that are only set every few hours. Defaults to 600s. Can be set globally and per metric.
87 | period_seconds | Optional. [Period](http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/cloudwatch_concepts.html#CloudWatchPeriods) to request the metric for. Only the most recent data point is used. Defaults to 60s. Can be set globally and per metric.
88 | set_timestamp | Optional. Boolean for whether to set the Prometheus metric timestamp as the original Cloudwatch timestamp. For some metrics which are updated very infrequently (such as S3/BucketSize), Prometheus may refuse to scrape them if this is set to true (see #100). Defaults to true. Can be set globally and per metric.
89 | use_get_metric_data | Optional. Boolean (experimental) Use GetMetricData API to get metrics instead of GetMetricStatistics. Can be set globally and per metric.
90 | list_metrics_cache_ttl | Optional. Number of seconds to cache the result of calling the ListMetrics API. Defaults to 0 (no cache). Can be set globally and per metric.
91 | warn_on_empty_list_dimensions | Optional. Boolean Emit warning if the exporter cannot determine what metrics to request
92 |
93 |
94 | The above config will export time series such as
95 | ```
96 | # HELP aws_elb_request_count_sum CloudWatch metric AWS/ELB RequestCount Dimensions: ["AvailabilityZone","LoadBalancerName"] Statistic: Sum Unit: Count
97 | # TYPE aws_elb_request_count_sum gauge
98 | aws_elb_request_count_sum{job="aws_elb",instance="",load_balancer_name="mylb",availability_zone="eu-west-1c",} 42.0
99 | aws_elb_request_count_sum{job="aws_elb",instance="",load_balancer_name="myotherlb",availability_zone="eu-west-1c",} 7.0
100 | ```
101 |
102 | If the `aws_tag_select` feature was used, an additional information metric will be exported for each AWS tagged resource matched by the resource type selection and tag selection (if specified), such as
103 | ```
104 | # HELP aws_resource_info AWS information available for resource
105 | # TYPE aws_resource_info gauge
106 | aws_resource_info{job="aws_elb",instance="",arn="arn:aws:elasticloadbalancing:eu-west-1:121212121212:loadbalancer/mylb",load_balancer_name="mylb",tag_Monitoring="enabled",tag_MyOtherKey="MyOtherValue",} 1.0
107 | ```
108 | aws_recource_info can be joined with other metrics using group_left in PromQL such as the following:
109 | ```
110 | aws_elb_request_count_sum
111 | * on(load_balancer_name) group_left(tag_MyOtherKey)
112 | aws_resource_info
113 | ```
114 | All metrics are exported as gauges.
115 |
116 | In addition `cloudwatch_exporter_scrape_error` will be non-zero if an error
117 | occurred during the scrape, and `cloudwatch_exporter_scrape_duration_seconds`
118 | contains the duration of that scrape. `cloudwatch_exporter_build_info` contains
119 | labels referencing the current build version and build release date.
120 |
121 | ### Build Info Metric
122 |
123 | `cloudwatch_exporter_build_info` is a default cloudwatch exporter metric that contains the current
124 | cloudwatch exporter version and release date as label values. The numeric metric value is statically
125 | set to 1. If the metrics label values are "unknown" the build information scrap failed.
126 |
127 | ### CloudWatch doesn't always report data
128 |
129 | Cloudwatch reports data either always or only in some cases, example only if there is a non-zero value. The CloudWatch Exporter mirrors this behavior, so you should refer to the Cloudwatch documentation to find out if your metric is always reported or not.
130 |
131 | ### Timestamps
132 |
133 | CloudWatch has been observed to sometimes take minutes for reported values to converge. The
134 | default `delay_seconds` will result in data that is at least 10 minutes old
135 | being requested to mitigate this. The samples exposed will have the timestamps of the
136 | data from CloudWatch, so usual staleness semantics will not apply and values will persist
137 | for 5m for instant vectors.
138 |
139 | In practice this means that if you evaluate an instant vector at the current
140 | time, you will not see data from CloudWatch. An expression such as
141 | `aws_elb_request_count_sum offset 10m` will allow you to access the data, and
142 | should be used in recording rules and alerts.
143 |
144 | For certain metrics which update relatively rarely, such as from S3,
145 | `set_timestamp` should be configured to false so that they are not exposed with
146 | a timestamp. This is as the true timestamp from CloudWatch could be so old that
147 | Prometheus would reject the sample.
148 |
149 | #### FAQ: I can see the metrics in `/metrics` but not in the Prometheus web console
150 |
151 | The metrics will be visible in Prometheus if you look more than `delay_seconds` in the past.
152 | Try the graph view.
153 |
154 | This is an unfortunate result of a fundamental mismatch between CloudWatch and Prometheus.
155 | CloudWatch metrics converge over time, that is, the value at time `T` can change up to some later time `T+dT`.
156 | Meanwhile, Prometheus assumes that once it has scraped a sample, that is the truth, and the past does not change.
157 |
158 | To compensate for this, by default the exporter [delays fetching metrics](https://github.com/prometheus/cloudwatch_exporter/blob/master/README.md#timestamps), that is, it only asks for data 10 minutes later, when _almost_ all AWS services have converged.
159 | It also reports to Prometheus that this sample is from the past.
160 | Because Prometheus, for an instant request, only looks back 5 minutes, it never sees any data "now".
161 |
162 | ### Special handling for certain DynamoDB metrics
163 |
164 | The DynamoDB metrics listed below break the usual CloudWatch data model.
165 |
166 | * ConsumedReadCapacityUnits
167 | * ConsumedWriteCapacityUnits
168 | * ProvisionedReadCapacityUnits
169 | * ProvisionedWriteCapacityUnits
170 | * ReadThrottleEvents
171 | * WriteThrottleEvents
172 |
173 | When these metrics are requested in the TableName dimension CloudWatch will
174 | return data only for the table itself, not for its Global Secondary Indexes.
175 | Retrieving data for indexes requires requesting data across both the TableName
176 | and GlobalSecondaryIndexName dimensions. This behaviour is different to that
177 | of every other CloudWatch namespace and requires that the exporter handle these
178 | metrics differently to avoid generating duplicate HELP and TYPE lines.
179 |
180 | When exporting one of the problematic metrics for an index the exporter will use
181 | a metric name in the format `aws_dynamodb_METRIC_index_STATISTIC` rather than
182 | the usual `aws_dynamodb_METRIC_STATISTIC`. The regular naming scheme will still
183 | be used when exporting these metrics for a table, and when exporting any other
184 | DynamoDB metrics not listed above.
185 |
186 | ### Reloading Configuration
187 |
188 | There are two ways to reload configuration:
189 |
190 | 1. Send a SIGHUP signal to the pid: `kill -HUP 1234`
191 | 2. POST to the `reload` endpoint: `curl -X POST localhost:9106/-/reload`
192 |
193 | If an error occurs during the reload, check the exporter's log output.
194 |
195 | ### Cost
196 |
197 | Amazon charges for every CloudWatch API request or for every Cloudwatch metric requested, see the [current charges](http://aws.amazon.com/cloudwatch/pricing/).
198 |
199 | - In case of using `GetMetricStatistics` (default) - Every metric retrieved requires one API request, which can include multiple
200 | statistics.
201 | - In addition, when `aws_dimensions` is provided, the exporter needs to do API requests to determine what metrics to request. This should be negligible compared to the requests for the metrics themselves.
202 |
203 | In the case that all `aws_dimensions` are provided in the `aws_dimension_select` list, the exporter will not perform the
204 | above API request. It will request all possible combination of values for those dimensions.
205 | This will reduce cost as the values for the dimensions do not need to be queried anymore, assuming that all possible value combinations are present in CloudWatch.
206 |
207 | If you have 100 API requests every minute, with the price of USD$10 per million
208 | requests (as of Aug 2018), that is around $45 per month. The
209 | `cloudwatch_requests_total` counter tracks how many requests are being made.
210 |
211 | When using the `aws_tag_select` feature, additional requests are made to the Resource Groups Tagging API, but these are [free](https://aws.amazon.com/blogs/aws/new-aws-resource-tagging-api/).
212 | The `tagging_api_requests_total` counter tracks how many requests are being made for these.
213 |
214 | ### Experimental GetMetricData
215 | We are transitioning to use `GetMetricsData` instead of `GetMetricsStatistics`.
216 | The benefits of using `GetMetricsData` is mainly around much better performence.
217 |
218 | Please refer to [this doc](https://aws.amazon.com/premiumsupport/knowledge-center/cloudwatch-getmetricdata-api/) explaining why it is best practice to use `GetMetricData`
219 |
220 | API | performence | Costs | Stability
221 | --- |--- |--- |---
222 | `GetMetricStatistics` | May be slow at scale | Charged per API request | stable. (Default option)
223 | `GetMetricData` | Can retrieve data faster at scale | Charged per **metric** requested | New (opt-in via configuration)
224 |
225 | #### Transition plan
226 | At first this feature would be opt-in to allow you to decide when and how to test it
227 | On later versions we would swap the default so everyone can enjoy the benefits.
228 |
229 | Cloudwatch exporter also expose a new self metric called `cloudwatch_metrics_requested_total` that allows you to track number of requested metrics in addition to the number of API requests.
230 |
231 | ## Docker Images
232 |
233 | To run the CloudWatch exporter on Docker, you can use the image from
234 |
235 | * [prom/cloudwatch-exporter](https://hub.docker.com/r/prom/cloudwatch-exporter/)
236 | * [quay.io/prometheus/cloudwatch-exporter](https://quay.io/repository/prometheus/cloudwatch-exporter)
237 |
238 | The available tags are
239 |
240 | * `main`: snapshot updated on every push to the main branch
241 | * `latest`: the latest released version
242 | * `vX.Y.Z`: the specific version X.Y.Z. Note that up to version 0.11.0, the format was `cloudwatch-exporter_X.Y.Z`.
243 |
244 | The image exposes port 9106 and expects the config in `/config/config.yml`.
245 | To configure it, you can bind-mount a config from your host:
246 |
247 | ```sh
248 | docker run -p 9106 -v /path/on/host/config.yml:/config/config.yml quay.io/prometheus/cloudwatch-exporter
249 | ```
250 |
251 | Specify the config as the CMD:
252 |
253 | ```sh
254 | docker run -p 9106 -v /path/on/host/us-west-1.yml:/config/us-west-1.yml quay.io/prometheus/cloudwatch-exporter /config/us-west-1.yml
255 | ```
256 |
257 | Or create a config file named `config.yml` along with following
258 | Dockerfile in the same directory and build it with `docker build`:
259 |
260 | ```Dockerfile
261 | FROM prom/cloudwatch-exporter
262 | ADD config.yml /config/
263 | ```
264 |
--------------------------------------------------------------------------------
/RELEASING.md:
--------------------------------------------------------------------------------
1 | # Releasing the CloudWatch exporter
2 |
3 | Only maintainers can do this.
4 | The process is based on the [`java_client` release process](https://github.com/prometheus/client_java/wiki/Development).
5 |
6 | ## Requirements
7 |
8 | * [Temurin JDK 21](https://adoptium.net/)
9 | * Maven
10 | * GPG
11 |
12 | ## Access to the OSS Sonatype repository
13 |
14 | Sign up through [Sonatype JIRA](https://issues.sonatype.org) if you don't have an account already.
15 | [File a Publishing Support ticket](https://central.sonatype.org/faq/get-support/#producers) ([example](https://issues.sonatype.org/browse/OSSRH-70163)) to gain access to the `io.prometheus` group in the Sonatype OSSRH.
16 | The same login will be used for the repository.
17 |
18 | Verify that you can log into [OSSRH](https://oss.sonatype.org/).
19 | The CloudWatch Exporter is at [io.prometheus.cloudwatch](https://oss.sonatype.org/#nexus-search;quick~io.prometheus.cloudwatch).
20 |
21 | Set up [Maven publishing](https://central.sonatype.org/publish/publish-maven/), specifically the `` block in `~/.m2/settings.xml`.
22 | Fetch your user token according to [these instructions](https://central.sonatype.org/publish/generate-token/).
23 | A minimal config:
24 |
25 | ```xml
26 |
30 |
31 |
32 |
33 | ossrh
34 |
35 | token-user
36 | token-password
37 |
38 |
39 |
40 | ```
41 |
42 | The project setup is already done.
43 |
44 | ## Push a snapshot
45 |
46 | To push a snapshot, check out the latest main branch and run
47 |
48 | ```sh
49 | mvn clean deploy
50 | ```
51 |
52 | This should succeed.
53 |
54 | ## Start a release
55 |
56 | To prepare a release:
57 |
58 | ```sh
59 | mvn release:clean release:prepare
60 | ```
61 |
62 | This will
63 |
64 | 1. prompt for the version
65 | 2. update `pom.xml` with this version
66 | 3. create and push a git tag
67 | 4. build everything
68 | 5. GPG-sign the artifacts
69 |
70 | To actually release:
71 |
72 | ```sh
73 | mvn release:perform
74 | ```
75 |
76 | This will upload everything to OSSRH into a **staging repository**.
77 | To locate it, [log into Sonatype OSS](https://oss.sonatype.org/), then open [Staging Repositories](https://oss.sonatype.org/#stagingRepositories).
78 | If it spins forever, open the [main page](https://oss.sonatype.org/) and log in first.
79 | If nothing shows up, you probably forgot to `mvn release:perform`.
80 |
81 | Press "Close" to promote the release.
82 |
83 | The staging repository will show "Activity: Operation in progress" for a few seconds.
84 | Refresh or check the Activity tab to see what's going on.
85 |
86 | Once closing is done, the "Release" button unlocks.
87 | Press it.
88 |
89 | This runs for a while, and the new version should become available on [OSSRH](https://oss.sonatype.org/#nexus-search;quick~io.prometheus.cloudwatch).
90 | It usually appears immediately after the release process is done, but can take a few hours to show up.
91 |
92 | ## Docker images
93 |
94 | As part of the release process, `mvn` will create the git tag.
95 | This tag is picked up by [CircleCI](https://app.circleci.com/pipelines/github/prometheus/cloudwatch_exporter?branch=master), which builds and pushes the [Docker images](README.md#docker-images).
96 |
97 | ## GitHub Release
98 |
99 | Create a [new GitHub release](https://github.com/prometheus/cloudwatch_exporter/releases/new).
100 | Select the tag for this version that Maven pushed.
101 |
102 | Use the format `A.B.C / YYYY-MM-DD` as the release title.
103 | Summarize the changes.
104 |
105 | The release files and signatures are available in `target/checkout/target/`.
106 | Upload the `.jar` and `.jar.asc` files to the GitHub release.
107 |
108 | Publish the release.
109 |
110 | ## Announcement
111 |
112 | Announce the changes to [prometheus-announce](mailto:prometheus-announce@groups.google.com), linking to OSSRH and the GitHub release.
113 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Reporting a security issue
2 |
3 | The Prometheus security policy, including how to report vulnerabilities, can be
4 | found here:
5 |
6 |
7 |
--------------------------------------------------------------------------------
/example.yml:
--------------------------------------------------------------------------------
1 | ---
2 | region: eu-west-1
3 | metrics:
4 | - aws_namespace: AWS/NetworkELB
5 | aws_metric_name: HealthyHostCount
6 | aws_dimensions: [AvailabilityZone, LoadBalancer, TargetGroup]
7 | aws_statistics: [Average]
8 |
9 | - aws_namespace: AWS/NetworkELB
10 | aws_metric_name: UnHealthyHostCount
11 | aws_dimensions: [AvailabilityZone, LoadBalancer, TargetGroup]
12 | aws_statistics: [Average]
13 |
14 | - aws_namespace: AWS/ApplicationELB
15 | aws_metric_name: HealthyHostCount
16 | aws_dimensions: [AvailabilityZone, LoadBalancer, TargetGroup]
17 | aws_statistics: [Average]
18 |
19 | - aws_namespace: AWS/ApplicationELB
20 | aws_metric_name: UnHealthyHostCount
21 | aws_dimensions: [AvailabilityZone, LoadBalancer, TargetGroup]
22 | aws_statistics: [Average]
23 |
24 | - aws_namespace: AWS/ApplicationELB
25 | aws_metric_name: RequestCount
26 | aws_dimensions: [AvailabilityZone, LoadBalancer]
27 | aws_statistics: [Average]
28 |
29 | - aws_namespace: AWS/ElastiCache
30 | aws_metric_name: CPUUtilization
31 | aws_dimensions: [CacheClusterId]
32 | aws_statistics: [Average]
33 |
34 | - aws_namespace: AWS/ElastiCache
35 | aws_metric_name: NetworkBytesIn
36 | aws_dimensions: [CacheClusterId]
37 | aws_statistics: [Average]
38 |
39 | - aws_namespace: AWS/ElastiCache
40 | aws_metric_name: NetworkBytesOut
41 | aws_dimensions: [CacheClusterId]
42 | aws_statistics: [Average]
43 |
44 | - aws_namespace: AWS/ElastiCache
45 | aws_metric_name: FreeableMemory
46 | aws_dimensions: [CacheClusterId]
47 | aws_statistics: [Average]
48 |
49 | - aws_namespace: AWS/ElastiCache
50 | aws_metric_name: BytesUsedForCache
51 | aws_dimensions: [CacheClusterId]
52 | aws_statistics: [Average]
53 |
54 | - aws_namespace: AWS/ElastiCache
55 | aws_metric_name: CurrConnections
56 | aws_dimensions: [CacheClusterId]
57 | aws_statistics: [Average]
58 |
59 | - aws_namespace: AWS/ElastiCache
60 | aws_metric_name: NewConnections
61 | aws_dimensions: [CacheClusterId]
62 | aws_statistics: [Average]
63 |
64 | - aws_namespace: AWS/ElastiCache
65 | aws_metric_name: CacheHits
66 | aws_dimensions: [CacheClusterId]
67 | aws_statistics: [Average]
68 |
69 | - aws_namespace: AWS/ElastiCache
70 | aws_metric_name: CacheMisses
71 | aws_dimensions: [CacheClusterId]
72 | aws_statistics: [Average]
73 |
74 | - aws_namespace: AWS/ElastiCache
75 | aws_metric_name: ReplicationLag
76 | aws_dimensions: [CacheClusterId]
77 | aws_statistics: [Average]
78 |
79 | - aws_namespace: AWS/Redshift
80 | aws_metric_name: DatabaseConnections
81 | aws_dimensions: [ClusterIdentifier]
82 | aws_statistics: [Average]
83 |
84 | - aws_namespace: AWS/Redshift
85 | aws_metric_name: HealthStatus
86 | aws_dimensions: [ClusterIdentifier]
87 | aws_statistics: [Average]
88 |
89 | - aws_namespace: AWS/Redshift
90 | aws_metric_name: MaintenanceMode
91 | aws_dimensions: [ClusterIdentifier]
92 | aws_statistics: [Average]
93 |
94 | - aws_namespace: AWS/Redshift
95 | aws_metric_name: CPUUtilization
96 | aws_dimensions: [NodeID, ClusterIdentifier]
97 | aws_statistics: [Average]
98 |
99 | - aws_namespace: AWS/Redshift
100 | aws_metric_name: PercentageDiskSpaceUsed
101 | aws_dimensions: [NodeID, ClusterIdentifier]
102 | aws_statistics: [Average]
103 |
104 | - aws_namespace: AWS/Redshift
105 | aws_metric_name: NetworkReceiveThroughput
106 | aws_dimensions: [NodeID, ClusterIdentifier]
107 | aws_statistics: [Average]
108 |
109 | - aws_namespace: AWS/Redshift
110 | aws_metric_name: NetworkTransmitThroughput
111 | aws_dimensions: [NodeID, ClusterIdentifier]
112 | aws_statistics: [Average]
113 |
114 | - aws_namespace: AWS/Redshift
115 | aws_metric_name: ReadLatency
116 | aws_dimensions: [NodeID, ClusterIdentifier]
117 | aws_statistics: [Average]
118 |
119 | - aws_namespace: AWS/Redshift
120 | aws_metric_name: ReadThroughput
121 | aws_dimensions: [NodeID, ClusterIdentifier]
122 | aws_statistics: [Average]
123 |
124 | - aws_namespace: AWS/Redshift
125 | aws_metric_name: ReadIOPS
126 | aws_dimensions: [NodeID, ClusterIdentifier]
127 | aws_statistics: [Average]
128 |
129 | - aws_namespace: AWS/Redshift
130 | aws_metric_name: WriteLatency
131 | aws_dimensions: [NodeID, ClusterIdentifier]
132 | aws_statistics: [Average]
133 |
134 | - aws_namespace: AWS/Redshift
135 | aws_metric_name: WriteThroughput
136 | aws_dimensions: [NodeID, ClusterIdentifier]
137 | aws_statistics: [Average]
138 |
139 | - aws_namespace: AWS/Redshift
140 | aws_metric_name: WriteIOPS
141 | aws_dimensions: [NodeID, ClusterIdentifier]
142 | aws_statistics: [Average]
143 |
144 | # S3 Storage metrics are published to Cloudwatch 1x per day with a timestamp of midnight UTC, hence period_seconds: 86400
145 | # Publishing does not always occur at the same time, but it will occur before the next day, hence range_seconds: 172800
146 | - aws_namespace: AWS/S3
147 | aws_metric_name: BucketSizeBytes
148 | aws_dimensions: [BucketName, StorageType]
149 | aws_statistics: [Average] # Valid statistics (https://docs.aws.amazon.com/AmazonS3/latest/dev/cloudwatch-monitoring.html): Average
150 | range_seconds: 172800
151 | period_seconds: 86400
152 |
153 | - aws_namespace: AWS/S3
154 | aws_metric_name: NumberOfObjects
155 | aws_dimensions: [BucketName, StorageType]
156 | aws_statistics: [Average] # Valid statistics (https://docs.aws.amazon.com/AmazonS3/latest/dev/cloudwatch-monitoring.html): Average
157 | range_seconds: 172800
158 | period_seconds: 86400
159 |
160 | # For CloudFront metrics, you have to set the region to us-east-1
161 | - aws_namespace: AWS/CloudFront
162 | aws_metric_name: Requests
163 | aws_statistics: [Sum]
164 | aws_dimensions: [DistributionId, Region]
165 | aws_dimension_select:
166 | Region: [Global]
167 |
168 | - aws_namespace: AWS/CloudFront
169 | aws_metric_name: BytesDownloaded
170 | aws_statistics: [Sum]
171 | aws_dimensions: [DistributionId, Region]
172 | aws_dimension_select:
173 | Region: [Global]
174 |
175 | - aws_namespace: AWS/CloudFront
176 | aws_metric_name: 4xxErrorRate
177 | aws_statistics: [Average]
178 | aws_dimensions: [DistributionId, Region]
179 | aws_dimension_select:
180 | Region: [Global]
181 |
182 | - aws_namespace: AWS/CloudFront
183 | aws_metric_name: 5xxErrorRate
184 | aws_statistics: [Average]
185 | aws_dimensions: [DistributionId, Region]
186 | aws_dimension_select:
187 | Region: [Global]
188 |
189 | - aws_namespace: AWS/CloudFront
190 | aws_metric_name: BytesUploaded
191 | aws_statistics: [Sum]
192 | aws_dimensions: [DistributionId, Region]
193 | aws_dimension_select:
194 | Region: [Global]
195 |
196 | - aws_namespace: AWS/CloudFront
197 | aws_metric_name: TotalErrorRate
198 | aws_statistics: [Average]
199 | aws_dimensions: [DistributionId, Region]
200 | aws_dimension_select:
201 | Region: [Global]
202 |
--------------------------------------------------------------------------------
/examples/AmazonMQ.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - Broker
5 | aws_metric_name: TotalProducerCount
6 | aws_namespace: AWS/AmazonMQ
7 | aws_statistics:
8 | - Maximum
9 |
10 | - aws_dimensions:
11 | - Broker
12 | aws_metric_name: TotalConsumerCount
13 | aws_namespace: AWS/AmazonMQ
14 | aws_statistics:
15 | - Maximum
16 | - aws_dimensions:
17 | - Broker
18 | aws_metric_name: JournalFilesForFullRecovery
19 | aws_namespace: AWS/AmazonMQ
20 | aws_statistics:
21 | - Maximum
22 | - aws_dimensions:
23 | - Broker
24 | aws_metric_name: JournalFilesForFastRecovery
25 | aws_namespace: AWS/AmazonMQ
26 | aws_statistics:
27 | - Maximum
28 | - aws_dimensions:
29 | - Broker
30 | aws_metric_name: HeapUsage
31 | aws_namespace: AWS/AmazonMQ
32 | aws_statistics:
33 | - Maximum
34 | - aws_dimensions:
35 | - Broker
36 | aws_metric_name: CpuUtilization
37 | aws_namespace: AWS/AmazonMQ
38 | aws_statistics:
39 | - Maximum
40 | - aws_dimensions:
41 | - Broker
42 | aws_metric_name: TotalConsumerCount
43 | aws_namespace: AWS/AmazonMQ
44 | aws_statistics:
45 | - SampleCount
46 | - aws_dimensions:
47 | - Broker
48 | aws_metric_name: StorePercentUsage
49 | aws_namespace: AWS/AmazonMQ
50 | aws_statistics:
51 | - Maximum
52 | - aws_dimensions:
53 | - Broker
54 | aws_metric_name: NetworkIn
55 | aws_namespace: AWS/AmazonMQ
56 | aws_statistics:
57 | - Maximum
58 | - aws_dimensions:
59 | - Broker
60 | aws_metric_name: NetworkOut
61 | aws_namespace: AWS/AmazonMQ
62 | aws_statistics:
63 | - Maximum
64 | - aws_dimensions:
65 | - Queue
66 | aws_metric_name: QueueSize
67 | aws_namespace: AWS/AmazonMQ
68 | aws_statistics:
69 | - Maximum
70 | - aws_dimensions:
71 | - Broker
72 | - Topic
73 | - Queue
74 | aws_metric_name: ConsumerCount
75 | aws_namespace: AWS/AmazonMQ
76 | aws_statistics:
77 | - Maximum
78 | - aws_dimensions:
79 | - Broker
80 | - Topic
81 | - Queue
82 | aws_metric_name: DispatchCount
83 | aws_namespace: AWS/AmazonMQ
84 | aws_statistics:
85 | - Maximum
86 | - aws_dimensions:
87 | - Broker
88 | - Topic
89 | - Queue
90 | aws_metric_name: ProducerCount
91 | aws_namespace: AWS/AmazonMQ
92 | aws_statistics:
93 | - Maximum
94 | - aws_dimensions:
95 | - Broker
96 | - Topic
97 | aws_metric_name: ReceiveCount
98 | aws_namespace: AWS/AmazonMQ
99 | aws_statistics:
100 | - Maximum
101 | - aws_dimensions:
102 | - Broker
103 | - Topic
104 | - Queue
105 | aws_metric_name: EnqueueCount
106 | aws_namespace: AWS/AmazonMQ
107 | aws_statistics:
108 | - Maximum
109 | - aws_dimensions:
110 | - Broker
111 | - Topic
112 | - Queue
113 | aws_metric_name: DequeueCount
114 | aws_namespace: AWS/AmazonMQ
115 | aws_statistics:
116 | - Maximum
117 | - aws_dimensions:
118 | - Broker
119 | - Topic
120 | - Queue
121 | aws_metric_name: ExpiredCount
122 | aws_namespace: AWS/AmazonMQ
123 | aws_statistics:
124 | - Maximum
125 | - aws_dimensions:
126 | - Broker
127 | - Topic
128 | - Queue
129 | aws_metric_name: EnqueueTime
130 | aws_namespace: AWS/AmazonMQ
131 | aws_statistics:
132 | - Maximum
133 | - aws_dimensions:
134 | - Broker
135 | - Topic
136 | aws_metric_name: MemoryUsage
137 | aws_namespace: AWS/AmazonMQ
138 | aws_statistics:
139 | - Maximum
140 |
--------------------------------------------------------------------------------
/examples/ApiGateway.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - Stage
5 | - ApiName
6 | aws_metric_name: Count
7 | aws_namespace: AWS/ApiGateway
8 | aws_statistics:
9 | - SampleCount
10 | - aws_dimensions:
11 | - Stage
12 | - ApiName
13 | aws_metric_name: Latency
14 | aws_namespace: AWS/ApiGateway
15 | aws_statistics:
16 | - Average
17 | - aws_dimensions:
18 | - Stage
19 | - ApiName
20 | aws_metric_name: IntegrationLatency
21 | aws_namespace: AWS/ApiGateway
22 | aws_statistics:
23 | - Average
24 | - aws_dimensions:
25 | - Stage
26 | - ApiName
27 | aws_metric_name: 4XXError
28 | aws_namespace: AWS/ApiGateway
29 | aws_statistics:
30 | - Sum
31 | - aws_dimensions:
32 | - Stage
33 | - ApiName
34 | aws_metric_name: 5XXError
35 | aws_namespace: AWS/ApiGateway
36 | aws_statistics:
37 | - Sum
38 | - aws_dimensions:
39 | - Stage
40 | - ApiName
41 | aws_metric_name: CacheHitCount
42 | aws_namespace: AWS/ApiGateway
43 | aws_statistics:
44 | - Sum
45 | - aws_dimensions:
46 | - Stage
47 | - ApiName
48 | aws_metric_name: CacheMissCount
49 | aws_namespace: AWS/ApiGateway
50 | aws_statistics:
51 | - Sum
52 |
--------------------------------------------------------------------------------
/examples/AppRunner.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_namespace: AWS/AppRunner
4 | aws_metric_name: Requests
5 | aws_dimensions: [ServiceID, ServiceName]
6 | aws_statistics: [Sum]
7 | - aws_namespace: AWS/AppRunner
8 | aws_metric_name: 2xxStatusResponses
9 | aws_dimensions: [ServiceID, ServiceName]
10 | aws_statistics: [Sum]
11 | - aws_namespace: AWS/AppRunner
12 | aws_metric_name: 4xxStatusResponses
13 | aws_dimensions: [ServiceID, ServiceName]
14 | aws_statistics: [Sum]
15 | - aws_namespace: AWS/AppRunner
16 | aws_metric_name: 5xxStatusResponses
17 | aws_dimensions: [ServiceID, ServiceName]
18 | aws_statistics: [Sum]
19 | - aws_namespace: AWS/AppRunner
20 | aws_metric_name: ActiveConnections
21 | aws_dimensions: [ServiceID, ServiceName]
22 | aws_statistics: [Sum]
23 | - aws_namespace: AWS/AppRunner
24 | aws_metric_name: DroppedConnections
25 | aws_dimensions: [ServiceID, ServiceName]
26 | aws_statistics: [Sum]
27 | - aws_namespace: AWS/AppRunner
28 | aws_metric_name: RequestLatency
29 | aws_dimensions: [ServiceID, ServiceName]
30 | aws_statistics: [Average]
31 | - aws_namespace: AWS/AppRunner
32 | aws_metric_name: ActiveInstances
33 | aws_dimensions: [ServiceID, ServiceName]
34 | aws_statistics: [Average]
35 | - aws_namespace: AWS/AppRunner
36 | aws_metric_name: ProvisionedInstances
37 | aws_dimensions: [ServiceID, ServiceName]
38 | aws_statistics: [Average]
39 | - aws_namespace: AWS/AppRunner
40 | aws_metric_name: CPUUtilization
41 | aws_dimensions: [ServiceID, ServiceName]
42 | aws_statistics: [Average]
43 | - aws_namespace: AWS/AppRunner
44 | aws_metric_name: MemoryUtilization
45 | aws_dimensions: [ServiceID, ServiceName]
46 | aws_statistics: [Average]
47 |
--------------------------------------------------------------------------------
/examples/ApplicationELB.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_namespace: AWS/ApplicationELB
4 | aws_metric_name: HealthyHostCount
5 | aws_dimensions:
6 | - LoadBalancer
7 | - TargetGroup
8 | aws_statistics:
9 | - Minimum
10 | # In case you want to use some tag to select target group to monitor, or to have additional `info` metric
11 | # with all target group tags as labels, use `aws_tag_select`.
12 | # Since the TargetGroup dimension doesn't follow the convention for how to extract resource ids from ARN
13 | # `arn_resource_id_regexp` is specified with an alternative regular expression.
14 | aws_tag_select:
15 | resource_type_selection: elasticloadbalancing:targetgroup
16 | resource_id_dimension: TargetGroup
17 | arn_resource_id_regexp: "(targetgroup/.*)$"
18 | tag_selections:
19 | Environment:
20 | - production
21 | - aws_namespace: AWS/ApplicationELB
22 | aws_metric_name: UnHealthyHostCount
23 | aws_dimensions:
24 | - LoadBalancer
25 | aws_statistics:
26 | - Sum
27 | - aws_namespace: AWS/ApplicationELB
28 | aws_metric_name: RequestCount
29 | aws_dimensions:
30 | - LoadBalancer
31 | aws_statistics:
32 | - Average
33 | - aws_namespace: AWS/ApplicationELB
34 | aws_metric_name: TargetResponseTime
35 | aws_dimensions:
36 | - LoadBalancer
37 | aws_statistics:
38 | - Average
39 | - aws_namespace: AWS/ApplicationELB
40 | aws_metric_name: ActiveConnectionCount
41 | aws_dimensions:
42 | - LoadBalancer
43 | aws_statistics:
44 | - Sum
45 | - aws_namespace: AWS/ApplicationELB
46 | aws_metric_name: NewConnectionCount
47 | aws_dimensions:
48 | - LoadBalancer
49 | aws_statistics:
50 | - Sum
51 | - aws_namespace: AWS/ApplicationELB
52 | aws_metric_name: RejectedConnectionCount
53 | aws_dimensions:
54 | - LoadBalancer
55 | aws_statistics:
56 | - Sum
57 | - aws_namespace: AWS/ApplicationELB
58 | aws_metric_name: TargetConnectionErrorCount
59 | aws_dimensions:
60 | - LoadBalancer
61 | aws_statistics:
62 | - Sum
63 | - aws_namespace: AWS/ApplicationELB
64 | aws_metric_name: RequestCount
65 | aws_dimensions:
66 | - LoadBalancer
67 | aws_statistics:
68 | - Sum
69 | - aws_namespace: AWS/ApplicationELB
70 | aws_metric_name: IPv6RequestCount
71 | aws_dimensions:
72 | - LoadBalancer
73 | aws_statistics:
74 | - Sum
75 | - aws_namespace: AWS/ApplicationELB
76 | aws_metric_name: RequestCountPerTarget
77 | aws_dimensions:
78 | - LoadBalancer
79 | aws_statistics:
80 | - Sum
81 | - aws_namespace: AWS/ApplicationELB
82 | aws_metric_name: NonStickyRequestCount
83 | aws_dimensions:
84 | - LoadBalancer
85 | aws_statistics:
86 | - Sum
87 | - aws_namespace: AWS/ApplicationELB
88 | aws_metric_name: HTTPCode_Target_2XX_Count
89 | aws_dimensions:
90 | - LoadBalancer
91 | aws_statistics:
92 | - Sum
93 | - aws_namespace: AWS/ApplicationELB
94 | aws_metric_name: HTTPCode_Target_3XX_Count
95 | aws_dimensions:
96 | - LoadBalancer
97 | aws_statistics:
98 | - Sum
99 | - aws_namespace: AWS/ApplicationELB
100 | aws_metric_name: HTTPCode_Target_4XX_Count
101 | aws_dimensions:
102 | - LoadBalancer
103 | aws_statistics:
104 | - Sum
105 | - aws_namespace: AWS/ApplicationELB
106 | aws_metric_name: HTTPCode_Target_5XX_Count
107 | aws_dimensions:
108 | - LoadBalancer
109 | aws_statistics:
110 | - Sum
111 | - aws_namespace: AWS/ApplicationELB
112 | aws_metric_name: HTTPCode_ELB_3XX_Count
113 | aws_dimensions:
114 | - LoadBalancer
115 | aws_statistics:
116 | - Sum
117 | - aws_namespace: AWS/ApplicationELB
118 | aws_metric_name: HTTPCode_ELB_4XX_Count
119 | aws_dimensions:
120 | - LoadBalancer
121 | aws_statistics:
122 | - Sum
123 | - aws_namespace: AWS/ApplicationELB
124 | aws_metric_name: HTTPCode_ELB_5XX_Count
125 | aws_dimensions:
126 | - LoadBalancer
127 | aws_statistics:
128 | - Sum
129 | - aws_namespace: AWS/ApplicationELB
130 | aws_metric_name: ProcessedBytes
131 | aws_dimensions:
132 | - LoadBalancer
133 | aws_statistics:
134 | - Sum
135 | - aws_namespace: AWS/ApplicationELB
136 | aws_metric_name: IPv6ProcessedBytes
137 | aws_dimensions:
138 | - LoadBalancer
139 | aws_statistics:
140 | - Sum
141 | - aws_namespace: AWS/ApplicationELB
142 | aws_metric_name: ConsumedLCUs
143 | # ALBs take 30 minutes to report this metrics.
144 | delay_seconds: 1800
145 | aws_dimensions:
146 | - LoadBalancer
147 | aws_statistics:
148 | - Sum
149 | - aws_namespace: AWS/ApplicationELB
150 | aws_metric_name: ClientTLSNegotiationErrorCount
151 | aws_dimensions:
152 | - LoadBalancer
153 | aws_statistics:
154 | - Sum
155 | - aws_namespace: AWS/ApplicationELB
156 | aws_metric_name: TargetTLSNegotiationErrorCount
157 | aws_dimensions:
158 | - LoadBalancer
159 | aws_statistics:
160 | - Sum
161 | - aws_namespace: AWS/ApplicationELB
162 | aws_metric_name: RuleEvaluations
163 | aws_dimensions:
164 | - LoadBalancer
165 | aws_statistics:
166 | - Sum
167 |
--------------------------------------------------------------------------------
/examples/Athena.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - QueryState
5 | - QueryType
6 | aws_metric_name: ProcessedBytes
7 | aws_namespace: AWS/Athena
8 | aws_statistics:
9 | - Maximum
10 | - aws_dimensions:
11 | - QueryState
12 | - QueryType
13 | aws_metric_name: TotalExecutionTime
14 | aws_namespace: AWS/Athena
15 | aws_statistics:
16 | - Maximum
17 | - aws_dimensions:
18 | - QueryType
19 | - QueryState
20 | aws_metric_name: Total
21 | aws_namespace: AWS/Athena
22 |
--------------------------------------------------------------------------------
/examples/AuroraServerless.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - DBInstanceIdentifier
5 | aws_metric_name: BufferCacheHitRatio
6 | aws_namespace: AWS/RDS
7 | aws_statistics:
8 | - Average
9 | - aws_dimensions:
10 | - DBInstanceIdentifier
11 | aws_metric_name: CommitLatency
12 | aws_namespace: AWS/RDS
13 | aws_statistics:
14 | - Average
15 | - aws_dimensions:
16 | - DBInstanceIdentifier
17 | aws_metric_name: CommitThroughput
18 | aws_namespace: AWS/RDS
19 | aws_statistics:
20 | - Average
21 | - aws_dimensions:
22 | - DBInstanceIdentifier
23 | aws_metric_name: CPUUtilization
24 | aws_namespace: AWS/RDS
25 | aws_statistics:
26 | - Average
27 | - aws_dimensions:
28 | - DBInstanceIdentifier
29 | aws_metric_name: DatabaseConnections
30 | aws_namespace: AWS/RDS
31 | aws_statistics:
32 | - Sum
33 | - aws_dimensions:
34 | - DBInstanceIdentifier
35 | aws_metric_name: DBLoad
36 | aws_namespace: AWS/RDS
37 | aws_statistics:
38 | - Sum
39 | - aws_dimensions:
40 | - DBInstanceIdentifier
41 | aws_metric_name: DBLoadCPU
42 | aws_namespace: AWS/RDS
43 | aws_statistics:
44 | - Sum
45 | - aws_dimensions:
46 | - DBInstanceIdentifier
47 | aws_metric_name: DBLoadNonCPU
48 | aws_namespace: AWS/RDS
49 | aws_statistics:
50 | - Sum
51 | - aws_dimensions:
52 | - DBInstanceIdentifier
53 | aws_metric_name: Deadlocks
54 | aws_namespace: AWS/RDS
55 | aws_statistics:
56 | - Sum
57 | - aws_dimensions:
58 | - DBInstanceIdentifier
59 | aws_metric_name: DiskQueueDepth
60 | aws_namespace: AWS/RDS
61 | aws_statistics:
62 | - Average
63 | - aws_dimensions:
64 | - DBInstanceIdentifier
65 | aws_metric_name: FreeableMemory
66 | aws_namespace: AWS/RDS
67 | aws_statistics:
68 | - Average
69 | - aws_dimensions:
70 | - DBInstanceIdentifier
71 | aws_metric_name: ReadIOPS
72 | aws_namespace: AWS/RDS
73 | aws_statistics:
74 | - Average
75 | - aws_dimensions:
76 | - DBInstanceIdentifier
77 | aws_metric_name: ReadLatency
78 | aws_namespace: AWS/RDS
79 | aws_statistics:
80 | - Average
81 | - aws_dimensions:
82 | - DBInstanceIdentifier
83 | aws_metric_name: ReadThroughput
84 | aws_namespace: AWS/RDS
85 | aws_statistics:
86 | - Average
87 | - aws_dimensions:
88 | - DBInstanceIdentifier
89 | aws_metric_name: SwapUsage
90 | aws_namespace: AWS/RDS
91 | aws_statistics:
92 | - Average
93 | - aws_dimensions:
94 | - DBInstanceIdentifier
95 | aws_metric_name: WriteIOPS
96 | aws_namespace: AWS/RDS
97 | aws_statistics:
98 | - Average
99 | - aws_dimensions:
100 | - DBInstanceIdentifier
101 | aws_metric_name: WriteLatency
102 | aws_namespace: AWS/RDS
103 | aws_statistics:
104 | - Average
105 | - aws_dimensions:
106 | - DBInstanceIdentifier
107 | aws_metric_name: WriteThroughput
108 | aws_namespace: AWS/RDS
109 | aws_statistics:
110 | - Average
111 |
112 |
113 | - aws_dimensions:
114 | - DBClusterIdentifier
115 | aws_metric_name: ACUUtilization
116 | aws_namespace: AWS/RDS
117 | aws_statistics:
118 | - Average
119 | - aws_dimensions:
120 | - DBClusterIdentifier
121 | aws_metric_name: CPUUtilization
122 | aws_namespace: AWS/RDS
123 | aws_statistics:
124 | - Maximum
125 | - aws_dimensions:
126 | - DBClusterIdentifier
127 | aws_metric_name: FreeableMemory
128 | aws_namespace: AWS/RDS
129 | aws_statistics:
130 | - Sum
131 | - aws_dimensions:
132 | - DBClusterIdentifier
133 | aws_metric_name: FreeLocalStorage
134 | aws_namespace: AWS/RDS
135 | aws_statistics:
136 | - Minimum
137 | - aws_dimensions:
138 | - DBClusterIdentifier
139 | aws_metric_name: ServerlessDatabaseCapacity
140 | aws_namespace: AWS/RDS
141 | aws_statistics:
142 | - Average
143 | - aws_dimensions:
144 | - DBClusterIdentifier
145 | aws_metric_name: TempStorageIops
146 | aws_namespace: AWS/RDS
147 | aws_statistics:
148 | - Average
149 | - aws_dimensions:
150 | - DBClusterIdentifier
151 | aws_metric_name: TempStorageThroughput
152 | aws_namespace: AWS/RDS
153 | aws_statistics:
154 | - Sum
155 | - aws_dimensions:
156 | - DBClusterIdentifier
157 | aws_metric_name: VolumeBytesUsed
158 | aws_namespace: AWS/RDS
159 | aws_statistics:
160 | - Average
161 | - aws_dimensions:
162 | - DBClusterIdentifier
163 | aws_metric_name: VolumeReadIOPs
164 | aws_namespace: AWS/RDS
165 | aws_statistics:
166 | - Average
167 | - aws_dimensions:
168 | - DBClusterIdentifier
169 | aws_metric_name: VolumeWriteIOPs
170 | aws_namespace: AWS/RDS
171 | aws_statistics:
172 | - Average
173 |
--------------------------------------------------------------------------------
/examples/AutoScaling.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - AutoScalingGroupName
5 | aws_metric_name: GroupTotalInstances
6 | aws_namespace: AWS/AutoScaling
7 | aws_statistics:
8 | - Average
9 | - aws_dimensions:
10 | - AutoScalingGroupName
11 | aws_metric_name: GroupMaxSize
12 | aws_namespace: AWS/AutoScaling
13 | aws_statistics:
14 | - Average
15 | - aws_dimensions:
16 | - AutoScalingGroupName
17 | aws_metric_name: GroupMinSize
18 | aws_namespace: AWS/AutoScaling
19 | aws_statistics:
20 | - Average
21 | - aws_dimensions:
22 | - AutoScalingGroupName
23 | aws_metric_name: GroupTerminatingInstances
24 | aws_namespace: AWS/AutoScaling
25 | aws_statistics:
26 | - Average
27 | - aws_dimensions:
28 | - AutoScalingGroupName
29 | aws_metric_name: GroupPendingInstances
30 | aws_namespace: AWS/AutoScaling
31 | aws_statistics:
32 | - Average
33 | - aws_dimensions:
34 | - AutoScalingGroupName
35 | aws_metric_name: GroupStandbyInstances
36 | aws_namespace: AWS/AutoScaling
37 | aws_statistics:
38 | - Average
39 | - aws_dimensions:
40 | - AutoScalingGroupName
41 | aws_metric_name: GroupDesiredCapacity
42 | aws_namespace: AWS/AutoScaling
43 | aws_statistics:
44 | - Average
45 | - aws_dimensions:
46 | - AutoScalingGroupName
47 | aws_metric_name: GroupInServiceInstances
48 | aws_namespace: AWS/AutoScaling
49 | aws_statistics:
50 | - Average
51 |
--------------------------------------------------------------------------------
/examples/Backup.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - BackupVaultName
5 | aws_metric_name: NumberOfBackupJobsCreated
6 | aws_namespace: AWS/Backup
7 | aws_statistics:
8 | - Sum
9 | - aws_dimensions:
10 | - BackupVaultName
11 | aws_metric_name: NumberOfBackupJobsFailed
12 | aws_namespace: AWS/Backup
13 | aws_statistics:
14 | - Sum
15 | - aws_dimensions:
16 | - BackupVaultName
17 | aws_metric_name: NumberOfBackupJobsCompleted
18 | aws_namespace: AWS/Backup
19 | aws_statistics:
20 | - Sum
21 | - aws_dimensions:
22 | - BackupVaultName
23 | aws_metric_name: NumberOfCopyJobsCreated
24 | aws_namespace: AWS/Backup
25 | aws_statistics:
26 | - Sum
27 | - aws_dimensions:
28 | - BackupVaultName
29 | aws_metric_name: NumberOfCopyJobsFailed
30 | aws_namespace: AWS/Backup
31 | aws_statistics:
32 | - Sum
33 | - aws_dimensions:
34 | - BackupVaultName
35 | aws_metric_name: NumberOfCopyJobsCompleted
36 | aws_namespace: AWS/Backup
37 | aws_statistics:
38 | - Sum
--------------------------------------------------------------------------------
/examples/CloudFront.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - DistributionId
5 | - Region
6 | aws_metric_name: Requests
7 | aws_namespace: AWS/CloudFront
8 | aws_statistics:
9 | - Sum
10 | - aws_dimensions:
11 | - DistributionId
12 | - Region
13 | aws_metric_name: BytesDownloaded
14 | aws_namespace: AWS/CloudFront
15 | aws_statistics:
16 | - Sum
17 | - aws_dimensions:
18 | - DistributionId
19 | - Region
20 | aws_metric_name: BytesUploaded
21 | aws_namespace: AWS/CloudFront
22 | aws_statistics:
23 | - Sum
24 | - aws_dimensions:
25 | - DistributionId
26 | - Region
27 | aws_metric_name: 4xxErrorRate
28 | aws_namespace: AWS/CloudFront
29 | aws_statistics:
30 | - Sum
31 | - aws_dimensions:
32 | - DistributionId
33 | - Region
34 | aws_metric_name: 5xxErrorRate
35 | aws_namespace: AWS/CloudFront
36 | aws_statistics:
37 | - Sum
38 | - aws_dimensions:
39 | - DistributionId
40 | - Region
41 | aws_metric_name: TotalErrorRate
42 | aws_namespace: AWS/CloudFront
43 | aws_statistics:
44 | - Sum
45 |
--------------------------------------------------------------------------------
/examples/DDoSProtection.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | aws_metric_name: DDoSDetected
5 | aws_namespace: AWS/DDoSProtection
6 | aws_statistics:
7 | - Sum
8 | - aws_dimensions:
9 | - ACKFlood
10 | - ChargenReflection
11 | - DNSReflection
12 | - GenericUDPReflection
13 | - MemcachedReflection
14 | - MSSQLReflection
15 | - NetBIOSReflection
16 | - NTPReflection
17 | - PortMapper
18 | - RequestFlood
19 | - RIPReflection
20 | - SNMPReflection
21 | - SSDPReflection
22 | - SYNFlood
23 | - UDPFragment
24 | - UDPTraffic
25 | - UDPReflection
26 | aws_metric_name: DDoSAttackBitsPerSecond
27 | aws_namespace: AWS/DDoSProtection
28 | aws_statistics:
29 | - Sum
30 | - aws_dimensions:
31 | - ACKFlood
32 | - ChargenReflection
33 | - DNSReflection
34 | - GenericUDPReflection
35 | - MemcachedReflection
36 | - MSSQLReflection
37 | - NetBIOSReflection
38 | - NTPReflection
39 | - PortMapper
40 | - RequestFlood
41 | - RIPReflection
42 | - SNMPReflection
43 | - SSDPReflection
44 | - SYNFlood
45 | - UDPFragment
46 | - UDPTraffic
47 | - UDPReflection
48 | aws_metric_name: DDoSAttackPacketsPerSecond
49 | aws_namespace: AWS/DDoSProtection
50 | aws_statistics:
51 | - Sum
52 | - aws_dimensions:
53 | - ACKFlood
54 | - ChargenReflection
55 | - DNSReflection
56 | - GenericUDPReflection
57 | - MemcachedReflection
58 | - MSSQLReflection
59 | - NetBIOSReflection
60 | - NTPReflection
61 | - PortMapper
62 | - RequestFlood
63 | - RIPReflection
64 | - SNMPReflection
65 | - SSDPReflection
66 | - SYNFlood
67 | - UDPFragment
68 | - UDPTraffic
69 | - UDPReflection
70 | aws_metric_name: DDoSAttackRequestsPerSecond
71 | aws_namespace: AWS/DDoSProtection
72 | aws_statistics:
73 | - Sum
74 | - aws_dimensions:
75 | - ResourceArn
76 | - MitigationAction
77 | aws_metric_name: VolumePacketsPerSecond
78 | aws_namespace: AWS/DDoSProtection
79 | aws_statistics:
80 | - Sum
81 | - aws_dimensions:
82 | - ResourceArn
83 | - Protocol
84 | - SourceIp
85 | aws_metric_name: VolumePacketsPerSecond
86 | aws_namespace: AWS/DDoSProtection
87 | aws_statistics:
88 | - Sum
89 | - aws_dimensions:
90 | - ResourceArn
91 | - Protocol
92 | - SourceIp
93 | aws_metric_name: VolumeBitsPerSecond
94 | aws_namespace: AWS/DDoSProtection
95 | aws_statistics:
96 | - Sum
97 |
--------------------------------------------------------------------------------
/examples/DMS.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - ReplicationInstanceIdentifier
5 | aws_metric_name: ReadLatency
6 | aws_namespace: AWS/DMS
7 | aws_statistics:
8 | - Average
9 | - aws_dimensions:
10 | - ReplicationInstanceIdentifier
11 | aws_metric_name: WriteLatency
12 | aws_namespace: AWS/DMS
13 | aws_statistics:
14 | - Average
15 | - aws_dimensions:
16 | - ReplicationInstanceIdentifier
17 | aws_metric_name: ReadThroughput
18 | aws_namespace: AWS/DMS
19 | aws_statistics:
20 | - Average
21 | - aws_dimensions:
22 | - ReplicationInstanceIdentifier
23 | aws_metric_name: WriteThroughput
24 | aws_namespace: AWS/DMS
25 | aws_statistics:
26 | - Average
27 | - aws_dimensions:
28 | - ReplicationInstanceIdentifier
29 | aws_metric_name: CPUUtilization
30 | aws_namespace: AWS/DMS
31 | aws_statistics:
32 | - Average
33 | - aws_dimensions:
34 | - ReplicationInstanceIdentifier
35 | aws_metric_name: AvailableMemory
36 | aws_namespace: AWS/DMS
37 | aws_statistics:
38 | - Average
39 |
--------------------------------------------------------------------------------
/examples/DocumentDB.yml:
--------------------------------------------------------------------------------
1 | ---
2 | region: us-east-1
3 | metrics:
4 | - aws_dimensions:
5 | - DBInstanceIdentifier
6 | aws_metric_name: CPUUtilization
7 | aws_namespace: AWS/DocDB
8 | aws_statistics:
9 | - Average
10 | - aws_dimensions:
11 | - DBInstanceIdentifier
12 | aws_metric_name: DatabaseConnections
13 | aws_namespace: AWS/DocDB
14 | aws_statistics:
15 | - Maximum
16 | - aws_dimensions:
17 | - DBInstanceIdentifier
18 | aws_metric_name: FreeableMemory
19 | aws_namespace: AWS/DocDB
20 | aws_statistics:
21 | - Average
22 | - aws_dimensions:
23 | - DBInstanceIdentifier
24 | aws_metric_name: WriteIOPS
25 | aws_namespace: AWS/DocDB
26 | aws_statistics:
27 | - Sum
28 | - aws_dimensions:
29 | - DBInstanceIdentifier
30 | aws_metric_name: ReadIOPS
31 | aws_namespace: AWS/DocDB
32 | aws_statistics:
33 | - Sum
34 | - aws_dimensions:
35 | - DBInstanceIdentifier
36 | aws_metric_name: WriteLatency
37 | aws_namespace: AWS/DocDB
38 | aws_statistics:
39 | - Average
40 | - aws_dimensions:
41 | - DBInstanceIdentifier
42 | aws_metric_name: ReadLatency
43 | aws_namespace: AWS/DocDB
44 | aws_statistics:
45 | - Average
46 | - aws_dimensions:
47 | - DBInstanceIdentifier
48 | aws_metric_name: ReadThroughput
49 | aws_namespace: AWS/DocDB
50 | aws_statistics:
51 | - Average
52 | - aws_dimensions:
53 | - DBInstanceIdentifier
54 | aws_metric_name: WriteThroughput
55 | aws_namespace: AWS/DocDB
56 | aws_statistics:
57 | - Average
58 | - aws_dimensions:
59 | - DBInstanceIdentifier
60 | aws_metric_name: FreeLocalStorage
61 | aws_namespace: AWS/DocDB
62 | aws_statistics:
63 | - Average
64 | - aws_dimensions:
65 | - DBInstanceIdentifier
66 | aws_metric_name: VolumeBytesUsed
67 | aws_namespace: AWS/DocDB
68 | aws_statistics:
69 | - Average
70 | - aws_dimensions:
71 | - DBInstanceIdentifier
72 | aws_metric_name: DiskQueueDepth
73 | aws_namespace: AWS/DocDB
74 | aws_statistics:
75 | - Average
76 | - aws_dimensions:
77 | - DBInstanceIdentifier
78 | aws_metric_name: NetworkTransmitThroughput
79 | aws_namespace: AWS/DocDB
80 | aws_statistics:
81 | - Average
82 | - aws_dimensions:
83 | - DBInstanceIdentifier
84 | aws_metric_name: NetworkReceiveThroughput
85 | aws_namespace: AWS/DocDB
86 | aws_statistics:
87 | - Average
88 | - aws_dimensions:
89 | - DBInstanceIdentifier
90 | aws_metric_name: DatabaseCursors
91 | aws_namespace: AWS/DocDB
92 | aws_statistics:
93 | - Average
94 | - aws_dimensions:
95 | - DBInstanceIdentifier
96 | aws_metric_name: DatabaseCursorsMax
97 | aws_namespace: AWS/DocDB
98 | aws_statistics:
99 | - Average
100 | - aws_dimensions:
101 | - DBInstanceIdentifier
102 | aws_metric_name: DatabaseCursorsTimedOut
103 | aws_namespace: AWS/DocDB
104 | aws_statistics:
105 | - Average
106 | - aws_dimensions:
107 | - DBInstanceIdentifier
108 | aws_metric_name: BufferCacheHitRatio
109 | aws_namespace: AWS/DocDB
110 | aws_statistics:
111 | - Average
112 | - aws_dimensions:
113 | - DBInstanceIdentifier
114 | aws_metric_name: IndexBufferCacheHitRatio
115 | aws_namespace: AWS/DocDB
116 | aws_statistics:
117 | - Average
118 | - aws_dimensions:
119 | - DBInstanceIdentifier
120 | aws_metric_name: CPUCreditBalance
121 | aws_namespace: AWS/DocDB
122 | aws_statistics:
123 | - Average
124 | - aws_dimensions:
125 | - DBInstanceIdentifier
126 | aws_metric_name: CPUCreditUsage
127 | aws_namespace: AWS/DocDB
128 | aws_statistics:
129 | - Average
130 | - aws_dimensions:
131 | - DBInstanceIdentifier
132 | aws_metric_name: OpcountersDelete
133 | aws_namespace: AWS/DocDB
134 | aws_statistics:
135 | - Average
136 | - aws_dimensions:
137 | - DBInstanceIdentifier
138 | aws_metric_name: OpcountersCommand
139 | aws_namespace: AWS/DocDB
140 | aws_statistics:
141 | - Average
142 | - aws_dimensions:
143 | - DBInstanceIdentifier
144 | aws_metric_name: OpcountersGetmore
145 | aws_namespace: AWS/DocDB
146 | aws_statistics:
147 | - Average
148 | - aws_dimensions:
149 | - DBInstanceIdentifier
150 | aws_metric_name: OpcountersQuery
151 | aws_namespace: AWS/DocDB
152 | aws_statistics:
153 | - Average
154 | - aws_dimensions:
155 | - DBInstanceIdentifier
156 | aws_metric_name: OpcountersUpdate
157 | aws_namespace: AWS/DocDB
158 | aws_statistics:
159 | - Average
160 | - aws_dimensions:
161 | - DBInstanceIdentifier
162 | aws_metric_name: DBInstanceReplicaLag
163 | aws_namespace: AWS/DocDB
164 | aws_statistics:
165 | - Average
166 | - aws_dimensions:
167 | - DBInstanceIdentifier
168 | aws_metric_name: DBClusterReplicaLagMaximum
169 | aws_namespace: AWS/DocDB
170 | aws_statistics:
171 | - Average
--------------------------------------------------------------------------------
/examples/DynamoDB.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - TableName
5 | - GlobalSecondaryIndexName
6 | aws_metric_name: ConsumedReadCapacityUnits
7 | aws_namespace: AWS/DynamoDB
8 | aws_statistics:
9 | - Maximum
10 | - aws_dimensions:
11 | - TableName
12 | - GlobalSecondaryIndexName
13 | aws_metric_name: ConsumedWriteCapacityUnits
14 | aws_namespace: AWS/DynamoDB
15 | aws_statistics:
16 | - Maximum
17 | - aws_dimensions:
18 | - TableName
19 | - Operation
20 | aws_metric_name: ThrottledRequests
21 | aws_namespace: AWS/DynamoDB
22 | aws_statistics:
23 | - Sum
24 | - aws_dimensions:
25 | - TableName
26 | - Operation
27 | aws_metric_name: SystemErrors
28 | aws_namespace: AWS/DynamoDB
29 | aws_statistics:
30 | - Sum
31 | - aws_dimensions:
32 | - TableName
33 | - Operation
34 | aws_metric_name: SuccessfulRequestLatency
35 | aws_namespace: AWS/DynamoDB
36 | aws_statistics:
37 | - Maximum
38 | - aws_dimensions:
39 | - TableName
40 | - GlobalSecondaryIndexName
41 | aws_metric_name: WriteThrottleEvents
42 | aws_namespace: AWS/DynamoDB
43 | aws_statistics:
44 | - Sum
45 | - aws_dimensions:
46 | - TableName
47 | - GlobalSecondaryIndexName
48 | aws_metric_name: ReadThrottleEvents
49 | aws_namespace: AWS/DynamoDB
50 | aws_statistics:
51 | - Sum
52 |
--------------------------------------------------------------------------------
/examples/EBS.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - VolumeId
5 | aws_metric_name: VolumeWriteBytes
6 | aws_namespace: AWS/EBS
7 | aws_statistics:
8 | - Maximum
9 | - Average
10 | - aws_dimensions:
11 | - VolumeId
12 | aws_metric_name: VolumeReadBytes
13 | aws_namespace: AWS/EBS
14 | aws_statistics:
15 | - Maximum
16 | - Average
17 | - aws_dimensions:
18 | - VolumeId
19 | aws_metric_name: VolumeReadOps
20 | aws_namespace: AWS/EBS
21 | aws_statistics:
22 | - Average
23 | - aws_dimensions:
24 | - VolumeId
25 | aws_metric_name: VolumeWriteOps
26 | aws_namespace: AWS/EBS
27 | aws_statistics:
28 | - Average
29 | - aws_dimensions:
30 | - VolumeId
31 | aws_metric_name: VolumeTotalReadTime
32 | aws_namespace: AWS/EBS
33 | aws_statistics:
34 | - Sum
35 | - Average
36 | - aws_dimensions:
37 | - VolumeId
38 | aws_metric_name: VolumeTotalWriteTime
39 | aws_namespace: AWS/EBS
40 | aws_statistics:
41 | - Sum
42 | - Average
43 | - aws_dimensions:
44 | - VolumeId
45 | aws_metric_name: VolumeQueueLength
46 | aws_namespace: AWS/EBS
47 | aws_statistics:
48 | - Average
49 | - aws_dimensions:
50 | - VolumeId
51 | aws_metric_name: BurstBalance
52 | aws_namespace: AWS/EBS
53 | aws_statistics:
54 | - Average
55 | - aws_dimensions:
56 | - VolumeId
57 | aws_metric_name: VolumeIdleTime
58 | aws_namespace: AWS/EBS
59 | aws_statistics:
60 | - Sum
61 |
62 |
--------------------------------------------------------------------------------
/examples/EC2.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - InstanceId
5 | aws_metric_name: CPUUtilization
6 | aws_namespace: AWS/EC2
7 | aws_statistics:
8 | - Average
9 | aws_tag_select:
10 | resource_type_selection: ec2:instance
11 | resource_id_dimension: InstanceId
12 | - aws_dimensions:
13 | - InstanceId
14 | aws_metric_name: NetworkIn
15 | aws_namespace: AWS/EC2
16 | aws_statistics:
17 | - Average
18 | - aws_dimensions:
19 | - InstanceId
20 | aws_metric_name: NetworkOut
21 | aws_namespace: AWS/EC2
22 | aws_statistics:
23 | - Average
24 | - aws_dimensions:
25 | - InstanceId
26 | aws_metric_name: NetworkPacketsIn
27 | aws_namespace: AWS/EC2
28 | aws_statistics:
29 | - Average
30 | - aws_dimensions:
31 | - InstanceId
32 | aws_metric_name: NetworkPacketsOut
33 | aws_namespace: AWS/EC2
34 | aws_statistics:
35 | - Average
36 | - aws_dimensions:
37 | - InstanceId
38 | aws_metric_name: DiskWriteBytes
39 | aws_namespace: AWS/EC2
40 | aws_statistics:
41 | - Average
42 | - aws_dimensions:
43 | - InstanceId
44 | aws_metric_name: DiskReadBytes
45 | aws_namespace: AWS/EC2
46 | aws_statistics:
47 | - Average
48 | - aws_dimensions:
49 | - InstanceId
50 | aws_metric_name: CPUCreditBalance
51 | aws_namespace: AWS/EC2
52 | aws_statistics:
53 | - Average
54 | - aws_dimensions:
55 | - InstanceId
56 | aws_metric_name: CPUCreditUsage
57 | aws_namespace: AWS/EC2
58 | aws_statistics:
59 | - Average
60 | - aws_dimensions:
61 | - InstanceId
62 | aws_metric_name: StatusCheckFailed
63 | aws_namespace: AWS/EC2
64 | aws_statistics:
65 | - Sum
66 | - aws_dimensions:
67 | - InstanceId
68 | aws_metric_name: StatusCheckFailed_Instance
69 | aws_namespace: AWS/EC2
70 | aws_statistics:
71 | - Sum
72 | - aws_dimensions:
73 | - InstanceId
74 | aws_metric_name: StatusCheckFailed_System
75 | aws_namespace: AWS/EC2
76 | aws_statistics:
77 | - Sum
78 |
--------------------------------------------------------------------------------
/examples/ECS.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - ClusterName
5 | - ServiceName
6 | aws_metric_name: CPUUtilization
7 | aws_namespace: AWS/ECS
8 | aws_statistics:
9 | - Average
10 | - aws_dimensions:
11 | - ClusterName
12 | - ServiceName
13 | aws_metric_name: MemoryUtilization
14 | aws_namespace: AWS/ECS
15 | aws_statistics:
16 | - Average
17 | - aws_dimensions:
18 | - ClusterName
19 | aws_metric_name: GPUReservation
20 | aws_namespace: AWS/ECS
21 | aws_statistics:
22 | - Average
23 | - aws_dimensions:
24 | - ClusterName
25 | aws_metric_name: CPUReservation
26 | aws_namespace: AWS/ECS
27 | aws_statistics:
28 | - Average
29 | - aws_dimensions:
30 | - ClusterName
31 | aws_metric_name: MemoryReservation
32 | aws_namespace: AWS/ECS
33 | aws_statistics:
34 | - Average
35 |
--------------------------------------------------------------------------------
/examples/EFS.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - FileSystemId
5 | aws_metric_name: ClientConnections
6 | aws_namespace: AWS/EFS
7 | aws_statistics:
8 | - Maximum
9 | - aws_dimensions:
10 | - FileSystemId
11 | aws_metric_name: DataWriteIOBytes
12 | aws_namespace: AWS/EFS
13 | aws_statistics:
14 | - Maximum
15 | - aws_dimensions:
16 | - FileSystemId
17 | aws_metric_name: DataReadIOBytes
18 | aws_namespace: AWS/EFS
19 | aws_statistics:
20 | - Maximum
21 | - aws_dimensions:
22 | - FileSystemId
23 | aws_metric_name: PermittedThroughput
24 | aws_namespace: AWS/EFS
25 | aws_statistics:
26 | - Maximum
27 | - aws_dimensions:
28 | - FileSystemId
29 | aws_metric_name: BurstCreditBalance
30 | aws_namespace: AWS/EFS
31 | aws_statistics:
32 | - Average
33 | - aws_dimensions:
34 | - FileSystemId
35 | aws_metric_name: PercentIOLimit
36 | aws_namespace: AWS/EFS
37 | aws_statistics:
38 | - Average
39 |
--------------------------------------------------------------------------------
/examples/ELB.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - AvailabilityZone
5 | - LoadBalancerName
6 | aws_metric_name: BackendConnectionErrors
7 | aws_namespace: AWS/ELB
8 | aws_statistics:
9 | - Sum
10 | - aws_dimensions:
11 | - AvailabilityZone
12 | - LoadBalancerName
13 | aws_metric_name: HTTPCode_Backend_5XX
14 | aws_namespace: AWS/ELB
15 | aws_statistics:
16 | - Sum
17 | - aws_dimensions:
18 | - AvailabilityZone
19 | - LoadBalancerName
20 | aws_metric_name: HTTPCode_Backend_4XX
21 | aws_namespace: AWS/ELB
22 | aws_statistics:
23 | - Sum
24 | - aws_dimensions:
25 | - AvailabilityZone
26 | - LoadBalancerName
27 | aws_metric_name: HTTPCode_Backend_3XX
28 | aws_namespace: AWS/ELB
29 | aws_statistics:
30 | - Sum
31 | - aws_dimensions:
32 | - AvailabilityZone
33 | - LoadBalancerName
34 | aws_metric_name: HTTPCode_Backend_2XX
35 | aws_namespace: AWS/ELB
36 | aws_statistics:
37 | - Sum
38 | - aws_dimensions:
39 | - LoadBalancerName
40 | - AvailabilityZone
41 | aws_metric_name: HTTPCode_ELB_5XX
42 | aws_namespace: AWS/ELB
43 | aws_statistics:
44 | - Sum
45 | - aws_dimensions:
46 | - LoadBalancerName
47 | - AvailabilityZone
48 | aws_metric_name: RequestCount
49 | aws_namespace: AWS/ELB
50 | aws_statistics:
51 | - Average
52 | - aws_dimensions:
53 | - LoadBalancerName
54 | - AvailabilityZone
55 | aws_metric_name: HTTPCode_ELB_4XX
56 | aws_namespace: AWS/ELB
57 | aws_statistics:
58 | - Sum
59 | - aws_dimensions:
60 | - AvailabilityZone
61 | - LoadBalancerName
62 | aws_metric_name: Latency
63 | aws_namespace: AWS/ELB
64 | aws_statistics:
65 | - Average
66 | - aws_dimensions:
67 | - LoadBalancerName
68 | - AvailabilityZone
69 | aws_metric_name: SurgeQueueLength
70 | aws_namespace: AWS/ELB
71 | - aws_dimensions:
72 | - LoadBalancer
73 | aws_metric_name: ActiveFlowCount
74 | aws_namespace: AWS/ELB
75 | aws_statistics:
76 | - Average
77 | - aws_dimensions:
78 | - LoadBalancer
79 | aws_metric_name: ActiveFlowCount_TLS
80 | aws_namespace: AWS/ELB
81 | aws_statistics:
82 | - Average
83 | - aws_dimensions:
84 | - LoadBalancer
85 | aws_metric_name: ProcessedBytes
86 | aws_namespace: AWS/ELB
87 | aws_statistics:
88 | - Sum
89 | - aws_dimensions:
90 | - LoadBalancer
91 | aws_metric_name: ProcessedBytes_TLS
92 | aws_namespace: AWS/ELB
93 | aws_statistics:
94 | - Sum
95 | - aws_dimensions:
96 | - LoadBalancer
97 | aws_metric_name: HealthyHostCount
98 | aws_namespace: AWS/ELB
99 | aws_statistics:
100 | - Minimum
101 | - aws_dimensions:
102 | - LoadBalancer
103 | aws_metric_name: HealthyHostCount
104 | aws_namespace: AWS/ELB
105 | aws_statistics:
106 | - Maximum
107 | - aws_dimensions:
108 | - LoadBalancer
109 | aws_metric_name: UnHealthyHostCount
110 | aws_namespace: AWS/ELB
111 | aws_statistics:
112 | - Maximum
113 | - aws_dimensions:
114 | - LoadBalancer
115 | aws_metric_name: UnHealthyHostCount
116 | aws_namespace: AWS/ELB
117 | aws_statistics:
118 | - Minimum
119 | - aws_dimensions:
120 | - LoadBalancer
121 | aws_metric_name: NewFlowCount
122 | aws_namespace: AWS/ELB
123 | aws_statistics:
124 | - Sum
125 | - aws_dimensions:
126 | - LoadBalancer
127 | aws_metric_name: NewFlowCount_TLS
128 | aws_namespace: AWS/ELB
129 | aws_statistics:
130 | - Sum
131 | - aws_dimensions:
132 | - LoadBalancer
133 | aws_metric_name: TCP_Client_Reset_Count
134 | aws_namespace: AWS/ELB
135 | aws_statistics:
136 | - Sum
137 | - aws_dimensions:
138 | - LoadBalancer
139 | aws_metric_name: TCP_Target_Reset_Count
140 | aws_namespace: AWS/ELB
141 | aws_statistics:
142 | - Sum
143 | - aws_dimensions:
144 | - LoadBalancer
145 | aws_metric_name: TCP_ELB_Reset_Count
146 | aws_namespace: AWS/ELB
147 | aws_statistics:
148 | - Sum
149 | - aws_dimensions:
150 | - LoadBalancer
151 | aws_metric_name: ClientTLSNegotiationErrorCount
152 | aws_namespace: AWS/ELB
153 | aws_statistics:
154 | - Sum
155 | - aws_dimensions:
156 | - LoadBalancer
157 | aws_metric_name: TargetTLSNegotiationErrorCount
158 | aws_namespace: AWS/ELB
159 | aws_statistics:
160 | - Sum
161 | - aws_dimensions:
162 | - LoadBalancer
163 | aws_metric_name: ConsumedLCUs
164 | aws_namespace: AWS/ELB
165 | aws_statistics:
166 | - Sum
167 |
--------------------------------------------------------------------------------
/examples/ElastiCache.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - CacheNodeId
5 | - CacheClusterId
6 | aws_metric_name: CPUUtilization
7 | aws_namespace: AWS/ElastiCache
8 | aws_statistics:
9 | - Average
10 | - aws_dimensions:
11 | - CacheNodeId
12 | - CacheClusterId
13 | aws_metric_name: CPUCreditBalance
14 | aws_namespace: AWS/ElastiCache
15 | aws_statistics:
16 | - Average
17 | - aws_dimensions:
18 | - CacheNodeId
19 | - CacheClusterId
20 | aws_metric_name: FreeableMemory
21 | aws_namespace: AWS/ElastiCache
22 | aws_statistics:
23 | - Average
24 | - aws_dimensions:
25 | - CacheNodeId
26 | - CacheClusterId
27 | aws_metric_name: NetworkBytesIn
28 | aws_namespace: AWS/ElastiCache
29 | aws_statistics:
30 | - Average
31 | - aws_dimensions:
32 | - CacheNodeId
33 | - CacheClusterId
34 | aws_metric_name: NetworkBytesOut
35 | aws_namespace: AWS/ElastiCache
36 | aws_statistics:
37 | - Average
38 | - aws_dimensions:
39 | - CacheNodeId
40 | - CacheClusterId
41 | aws_metric_name: SwapUsage
42 | aws_namespace: AWS/ElastiCache
43 | aws_statistics:
44 | - Average
45 | - aws_dimensions:
46 | - CacheNodeId
47 | - CacheClusterId
48 | aws_metric_name: CacheHits
49 | aws_namespace: AWS/ElastiCache
50 | aws_statistics:
51 | - Average
52 | - aws_dimensions:
53 | - CacheNodeId
54 | - CacheClusterId
55 | aws_metric_name: CacheMisses
56 | aws_namespace: AWS/ElastiCache
57 | aws_statistics:
58 | - Average
59 | - aws_dimensions:
60 | - CacheNodeId
61 | - CacheClusterId
62 | aws_metric_name: CurrConnections
63 | aws_namespace: AWS/ElastiCache
64 | aws_statistics:
65 | - Average
66 | - aws_dimensions:
67 | - CacheNodeId
68 | - CacheClusterId
69 | aws_metric_name: NewConnections
70 | aws_namespace: AWS/ElastiCache
71 | aws_statistics:
72 | - Average
73 | - aws_dimensions:
74 | - CacheNodeId
75 | - CacheClusterId
76 | aws_metric_name: GetTypeCmds
77 | aws_namespace: AWS/ElastiCache
78 | aws_statistics:
79 | - Average
80 | - aws_dimensions:
81 | - CacheNodeId
82 | - CacheClusterId
83 | aws_metric_name: SetTypeCmds
84 | aws_namespace: AWS/ElastiCache
85 | aws_statistics:
86 | - Average
87 | - aws_dimensions:
88 | - CacheNodeId
89 | - CacheClusterId
90 | aws_metric_name: EngineCPUUtilization
91 | aws_namespace: AWS/ElastiCache
92 | aws_statistics:
93 | - Average
94 | - aws_dimensions:
95 | - CacheNodeId
96 | - CacheClusterId
97 | aws_metric_name: BytesUsedForCache
98 | aws_namespace: AWS/ElastiCache
99 | aws_statistics:
100 | - Average
101 | - aws_dimensions:
102 | - CacheNodeId
103 | - CacheClusterId
104 | aws_metric_name: HashBasedCmds
105 | aws_namespace: AWS/ElastiCache
106 | aws_statistics:
107 | - Average
108 | - aws_dimensions:
109 | - CacheNodeId
110 | - CacheClusterId
111 | aws_metric_name: HyperLogLogBasedCmds
112 | aws_namespace: AWS/ElastiCache
113 | aws_statistics:
114 | - Average
115 | - aws_dimensions:
116 | - CacheNodeId
117 | - CacheClusterId
118 | aws_metric_name: KeyBasedCmds
119 | aws_namespace: AWS/ElastiCache
120 | aws_statistics:
121 | - Average
122 | - aws_dimensions:
123 | - CacheNodeId
124 | - CacheClusterId
125 | aws_metric_name: ListBasedCmds
126 | aws_namespace: AWS/ElastiCache
127 | aws_statistics:
128 | - Average
129 | - aws_dimensions:
130 | - CacheNodeId
131 | - CacheClusterId
132 | aws_metric_name: SetBasedCmds
133 | aws_namespace: AWS/ElastiCache
134 | aws_statistics:
135 | - Average
136 | - aws_dimensions:
137 | - CacheNodeId
138 | - CacheClusterId
139 | aws_metric_name: SetTypeCmds
140 | aws_namespace: AWS/ElastiCache
141 | aws_statistics:
142 | - Average
143 | - aws_dimensions:
144 | - CacheNodeId
145 | - CacheClusterId
146 | aws_metric_name: SortedSetBasedCmds
147 | aws_namespace: AWS/ElastiCache
148 | aws_statistics:
149 | - Average
150 | - aws_dimensions:
151 | - CacheNodeId
152 | - CacheClusterId
153 | aws_metric_name: StringBasedCmds
154 | aws_namespace: AWS/ElastiCache
155 | aws_statistics:
156 | - Average
157 | - aws_dimensions:
158 | - CacheNodeId
159 | - CacheClusterId
160 | aws_metric_name: StreamBasedCmds
161 | aws_namespace: AWS/ElastiCache
162 | aws_statistics:
163 | - Average
164 | - aws_dimensions:
165 | - CacheNodeId
166 | - CacheClusterId
167 | aws_metric_name: CurrItems
168 | aws_namespace: AWS/ElastiCache
169 | aws_statistics:
170 | - Average
171 | - aws_dimensions:
172 | - CacheNodeId
173 | - CacheClusterId
174 | aws_metric_name: ActiveDefragHits
175 | aws_namespace: AWS/ElastiCache
176 | aws_statistics:
177 | - Average
178 | - aws_dimensions:
179 | - CacheNodeId
180 | - CacheClusterId
181 | aws_metric_name: Evictions
182 | aws_namespace: AWS/ElastiCache
183 | aws_statistics:
184 | - Average
185 | - aws_dimensions:
186 | - CacheNodeId
187 | - CacheClusterId
188 | aws_metric_name: Reclaimed
189 | aws_namespace: AWS/ElastiCache
190 | aws_statistics:
191 | - Average
192 | - aws_dimensions:
193 | - CacheNodeId
194 | - CacheClusterId
195 | aws_metric_name: SaveInProgress
196 | aws_namespace: AWS/ElastiCache
197 | aws_statistics:
198 | - Average
199 | - aws_dimensions:
200 | - CacheNodeId
201 | - CacheClusterId
202 | aws_metric_name: ReplicationLag
203 | aws_namespace: AWS/ElastiCache
204 | aws_statistics:
205 | - Average
206 | - aws_dimensions:
207 | - CacheNodeId
208 | - CacheClusterId
209 | aws_metric_name: ReplicationBytes
210 | aws_namespace: AWS/ElastiCache
211 | aws_statistics:
212 | - Average
213 |
--------------------------------------------------------------------------------
/examples/Fargate.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - ClusterName
5 | - ServiceName
6 | aws_metric_name: CPUUtilization
7 | aws_namespace: AWS/Fargate
8 | aws_statistics:
9 | - Average
10 | - aws_dimensions:
11 | - ClusterName
12 | - ServiceName
13 | aws_metric_name: MemoryUtilization
14 | aws_namespace: AWS/Fargate
15 | aws_statistics:
16 | - Average
17 |
--------------------------------------------------------------------------------
/examples/Firehose.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - DeliveryStreamName
5 | aws_metric_name: IncomingRecords
6 | aws_namespace: AWS/Firehose
7 | aws_statistics:
8 | - Sum
9 | - aws_dimensions:
10 | - DeliveryStreamName
11 | aws_metric_name: IncomingBytes
12 | aws_namespace: AWS/Firehose
13 | aws_statistics:
14 | - Sum
15 | - aws_dimensions:
16 | - DeliveryStreamName
17 | aws_metric_name: IncomingPutRequests
18 | aws_namespace: AWS/Firehose
19 | aws_statistics:
20 | - Sum
21 | - aws_dimensions:
22 | - DeliveryStreamName
23 | aws_metric_name: PutRecord.Latency
24 | aws_namespace: AWS/Firehose
25 | aws_statistics:
26 | - Sum
27 | - aws_dimensions:
28 | - DeliveryStreamName
29 | aws_metric_name: PutRecordBatch.Latency
30 | aws_namespace: AWS/Firehose
31 | aws_statistics:
32 | - Sum
33 | - aws_dimensions:
34 | - DeliveryStreamName
35 | aws_metric_name: DataReadFromKinesisStream.Records
36 | aws_namespace: AWS/Firehose
37 | aws_statistics:
38 | - Sum
39 | - aws_dimensions:
40 | - DeliveryStreamName
41 | aws_metric_name: DataReadFromKinesisStream.Bytes
42 | aws_namespace: AWS/Firehose
43 | aws_statistics:
44 | - Sum
45 | - aws_dimensions:
46 | - DeliveryStreamName
47 | aws_metric_name: ThrottledGetRecords
48 | aws_namespace: AWS/Firehose
49 | aws_statistics:
50 | - Sum
51 | - aws_dimensions:
52 | - DeliveryStreamName
53 | aws_metric_name: SucceedProcessing.Records
54 | aws_namespace: AWS/Firehose
55 | aws_statistics:
56 | - Sum
57 | - aws_dimensions:
58 | - DeliveryStreamName
59 | aws_metric_name: SucceedProcessing.Bytes
60 | aws_namespace: AWS/Firehose
61 | aws_statistics:
62 | - Sum
63 | - aws_dimensions:
64 | - DeliveryStreamName
65 | aws_metric_name: ExecuteProcessing.Duration
66 | aws_namespace: AWS/Firehose
67 | aws_statistics:
68 | - Sum
69 | - aws_dimensions:
70 | - DeliveryStreamName
71 | aws_metric_name: ExecuteProcessing.Success
72 | aws_namespace: AWS/Firehose
73 | aws_statistics:
74 | - Sum
75 | - aws_dimensions:
76 | - DeliveryStreamName
77 | aws_metric_name: DeliveryToS3.Success
78 | aws_namespace: AWS/Firehose
79 | aws_statistics:
80 | - Sum
81 | - aws_dimensions:
82 | - DeliveryStreamName
83 | aws_metric_name: DeliveryToS3.DataFreshness
84 | aws_namespace: AWS/Firehose
85 | aws_statistics:
86 | - Sum
87 | - aws_dimensions:
88 | - DeliveryStreamName
89 | aws_metric_name: DeliveryToS3.Records
90 | aws_namespace: AWS/Firehose
91 | aws_statistics:
92 | - Sum
93 | - aws_dimensions:
94 | - DeliveryStreamName
95 | aws_metric_name: DeliveryToS3.Bytes
96 | aws_namespace: AWS/Firehose
97 | aws_statistics:
98 | - Sum
99 | - aws_dimensions:
100 | - DeliveryStreamName
101 | aws_metric_name: DeliveryToElasticsearch.Success
102 | aws_namespace: AWS/Firehose
103 | aws_statistics:
104 | - Sum
105 | - aws_dimensions:
106 | - DeliveryStreamName
107 | aws_metric_name: DeliveryToElasticsearch.DataFreshness
108 | aws_namespace: AWS/Firehose
109 | aws_statistics:
110 | - Sum
111 | - aws_dimensions:
112 | - DeliveryStreamName
113 | aws_metric_name: DeliveryToElasticsearch.Records
114 | aws_namespace: AWS/Firehose
115 | aws_statistics:
116 | - Sum
117 | - aws_dimensions:
118 | - DeliveryStreamName
119 | aws_metric_name: DeliveryToElasticsearch.Bytes
120 | aws_namespace: AWS/Firehose
121 | aws_statistics:
122 | - Sum
123 | - aws_dimensions:
124 | - DeliveryStreamName
125 | aws_metric_name: DeliveryToRedshift.Success
126 | aws_namespace: AWS/Firehose
127 | aws_statistics:
128 | - Sum
129 | - aws_dimensions:
130 | - DeliveryStreamName
131 | aws_metric_name: DeliveryToRedshift.DataFreshness
132 | aws_namespace: AWS/Firehose
133 | aws_statistics:
134 | - Sum
135 | - aws_dimensions:
136 | - DeliveryStreamName
137 | aws_metric_name: DeliveryToRedshift.Records
138 | aws_namespace: AWS/Firehose
139 | aws_statistics:
140 | - Sum
141 | - aws_dimensions:
142 | - DeliveryStreamName
143 | aws_metric_name: DeliveryToRedshift.Bytes
144 | aws_namespace: AWS/Firehose
145 | aws_statistics:
146 | - Sum
147 | - aws_dimensions:
148 | - DeliveryStreamName
149 | aws_metric_name: DeliveryToHttpEndpoint.Success
150 | aws_namespace: AWS/Firehose
151 | aws_statistics:
152 | - Sum
153 | - aws_dimensions:
154 | - DeliveryStreamName
155 | aws_metric_name: DeliveryToHttpEndpoint.DataFreshness
156 | aws_namespace: AWS/Firehose
157 | aws_statistics:
158 | - Sum
159 | - aws_dimensions:
160 | - DeliveryStreamName
161 | aws_metric_name: DeliveryToHttpEndpoint.Records
162 | aws_namespace: AWS/Firehose
163 | aws_statistics:
164 | - Sum
165 | - aws_dimensions:
166 | - DeliveryStreamName
167 | aws_metric_name: DeliveryToHttpEndpoint.ProcessedRecords
168 | aws_namespace: AWS/Firehose
169 | aws_statistics:
170 | - Sum
171 | - aws_dimensions:
172 | - DeliveryStreamName
173 | aws_metric_name: DeliveryToHttpEndpoint.Bytes
174 | aws_namespace: AWS/Firehose
175 | aws_statistics:
176 | - Sum
177 | - aws_dimensions:
178 | - DeliveryStreamName
179 | aws_metric_name: DeliveryToHttpEndpoint.ProcessedBytes
180 | aws_namespace: AWS/Firehose
181 | aws_statistics:
182 | - Sum
183 |
--------------------------------------------------------------------------------
/examples/Kafka.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | period_seconds: 240
3 | metrics:
4 | - aws_dimensions: [Cluster Name, Broker ID]
5 | aws_metric_name: RootDiskUsed
6 | aws_namespace: AWS/Kafka
7 | aws_statistics:
8 | - Average
9 | - aws_dimensions: [Cluster Name, Broker ID]
10 | aws_metric_name: KafkaDataLogsDiskUsed
11 | aws_namespace: AWS/Kafka
12 | aws_statistics:
13 | - Average
14 | - aws_dimensions: [Cluster Name, Broker ID]
15 | aws_metric_name: KafkaAppLogsDiskUsed
16 | aws_namespace: AWS/Kafka
17 | aws_statistics:
18 | - Average
19 | - aws_dimensions: [Cluster Name, Broker ID]
20 | aws_metric_name: MemoryFree
21 | aws_namespace: AWS/Kafka
22 | aws_statistics:
23 | - Average
24 | - aws_dimensions: [Cluster Name, Broker ID]
25 | aws_metric_name: MemoryUsed
26 | aws_namespace: AWS/Kafka
27 | aws_statistics:
28 | - Average
29 | - aws_dimensions: [Cluster Name, Broker ID]
30 | aws_metric_name: NetworkRxPackets
31 | aws_namespace: AWS/Kafka
32 | aws_statistics:
33 | - Average
34 | - aws_dimensions: [Cluster Name, Broker ID]
35 | aws_metric_name: NetworkRxPackets
36 | aws_namespace: AWS/Kafka
37 | aws_statistics:
38 | - Maximum
39 | - aws_dimensions: [Cluster Name, Broker ID]
40 | aws_metric_name: NetworkTxPackets
41 | aws_namespace: AWS/Kafka
42 | aws_statistics:
43 | - Maximum
44 | - aws_dimensions: [Cluster Name, Broker ID]
45 | aws_metric_name: SwapFree
46 | aws_namespace: AWS/Kafka
47 | aws_statistics:
48 | - Average
49 | - aws_dimensions: [Cluster Name, Broker ID]
50 | aws_metric_name: SwapUsed
51 | aws_namespace: AWS/Kafka
52 | aws_statistics:
53 | - Average
54 | - aws_dimensions: [Cluster Name, Broker ID]
55 | aws_metric_name: GlobalTopicCount
56 | aws_namespace: AWS/Kafka
57 | aws_statistics:
58 | - Maximum
59 | - aws_dimensions: [Cluster Name, Broker ID]
60 | aws_metric_name: CpuUser
61 | aws_namespace: AWS/Kafka
62 | aws_statistics:
63 | - Average
64 |
--------------------------------------------------------------------------------
/examples/Kinesis.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - StreamName
5 | aws_metric_name: IncomingBytes
6 | aws_namespace: AWS/Kinesis
7 | aws_statistics:
8 | - Sum
9 | - aws_dimensions:
10 | - StreamName
11 | aws_metric_name: PutRecord.Latency
12 | aws_namespace: AWS/Kinesis
13 | aws_statistics:
14 | - Average
15 | - aws_dimensions:
16 | - StreamName
17 | aws_metric_name: PutRecords.Latency
18 | aws_namespace: AWS/Kinesis
19 | aws_statistics:
20 | - Average
21 | - aws_dimensions:
22 | - StreamName
23 | aws_metric_name: GetRecords.Latency
24 | aws_namespace: AWS/Kinesis
25 | aws_statistics:
26 | - Average
27 | - aws_dimensions:
28 | - StreamName
29 | aws_metric_name: GetRecords.Records
30 | aws_namespace: AWS/Kinesis
31 | aws_statistics:
32 | - Sum
33 | - aws_dimensions:
34 | - StreamName
35 | aws_metric_name: GetRecords.Bytes
36 | aws_namespace: AWS/Kinesis
37 | aws_statistics:
38 | - Sum
39 | - aws_dimensions:
40 | - StreamName
41 | aws_metric_name: GetRecords.IteratorAgeMilliseconds
42 | aws_namespace: AWS/Kinesis
43 | aws_statistics:
44 | - Average
45 | - aws_dimensions:
46 | - StreamName
47 | aws_metric_name: IncomingRecords
48 | aws_namespace: AWS/Kinesis
49 | aws_statistics:
50 | - Sum
51 | - aws_dimensions:
52 | - StreamName
53 | aws_metric_name: IncomingBytes
54 | aws_namespace: AWS/Kinesis
55 | aws_statistics:
56 | - Sum
57 | - aws_dimensions:
58 | - StreamName
59 | aws_metric_name: WriteProvisionedThroughputExceeded
60 | aws_namespace: AWS/Kinesis
61 | aws_statistics:
62 | - Average
63 | - aws_dimensions:
64 | - StreamName
65 | aws_metric_name: ReadProvisionedThroughputExceeded
66 | aws_namespace: AWS/Kinesis
67 | aws_statistics:
68 | - Average
69 |
--------------------------------------------------------------------------------
/examples/Lambda.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - FunctionName
5 | - Resource
6 | aws_metric_name: Invocations
7 | aws_namespace: AWS/Lambda
8 | aws_statistics:
9 | - Sum
10 | - aws_dimensions:
11 | - FunctionName
12 | - Resource
13 | aws_metric_name: Errors
14 | aws_namespace: AWS/Lambda
15 | aws_statistics:
16 | - Sum
17 | - aws_dimensions:
18 | - FunctionName
19 | - Resource
20 | aws_metric_name: Duration
21 | aws_namespace: AWS/Lambda
22 | aws_statistics:
23 | - Average
24 | - aws_dimensions:
25 | - FunctionName
26 | - Resource
27 | aws_metric_name: Duration
28 | aws_namespace: AWS/Lambda
29 | aws_statistics:
30 | - Maximum
31 | - aws_dimensions:
32 | - FunctionName
33 | - Resource
34 | aws_metric_name: Duration
35 | aws_namespace: AWS/Lambda
36 | aws_statistics:
37 | - Minimum
38 | - aws_dimensions:
39 | - FunctionName
40 | - Resource
41 | aws_metric_name: Throttles
42 | aws_namespace: AWS/Lambda
43 | aws_statistics:
44 | - Sum
45 | - aws_dimensions:
46 | - FunctionName
47 | - Resource
48 | aws_metric_name: ConcurrentExecutions
49 | aws_namespace: AWS/Lambda
50 | aws_statistics:
51 | - Sum
52 | - aws_dimensions:
53 | - FunctionName
54 | - Resource
55 | aws_metric_name: UnreservedConcurrentExecutions
56 | aws_namespace: AWS/Lambda
57 | aws_statistics:
58 | - Sum
59 |
--------------------------------------------------------------------------------
/examples/NATGateway.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - NatGatewayId
5 | aws_metric_name: ActiveConnectionCount
6 | aws_namespace: AWS/NATGateway
7 | aws_statistics:
8 | - Max
9 | - aws_dimensions:
10 | - NatGatewayId
11 | aws_metric_name: BytesInFromDestination
12 | aws_namespace: AWS/NATGateway
13 | aws_statistics:
14 | - Sum
15 | - aws_dimensions:
16 | - NatGatewayId
17 | aws_metric_name: BytesInFromSource
18 | aws_namespace: AWS/NATGateway
19 | aws_statistics:
20 | - Sum
21 | - aws_dimensions:
22 | - NatGatewayId
23 | aws_metric_name: BytesOutToDestination
24 | aws_namespace: AWS/NATGateway
25 | aws_statistics:
26 | - Sum
27 | - aws_dimensions:
28 | - NatGatewayId
29 | aws_metric_name: BytesOutToSource
30 | aws_namespace: AWS/NATGateway
31 | aws_statistics:
32 | - Sum
33 | - aws_dimensions:
34 | - NatGatewayId
35 | aws_metric_name: ConnectionAttemptCount
36 | aws_namespace: AWS/NATGateway
37 | aws_statistics:
38 | - Sum
39 | - aws_dimensions:
40 | - NatGatewayId
41 | aws_metric_name: ConnectionEstablishedCount
42 | aws_namespace: AWS/NATGateway
43 | aws_statistics:
44 | - Sum
45 | - aws_dimensions:
46 | - NatGatewayId
47 | aws_metric_name: IdleTimeoutCount
48 | aws_namespace: AWS/NATGateway
49 | aws_statistics:
50 | - Sum
51 | - aws_dimensions:
52 | - NatGatewayId
53 | aws_metric_name: PacketsDropCount
54 | aws_namespace: AWS/NATGateway
55 | aws_statistics:
56 | - Sum
57 | - aws_dimensions:
58 | - NatGatewayId
59 | aws_metric_name: PacketsInFromDestination
60 | aws_namespace: AWS/NATGateway
61 | aws_statistics:
62 | - Sum
63 | - aws_dimensions:
64 | - NatGatewayId
65 | aws_metric_name: PacketsInFromSource
66 | aws_namespace: AWS/NATGateway
67 | aws_statistics:
68 | - Sum
69 | - aws_dimensions:
70 | - NatGatewayId
71 | aws_metric_name: PacketsOutToDestination
72 | aws_namespace: AWS/NATGateway
73 | aws_statistics:
74 | - Sum
75 | - aws_dimensions:
76 | - NatGatewayId
77 | aws_metric_name: PacketsOutToSource
78 | aws_namespace: AWS/NATGateway
79 | aws_statistics:
80 | - Sum
81 |
--------------------------------------------------------------------------------
/examples/NetworkELB.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - AvailabilityZone
5 | - LoadBalancer
6 | - TargetGroup
7 | aws_metric_name: ActiveFlowCount
8 | aws_namespace: AWS/NetworkELB
9 | aws_statistics:
10 | - Average
11 | - aws_dimensions:
12 | - AvailabilityZone
13 | - LoadBalancer
14 | - TargetGroup
15 | aws_metric_name: ActiveFlowCount_TCP
16 | aws_namespace: AWS/NetworkELB
17 | aws_statistics:
18 | - Average
19 | - aws_dimensions:
20 | - AvailabilityZone
21 | - LoadBalancer
22 | - TargetGroup
23 | aws_metric_name: ActiveFlowCount_UDP
24 | aws_namespace: AWS/NetworkELB
25 | aws_statistics:
26 | - Average
27 | - aws_dimensions:
28 | - AvailabilityZone
29 | - LoadBalancer
30 | - TargetGroup
31 | aws_metric_name: ClientTLSNegotiationErrorCount
32 | aws_namespace: AWS/NetworkELB
33 | aws_statistics:
34 | - Sum
35 | - aws_dimensions:
36 | - LoadBalancer
37 | aws_metric_name: ConsumedLCUs
38 | aws_namespace: AWS/NetworkELB
39 | aws_statistics:
40 | - Average
41 | - aws_dimensions:
42 | - LoadBalancer
43 | aws_metric_name: ConsumedLCUs_TCP
44 | aws_namespace: AWS/NetworkELB
45 | aws_statistics:
46 | - Average
47 | - aws_dimensions:
48 | - LoadBalancer
49 | aws_metric_name: ConsumedLCUs_TLS
50 | aws_namespace: AWS/NetworkELB
51 | aws_statistics:
52 | - Average
53 | - aws_dimensions:
54 | - LoadBalancer
55 | aws_metric_name: ConsumedLCUs_UDP
56 | aws_namespace: AWS/NetworkELB
57 | aws_statistics:
58 | - Average
59 | - aws_dimensions:
60 | - AvailabilityZone
61 | - LoadBalancer
62 | - TargetGroup
63 | aws_metric_name: HealthyHostCount
64 | aws_namespace: AWS/NetworkELB
65 | aws_statistics:
66 | - Minimum
67 | - aws_dimensions:
68 | - AvailabilityZone
69 | - LoadBalancer
70 | - TargetGroup
71 | aws_metric_name: NewFlowCount
72 | aws_namespace: AWS/NetworkELB
73 | aws_statistics:
74 | - Sum
75 | - aws_dimensions:
76 | - AvailabilityZone
77 | - LoadBalancer
78 | - TargetGroup
79 | aws_metric_name: NewFlowCount_TCP
80 | aws_namespace: AWS/NetworkELB
81 | aws_statistics:
82 | - Sum
83 | - aws_dimensions:
84 | - AvailabilityZone
85 | - LoadBalancer
86 | - TargetGroup
87 | aws_metric_name: NewFlowCount_TLS
88 | aws_namespace: AWS/NetworkELB
89 | aws_statistics:
90 | - Sum
91 | - aws_dimensions:
92 | - AvailabilityZone
93 | - LoadBalancer
94 | - TargetGroup
95 | aws_metric_name: NewFlowCount_UDP
96 | aws_namespace: AWS/NetworkELB
97 | aws_statistics:
98 | - Sum
99 | - aws_dimensions:
100 | - AvailabilityZone
101 | - LoadBalancer
102 | - TargetGroup
103 | aws_metric_name: ProcessedBytes
104 | aws_namespace: AWS/NetworkELB
105 | aws_statistics:
106 | - Sum
107 | - aws_dimensions:
108 | - AvailabilityZone
109 | - LoadBalancer
110 | - TargetGroup
111 | aws_metric_name: ProcessedBytes_TLS
112 | aws_namespace: AWS/NetworkELB
113 | aws_statistics:
114 | - Sum
115 | - aws_dimensions:
116 | - AvailabilityZone
117 | - LoadBalancer
118 | - TargetGroup
119 | aws_metric_name: ProcessedBytes_UDP
120 | aws_namespace: AWS/NetworkELB
121 | aws_statistics:
122 | - Sum
123 | - aws_dimensions:
124 | - AvailabilityZone
125 | - LoadBalancer
126 | - TargetGroup
127 | aws_metric_name: ProcessedPackets
128 | aws_namespace: AWS/NetworkELB
129 | aws_statistics:
130 | - Sum
131 | - aws_dimensions:
132 | - AvailabilityZone
133 | - LoadBalancer
134 | - TargetGroup
135 | aws_metric_name: TargetTLSNegotiationErrorCount
136 | aws_namespace: AWS/NetworkELB
137 | aws_statistics:
138 | - Sum
139 | - aws_dimensions:
140 | - AvailabilityZone
141 | - LoadBalancer
142 | - TargetGroup
143 | aws_metric_name: TCP_Client_Reset_Count
144 | aws_namespace: AWS/NetworkELB
145 | aws_statistics:
146 | - Sum
147 | - aws_dimensions:
148 | - AvailabilityZone
149 | - LoadBalancer
150 | - TargetGroup
151 | aws_metric_name: TCP_Target_Reset_Count
152 | aws_namespace: AWS/NetworkELB
153 | aws_statistics:
154 | - Sum
155 | - aws_dimensions:
156 | - AvailabilityZone
157 | - LoadBalancer
158 | - TargetGroup
159 | aws_metric_name: UnHealthyHostCount
160 | aws_namespace: AWS/NetworkELB
161 | aws_statistics:
162 | - Maximum
163 |
164 |
--------------------------------------------------------------------------------
/examples/RDS.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - DBInstanceIdentifier
5 | aws_metric_name: DatabaseConnections
6 | aws_namespace: AWS/RDS
7 | aws_statistics:
8 | - Maximum
9 | - aws_dimensions:
10 | - DBInstanceIdentifier
11 | aws_metric_name: FreeStorageSpace
12 | aws_namespace: AWS/RDS
13 | aws_statistics:
14 | - Average
15 | - aws_dimensions:
16 | - DBInstanceIdentifier
17 | aws_metric_name: FreeableMemory
18 | aws_namespace: AWS/RDS
19 | aws_statistics:
20 | - Average
21 | - aws_dimensions:
22 | - DBInstanceIdentifier
23 | aws_metric_name: CPUUtilization
24 | aws_namespace: AWS/RDS
25 | aws_statistics:
26 | - Average
27 | - aws_dimensions:
28 | - DBInstanceIdentifier
29 | aws_metric_name: ReadIOPS
30 | aws_namespace: AWS/RDS
31 | aws_statistics:
32 | - Sum
33 | - aws_dimensions:
34 | - DBInstanceIdentifier
35 | aws_metric_name: WriteIOPS
36 | aws_namespace: AWS/RDS
37 | aws_statistics:
38 | - Sum
39 | - aws_dimensions:
40 | - DBInstanceIdentifier
41 | aws_metric_name: ReadLatency
42 | aws_namespace: AWS/RDS
43 | aws_statistics:
44 | - Average
45 | - aws_dimensions:
46 | - DBInstanceIdentifier
47 | aws_metric_name: WriteLatency
48 | aws_namespace: AWS/RDS
49 | aws_statistics:
50 | - Average
51 | - aws_dimensions:
52 | - DBInstanceIdentifier
53 | aws_metric_name: ReadThroughput
54 | aws_namespace: AWS/RDS
55 | aws_statistics:
56 | - Average
57 | - aws_dimensions:
58 | - DBInstanceIdentifier
59 | aws_metric_name: WriteThroughput
60 | aws_namespace: AWS/RDS
61 | aws_statistics:
62 | - Average
63 | - aws_dimensions:
64 | - DBInstanceIdentifier
65 | aws_metric_name: CPUCreditUsage
66 | aws_namespace: AWS/RDS
67 | aws_statistics:
68 | - Average
69 | - aws_dimensions:
70 | - DBInstanceIdentifier
71 | aws_metric_name: CPUCreditBalance
72 | aws_namespace: AWS/RDS
73 | aws_statistics:
74 | - Average
75 | - aws_dimensions:
76 | - DBInstanceIdentifier
77 | aws_metric_name: DiskQueueDepth
78 | aws_namespace: AWS/RDS
79 | aws_statistics:
80 | - Average
81 | - aws_dimensions:
82 | - DBInstanceIdentifier
83 | aws_metric_name: NetworkTransmitThroughput
84 | aws_namespace: AWS/RDS
85 | aws_statistics:
86 | - Average
87 | - aws_dimensions:
88 | - DBInstanceIdentifier
89 | aws_metric_name: NetworkReceiveThroughput
90 | aws_namespace: AWS/RDS
91 | aws_statistics:
92 | - Average
93 | - aws_dimensions:
94 | - DBInstanceIdentifier
95 | aws_metric_name: TransactionLogsDiskUsage
96 | aws_namespace: AWS/RDS
97 | aws_statistics:
98 | - Average
99 |
--------------------------------------------------------------------------------
/examples/Redshift.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - ClusterIdentifier
5 | aws_metric_name: HealthStatus
6 | aws_namespace: AWS/Redshift
7 | aws_statistics:
8 | - Average
9 | - aws_dimensions:
10 | - ClusterIdentifier
11 | aws_metric_name: CPUUtilization
12 | aws_namespace: AWS/Redshift
13 | aws_statistics:
14 | - Average
15 | - aws_dimensions:
16 | - ClusterIdentifier
17 | aws_metric_name: DatabaseConnections
18 | aws_namespace: AWS/Redshift
19 | aws_statistics:
20 | - Average
21 | - aws_dimensions:
22 | - ClusterIdentifier
23 | aws_metric_name: MaintenanceMode
24 | aws_namespace: AWS/Redshift
25 | aws_statistics:
26 | - Average
27 | - aws_dimensions:
28 | - ClusterIdentifier
29 | aws_metric_name: NetworkReceiveThroughput$AVG
30 | aws_namespace: AWS/Redshift
31 | - aws_dimensions:
32 | - ClusterIdentifier
33 | aws_metric_name: NetworkTransmitThroughput
34 | aws_namespace: AWS/Redshift
35 | aws_statistics:
36 | - Average
37 | - aws_dimensions:
38 | - ClusterIdentifier
39 | aws_metric_name: ReadIOPS
40 | aws_namespace: AWS/Redshift
41 | aws_statistics:
42 | - Maximum
43 | - aws_dimensions:
44 | - ClusterIdentifier
45 | aws_metric_name: WriteIOPS
46 | aws_namespace: AWS/Redshift
47 | aws_statistics:
48 | - Maximum
49 | - aws_dimensions:
50 | - ClusterIdentifier
51 | aws_metric_name: ReadLatency
52 | aws_namespace: AWS/Redshift
53 | aws_statistics:
54 | - Maximum
55 | - aws_dimensions:
56 | - ClusterIdentifier
57 | aws_metric_name: WriteLatency
58 | aws_namespace: AWS/Redshift
59 | aws_statistics:
60 | - Maximum
61 | - aws_dimensions:
62 | - ClusterIdentifier
63 | aws_metric_name: ReadThroughput
64 | aws_namespace: AWS/Redshift
65 | aws_statistics:
66 | - Average
67 | - aws_dimensions:
68 | - ClusterIdentifier
69 | aws_metric_name: WriteThroughput
70 | aws_namespace: AWS/Redshift
71 | aws_statistics:
72 | - Average
73 | - aws_dimensions:
74 | - ClusterIdentifier
75 | aws_metric_name: QueryDuration
76 | aws_namespace: AWS/Redshift
77 | aws_statistics:
78 | - Average
79 | - aws_dimensions:
80 | - ClusterIdentifier
81 | aws_metric_name: QueriesCompletedPerSecond
82 | aws_namespace: AWS/Redshift
83 | aws_statistics:
84 | - Average
85 |
--------------------------------------------------------------------------------
/examples/Route53.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - HealthCheckId
5 | aws_metric_name: TimeToFirstByte
6 | aws_namespace: AWS/Route53
7 | aws_statistics:
8 | - Average
9 | - aws_dimensions:
10 | - HealthCheckId
11 | aws_metric_name: HealthCheckPercentageHealthy
12 | aws_namespace: AWS/Route53
13 | aws_statistics:
14 | - Average
15 | - aws_dimensions:
16 | - HealthCheckId
17 | aws_metric_name: HealthCheckStatus
18 | aws_namespace: AWS/Route53
19 | aws_statistics:
20 | - Minimum
21 | - aws_dimensions:
22 | - HealthCheckId
23 | aws_metric_name: ChildHealthCheckHealthyCount
24 | aws_namespace: AWS/Route53
25 | aws_statistics:
26 | - Average
27 | - aws_dimensions:
28 | - HealthCheckId
29 | aws_metric_name: ConnectionTime
30 | aws_namespace: AWS/Route53
31 | aws_statistics:
32 | - Average
33 | - aws_dimensions:
34 | - HealthCheckId
35 | aws_metric_name: SSLHandshakeTime
36 | aws_namespace: AWS/Route53
37 | aws_statistics:
38 | - Average
39 |
--------------------------------------------------------------------------------
/examples/S3.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - BucketName
5 | - FilterId
6 | aws_metric_name: 4xxErrors
7 | aws_namespace: AWS/S3
8 | aws_statistics:
9 | - Sum
10 | - aws_dimensions:
11 | - BucketName
12 | - FilterId
13 | aws_metric_name: 5xxErrors
14 | aws_namespace: AWS/S3
15 | aws_statistics:
16 | - Sum
17 | - aws_dimensions:
18 | - BucketName
19 | - FilterId
20 | aws_metric_name: AllRequests
21 | aws_namespace: AWS/S3
22 | aws_statistics:
23 | - Sum
24 | - aws_dimensions:
25 | - BucketName
26 | - FilterId
27 | aws_metric_name: FirstByteLatency
28 | aws_namespace: AWS/S3
29 | aws_statistics:
30 | - Average
31 | - aws_dimensions:
32 | - BucketName
33 | - FilterId
34 | aws_metric_name: TotalRequestLatency
35 | aws_namespace: AWS/S3
36 | aws_statistics:
37 | - Average
38 | - aws_dimensions:
39 | - BucketName
40 | - FilterId
41 | aws_metric_name: BytesDownloaded
42 | aws_namespace: AWS/S3
43 | aws_statistics:
44 | - Sum
45 | - Average
46 | - aws_dimensions:
47 | - BucketName
48 | - FilterId
49 | aws_metric_name: BytesUploaded
50 | aws_namespace: AWS/S3
51 | aws_statistics:
52 | - Sum
53 | - Average
54 | - aws_dimensions:
55 | - BucketName
56 | - FilterId
57 | aws_metric_name: PutRequests
58 | aws_namespace: AWS/S3
59 | aws_statistics:
60 | - Sum
61 | - aws_dimensions:
62 | - BucketName
63 | - FilterId
64 | aws_metric_name: ListRequests
65 | aws_namespace: AWS/S3
66 | aws_statistics:
67 | - Sum
68 | - aws_dimensions:
69 | - BucketName
70 | - FilterId
71 | aws_metric_name: HeadRequests
72 | aws_namespace: AWS/S3
73 | aws_statistics:
74 | - Sum
75 | - aws_dimensions:
76 | - BucketName
77 | - FilterId
78 | aws_metric_name: GetRequests
79 | aws_namespace: AWS/S3
80 | aws_statistics:
81 | - Sum
82 | - aws_namespace: AWS/S3
83 | aws_metric_name: BucketSizeBytes
84 | aws_dimensions: [BucketName, StorageType]
85 | aws_statistics: [Average]
86 | range_seconds: 172800
87 | period_seconds: 86400
88 | set_timestamp: false
89 | - aws_namespace: AWS/S3
90 | aws_metric_name: NumberOfObjects
91 | aws_dimensions: [BucketName, StorageType]
92 | aws_statistics: [Average]
93 | range_seconds: 172800
94 | period_seconds: 86400
95 | set_timestamp: false
96 | # In case you want to use some bucket level Tag to select buckets to monitor,
97 | # or to have additional `info` metric with all bucket Tags as labels, use `aws_tag_select`:
98 | aws_tag_select:
99 | tag_selections:
100 | Monitoring: ["enabled"]
101 | resource_type_selection: "s3:"
102 | resource_id_dimension: BucketName
--------------------------------------------------------------------------------
/examples/SES.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_namespace: AWS/SES
4 | aws_metric_name: Send
5 | - aws_namespace: AWS/SES
6 | aws_metric_name: Delivery
7 | - aws_namespace: AWS/SES
8 | aws_metric_name: Bounce
9 | - aws_namespace: AWS/SES
10 | aws_metric_name: Complaint
11 | - aws_namespace: AWS/SES
12 | aws_metric_name: Reputation.BounceRate
13 | - aws_namespace: AWS/SES
14 | aws_metric_name: Reputation.ComplaintRate
15 |
--------------------------------------------------------------------------------
/examples/SNS.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - TopicName
5 | aws_metric_name: NumberOfMessagesPublished
6 | aws_namespace: AWS/SNS
7 | aws_statistics:
8 | - Sum
9 | - aws_dimensions:
10 | - TopicName
11 | aws_metric_name: NumberOfNotificationsDelivered
12 | aws_namespace: AWS/SNS
13 | aws_statistics:
14 | - Sum
15 | - aws_dimensions:
16 | - TopicName
17 | aws_metric_name: NumberOfNotificationsFailed
18 | aws_namespace: AWS/SNS
19 | aws_statistics:
20 | - Sum
21 | - aws_dimensions:
22 | - TopicName
23 | aws_metric_name: PublishSize
24 | aws_namespace: AWS/SNS
25 | aws_statistics:
26 | - Average
27 | - aws_dimensions:
28 | - TopicName
29 | aws_metric_name: NumberOfNotificationsFilteredOut
30 | aws_namespace: AWS/SNS
31 | aws_statistics:
32 | - Sum
33 | - aws_dimensions:
34 | - TopicName
35 | aws_metric_name: NumberOfNotificationsFilteredOut-InvalidAttributes
36 | aws_namespace: AWS/SNS
37 | aws_statistics:
38 | - Sum
39 | - aws_dimensions:
40 | - TopicName
41 | aws_metric_name: NumberOfNotificationsFilteredOut-NoMessageAttributes
42 | aws_namespace: AWS/SNS
43 | aws_statistics:
44 | - Sum
45 |
--------------------------------------------------------------------------------
/examples/SQS.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - QueueName
5 | aws_metric_name: NumberOfMessagesSent
6 | aws_namespace: AWS/SQS
7 | aws_statistics:
8 | - Average
9 | - aws_dimensions:
10 | - QueueName
11 | aws_metric_name: NumberOfMessagesReceived
12 | aws_namespace: AWS/SQS
13 | aws_statistics:
14 | - Average
15 | - aws_dimensions:
16 | - QueueName
17 | aws_metric_name: NumberOfEmptyReceives
18 | aws_namespace: AWS/SQS
19 | aws_statistics:
20 | - Average
21 | - aws_dimensions:
22 | - QueueName
23 | aws_metric_name: NumberOfMessagesDeleted
24 | aws_namespace: AWS/SQS
25 | aws_statistics:
26 | - Average
27 | - aws_dimensions:
28 | - QueueName
29 | aws_metric_name: ApproximateNumberOfMessagesDelayed
30 | aws_namespace: AWS/SQS
31 | aws_statistics:
32 | - Average
33 | - aws_dimensions:
34 | - QueueName
35 | aws_metric_name: ApproximateAgeOfOldestMessage
36 | aws_namespace: AWS/SQS
37 | aws_statistics:
38 | - Average
39 | - aws_dimensions:
40 | - QueueName
41 | aws_metric_name: ApproximateNumberOfMessagesNotVisible
42 | aws_namespace: AWS/SQS
43 | aws_statistics:
44 | - Average
45 | - aws_dimensions:
46 | - QueueName
47 | aws_metric_name: ApproximateNumberOfMessagesVisible
48 | aws_namespace: AWS/SQS
49 | aws_statistics:
50 | - Average
51 |
--------------------------------------------------------------------------------
/examples/Sagemaker.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - EndpointName
5 | - VariantName
6 | aws_metric_name: Invocation4XXErrors
7 | aws_namespace: AWS/SageMaker
8 | aws_statistics:
9 | - Sum
10 | - aws_dimensions:
11 | - EndpointName
12 | - VariantName
13 | aws_metric_name: Invocation5XXErrors
14 | aws_namespace: AWS/SageMaker
15 | aws_statistics:
16 | - Sum
17 | - aws_dimensions:
18 | - EndpointName
19 | - VariantName
20 | aws_metric_name: Invocations
21 | aws_namespace: AWS/SageMaker
22 | aws_statistics:
23 | - Sum
24 | - aws_dimensions:
25 | - EndpointName
26 | - VariantName
27 | aws_metric_name: InvocationsPerInstance
28 | aws_namespace: AWS/SageMaker
29 | aws_statistics:
30 | - Sum
31 | - aws_dimensions:
32 | - EndpointName
33 | - VariantName
34 | aws_metric_name: ModelLatency
35 | aws_namespace: AWS/SageMaker
36 | aws_statistics:
37 | - Average
38 | - aws_dimensions:
39 | - EndpointName
40 | - VariantName
41 | aws_metric_name: OverheadLatency
42 | aws_namespace: AWS/SageMaker
43 | aws_statistics:
44 | - Average
45 | - aws_dimensions:
46 | - EndpointName
47 | - VariantName
48 | aws_metric_name: OverallLatency
49 | aws_namespace: AWS/SageMaker
50 | aws_statistics:
51 | - Average
52 |
--------------------------------------------------------------------------------
/examples/VPN.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - VpnId
5 | - TunnelIpAddress
6 | aws_metric_name: TunnelState
7 | aws_namespace: AWS/VPN
8 | aws_statistics:
9 | - Average
10 | - aws_dimensions:
11 | - VpnId
12 | - TunnelIpAddress
13 | aws_metric_name: TunnelDataIn
14 | aws_namespace: AWS/VPN
15 | aws_statistics:
16 | - Sum
17 | - aws_dimensions:
18 | - VpnId
19 | - TunnelIpAddress
20 | aws_metric_name: TunnelDataOut
21 | aws_namespace: AWS/VPN
22 | aws_statistics:
23 | - Sum
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/examples/WAF.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - Region
5 | - Rule
6 | - RuleGroup
7 | - WebACL
8 | aws_metric_name: AllowedRequests
9 | aws_namespace: AWS/WAF
10 | aws_statistics:
11 | - Sum
12 | - aws_dimensions:
13 | - Region
14 | - Rule
15 | - RuleGroup
16 | - WebACL
17 | aws_metric_name: BlockedRequests
18 | aws_namespace: AWS/WAF
19 | aws_statistics:
20 | - Sum
21 | - aws_dimensions:
22 | - Region
23 | - Rule
24 | - RuleGroup
25 | - WebACL
26 | aws_metric_name: CountedRequests
27 | aws_namespace: AWS/WAF
28 | aws_statistics:
29 | - Sum
30 | - aws_dimensions:
31 | - Region
32 | - Rule
33 | - RuleGroup
34 | - WebACL
35 | aws_metric_name: PassedRequests
36 | aws_namespace: AWS/WAF
37 | aws_statistics:
38 | - Sum
39 | - aws_dimensions:
40 | - Region
41 | - RuleGroup
42 | - WebACL
43 | - LabelNamespace
44 | - Label
45 | aws_metric_name: AllowedRequests
46 | aws_namespace: AWS/WAF
47 | aws_statistics:
48 | - Sum
49 | - aws_dimensions:
50 | - Region
51 | - RuleGroup
52 | - WebACL
53 | - LabelNamespace
54 | - Label
55 | aws_metric_name: BlockedRequests
56 | aws_namespace: AWS/WAF
57 | aws_statistics:
58 | - Sum
59 | - aws_dimensions:
60 | - Region
61 | - RuleGroup
62 | - WebACL
63 | - LabelNamespace
64 | - Label
65 | aws_metric_name: CountedRequests
66 | aws_namespace: AWS/WAF
67 | aws_statistics:
68 | - Sum
69 | - aws_dimensions:
70 | - Region
71 | - BotCategory
72 | - WebACL
73 | aws_metric_name: SampleAllowedRequests
74 | aws_namespace: AWS/WAF
75 | aws_statistics:
76 | - Sum
77 | - aws_dimensions:
78 | - Region
79 | - BotCategory
80 | - WebACL
81 | aws_metric_name: SampleBlockedRequests
82 | aws_namespace: AWS/WAF
83 | aws_statistics:
84 | - Sum
85 | - aws_dimensions:
86 | aws_metric_name: DDoSDetected
87 | aws_namespace: AWS/WAF
88 | aws_statistics:
89 | - Sum
90 | - aws_dimensions:
91 | - ACKFlood
92 | - ChargenReflection
93 | - DNSReflection
94 | - GenericUDPReflection
95 | - MemcachedReflection
96 | - MSSQLReflection
97 | - NetBIOSReflection
98 | - NTPReflection
99 | - PortMapper
100 | - RequestFlood
101 | - RIPReflection
102 | - SNMPReflection
103 | - SSDPReflection
104 | - SYNFlood
105 | - UDPFragment
106 | - UDPTraffic
107 | - UDPReflection
108 | aws_metric_name: DDoSAttackBitsPerSecond
109 | aws_namespace: AWS/WAF
110 | aws_statistics:
111 | - Sum
112 | - aws_dimensions:
113 | - ACKFlood
114 | - ChargenReflection
115 | - DNSReflection
116 | - GenericUDPReflection
117 | - MemcachedReflection
118 | - MSSQLReflection
119 | - NetBIOSReflection
120 | - NTPReflection
121 | - PortMapper
122 | - RequestFlood
123 | - RIPReflection
124 | - SNMPReflection
125 | - SSDPReflection
126 | - SYNFlood
127 | - UDPFragment
128 | - UDPTraffic
129 | - UDPReflection
130 | aws_metric_name: DDoSAttackPacketsPerSecond
131 | aws_namespace: AWS/WAF
132 | aws_statistics:
133 | - Sum
134 | - aws_dimensions:
135 | - ACKFlood
136 | - ChargenReflection
137 | - DNSReflection
138 | - GenericUDPReflection
139 | - MemcachedReflection
140 | - MSSQLReflection
141 | - NetBIOSReflection
142 | - NTPReflection
143 | - PortMapper
144 | - RequestFlood
145 | - RIPReflection
146 | - SNMPReflection
147 | - SSDPReflection
148 | - SYNFlood
149 | - UDPFragment
150 | - UDPTraffic
151 | - UDPReflection
152 | aws_metric_name: DDoSAttackRequestsPerSecond
153 | aws_namespace: AWS/WAF
154 | aws_statistics:
155 | - Sum
156 | - aws_dimensions:
157 | - ResourceArn
158 | - MitigationAction
159 | aws_metric_name: VolumePacketsPerSecond
160 | aws_namespace: AWS/WAF
161 | aws_statistics:
162 | - Sum
163 | - aws_dimensions:
164 | - ResourceArn
165 | - Protocol
166 | - SourceIp
167 | aws_metric_name: VolumePacketsPerSecond
168 | aws_namespace: AWS/WAF
169 | aws_statistics:
170 | - Sum
171 | - aws_dimensions:
172 | - ResourceArn
173 | - Protocol
174 | - SourceIp
175 | aws_metric_name: VolumeBitsPerSecond
176 | aws_namespace: AWS/WAF
177 | aws_statistics:
178 | - Sum
179 |
--------------------------------------------------------------------------------
/examples/WAFV2.yml:
--------------------------------------------------------------------------------
1 | region: us-east-1
2 | metrics:
3 | - aws_dimensions:
4 | - Region
5 | - Rule
6 | - RuleGroup
7 | - WebACL
8 | aws_metric_name: AllowedRequests
9 | aws_namespace: AWS/WAFV2
10 | aws_statistics:
11 | - Sum
12 | # In case you want to use some tag to select web acls to monitor, or to have additional `info` metric
13 | # with all web acl tags as labels, use `aws_tag_select`.
14 | # Since the WebACL dimension doesn't follow the convention for how to extract resource ids from ARN
15 | # `arn_resource_id_regexp` is specified with an alternative regular expression.
16 | aws_tag_select:
17 | resource_type_selection: wafv2:regional/webacl
18 | resource_id_dimension: WebACL
19 | arn_resource_id_regexp: "([^/]+)/[^/]+$"
20 | tag_selections:
21 | Environment:
22 | - production
23 | - aws_dimensions:
24 | - Region
25 | - Rule
26 | - RuleGroup
27 | - WebACL
28 | aws_metric_name: BlockedRequests
29 | aws_namespace: AWS/WAFV2
30 | aws_statistics:
31 | - Sum
32 | - aws_dimensions:
33 | - Region
34 | - Rule
35 | - RuleGroup
36 | - WebACL
37 | aws_metric_name: CountedRequests
38 | aws_namespace: AWS/WAFV2
39 | aws_statistics:
40 | - Sum
41 | - aws_dimensions:
42 | - Region
43 | - Rule
44 | - RuleGroup
45 | - WebACL
46 | aws_metric_name: PassedRequests
47 | aws_namespace: AWS/WAFV2
48 | aws_statistics:
49 | - Sum
50 | - aws_dimensions:
51 | - Region
52 | - RuleGroup
53 | - WebACL
54 | - LabelNamespace
55 | - Label
56 | aws_metric_name: AllowedRequests
57 | aws_namespace: AWS/WAFV2
58 | aws_statistics:
59 | - Sum
60 | - aws_dimensions:
61 | - Region
62 | - RuleGroup
63 | - WebACL
64 | - LabelNamespace
65 | - Label
66 | aws_metric_name: BlockedRequests
67 | aws_namespace: AWS/WAFV2
68 | aws_statistics:
69 | - Sum
70 | - aws_dimensions:
71 | - Region
72 | - RuleGroup
73 | - WebACL
74 | - LabelNamespace
75 | - Label
76 | aws_metric_name: CountedRequests
77 | aws_namespace: AWS/WAFV2
78 | aws_statistics:
79 | - Sum
80 | - aws_dimensions:
81 | - Region
82 | - BotCategory
83 | - WebACL
84 | aws_metric_name: SampleAllowedRequests
85 | aws_namespace: AWS/WAFV2
86 | aws_statistics:
87 | - Sum
88 | - aws_dimensions:
89 | - Region
90 | - BotCategory
91 | - WebACL
92 | aws_metric_name: SampleBlockedRequests
93 | aws_namespace: AWS/WAFV2
94 | aws_statistics:
95 | - Sum
96 | - aws_dimensions:
97 | aws_metric_name: DDoSDetected
98 | aws_namespace: AWS/WAFV2
99 | aws_statistics:
100 | - Sum
101 | - aws_dimensions:
102 | - ACKFlood
103 | - ChargenReflection
104 | - DNSReflection
105 | - GenericUDPReflection
106 | - MemcachedReflection
107 | - MSSQLReflection
108 | - NetBIOSReflection
109 | - NTPReflection
110 | - PortMapper
111 | - RequestFlood
112 | - RIPReflection
113 | - SNMPReflection
114 | - SSDPReflection
115 | - SYNFlood
116 | - UDPFragment
117 | - UDPTraffic
118 | - UDPReflection
119 | aws_metric_name: DDoSAttackBitsPerSecond
120 | aws_namespace: AWS/WAFV2
121 | aws_statistics:
122 | - Sum
123 | - aws_dimensions:
124 | - ACKFlood
125 | - ChargenReflection
126 | - DNSReflection
127 | - GenericUDPReflection
128 | - MemcachedReflection
129 | - MSSQLReflection
130 | - NetBIOSReflection
131 | - NTPReflection
132 | - PortMapper
133 | - RequestFlood
134 | - RIPReflection
135 | - SNMPReflection
136 | - SSDPReflection
137 | - SYNFlood
138 | - UDPFragment
139 | - UDPTraffic
140 | - UDPReflection
141 | aws_metric_name: DDoSAttackPacketsPerSecond
142 | aws_namespace: AWS/WAFV2
143 | aws_statistics:
144 | - Sum
145 | - aws_dimensions:
146 | - ACKFlood
147 | - ChargenReflection
148 | - DNSReflection
149 | - GenericUDPReflection
150 | - MemcachedReflection
151 | - MSSQLReflection
152 | - NetBIOSReflection
153 | - NTPReflection
154 | - PortMapper
155 | - RequestFlood
156 | - RIPReflection
157 | - SNMPReflection
158 | - SSDPReflection
159 | - SYNFlood
160 | - UDPFragment
161 | - UDPTraffic
162 | - UDPReflection
163 | aws_metric_name: DDoSAttackRequestsPerSecond
164 | aws_namespace: AWS/WAFV2
165 | aws_statistics:
166 | - Sum
167 | - aws_dimensions:
168 | - ResourceArn
169 | - MitigationAction
170 | aws_metric_name: VolumePacketsPerSecond
171 | aws_namespace: AWS/WAFV2
172 | aws_statistics:
173 | - Sum
174 | - aws_dimensions:
175 | - ResourceArn
176 | - Protocol
177 | - SourceIp
178 | aws_metric_name: VolumePacketsPerSecond
179 | aws_namespace: AWS/WAFV2
180 | aws_statistics:
181 | - Sum
182 | - aws_dimensions:
183 | - ResourceArn
184 | - Protocol
185 | - SourceIp
186 | aws_metric_name: VolumeBitsPerSecond
187 | aws_namespace: AWS/WAFV2
188 | aws_statistics:
189 | - Sum
190 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | io.prometheus.cloudwatch
5 | cloudwatch_exporter
6 | 0.16.1-SNAPSHOT
7 |
8 | An exporter for AWS CloudWatch metrics, for use with Prometheus.
9 |
10 | http://github.com/prometheus/cloudwatch_exporter
11 |
12 |
13 | org.sonatype.oss
14 | oss-parent
15 | 7
16 |
17 |
18 |
19 |
20 | ossrh
21 | https://oss.sonatype.org/content/repositories/snapshots
22 |
23 |
24 | ossrh
25 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
26 |
27 |
28 |
29 |
30 |
31 | The Apache Software License, Version 2.0
32 | http://www.apache.org/licenses/LICENSE-2.0.txt
33 | repo
34 |
35 |
36 |
37 |
38 | scm:git:git@github.com:prometheus/cloudwatch_exporter.git
39 | scm:git:git@github.com:prometheus/cloudwatch_exporter.git
40 | git@github.com:prometheus/cloudwatch_exporter.git
41 | HEAD
42 |
43 |
44 |
45 | yyyy-MM-dd
46 | UTF-8
47 | UTF-8
48 | ${maven.build.timestamp}
49 | 2.29.40
50 | 0.16.0
51 |
52 |
53 |
54 |
55 | software.amazon.awssdk
56 | cloudwatch
57 | ${software.amazon.awssdk.version}
58 |
59 |
60 | software.amazon.awssdk
61 | sts
62 | ${software.amazon.awssdk.version}
63 |
64 |
65 | software.amazon.awssdk
66 | resourcegroupstaggingapi
67 | ${software.amazon.awssdk.version}
68 |
69 |
70 | commons-codec
71 | commons-codec
72 | 1.17.1
73 |
74 |
75 | org.slf4j
76 | slf4j-jdk14
77 | 2.0.16
78 |
79 |
80 | org.yaml
81 | snakeyaml
82 | 2.3
83 |
84 |
85 | io.prometheus
86 | simpleclient
87 | ${io.prometheus.version}
88 |
89 |
90 | io.prometheus
91 | simpleclient_servlet_jakarta
92 | ${io.prometheus.version}
93 |
94 |
95 | io.prometheus
96 | simpleclient_hotspot
97 | ${io.prometheus.version}
98 |
99 |
100 | org.eclipse.jetty
101 | jetty-servlet
102 | 11.0.24
103 |
104 |
105 | com.github.ben-manes.caffeine
106 | caffeine
107 | 3.1.8
108 |
109 |
110 |
111 | junit
112 | junit
113 | 4.13.2
114 | test
115 |
116 |
117 | org.mockito
118 | mockito-core
119 | 5.14.2
120 | test
121 |
122 |
123 | org.hamcrest
124 | hamcrest
125 | 3.0
126 | test
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 | src/main/resources
135 | true
136 |
137 |
138 |
139 |
140 | org.apache.maven.plugins
141 | maven-compiler-plugin
142 | 3.13.0
143 |
144 | 11
145 |
146 |
147 |
148 |
149 | maven-assembly-plugin
150 |
151 |
152 |
153 | io.prometheus.cloudwatch.WebServer
154 |
155 |
156 |
157 | jar-with-dependencies
158 |
159 |
160 |
161 |
162 | make-assembly
163 | package
164 |
165 | single
166 |
167 |
168 |
169 |
170 |
171 | maven-release-plugin
172 | org.apache.maven.plugins
173 | 3.1.1
174 |
175 | true
176 | false
177 | release
178 | deploy
179 | v@{project.version}
180 |
181 |
182 |
183 | maven-deploy-plugin
184 | org.apache.maven.plugins
185 | 3.1.3
186 |
187 |
188 | org.apache.felix
189 | maven-bundle-plugin
190 | 6.0.0
191 | true
192 |
193 |
194 | org.apache.maven.plugins
195 | maven-surefire-plugin
196 | 3.5.2
197 |
198 | -Djdk.net.URLClassPath.disableClassPathURLCheck=true
199 |
200 |
201 |
202 | org.apache.maven.plugins
203 | maven-javadoc-plugin
204 | 3.11.2
205 |
206 | UTF-8
207 | UTF-8
208 | true
209 | 8
210 | ${java.home}/bin/javadoc
211 |
212 |
213 |
214 | generate-javadoc-site-report
215 | site
216 |
217 | javadoc
218 |
219 |
220 |
221 |
222 |
223 | com.spotify.fmt
224 | fmt-maven-plugin
225 | 2.25
226 |
227 |
228 |
229 | format
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 | release
240 |
241 |
242 |
243 | org.apache.maven.plugins
244 | maven-gpg-plugin
245 | 3.2.7
246 |
247 |
248 | sign-artifacts
249 | verify
250 |
251 | sign
252 |
253 |
254 |
255 |
256 |
257 | org.apache.maven.plugins
258 | maven-source-plugin
259 | 3.3.1
260 |
261 |
262 | attach-sources
263 |
264 | jar-no-fork
265 |
266 |
267 |
268 |
269 |
270 | org.apache.maven.plugins
271 | maven-javadoc-plugin
272 | 3.11.2
273 |
274 |
275 | attach-javadocs
276 |
277 | jar
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
--------------------------------------------------------------------------------
/src/main/java/io/prometheus/cloudwatch/BuildInfoCollector.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import io.prometheus.client.Collector;
4 | import java.io.IOException;
5 | import java.util.ArrayList;
6 | import java.util.List;
7 | import java.util.Properties;
8 | import java.util.logging.Level;
9 | import java.util.logging.Logger;
10 |
11 | public class BuildInfoCollector extends Collector {
12 | private static final Logger LOGGER = Logger.getLogger(CloudWatchCollector.class.getName());
13 |
14 | public List collect() {
15 | List mfs = new ArrayList<>();
16 | List samples;
17 | List labelNames = new ArrayList<>();
18 | List labelValues = new ArrayList<>();
19 |
20 | String buildVersion = "";
21 | String releaseDate = "";
22 | try {
23 | final Properties properties = new Properties();
24 | properties.load(
25 | CloudWatchCollector.class.getClassLoader().getResourceAsStream(".properties"));
26 | buildVersion = properties.getProperty("BuildVersion");
27 | releaseDate = properties.getProperty("ReleaseDate");
28 |
29 | } catch (IOException e) {
30 | buildVersion = "unknown";
31 | releaseDate = "unknown";
32 | LOGGER.log(Level.WARNING, "CloudWatch build info scrape failed", e);
33 | }
34 |
35 | labelNames.add("build_version");
36 | labelValues.add(buildVersion);
37 | labelNames.add("release_date");
38 | labelValues.add(releaseDate);
39 |
40 | samples = new ArrayList<>();
41 | samples.add(
42 | new MetricFamilySamples.Sample(
43 | "cloudwatch_exporter_build_info", labelNames, labelValues, 1));
44 | mfs.add(
45 | new MetricFamilySamples(
46 | "cloudwatch_exporter_build_info",
47 | Type.GAUGE,
48 | "Non-zero if build info scrape failed.",
49 | samples));
50 |
51 | return mfs;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/io/prometheus/cloudwatch/CachingDimensionSource.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import com.github.benmanes.caffeine.cache.Cache;
4 | import com.github.benmanes.caffeine.cache.Caffeine;
5 | import com.github.benmanes.caffeine.cache.Expiry;
6 | import java.time.Duration;
7 | import java.util.ArrayList;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.util.Objects;
11 | import java.util.function.Function;
12 | import java.util.stream.Collectors;
13 |
14 | final class CachingDimensionSource implements DimensionSource {
15 |
16 | private final DimensionSource delegate;
17 | private final Cache cache;
18 |
19 | /**
20 | * Create a new DimensionSource that will cache the results from another {@link DimensionSource}
21 | *
22 | * @param source
23 | * @param config - config used to configure the expiry (ttl) for entries in the cache
24 | * @return a new CachingDimensionSource
25 | */
26 | CachingDimensionSource(DimensionSource source, DimensionCacheConfig config) {
27 | this.delegate = source;
28 | this.cache =
29 | Caffeine.newBuilder()
30 | .expireAfter(new DimensionExpiry(config.defaultExpiry, config.metricConfig))
31 | .build();
32 | }
33 |
34 | @Override
35 | public DimensionData getDimensions(MetricRule rule, List tagBasedResourceIds) {
36 | DimensionData cachedDimensions =
37 | this.cache.getIfPresent(new DimensionCacheKey(rule, tagBasedResourceIds));
38 | if (cachedDimensions != null) {
39 | return cachedDimensions;
40 | }
41 | DimensionData dimensions = delegate.getDimensions(rule, tagBasedResourceIds);
42 | this.cache.put(new DimensionCacheKey(rule, tagBasedResourceIds), dimensions);
43 | return dimensions;
44 | }
45 |
46 | static class DimensionExpiry implements Expiry {
47 |
48 | private final Duration defaultExpiry;
49 | private final Map durationMap;
50 |
51 | public DimensionExpiry(Duration defaultExpiry, List expiryOverrides) {
52 | this.defaultExpiry = defaultExpiry;
53 | this.durationMap =
54 | expiryOverrides.stream()
55 | .collect(Collectors.toMap(Function.identity(), dcp -> dcp.listMetricsCacheTtl));
56 | }
57 |
58 | @Override
59 | public long expireAfterCreate(DimensionCacheKey key, DimensionData value, long currentTime) {
60 | return durationMap.getOrDefault(key.rule, this.defaultExpiry).toNanos();
61 | }
62 |
63 | @Override
64 | public long expireAfterUpdate(
65 | DimensionCacheKey key, DimensionData value, long currentTime, long currentDuration) {
66 | return currentDuration;
67 | }
68 |
69 | @Override
70 | public long expireAfterRead(
71 | DimensionCacheKey key, DimensionData value, long currentTime, long currentDuration) {
72 | return currentDuration;
73 | }
74 | }
75 |
76 | static class DimensionCacheConfig {
77 | final Duration defaultExpiry;
78 | final List metricConfig = new ArrayList<>();
79 |
80 | DimensionCacheConfig(Duration defaultExpiry) {
81 | this.defaultExpiry = defaultExpiry;
82 | }
83 |
84 | /**
85 | * Add a MetricRule to be used to configure a custom TTL using the value from {@link
86 | * MetricRule#listMetricsCacheTtl} to override the default expiry
87 | *
88 | * @param metricRule
89 | * @return this
90 | */
91 | DimensionCacheConfig addOverride(MetricRule metricRule) {
92 | this.metricConfig.add(metricRule);
93 | return this;
94 | }
95 | }
96 |
97 | static class DimensionCacheKey {
98 | private final MetricRule rule;
99 | private final List tagBasedResourceIds;
100 |
101 | DimensionCacheKey(MetricRule rule, List tagBasedResourceIds) {
102 | this.rule = rule;
103 | this.tagBasedResourceIds = tagBasedResourceIds;
104 | }
105 |
106 | @Override
107 | public boolean equals(Object o) {
108 | if (this == o) return true;
109 | if (o == null || getClass() != o.getClass()) return false;
110 |
111 | DimensionCacheKey that = (DimensionCacheKey) o;
112 |
113 | if (!Objects.equals(rule, that.rule)) return false;
114 | return Objects.equals(tagBasedResourceIds, that.tagBasedResourceIds);
115 | }
116 |
117 | @Override
118 | public int hashCode() {
119 | int result = rule != null ? rule.hashCode() : 0;
120 | result = 31 * result + (tagBasedResourceIds != null ? tagBasedResourceIds.hashCode() : 0);
121 | return result;
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/main/java/io/prometheus/cloudwatch/DataGetter.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import java.time.Instant;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 | import software.amazon.awssdk.services.cloudwatch.model.Dimension;
8 | import software.amazon.awssdk.services.cloudwatch.model.Statistic;
9 |
10 | interface DataGetter {
11 | MetricRuleData metricRuleDataFor(List dimensions);
12 |
13 | class MetricRuleData {
14 | Map statisticValues;
15 | Map extendedValues;
16 | Instant timestamp;
17 |
18 | String unit;
19 |
20 | MetricRuleData(Instant timestamp, String unit) {
21 | this.timestamp = timestamp;
22 | this.unit = unit;
23 | this.statisticValues = new HashMap<>();
24 | this.extendedValues = new HashMap<>();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/io/prometheus/cloudwatch/DefaultDimensionSource.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import io.prometheus.client.Counter;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.Map;
7 | import java.util.Set;
8 | import java.util.logging.Logger;
9 | import java.util.regex.Pattern;
10 | import software.amazon.awssdk.services.cloudwatch.CloudWatchClient;
11 | import software.amazon.awssdk.services.cloudwatch.model.Dimension;
12 | import software.amazon.awssdk.services.cloudwatch.model.DimensionFilter;
13 | import software.amazon.awssdk.services.cloudwatch.model.ListMetricsRequest;
14 | import software.amazon.awssdk.services.cloudwatch.model.ListMetricsResponse;
15 | import software.amazon.awssdk.services.cloudwatch.model.Metric;
16 |
17 | final class DefaultDimensionSource implements DimensionSource {
18 |
19 | private static final Logger LOGGER = Logger.getLogger(DefaultDimensionSource.class.getName());
20 | private final Counter cloudwatchRequests;
21 | private final CloudWatchClient cloudWatchClient;
22 |
23 | public DefaultDimensionSource(CloudWatchClient cloudWatchClient, Counter cloudwatchRequests) {
24 | this.cloudWatchClient = cloudWatchClient;
25 | this.cloudwatchRequests = cloudwatchRequests;
26 | }
27 |
28 | public DimensionData getDimensions(MetricRule rule, List tagBasedResourceIds) {
29 | if (rule.awsDimensions != null
30 | && rule.awsDimensionSelect != null
31 | && !rule.awsDimensions.isEmpty()
32 | && rule.awsDimensions.size() == rule.awsDimensionSelect.size()
33 | && rule.awsDimensionSelect.keySet().containsAll(rule.awsDimensions)
34 | && rule.awsTagSelect == null) {
35 | // The full list of dimensions is known so no need to request it from cloudwatch.
36 | return new DimensionData(permuteDimensions(rule.awsDimensions, rule.awsDimensionSelect));
37 | } else {
38 | return new DimensionData(listDimensions(rule, tagBasedResourceIds, cloudWatchClient));
39 | }
40 | }
41 |
42 | private List> permuteDimensions(
43 | List dimensions, Map> dimensionValues) {
44 | ArrayList> result = new ArrayList<>();
45 |
46 | if (dimensions.isEmpty()) {
47 | result.add(new ArrayList<>());
48 | } else {
49 | List dimensionsCopy = new ArrayList<>(dimensions);
50 | String dimensionName = dimensionsCopy.remove(dimensionsCopy.size() - 1);
51 | for (List permutation : permuteDimensions(dimensionsCopy, dimensionValues)) {
52 | for (String dimensionValue : dimensionValues.get(dimensionName)) {
53 | Dimension.Builder dimensionBuilder = Dimension.builder();
54 | dimensionBuilder.value(dimensionValue);
55 | dimensionBuilder.name(dimensionName);
56 | ArrayList permutationCopy = new ArrayList<>(permutation);
57 | permutationCopy.add(dimensionBuilder.build());
58 | result.add(permutationCopy);
59 | }
60 | }
61 | }
62 | return result;
63 | }
64 |
65 | private List> listDimensions(
66 | MetricRule rule, List tagBasedResourceIds, CloudWatchClient cloudWatchClient) {
67 | List> dimensions = new ArrayList<>();
68 | if (rule.awsDimensions == null) {
69 | dimensions.add(new ArrayList<>());
70 | return dimensions;
71 | }
72 |
73 | ListMetricsRequest.Builder requestBuilder = ListMetricsRequest.builder();
74 | requestBuilder.namespace(rule.awsNamespace);
75 | requestBuilder.metricName(rule.awsMetricName);
76 |
77 | // 10800 seconds is 3 hours, this setting causes metrics older than 3 hours to not be listed
78 | if (rule.rangeSeconds < 10800) {
79 | requestBuilder.recentlyActive("PT3H");
80 | }
81 |
82 | List dimensionFilters = new ArrayList<>();
83 | for (String dimension : rule.awsDimensions) {
84 | dimensionFilters.add(DimensionFilter.builder().name(dimension).build());
85 | }
86 | requestBuilder.dimensions(dimensionFilters);
87 |
88 | String nextToken = null;
89 | do {
90 | requestBuilder.nextToken(nextToken);
91 | ListMetricsResponse response = cloudWatchClient.listMetrics(requestBuilder.build());
92 | cloudwatchRequests.labels("listMetrics", rule.awsNamespace).inc();
93 | for (Metric metric : response.metrics()) {
94 | if (metric.dimensions().size() != dimensionFilters.size()) {
95 | // AWS returns all the metrics with dimensions beyond the ones we ask for,
96 | // so filter them out.
97 | continue;
98 | }
99 | if (useMetric(rule, tagBasedResourceIds, metric)) {
100 | dimensions.add(metric.dimensions());
101 | }
102 | }
103 | nextToken = response.nextToken();
104 | } while (nextToken != null);
105 | if (rule.warnOnEmptyListDimensions && dimensions.isEmpty()) {
106 | LOGGER.warning(
107 | String.format(
108 | "(listDimensions) ignoring metric %s:%s due to dimensions mismatch",
109 | rule.awsNamespace, rule.awsMetricName));
110 | }
111 | return dimensions;
112 | }
113 |
114 | /**
115 | * Check if a metric should be used according to `aws_dimension_select`,
116 | * `aws_dimension_select_regex` and dynamic `aws_tag_select`
117 | */
118 | private boolean useMetric(MetricRule rule, List tagBasedResourceIds, Metric metric) {
119 | if (rule.awsDimensionSelect != null && !metricsIsInAwsDimensionSelect(rule, metric)) {
120 | return false;
121 | }
122 | if (rule.awsDimensionSelectRegex != null && !metricIsInAwsDimensionSelectRegex(rule, metric)) {
123 | return false;
124 | }
125 | if (rule.awsTagSelect != null && !metricIsInAwsTagSelect(rule, tagBasedResourceIds, metric)) {
126 | return false;
127 | }
128 | return true;
129 | }
130 |
131 | /** Check if a metric is matched in `aws_dimension_select` */
132 | private boolean metricsIsInAwsDimensionSelect(MetricRule rule, Metric metric) {
133 | Set dimensionSelectKeys = rule.awsDimensionSelect.keySet();
134 | for (Dimension dimension : metric.dimensions()) {
135 | String dimensionName = dimension.name();
136 | String dimensionValue = dimension.value();
137 | if (dimensionSelectKeys.contains(dimensionName)) {
138 | List allowedDimensionValues = rule.awsDimensionSelect.get(dimensionName);
139 | if (!allowedDimensionValues.contains(dimensionValue)) {
140 | return false;
141 | }
142 | }
143 | }
144 | return true;
145 | }
146 |
147 | /** Check if a metric is matched in `aws_dimension_select_regex` */
148 | private boolean metricIsInAwsDimensionSelectRegex(MetricRule rule, Metric metric) {
149 | Set dimensionSelectRegexKeys = rule.awsDimensionSelectRegex.keySet();
150 | for (Dimension dimension : metric.dimensions()) {
151 | String dimensionName = dimension.name();
152 | String dimensionValue = dimension.value();
153 | if (dimensionSelectRegexKeys.contains(dimensionName)) {
154 | List allowedDimensionValues = rule.awsDimensionSelectRegex.get(dimensionName);
155 | if (!regexListMatch(allowedDimensionValues, dimensionValue)) {
156 | return false;
157 | }
158 | }
159 | }
160 | return true;
161 | }
162 |
163 | /** Check if any regex string in a list matches a given input value */
164 | protected static boolean regexListMatch(List regexList, String input) {
165 | for (String regex : regexList) {
166 | if (Pattern.matches(regex, input)) {
167 | return true;
168 | }
169 | }
170 | return false;
171 | }
172 |
173 | /** Check if a metric is matched in `aws_tag_select` */
174 | private boolean metricIsInAwsTagSelect(
175 | MetricRule rule, List tagBasedResourceIds, Metric metric) {
176 | if (rule.awsTagSelect.tagSelections == null) {
177 | return true;
178 | }
179 | for (Dimension dimension : metric.dimensions()) {
180 | String dimensionName = dimension.name();
181 | String dimensionValue = dimension.value();
182 | if (rule.awsTagSelect.resourceIdDimension.equals(dimensionName)
183 | && !tagBasedResourceIds.contains(dimensionValue)) {
184 | return false;
185 | }
186 | }
187 | return true;
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/src/main/java/io/prometheus/cloudwatch/DimensionSource.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import java.util.List;
4 | import software.amazon.awssdk.services.cloudwatch.model.Dimension;
5 |
6 | interface DimensionSource {
7 |
8 | DimensionData getDimensions(MetricRule rule, List tagBasedResourceIds);
9 |
10 | class DimensionData {
11 | private final List> dimensions;
12 |
13 | DimensionData(List> dimensions) {
14 | this.dimensions = dimensions;
15 | }
16 |
17 | List> getDimensions() {
18 | return dimensions;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/io/prometheus/cloudwatch/DisallowHttpMethods.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import java.util.EnumSet;
4 | import org.eclipse.jetty.http.HttpMethod;
5 | import org.eclipse.jetty.http.HttpStatus;
6 | import org.eclipse.jetty.server.Connector;
7 | import org.eclipse.jetty.server.HttpConfiguration;
8 | import org.eclipse.jetty.server.Request;
9 |
10 | class DisallowHttpMethods implements HttpConfiguration.Customizer {
11 | private final EnumSet disallowedMethods;
12 |
13 | public DisallowHttpMethods(EnumSet disallowedMethods) {
14 | this.disallowedMethods = disallowedMethods;
15 | }
16 |
17 | @Override
18 | public void customize(Connector connector, HttpConfiguration channelConfig, Request request) {
19 | HttpMethod httpMethod = HttpMethod.fromString(request.getMethod());
20 | if (disallowedMethods.contains(httpMethod)) {
21 | request.setHandled(true);
22 | request.getResponse().setStatus(HttpStatus.METHOD_NOT_ALLOWED_405);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/io/prometheus/cloudwatch/DynamicReloadServlet.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import jakarta.servlet.ServletException;
4 | import jakarta.servlet.http.HttpServlet;
5 | import jakarta.servlet.http.HttpServletRequest;
6 | import jakarta.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | public class DynamicReloadServlet extends HttpServlet {
10 | private static final long serialVersionUID = 9078784531819993933L;
11 | private final CloudWatchCollector collector;
12 |
13 | public DynamicReloadServlet(CloudWatchCollector collector) {
14 | this.collector = collector;
15 | }
16 |
17 | static final String CONTENT_TYPE = "text/plain";
18 |
19 | @Override
20 | protected void doGet(HttpServletRequest req, HttpServletResponse resp)
21 | throws ServletException, IOException {
22 | resp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
23 | resp.setContentType(CONTENT_TYPE);
24 | try {
25 | resp.getWriter().print("Only POST requests allowed");
26 | } catch (IOException e) {
27 | // Ignored
28 | }
29 | }
30 |
31 | @Override
32 | protected void doPost(HttpServletRequest req, HttpServletResponse resp)
33 | throws ServletException, IOException {
34 | try {
35 | collector.reloadConfig();
36 | } catch (IOException e) {
37 | resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
38 | resp.setContentType(CONTENT_TYPE);
39 | try {
40 | resp.getWriter().print("Reloading config failed");
41 | } catch (IOException ee) {
42 | // Ignored
43 | }
44 | return;
45 | }
46 |
47 | resp.setContentType(CONTENT_TYPE);
48 | try {
49 | resp.getWriter().print("OK");
50 | } catch (IOException e) {
51 | // Ignored
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/io/prometheus/cloudwatch/GetMetricDataDataGetter.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import io.prometheus.client.Counter;
4 | import java.time.Instant;
5 | import java.util.ArrayList;
6 | import java.util.Date;
7 | import java.util.HashMap;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.util.UUID;
11 | import java.util.stream.Collectors;
12 | import software.amazon.awssdk.services.cloudwatch.CloudWatchClient;
13 | import software.amazon.awssdk.services.cloudwatch.model.Dimension;
14 | import software.amazon.awssdk.services.cloudwatch.model.GetMetricDataRequest;
15 | import software.amazon.awssdk.services.cloudwatch.model.GetMetricDataResponse;
16 | import software.amazon.awssdk.services.cloudwatch.model.Metric;
17 | import software.amazon.awssdk.services.cloudwatch.model.MetricDataQuery;
18 | import software.amazon.awssdk.services.cloudwatch.model.MetricDataResult;
19 | import software.amazon.awssdk.services.cloudwatch.model.MetricStat;
20 | import software.amazon.awssdk.services.cloudwatch.model.ScanBy;
21 | import software.amazon.awssdk.services.cloudwatch.model.Statistic;
22 |
23 | class GetMetricDataDataGetter implements DataGetter {
24 |
25 | private static final int MAX_QUERIES_PER_REQUEST = 500;
26 | // https://aws.amazon.com/cloudwatch/pricing/
27 | private final long start;
28 | private final MetricRule rule;
29 | private final CloudWatchClient client;
30 | private final Counter apiRequestsCounter;
31 | private final Counter metricsRequestedCounter;
32 | private final Map results;
33 | private double metricRequestedForBilling;
34 |
35 | private static String dimensionToString(Dimension d) {
36 | return String.format("%s=%s", d.name(), d.value());
37 | }
38 |
39 | private static String dimensionsToKey(List dimentions) {
40 | return dimentions.stream()
41 | .map(GetMetricDataDataGetter::dimensionToString)
42 | .sorted()
43 | .collect(Collectors.joining(","));
44 | }
45 |
46 | private List buildStatsList(MetricRule rule) {
47 | List stats = new ArrayList<>();
48 | if (rule.awsStatistics != null) {
49 | stats.addAll(
50 | rule.awsStatistics.stream().map(Statistic::toString).collect(Collectors.toList()));
51 | }
52 | if (rule.awsExtendedStatistics != null) {
53 | stats.addAll(rule.awsExtendedStatistics);
54 | }
55 | return stats;
56 | }
57 |
58 | private List buildMetricDataQueries(
59 | MetricRule rule, List> dimensionsList) {
60 | List queries = new ArrayList<>();
61 | List stats = buildStatsList(rule);
62 | for (String stat : stats) {
63 | for (List dl : dimensionsList) {
64 | Metric metric = buildMetric(dl);
65 | MetricStat metricStat = buildMetricStat(stat, metric);
66 | MetricDataQuery query = buildQuery(stat, dl, metricStat);
67 | queries.add(query);
68 | }
69 | }
70 | metricRequestedForBilling += queries.size();
71 | return queries;
72 | }
73 |
74 | private MetricDataQuery buildQuery(String stat, List dl, MetricStat metric) {
75 | // random id - we don't care about it
76 | String id = "i" + UUID.randomUUID().toString().replace("-", "");
77 | MetricDataQuery.Builder builder = MetricDataQuery.builder();
78 | builder.id(id);
79 |
80 | // important - used to locate back the results
81 | String label = MetricLabels.labelFor(stat, dl);
82 | builder.label(label);
83 | builder.metricStat(metric);
84 | return builder.build();
85 | }
86 |
87 | private MetricStat buildMetricStat(String stat, Metric metric) {
88 | MetricStat.Builder builder = MetricStat.builder();
89 | builder.period(rule.periodSeconds);
90 | builder.stat(stat);
91 | builder.metric(metric);
92 | return builder.build();
93 | }
94 |
95 | private Metric buildMetric(List dl) {
96 | Metric.Builder builder = Metric.builder();
97 | builder.namespace(rule.awsNamespace);
98 | builder.metricName(rule.awsMetricName);
99 | builder.dimensions(dl);
100 | return builder.build();
101 | }
102 |
103 | public static List> partitionByMaxSize(List list, int maxPartitionSize) {
104 | List> partitions = new ArrayList<>();
105 | List remaining = list;
106 | while (remaining.size() > 0) {
107 | if (remaining.size() < maxPartitionSize) {
108 | partitions.add(remaining);
109 | break;
110 | } else {
111 | partitions.add(remaining.subList(0, maxPartitionSize));
112 | remaining = remaining.subList(maxPartitionSize, remaining.size());
113 | }
114 | }
115 | return partitions;
116 | }
117 |
118 | private List buildMetricDataRequests(
119 | MetricRule rule, List> dimensionsList) {
120 | Date startDate = new Date(start - 1000L * rule.delaySeconds);
121 | Date endDate = new Date(start - 1000L * (rule.delaySeconds + rule.rangeSeconds));
122 | GetMetricDataRequest.Builder builder = GetMetricDataRequest.builder();
123 | builder.endTime(startDate.toInstant());
124 | builder.startTime(endDate.toInstant());
125 | builder.scanBy(ScanBy.TIMESTAMP_DESCENDING);
126 | List queries = buildMetricDataQueries(rule, dimensionsList);
127 | List requests = new ArrayList<>();
128 | for (List queriesPartition :
129 | partitionByMaxSize(queries, MAX_QUERIES_PER_REQUEST)) {
130 | requests.add(builder.metricDataQueries(queriesPartition).build());
131 | }
132 | return requests;
133 | }
134 |
135 | private Map fetchAllDataPoints(List> dimensionsList) {
136 | List results = new ArrayList<>();
137 | for (GetMetricDataRequest request : buildMetricDataRequests(rule, dimensionsList)) {
138 | GetMetricDataResponse response = client.getMetricData(request);
139 | apiRequestsCounter.labels("getMetricData", rule.awsNamespace).inc();
140 | results.addAll(response.metricDataResults());
141 | }
142 | metricsRequestedCounter
143 | .labels(rule.awsMetricName, rule.awsNamespace)
144 | .inc(metricRequestedForBilling);
145 | return toMap(results);
146 | }
147 |
148 | private Map toMap(List metricDataResults) {
149 | Map res = new HashMap<>();
150 | for (MetricDataResult dataResult : metricDataResults) {
151 | if (dataResult.timestamps().isEmpty() || dataResult.values().isEmpty()) {
152 | continue;
153 | }
154 | StatAndDimensions statAndDimensions = MetricLabels.decode(dataResult.label());
155 | String statString = statAndDimensions.stat;
156 | String labelsKey = statAndDimensions.dimetionsAsString;
157 | Instant timestamp = dataResult.timestamps().get(0);
158 | Double value = dataResult.values().get(0);
159 | MetricRuleData metricRuleData =
160 | res.getOrDefault(labelsKey, new MetricRuleData(timestamp, "N/A"));
161 | Statistic stat = Statistic.fromValue(statString);
162 | if (stat == Statistic.UNKNOWN_TO_SDK_VERSION) {
163 | metricRuleData.extendedValues.put(statString, value);
164 | } else {
165 | metricRuleData.statisticValues.put(stat, value);
166 | }
167 | res.put(labelsKey, metricRuleData);
168 | }
169 | return res;
170 | }
171 |
172 | GetMetricDataDataGetter(
173 | CloudWatchClient client,
174 | long start,
175 | MetricRule rule,
176 | Counter apiRequestsCounter,
177 | Counter metricsRequestedCounter,
178 | List> dimensionsList) {
179 | this.client = client;
180 | this.start = start;
181 | this.rule = rule;
182 | this.apiRequestsCounter = apiRequestsCounter;
183 | this.metricsRequestedCounter = metricsRequestedCounter;
184 | this.metricRequestedForBilling = 0d;
185 | this.results = fetchAllDataPoints(dimensionsList);
186 | }
187 |
188 | @Override
189 | public MetricRuleData metricRuleDataFor(List dimensions) {
190 | return results.get(dimensionsToKey(dimensions));
191 | }
192 |
193 | private static class StatAndDimensions {
194 | String dimetionsAsString;
195 | String stat;
196 |
197 | StatAndDimensions(String stat, String dimetionsAsString) {
198 | this.stat = stat;
199 | this.dimetionsAsString = dimetionsAsString;
200 | }
201 | }
202 |
203 | static class MetricLabels {
204 | static String labelFor(String stat, List dimensions) {
205 | return String.format("%s/%s", stat, dimensionsToKey(dimensions));
206 | }
207 |
208 | static StatAndDimensions decode(String label) {
209 | String[] labelParts = label.split("/", 2);
210 | if (labelParts.length != 2) {
211 | throw new UnexpectedLabel(label);
212 | }
213 | String statString = labelParts[0];
214 | String labelsKey = labelParts[1];
215 | return new StatAndDimensions(statString, labelsKey);
216 | }
217 |
218 | static class UnexpectedLabel extends RuntimeException {
219 | public UnexpectedLabel(String label) {
220 | super(String.format("Cannot decode label %s", label));
221 | }
222 | }
223 | }
224 | }
225 |
--------------------------------------------------------------------------------
/src/main/java/io/prometheus/cloudwatch/GetMetricStatisticsDataGetter.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import io.prometheus.client.Counter;
4 | import java.util.Date;
5 | import java.util.List;
6 | import java.util.Map;
7 | import software.amazon.awssdk.services.cloudwatch.CloudWatchClient;
8 | import software.amazon.awssdk.services.cloudwatch.model.Datapoint;
9 | import software.amazon.awssdk.services.cloudwatch.model.Dimension;
10 | import software.amazon.awssdk.services.cloudwatch.model.GetMetricStatisticsRequest;
11 | import software.amazon.awssdk.services.cloudwatch.model.GetMetricStatisticsResponse;
12 | import software.amazon.awssdk.services.cloudwatch.model.Statistic;
13 |
14 | class GetMetricStatisticsDataGetter implements DataGetter {
15 | private long start;
16 | private MetricRule rule;
17 | private CloudWatchClient client;
18 | private Counter apiRequestsCounter;
19 | private Counter metricsRequestedCounter;
20 |
21 | GetMetricStatisticsDataGetter(
22 | CloudWatchClient client,
23 | long start,
24 | MetricRule rule,
25 | Counter apiRequestsCounter,
26 | Counter metricsRequestedCounter) {
27 | this.client = client;
28 | this.start = start;
29 | this.rule = rule;
30 | this.apiRequestsCounter = apiRequestsCounter;
31 | this.metricsRequestedCounter = metricsRequestedCounter;
32 | }
33 |
34 | private GetMetricStatisticsRequest.Builder metricStatisticsRequestBuilder() {
35 | Date startDate = new Date(start - 1000 * rule.delaySeconds);
36 | Date endDate = new Date(start - 1000 * (rule.delaySeconds + rule.rangeSeconds));
37 | GetMetricStatisticsRequest.Builder builder = GetMetricStatisticsRequest.builder();
38 | builder.namespace(rule.awsNamespace);
39 | builder.metricName(rule.awsMetricName);
40 | builder.statistics(rule.awsStatistics);
41 | builder.extendedStatistics(rule.awsExtendedStatistics);
42 | builder.endTime(startDate.toInstant());
43 | builder.startTime(endDate.toInstant());
44 | builder.period(rule.periodSeconds);
45 | return builder;
46 | }
47 |
48 | @Override
49 | public MetricRuleData metricRuleDataFor(List dimensions) {
50 | GetMetricStatisticsRequest.Builder builder = metricStatisticsRequestBuilder();
51 | builder.dimensions(dimensions);
52 | GetMetricStatisticsResponse response = client.getMetricStatistics(builder.build());
53 | apiRequestsCounter.labels("getMetricStatistics", rule.awsNamespace).inc();
54 | metricsRequestedCounter.labels(rule.awsMetricName, rule.awsNamespace).inc();
55 | Datapoint latestDp = getNewestDatapoint(response.datapoints());
56 | return toMetricValues(latestDp);
57 | }
58 |
59 | private Datapoint getNewestDatapoint(List datapoints) {
60 | Datapoint newest = null;
61 | for (Datapoint d : datapoints) {
62 | if (newest == null || newest.timestamp().isBefore(d.timestamp())) {
63 | newest = d;
64 | }
65 | }
66 | return newest;
67 | }
68 |
69 | private MetricRuleData toMetricValues(Datapoint dp) {
70 | if (dp == null) {
71 | return null;
72 | }
73 | MetricRuleData values = new MetricRuleData(dp.timestamp(), dp.unitAsString());
74 | if (dp.sum() != null) {
75 | values.statisticValues.put(Statistic.SUM, dp.sum());
76 | }
77 | if (dp.sampleCount() != null) {
78 | values.statisticValues.put(Statistic.SAMPLE_COUNT, dp.sampleCount());
79 | }
80 | if (dp.minimum() != null) {
81 | values.statisticValues.put(Statistic.MINIMUM, dp.minimum());
82 | }
83 | if (dp.maximum() != null) {
84 | values.statisticValues.put(Statistic.MAXIMUM, dp.maximum());
85 | }
86 | if (dp.average() != null) {
87 | values.statisticValues.put(Statistic.AVERAGE, dp.average());
88 | }
89 | if (dp.extendedStatistics() != null) {
90 | for (Map.Entry entry : dp.extendedStatistics().entrySet()) {
91 | values.extendedValues.put(entry.getKey(), entry.getValue());
92 | }
93 | }
94 | return values;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/io/prometheus/cloudwatch/HealthServlet.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import jakarta.servlet.ServletException;
4 | import jakarta.servlet.http.HttpServlet;
5 | import jakarta.servlet.http.HttpServletRequest;
6 | import jakarta.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | public class HealthServlet extends HttpServlet {
10 | private static final long serialVersionUID = 5543118274931292897L;
11 |
12 | @Override
13 | protected void doGet(HttpServletRequest req, HttpServletResponse resp)
14 | throws ServletException, IOException {
15 | resp.setContentType("text/plain");
16 | resp.getWriter().print("ok");
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/io/prometheus/cloudwatch/HomePageServlet.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import jakarta.servlet.ServletException;
4 | import jakarta.servlet.http.HttpServlet;
5 | import jakarta.servlet.http.HttpServletRequest;
6 | import jakarta.servlet.http.HttpServletResponse;
7 | import java.io.IOException;
8 |
9 | public class HomePageServlet extends HttpServlet {
10 | private static final long serialVersionUID = 3239704246954810347L;
11 |
12 | @Override
13 | protected void doGet(HttpServletRequest req, HttpServletResponse resp)
14 | throws ServletException, IOException {
15 | resp.setContentType("text/html");
16 | try {
17 | resp.getWriter()
18 | .print(
19 | "\n"
20 | + "CloudWatch Exporter\n"
21 | + "\n"
22 | + "CloudWatch Exporter
\n"
23 | + "Metrics
\n"
24 | + "\n"
25 | + "");
26 | } catch (IOException e) {
27 | // Ignored
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/io/prometheus/cloudwatch/MetricRule.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import java.time.Duration;
4 | import java.util.List;
5 | import java.util.Map;
6 | import java.util.Objects;
7 | import software.amazon.awssdk.services.cloudwatch.model.Statistic;
8 |
9 | class MetricRule {
10 | String awsNamespace;
11 | String awsMetricName;
12 | int periodSeconds;
13 | int rangeSeconds;
14 | int delaySeconds;
15 | List awsStatistics;
16 | List awsExtendedStatistics;
17 | List awsDimensions;
18 | Map> awsDimensionSelect;
19 | Map> awsDimensionSelectRegex;
20 | CloudWatchCollector.AWSTagSelect awsTagSelect;
21 | String help;
22 | boolean cloudwatchTimestamp;
23 | boolean useGetMetricData;
24 | Duration listMetricsCacheTtl;
25 | boolean warnOnEmptyListDimensions;
26 |
27 | @Override
28 | public boolean equals(Object o) {
29 | if (this == o) return true;
30 | if (o == null || getClass() != o.getClass()) return false;
31 |
32 | MetricRule that = (MetricRule) o;
33 |
34 | if (periodSeconds != that.periodSeconds) return false;
35 | if (rangeSeconds != that.rangeSeconds) return false;
36 | if (delaySeconds != that.delaySeconds) return false;
37 | if (cloudwatchTimestamp != that.cloudwatchTimestamp) return false;
38 | if (useGetMetricData != that.useGetMetricData) return false;
39 | if (!Objects.equals(awsNamespace, that.awsNamespace)) return false;
40 | if (!Objects.equals(awsMetricName, that.awsMetricName)) return false;
41 | if (!Objects.equals(awsStatistics, that.awsStatistics)) return false;
42 | if (!Objects.equals(awsExtendedStatistics, that.awsExtendedStatistics)) return false;
43 | if (!Objects.equals(awsDimensions, that.awsDimensions)) return false;
44 | if (!Objects.equals(awsDimensionSelect, that.awsDimensionSelect)) return false;
45 | if (!Objects.equals(awsDimensionSelectRegex, that.awsDimensionSelectRegex)) return false;
46 | if (!Objects.equals(awsTagSelect, that.awsTagSelect)) return false;
47 | if (!Objects.equals(help, that.help)) return false;
48 | return Objects.equals(listMetricsCacheTtl, that.listMetricsCacheTtl);
49 | }
50 |
51 | @Override
52 | public int hashCode() {
53 | int result = awsNamespace != null ? awsNamespace.hashCode() : 0;
54 | result = 31 * result + (awsMetricName != null ? awsMetricName.hashCode() : 0);
55 | result = 31 * result + periodSeconds;
56 | result = 31 * result + rangeSeconds;
57 | result = 31 * result + delaySeconds;
58 | result = 31 * result + (awsStatistics != null ? awsStatistics.hashCode() : 0);
59 | result = 31 * result + (awsExtendedStatistics != null ? awsExtendedStatistics.hashCode() : 0);
60 | result = 31 * result + (awsDimensions != null ? awsDimensions.hashCode() : 0);
61 | result = 31 * result + (awsDimensionSelect != null ? awsDimensionSelect.hashCode() : 0);
62 | result =
63 | 31 * result + (awsDimensionSelectRegex != null ? awsDimensionSelectRegex.hashCode() : 0);
64 | result = 31 * result + (awsTagSelect != null ? awsTagSelect.hashCode() : 0);
65 | result = 31 * result + (help != null ? help.hashCode() : 0);
66 | result = 31 * result + (cloudwatchTimestamp ? 1 : 0);
67 | result = 31 * result + (useGetMetricData ? 1 : 0);
68 | result = 31 * result + (listMetricsCacheTtl != null ? listMetricsCacheTtl.hashCode() : 0);
69 | return result;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/io/prometheus/cloudwatch/ReloadSignalHandler.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import java.util.logging.Level;
4 | import java.util.logging.Logger;
5 | import sun.misc.Signal;
6 | import sun.misc.SignalHandler;
7 |
8 | class ReloadSignalHandler {
9 | private static final Logger LOGGER = Logger.getLogger(CloudWatchCollector.class.getName());
10 |
11 | protected static void start(final CloudWatchCollector collector) {
12 | Signal.handle(
13 | new Signal("HUP"),
14 | new SignalHandler() {
15 | public void handle(Signal signal) {
16 | try {
17 | collector.reloadConfig();
18 | } catch (Exception e) {
19 | LOGGER.log(Level.WARNING, "Configuration reload failed", e);
20 | }
21 | }
22 | });
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/io/prometheus/cloudwatch/WebServer.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import io.prometheus.client.hotspot.DefaultExports;
4 | import io.prometheus.client.servlet.jakarta.exporter.MetricsServlet;
5 | import java.io.FileReader;
6 | import java.util.EnumSet;
7 | import org.eclipse.jetty.http.HttpMethod;
8 | import org.eclipse.jetty.server.HttpConfiguration;
9 | import org.eclipse.jetty.server.HttpConnectionFactory;
10 | import org.eclipse.jetty.server.Server;
11 | import org.eclipse.jetty.server.ServerConnector;
12 | import org.eclipse.jetty.servlet.ServletContextHandler;
13 | import org.eclipse.jetty.servlet.ServletHolder;
14 |
15 | public class WebServer {
16 |
17 | public static String configFilePath;
18 |
19 | public static void main(String[] args) throws Exception {
20 | if (args.length < 2) {
21 | System.err.println("Usage: WebServer ");
22 | System.exit(1);
23 | }
24 |
25 | configFilePath = args[1];
26 | CloudWatchCollector collector = null;
27 | new BuildInfoCollector().register();
28 | try (FileReader reader = new FileReader(configFilePath); ) {
29 | collector = new CloudWatchCollector(reader).register();
30 | }
31 | DefaultExports.initialize();
32 |
33 | ReloadSignalHandler.start(collector);
34 |
35 | int port = Integer.parseInt(args[0]);
36 | Server server = new Server();
37 | HttpConfiguration httpConfig = new HttpConfiguration();
38 | httpConfig.addCustomizer(new DisallowHttpMethods(EnumSet.of(HttpMethod.TRACE)));
39 | ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory(httpConfig));
40 | connector.setPort(port);
41 | server.addConnector(connector);
42 |
43 | ServletContextHandler context = new ServletContextHandler();
44 | context.setContextPath("/");
45 | server.setHandler(context);
46 | context.addServlet(new ServletHolder(new MetricsServlet()), "/metrics");
47 | context.addServlet(new ServletHolder(new DynamicReloadServlet(collector)), "/-/reload");
48 | context.addServlet(new ServletHolder(new HealthServlet()), "/-/healthy");
49 | context.addServlet(new ServletHolder(new HealthServlet()), "/-/ready");
50 | context.addServlet(new ServletHolder(new HomePageServlet()), "/");
51 | server.start();
52 | server.join();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/resources/.properties:
--------------------------------------------------------------------------------
1 | ReleaseDate=${project.releaseDate}
2 | BuildVersion=${project.version}
3 |
--------------------------------------------------------------------------------
/src/test/java/io/prometheus/cloudwatch/CachingDimensionExpiryTest.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import io.prometheus.cloudwatch.CachingDimensionSource.DimensionCacheKey;
6 | import io.prometheus.cloudwatch.CachingDimensionSource.DimensionExpiry;
7 | import java.time.Duration;
8 | import java.time.Instant;
9 | import java.util.Collections;
10 | import java.util.List;
11 | import org.junit.Test;
12 |
13 | public class CachingDimensionExpiryTest {
14 |
15 | private final DimensionSource.DimensionData emptyData =
16 | new DimensionSource.DimensionData(Collections.emptyList());
17 |
18 | @Test
19 | public void expireAfterCreateUsesDefaultWithEmptyOverrides() {
20 | Duration defaultExpiry = Duration.ofSeconds(35);
21 | List expiryOverrides = Collections.emptyList();
22 | DimensionExpiry sut = new DimensionExpiry(defaultExpiry, expiryOverrides);
23 |
24 | long afterCreate =
25 | sut.expireAfterCreate(
26 | createDimensionCacheKey("AWS/Redshift", "WriteIOPS", 0),
27 | emptyData,
28 | Instant.now().toEpochMilli());
29 |
30 | assertEquals(35, Duration.ofNanos(afterCreate).toSeconds());
31 | }
32 |
33 | @Test
34 | public void expireAfterCreateUsesMetricLevelOverride() {
35 | Duration defaultExpiry = Duration.ofSeconds(35);
36 | List expiryOverrides = List.of(createMetricRule("AWS/S3", "BucketSizeBytes", 100));
37 | DimensionExpiry sut = new DimensionExpiry(defaultExpiry, expiryOverrides);
38 |
39 | long afterCreate =
40 | sut.expireAfterCreate(
41 | createDimensionCacheKey("AWS/S3", "BucketSizeBytes", 100),
42 | emptyData,
43 | Instant.now().toEpochMilli());
44 |
45 | assertEquals(100, Duration.ofNanos(afterCreate).toSeconds());
46 | }
47 |
48 | @Test
49 | public void expireAfterCreateUsesDefaultIfNoMatchedOverride() {
50 | Duration defaultExpiry = Duration.ofSeconds(35);
51 | List expiryOverrides = List.of(createMetricRule("AWS/S3", "BucketSizeBytes", 100));
52 | DimensionExpiry sut = new DimensionExpiry(defaultExpiry, expiryOverrides);
53 |
54 | long afterCreate =
55 | sut.expireAfterCreate(
56 | createDimensionCacheKey("AWS/Redshift", "WriteIOPS", 120),
57 | emptyData,
58 | Instant.now().toEpochMilli());
59 |
60 | assertEquals(35, Duration.ofNanos(afterCreate).toSeconds());
61 | }
62 |
63 | @Test
64 | public void expireAfterUpdateUsesCurrentDuration() {
65 | Duration defaultExpiry = Duration.ofSeconds(35);
66 | List expiryOverrides = Collections.emptyList();
67 | DimensionExpiry sut = new DimensionExpiry(defaultExpiry, expiryOverrides);
68 |
69 | long afterUpdate =
70 | sut.expireAfterUpdate(
71 | createDimensionCacheKey("AWS/Redshift", "WriteIOPS", 120),
72 | emptyData,
73 | Instant.now().toEpochMilli(),
74 | 10_000_000);
75 |
76 | assertEquals(10_000_000, afterUpdate);
77 | }
78 |
79 | @Test
80 | public void expireAfterReadUsesCurrentDuration() {
81 | Duration defaultExpiry = Duration.ofSeconds(35);
82 | List expiryOverrides = Collections.emptyList();
83 | DimensionExpiry sut = new DimensionExpiry(defaultExpiry, expiryOverrides);
84 |
85 | long afterRead =
86 | sut.expireAfterRead(
87 | createDimensionCacheKey("AWS/Redshift", "WriteIOPS", 100),
88 | emptyData,
89 | Instant.now().toEpochMilli(),
90 | 20_000_000);
91 | assertEquals(20_000_000, afterRead);
92 | }
93 |
94 | private DimensionCacheKey createDimensionCacheKey(
95 | String namespace, String name, int ttlInSeconds) {
96 | return new DimensionCacheKey(
97 | createMetricRule(namespace, name, ttlInSeconds), Collections.emptyList());
98 | }
99 |
100 | private MetricRule createMetricRule(String namespace, String name, int ttlInSeconds) {
101 | MetricRule metricRule = new MetricRule();
102 | metricRule.awsNamespace = namespace;
103 | metricRule.awsMetricName = name;
104 | metricRule.listMetricsCacheTtl = Duration.ofSeconds(ttlInSeconds);
105 | return metricRule;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/test/java/io/prometheus/cloudwatch/CachingDimensionSourceTest.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import static io.prometheus.cloudwatch.DimensionSource.DimensionData;
4 | import static org.junit.Assert.assertEquals;
5 |
6 | import io.prometheus.cloudwatch.CachingDimensionSource.DimensionCacheConfig;
7 | import java.time.Duration;
8 | import java.util.Collections;
9 | import java.util.List;
10 | import org.junit.Test;
11 | import software.amazon.awssdk.services.cloudwatch.model.Dimension;
12 |
13 | public class CachingDimensionSourceTest {
14 |
15 | @Test
16 | public void cachedFromDelegate() {
17 | DimensionCacheConfig config = new DimensionCacheConfig(Duration.ofSeconds(60));
18 | FakeDimensionSource source = new FakeDimensionSource();
19 | DimensionSource sut = new CachingDimensionSource(source, config);
20 |
21 | sut.getDimensions(createMetricRule("AWS/Redshift", "WriteIOPS"), Collections.emptyList());
22 | sut.getDimensions(createMetricRule("AWS/Redshift", "WriteIOPS"), Collections.emptyList());
23 | DimensionData expected =
24 | sut.getDimensions(createMetricRule("AWS/Redshift", "WriteIOPS"), Collections.emptyList());
25 |
26 | Dimension dimension = Dimension.builder().name("AWS/Redshift").value("WriteIOPS").build();
27 | assertEquals(1, source.called);
28 | assertEquals(dimension, expected.getDimensions().get(0).get(0));
29 | }
30 |
31 | private MetricRule createMetricRule(String namespace, String name) {
32 | MetricRule metricRule = new MetricRule();
33 | metricRule.awsNamespace = namespace;
34 | metricRule.awsMetricName = name;
35 | return metricRule;
36 | }
37 |
38 | static class FakeDimensionSource implements DimensionSource {
39 | int called = 0;
40 |
41 | @Override
42 | public DimensionData getDimensions(MetricRule rule, List tagBasedResourceIds) {
43 | called++;
44 | return new DimensionData(
45 | List.of(List.of(Dimension.builder().name("AWS/Redshift").value("WriteIOPS").build())));
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/test/java/io/prometheus/cloudwatch/GetMetricDataGetterTest.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import static org.junit.Assert.assertTrue;
4 |
5 | import java.util.Collections;
6 | import java.util.List;
7 | import org.junit.Test;
8 |
9 | public class GetMetricDataGetterTest {
10 | @Test
11 | public void testPartition() {
12 | List originalList = List.copyOf(Collections.nCopies(28, 0));
13 | List> partitions = GetMetricDataDataGetter.partitionByMaxSize(originalList, 40);
14 | for (List p : partitions) {
15 | assertTrue("partition must be smaller than 40", p.size() <= 40);
16 | assertTrue("partition should not be empty", !p.isEmpty());
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/io/prometheus/cloudwatch/RequestsMatchers.java:
--------------------------------------------------------------------------------
1 | package io.prometheus.cloudwatch;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.stream.Collectors;
6 | import org.hamcrest.BaseMatcher;
7 | import org.hamcrest.Description;
8 | import org.hamcrest.Matcher;
9 | import org.hamcrest.Matchers;
10 | import software.amazon.awssdk.services.cloudwatch.model.Dimension;
11 | import software.amazon.awssdk.services.cloudwatch.model.DimensionFilter;
12 | import software.amazon.awssdk.services.cloudwatch.model.GetMetricDataRequest;
13 | import software.amazon.awssdk.services.cloudwatch.model.GetMetricStatisticsRequest;
14 | import software.amazon.awssdk.services.cloudwatch.model.ListMetricsRequest;
15 | import software.amazon.awssdk.services.cloudwatch.model.Metric;
16 | import software.amazon.awssdk.services.cloudwatch.model.MetricDataQuery;
17 | import software.amazon.awssdk.services.cloudwatch.model.MetricStat;
18 | import software.amazon.awssdk.services.resourcegroupstaggingapi.model.GetResourcesRequest;
19 | import software.amazon.awssdk.services.resourcegroupstaggingapi.model.TagFilter;
20 |
21 | public class RequestsMatchers {
22 |
23 | static class ListMetricsRequestMatcher extends BaseMatcher {
24 | String namespace;
25 | String metricName;
26 | String nextToken;
27 | String recentlyActive;
28 | List dimensions = new ArrayList();
29 |
30 | public ListMetricsRequestMatcher Namespace(String namespace) {
31 | this.namespace = namespace;
32 | return this;
33 | }
34 |
35 | public ListMetricsRequestMatcher MetricName(String metricName) {
36 | this.metricName = metricName;
37 | return this;
38 | }
39 |
40 | public ListMetricsRequestMatcher NextToken(String nextToken) {
41 | this.nextToken = nextToken;
42 | return this;
43 | }
44 |
45 | public ListMetricsRequestMatcher Dimensions(String... dimensions) {
46 | this.dimensions = new ArrayList();
47 | for (int i = 0; i < dimensions.length; i++) {
48 | this.dimensions.add(DimensionFilter.builder().name(dimensions[i]).build());
49 | }
50 | return this;
51 | }
52 |
53 | public ListMetricsRequestMatcher RecentlyActive(String recentlyActive) {
54 | this.recentlyActive = recentlyActive;
55 | return this;
56 | }
57 |
58 | public boolean matches(Object o) {
59 | ListMetricsRequest request = (ListMetricsRequest) o;
60 | if (request == null) return false;
61 | if (namespace != null && !namespace.equals(request.namespace())) {
62 | return false;
63 | }
64 | if (metricName != null && !metricName.equals(request.metricName())) {
65 | return false;
66 | }
67 | if (nextToken == null ^ request.nextToken() == null) {
68 | return false;
69 | }
70 | if (nextToken != null && !nextToken.equals(request.nextToken())) {
71 | return false;
72 | }
73 | if (!dimensions.equals(request.dimensions())) {
74 | return false;
75 | }
76 | if (recentlyActive != null && !recentlyActive.equals(request.recentlyActive())) {
77 | return false;
78 | }
79 | return true;
80 | }
81 |
82 | public void describeTo(Description description) {
83 | description.appendText("list metrics request");
84 | }
85 | }
86 |
87 | static class GetMetricStatisticsRequestMatcher extends BaseMatcher {
88 | String namespace;
89 | String metricName;
90 | List dimensions = new ArrayList();
91 | Integer period;
92 |
93 | public GetMetricStatisticsRequestMatcher Namespace(String namespace) {
94 | this.namespace = namespace;
95 | return this;
96 | }
97 |
98 | public GetMetricStatisticsRequestMatcher MetricName(String metricName) {
99 | this.metricName = metricName;
100 | return this;
101 | }
102 |
103 | public GetMetricStatisticsRequestMatcher Dimension(String name, String value) {
104 | dimensions.add(Dimension.builder().name(name).value(value).build());
105 | return this;
106 | }
107 |
108 | public GetMetricStatisticsRequestMatcher Period(int period) {
109 | this.period = period;
110 | return this;
111 | }
112 |
113 | public boolean matches(Object o) {
114 | GetMetricStatisticsRequest request = (GetMetricStatisticsRequest) o;
115 | if (request == null) return false;
116 | if (namespace != null && !namespace.equals(request.namespace())) {
117 | return false;
118 | }
119 | if (metricName != null && !metricName.equals(request.metricName())) {
120 | return false;
121 | }
122 | if (!dimensions.equals(request.dimensions())) {
123 | return false;
124 | }
125 | if (period != null && !period.equals(request.period())) {
126 | return false;
127 | }
128 | return true;
129 | }
130 |
131 | public void describeTo(Description description) {
132 | description.appendText("get metrics statistics request");
133 | }
134 | }
135 |
136 | static class GetResourcesRequestMatcher extends BaseMatcher {
137 | String paginationToken = "";
138 | List resourceTypeFilters = new ArrayList();
139 | List tagFilters = new ArrayList();
140 |
141 | public GetResourcesRequestMatcher PaginationToken(String paginationToken) {
142 | this.paginationToken = paginationToken;
143 | return this;
144 | }
145 |
146 | public GetResourcesRequestMatcher ResourceTypeFilter(String resourceTypeFilter) {
147 | resourceTypeFilters.add(resourceTypeFilter);
148 | return this;
149 | }
150 |
151 | public GetResourcesRequestMatcher TagFilter(String key, List values) {
152 | tagFilters.add(TagFilter.builder().key(key).values(values).build());
153 | return this;
154 | }
155 |
156 | public boolean matches(Object o) {
157 | GetResourcesRequest request = (GetResourcesRequest) o;
158 | if (request == null) return false;
159 | if (paginationToken == "" ^ request.paginationToken() == "") {
160 | return false;
161 | }
162 | if (paginationToken != "" && !paginationToken.equals(request.paginationToken())) {
163 | return false;
164 | }
165 | if (!resourceTypeFilters.equals(request.resourceTypeFilters())) {
166 | return false;
167 | }
168 | if (!tagFilters.equals(request.tagFilters())) {
169 | return false;
170 | }
171 | return true;
172 | }
173 |
174 | public void describeTo(Description description) {
175 | description.appendText("get resources request");
176 | }
177 | }
178 |
179 | static class MetricMatcher extends BaseMatcher {
180 | String namespace;
181 | String metricName;
182 | List dimensions = new ArrayList();
183 |
184 | public MetricMatcher Namespace(String namespace) {
185 | this.namespace = namespace;
186 | return this;
187 | }
188 |
189 | public MetricMatcher MetricName(String metricName) {
190 | this.metricName = metricName;
191 | return this;
192 | }
193 |
194 | public MetricMatcher Dimension(String name, String value) {
195 | dimensions.add(Dimension.builder().name(name).value(value).build());
196 | return this;
197 | }
198 |
199 | @Override
200 | public boolean matches(Object o) {
201 | Metric metric = (Metric) o;
202 | if (metric == null) return false;
203 | if (namespace != null && !namespace.equals(metric.namespace())) {
204 | return false;
205 | }
206 | if (metricName != null && !metricName.equals(metric.metricName())) {
207 | return false;
208 | }
209 | if (!dimensions.equals(metric.dimensions())) {
210 | return false;
211 | }
212 | return true;
213 | }
214 |
215 | @Override
216 | public void describeTo(Description description) {
217 | description.appendText("Metric");
218 | List properties = new ArrayList<>();
219 | if (namespace != null) {
220 | properties.add(String.format("namespace=%s", namespace));
221 | }
222 | if (metricName != null) {
223 | properties.add(String.format("metricName=%s", metricName));
224 | }
225 | String dimentions =
226 | dimensions.stream()
227 | .map((d) -> d.name() + ":" + d.value())
228 | .collect(Collectors.joining(", "));
229 | properties.add(String.format("dimentions=[%s]", dimentions));
230 | description.appendValueList("(", ",", ")", properties);
231 | }
232 | }
233 |
234 | static class MetricStatMatcher extends BaseMatcher {
235 | MetricMatcher metricMatcher;
236 | String stat;
237 | Integer period;
238 |
239 | public MetricStatMatcher metric(MetricMatcher metricMatcher) {
240 | this.metricMatcher = metricMatcher;
241 | return this;
242 | }
243 |
244 | public MetricStatMatcher Period(int period) {
245 | this.period = period;
246 | return this;
247 | }
248 |
249 | public MetricStatMatcher Stat(String stat) {
250 | this.stat = stat;
251 | return this;
252 | }
253 |
254 | @Override
255 | public boolean matches(Object o) {
256 | MetricStat metricStat = (MetricStat) o;
257 | if (metricStat == null) return false;
258 | if (period != null && !period.equals(metricStat.period())) {
259 | return false;
260 | }
261 | if (metricMatcher != null && !metricMatcher.matches(metricStat.metric())) {
262 | return false;
263 | }
264 | if (stat != null && !stat.equals(metricStat.stat())) {
265 | return false;
266 | }
267 | return true;
268 | }
269 |
270 | @Override
271 | public void describeTo(Description description) {
272 | description.appendText("A metric stat");
273 | if (stat != null) {
274 | description.appendText(String.format(" with stat %s", stat));
275 | }
276 | if (period != null) {
277 | description.appendText(String.format(" with period %s", period));
278 | }
279 | if (metricMatcher != null) {
280 | description.appendText(" with metric ");
281 | metricMatcher.describeTo(description);
282 | }
283 | }
284 | }
285 |
286 | static class MetricDataQueryMatcher extends BaseMatcher {
287 | String label;
288 | MetricStatMatcher metricStat;
289 |
290 | public MetricDataQueryMatcher Label(String label) {
291 | this.label = label;
292 | return this;
293 | }
294 |
295 | public MetricDataQueryMatcher MetricStat(MetricStatMatcher metricStat) {
296 | this.metricStat = metricStat;
297 | return this;
298 | }
299 |
300 | @Override
301 | public boolean matches(Object o) {
302 | MetricDataQuery query = (MetricDataQuery) o;
303 | if (query == null) return false;
304 | if (label != null && !label.equals(query.label())) {
305 | return false;
306 | }
307 | if (metricStat != null && !metricStat.matches(query.metricStat())) {
308 | return false;
309 | }
310 | return true;
311 | }
312 |
313 | @Override
314 | public void describeTo(Description description) {
315 | description.appendText("metric data query");
316 | if (label != null) {
317 | description.appendText(String.format(" with label '%s'", label));
318 | }
319 | if (metricStat != null) {
320 | description.appendText(" with stat: ");
321 | metricStat.describeTo(description);
322 | }
323 | }
324 | }
325 |
326 | static class GetMetricDataRequestMatcher extends BaseMatcher {
327 | List queries = new ArrayList<>();
328 |
329 | public GetMetricDataRequestMatcher Query(MetricDataQueryMatcher query) {
330 | this.queries.add(query);
331 | return this;
332 | }
333 |
334 | private Matcher> queriesMatcher() {
335 | return Matchers.hasItems(queries.stream().toArray(MetricDataQueryMatcher[]::new));
336 | }
337 |
338 | @Override
339 | public boolean matches(Object o) {
340 | GetMetricDataRequest request = (GetMetricDataRequest) o;
341 | if (request == null) {
342 | return false;
343 | }
344 | if (!queries.isEmpty() && !queriesMatcher().matches(request.metricDataQueries())) {
345 | return false;
346 | }
347 | ;
348 | return true;
349 | }
350 |
351 | @Override
352 | public void describeTo(Description description) {
353 | description.appendText("a GetMetricDataRequest");
354 | if (!queries.isEmpty()) {
355 | description.appendText("with queries:\n");
356 | for (MetricDataQueryMatcher qmatcher : queries) {
357 | description.appendText("\t- ");
358 | qmatcher.describeTo(description);
359 | description.appendText("\n");
360 | }
361 | }
362 | }
363 | }
364 | }
365 |
--------------------------------------------------------------------------------