overcast local AWS emulator

Service Reference

CloudWatch — Amazon CloudWatch

Amazon CloudWatch (monitoring and alarms) answers all three protocols its model declares: the Query protocol, the JSON protocol the AWS CLI and SDKs send, and Smithy RPC v2 CBOR.

CloudWatch — Amazon CloudWatch

AWS docs: https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/

Amazon CloudWatch (monitoring and alarms) answers all three wire protocols its pinned model declares: the Query protocol — form-encoded POST requests with Action and Version=2010-08-01 parameters — the JSON protocol the AWS CLI and the AWS SDKs send, and Smithy RPC v2 CBOR, which newer SDK majors negotiate for a service that declares it.


Notes

  • Query protocol: POST / HTTP/1.1 with Action=<Operation>&Version=2010-08-01 in the form body.
  • JSON protocol: POST / HTTP/1.1 with Content-Type: application/x-amz-json-1.0 and X-Amz-Target: GraniteServiceVersion20100801.<Operation>. This is what the AWS CLI and the SDKs send.
  • Smithy RPC v2 CBOR: POST /service/GraniteServiceVersion20100801/operation/<Operation> with Content-Type: application/cbor and Smithy-Protocol: rpc-v2-cbor.
  • Every supported operation answers on all three, from one shared implementation per operation — the same call returns the same result whichever protocol an SDK negotiates.
  • Unrecognized Query operations return an XML 501 Not Implemented error response; unrecognized JSON targets return 400 UnknownOperationException, as on AWS; and an unimplemented operation addressed over RPC v2 returns 501 Not Implemented in CBOR.
  • PutMetricData appears in both Alarms and Metrics categories as it supports both use cases.
  • Metric datapoint retention diverges from real AWS: datapoints are retained for ~1 hour (all storage backends), enforced by read-time filtering plus a periodic background sweep — real CloudWatch retains metric data for up to 15 months at declining resolution. Overcast only bounds local growth; it is not suitable for historical metric analysis. An alarm whose Period × EvaluationPeriods reaches back further than that window sees the missing periods and resolves them through TreatMissingData.

Alarm evaluation

Alarms are evaluated automatically. A single background loop, driven by the injected clock, evaluates each alarm over the last EvaluationPeriods closed periods, aligned to the epoch the way real CloudWatch aligns them — so a datapoint published into the period still accumulating is not yet a datapoint to evaluate, and an alarm reacts to a breach within about one period.

StateValue moves between OK, ALARM and INSUFFICIENT_DATA with AWS’s StateReason sentence and StateReasonData JSON document. Every transition writes a StateUpdate item to DescribeAlarmHistory, publishes the CloudWatch Alarm State Change event to the default EventBridge bus (source aws.cloudwatch), and fires the actions configured for the state it moved into. Actions fire on a transition only — a re-evaluation landing on the same state fires nothing, exactly as on AWS.

What is evaluated

ConfigurationBehaviour
Namespace + MetricName + DimensionsEvaluated. An alarm sees only its own dimension set
StatisticAverage, Sum, SampleCount, Minimum, MaximumEvaluated
Threshold with GreaterThanThreshold, GreaterThanOrEqualToThreshold, LessThanThreshold, LessThanOrEqualToThresholdEvaluated
Period, EvaluationPeriods, DatapointsToAlarmEvaluated, including the “M out of N” rule
TreatMissingDatamissing, ignore, breaching, notBreachingEvaluated
AlarmActions / OKActions / InsufficientDataActions naming an SNS topicDelivered through the emulator’s own SNS Publish, carrying real CloudWatch’s notification body
ActionsEnabled, EnableAlarmActions, DisableAlarmActionsHonoured
UnitSelects which datapoints the alarm sees — a metric published under several units evaluates separately per unit
TagsApplied when the alarm is created. Ignored on a PutMetricAlarm that updates an existing alarm, as on AWS — use TagResource/UntagResource
SetAlarmStateForces the state and fires that state’s actions

Optional parameters and their defaults

PutMetricAlarm marks almost everything Required: No, but that is not the same as “has a default”. Three parameters AWS documents a default for, and Overcast applies the same one:

ParameterDefault when omitted
ActionsEnabledtrue
DatapointsToAlarmEvaluationPeriods — “N out of N”
TreatMissingDatamissing

Five more are optional only because a PromQL alarm carries them inside EvaluationCriteria instead. For an alarm on a metric they are required, and a request that omits one gets a 400 ValidationError rather than a substituted value — Statistic (or ExtendedStatistic), ComparisonOperator, Period, EvaluationPeriods and Threshold. Overcast used to fill these in with Average / GreaterThanThreshold / 60s / 1 period / 0.0, which is not a default so much as a different alarm from the one the caller half-described. Threshold: 0 is a value, not an omission.

AlarmName is required by PutMetricAlarm and optional on AWS::CloudWatch::Alarm — CloudFormation generates {StackName}-{LogicalID}-{RANDOM} when a template leaves it out, which is what CDK relies on.

What is created but not evaluated

An alarm whose configuration the evaluator cannot decide is created and says so, rather than being refused. An alarm that looks armed but is never watched is a real trap — the one the fidelity-risk veto exists to prevent — so it is never left silent; it is created and it declares itself, in all three places anyone looks:

  • StateValue stays INSUFFICIENT_DATA and StateReason says the state is not computed.
  • x-overcast-emulation-limitation on the PutMetricAlarm response names what is not emulated, for anything reading the wire. Ordinary alarms carry no such header — it marks the exceptions, and a header on every alarm would train people to ignore it.
  • ResourceStatusReason on the CloudFormation event, when the alarm came from a template, so it appears as the deploy goes past (see CloudFormation).
ConfigurationResult
Metrics (metric math / multi-metric alarms)created, not evaluated
ThresholdMetricId (anomaly detection)created, not evaluated
ExtendedStatistic (p99, tm99, …)created, not evaluated
LessThanLowerOrGreaterThanUpperThreshold, LessThanLowerThreshold, GreaterThanUpperThresholdcreated, not evaluated — anomaly-band operators

Refusing these used to fail the CloudFormation resource, and with it the stack and the whole deploy — a monitoring stack that builds one alarm per function took the environment down with it. The alarm’s own defect is that Overcast will not act on it; that is not a reason to refuse everything standing behind it.

What is refused

ConfigurationResponse
EvaluationCriteria (PromQL alarms)501 NotImplemented from PutMetricAlarm
PutCompositeAlarm, PutAnomalyDetector501 NotImplemented
An action ARN with no sink — EC2 instance actions, Systems Manager OpsItemsThe transition still happens and is still published; the undelivered action is logged and recorded as an Action history item saying it was NOT executed

A metric-math alarm that also names a Namespace/MetricName at the top level is one AWS itself rejects, and still gets 400 ValidationError. Accepting the shapes Overcast cannot evaluate is not a reason to accept the ones AWS would not have.

Values AWS itself rejects — an unknown Statistic, an unknown ComparisonOperator, an invalid TreatMissingData, a Period that is not 10, 20, 30 or a multiple of 60, or DatapointsToAlarm greater than EvaluationPeriods — get AWS’s 400 ValidationError, not a 501. The two claims are different: one says the request is wrong, the other says Overcast is incomplete.

Deliberate divergences

  • SetAlarmState is held longer than on AWS. Real CloudWatch reverts a forced state at the next evaluation, which can be almost immediately. Overcast protects it for one full evaluation range (Period × EvaluationPeriods) so a forced state is actually observable in DescribeAlarms and actually reaches its actions.
  • No look-back beyond the evaluation range. Real CloudWatch may reach further back in time to fill an evaluation range short of real datapoints. Overcast evaluates exactly the configured range and resolves the gaps through TreatMissingData.
  • Alarm history is bounded by count, not age. The most recent 100 items per alarm are kept; real CloudWatch keeps 14 days.
  • A datapoint published without a unit feeds an alarm that names one. AWS files an unqualified datapoint under None, so on AWS an alarm on Count never sees it and sits in INSUFFICIENT_DATA — the trap the PutMetricAlarm docs warn about when they recommend omitting Unit. Locally published metrics routinely omit the unit while the CDK construct that created the alarm supplied one, so Overcast lets the unqualified datapoint count. A datapoint that does name a unit is still held to it.
  • EvaluationWindow is accepted and ignored. Overcast always evaluates the period-aligned window described above, rather than AWS’s default sliding window.

Tagging

AWS tags four CloudWatch resource types — alarms, dashboards, metric streams and Contributor Insights rules. Overcast emulates alarms only, so the alarm is the whole taggable surface; an ARN naming any of the other three is well-formed but refers to a resource that does not exist here, and is answered accordingly.

ResourceTag on createTag after create
Alarm (arn:aws:cloudwatch:<region>:<account>:alarm:<name>)PutMetricAlarm TagsTagResource / UntagResource / ListTagsForResource
Dashboard, metric stream, Contributor Insights rulenot emulatednot emulated — ResourceNotFoundException
  • Tags apply at creation only. PutMetricAlarm applies Tags when it creates the alarm and ignores them when the same call updates an existing one, as on AWS. TagResource and UntagResource are the only way to change an existing alarm’s tags.
  • Tags are deleted with the alarm. DeleteAlarms drops the tags too, so an alarm recreated under the same name starts untagged.
  • An unknown resource is an error, not an empty tag set. All three tagging operations return 404 ResourceNotFoundException for an ARN whose alarm does not exist, and 400 InvalidParameterValue (InvalidParameterValueException over the JSON protocol — the model gives that shape a shorter awsQueryError code) for a ResourceARN that is not a CloudWatch ARN, including an empty one.
  • Tag sets are validated, on both entry points. A resource is capped at 50 tags, a key must be 1–128 characters and must not start with aws:, and a value must be 256 characters or fewer. A rejected set is not written, and the same rules apply whether the tags arrive on TagResource or on the Tags parameter of the PutMetricAlarm that creates the alarm — so a create carrying an invalid tag set fails outright rather than leaving an untagged alarm behind. The Query protocol’s flattened member list ends at the first missing Key, so an empty tag key can only be expressed — and only be rejected — over the JSON protocol.

Summary

Category✅ Supported❌ Unsupported
General152

Endpoints

General

OperationStatusNotesAWS Docs
DeleteAlarms✅ SupportedDeletes one or more alarms by name, along with their historydocs
DescribeAlarmHistory✅ SupportedReturns StateUpdate, ConfigurationUpdate and Action items; filters by alarm name, item type, date range, MaxRecords and ScanBy. The most recent 100 items per alarm are retaineddocs
DescribeAlarms✅ SupportedLists alarms, supports filtering; reports the evaluator’s live StateValue, StateReason and StateReasonDatadocs
DescribeAlarmsForMetric✅ SupportedLists alarms for a specific metricdocs
DisableAlarmActions✅ SupportedClears ActionsEnabled so transitions stop firing actionsdocs
EnableAlarmActions✅ SupportedSets ActionsEnabled so transitions fire actions againdocs
GetMetricData✅ SupportedReturns query-based metric values over time ranges, over all three protocols the model declares — Query, awsJson1_0 (primary, #886) and Smithy RPC v2 CBOR (#1280) — from one shared evaluation core, so an SDK gets the same result whichever it negotiates. Merges custom PutMetricData points with automatically-recorded service metrics (AWS/Lambda’s Invocations/Errors/Duration/Throttles/ConcurrentExecutions pilot — docs/plans/service-metrics-platform.md) from internal/metrics, read-through, when service-metrics collection is enableddocs
GetMetricStatistics✅ SupportedReturns aggregated datapoints by period, over Query, awsJson and rpcv2Cbor alike (#1280). Merges custom PutMetricData points with automatically-recorded service metrics from internal/metrics (docs/plans/service-metrics-platform.md), so an alarm on e.g. AWS/Lambda Errors evaluates against real invocation outcomesdocs
ListMetrics✅ SupportedLists available metrics over Query, awsJson and rpcv2Cbor (#1280), merging custom PutMetricData series with automatically-recorded service metrics (docs/plans/service-metrics-platform.md)docs
ListTagsForResource✅ SupportedLists tags for an alarm, over the Query, JSON and rpcv2Cbor protocols (#1280). Alarms are the only taggable CloudWatch resource Overcast emulates, so any other ResourceARN is ResourceNotFoundException — or InvalidParameterValue when it is not a CloudWatch ARN at alldocs
PutMetricAlarm✅ SupportedCreates or updates a single-metric alarm, which is then evaluated automatically (Threshold, ComparisonOperator, Period, EvaluationPeriods, DatapointsToAlarm, Dimensions, TreatMissingData). Metric-math/multi-metric alarms, anomaly detection (ThresholdMetricId) and extended statistics are created but never evaluated, and say so in the alarm’s StateReason and an x-overcast-emulation-limitation response header; PromQL alarms (EvaluationCriteria) are still refused with 501. Tags are applied at creation only and validated against the same rules as TagResource, so a create carrying an invalid tag set fails rather than leaving an untagged alarmdocs
PutMetricData✅ SupportedPublishes metric data pointsdocs
SetAlarmState✅ SupportedForces an alarm’s state and fires that state’s actions; the forced state is held against the evaluator for one evaluation rangedocs
PutAnomalyDetector❌ Unsupportedstub; returns 501 — there is no anomaly-detection model behind the emulatordocs
PutCompositeAlarm❌ Unsupportedstub; returns 501 — composite alarm rules are not evaluateddocs
TagResource✅ SupportedAdds or updates tags on an alarm, over the Query, JSON and rpcv2Cbor protocols (#1280). Tagging an alarm that does not exist is ResourceNotFoundException, as on AWS. Tag sets are validated — 50 tags per resource, keys 1-128 characters and not aws:-prefixed, values up to 256 — and a rejected set is not writtendocs
UntagResource✅ SupportedRemoves tags from an alarm, over the Query, JSON and rpcv2Cbor protocols (#1280). A key that is not present is ignored; an alarm that does not exist is ResourceNotFoundExceptiondocs