awscr-cloudwatch v1.0.0
awscr-cloudwatch
A low-level Crystal client for AWS CloudWatch:
- Metrics: publish counters and other data points, query statistics
- Alarms: create, inspect and delete metric and composite alarms
Dashboards, anomaly detectors, tags, metric streams and Contributor Insights rules are covered as well, but with less testing and should be considered experimental only.
For day-to-day use the easy-awscr library is recommended. It handles credentials, connection pooling and provides higher-level APIs like aggregating counters before uploading them.
Installation
-
Add the dependency to your
shard.yml:dependencies: awscr-cloudwatch: github: philipp-classen/awscr-cloudwatch -
Run
shards install
Usage
require "awscr-cloudwatch"
client = Awscr::CloudWatch::Client.new("us-east-1", "key", "secret")
# With temporary credentials: Client.new("us-east-1", "key", "secret", "session_token")
Publishing metrics
metrics = client.metrics
# One counter increment
metrics.put_counter("MyApp", "Requests", dimensions: {"Env" => "prod"})
# Several data points in one request (up to 1000 metrics / 1 MB)
metrics.put_metric_data("MyApp", [
Awscr::CloudWatch::MetricDatum.counter("Requests", 42, {"Env" => "prod"}),
Awscr::CloudWatch::MetricDatum.new("Latency", values: [1.5, 2.5], counts: [20.0, 1.0], unit: "Milliseconds"),
Awscr::CloudWatch::MetricDatum.new("BatchSize", unit: "Count",
statistic_values: Awscr::CloudWatch::StatisticSet.new(sample_count: 4, sum: 10, minimum: 1, maximum: 4)),
])
Calls return nil on success and raise Awscr::CloudWatch::ApiException when AWS rejects the request. Throttling, 5xx responses and connection errors are retried with exponential backoff (max_attempts: 3 by default).
Querying metrics
stats = metrics.get_metric_statistics("MyApp", "Requests",
start_time: Time.utc - 1.hour, end_time: Time.utc, period: 5.minutes,
statistics: ["Sum"], dimensions: {"Env" => "prod"})
stats.datapoints.each { |dp| puts "#{dp.timestamp}: #{dp.sum}" }
data = metrics.get_metric_data([
Awscr::CloudWatch::MetricDataQuery.new("requests",
metric_stat: Awscr::CloudWatch::MetricStat.new(Awscr::CloudWatch::Metric.new("MyApp", "Requests"), 5.minutes, "Sum")),
Awscr::CloudWatch::MetricDataQuery.new("per_second", expression: "requests / 300"),
], start_time: Time.utc - 1.hour, end_time: Time.utc)
data.metric_data_results.each { |r| puts "#{r.id}: #{r.values}" }
metrics.list_metrics(namespace: "MyApp").metrics.each { |m| puts m.metric_name }
Periods are Time::Spans. CloudWatch accepts multiples of one minute, plus 1, 5, 10, 20 and 30 seconds for high-resolution metrics. Anything else raises ArgumentError before a request is sent.
Alarms
alarms = client.alarms
alarms.put_metric_alarm("MyApp-HighErrorRate",
namespace: "MyApp", metric_name: "Errors", statistic: "Sum", period: 1.minute,
evaluation_periods: 3, threshold: 100, comparison_operator: "GreaterThanThreshold",
alarm_actions: ["arn:aws:sns:us-east-1:123456789012:oncall"])
alarms.describe_alarms(alarm_name_prefix: "MyApp-").metric_alarms.each do |alarm|
puts "#{alarm.alarm_name}: #{alarm.state_value}"
end
alarms.delete_alarms(["MyApp-HighErrorRate"])
MetricClient and AlarmClient can also be used on their own; they take the same constructor arguments as Client.
Custom endpoint and HTTP clients
# Local mock such as Ministack
client = Awscr::CloudWatch::Client.new("us-east-1", "dummy", "dummy", endpoint: "http://localhost:4566")
# Shorter timeouts (defaults: 15 s to connect, 60 s to read)
factory = Awscr::CloudWatch::DefaultHttpClientFactory.new(connect_timeout: 5.seconds, read_timeout: 10.seconds)
client = Awscr::CloudWatch::Client.new("us-east-1", "key", "secret", client_factory: factory)
# Connection pooling: subclass HttpClientFactory (acquire_client / release)
Development
crystal spec
crystal run lib/ameba/bin/ameba.cr
Integration specs only run with AWSCR_CLOUDWATCH_INTEGRATION=1. Against a local mock such as Ministack (which does not fully conform to the AWS API, so just the basic specs pass: uploads, dashboards, connection reuse):
export AWS_ENDPOINT_URL=http://localhost:4566
export AWSCR_CLOUDWATCH_INTEGRATION=1
crystal spec spec/integration
Against a real account:
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
AWS_REGION=us-east-1
AWSCR_CLOUDWATCH_INTEGRATION=1
AWSCR_CLOUDWATCH_TEST_PREFIX=my-test
crystal spec spec/integration
Be careful: this creates alarms, a dashboard and an anomaly detector under the test prefix, and published metrics cannot be deleted.
Contributing
- Fork it (https://github.com/philipp-classen/awscr-cloudwatch/fork)
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request
Contributors
- Philipp Claßen - creator and maintainer
awscr-cloudwatch
- 0
- 0
- 0
- 1
- 2
- 12 days ago
- September 19, 2026
MIT License
Thu, 01 Oct 2026 09:09:15 GMT