Repository navigation
E2E workflow: deploy the template into a throwaway AWS account and read telemetry back - #6
Merged
Merged
Conversation
…d read telemetry back The workflow creates an AWS source, deploys the template with that source's ClusterId, token and id, pastes the outputs back into the source, waits for the sync's subscription filters, produces logs, a custom metric, an X-Ray trace and a CloudTrail management event, and reads all four back through the team's SQL API connection with exact counts. Pull requests and pushes to main deploy the checkout's template; the daily schedule deploys the published one and fails when it differs from main. Everything is deleted afterwards, plus leftovers older than two hours. AWS access is OIDC through the role in e2e/bootstrap.yaml. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A cancelled job gets only a short grace period, so its cleanup can be killed while the stack is still deleting; the next run then collided with the leftover for up to two hours. The cleanup now lives in e2e/cleanup.sh, runs before and after every run, and deletes everything of ours regardless of age, since the concurrency group allows one run per account. It matches run stacks by their e2e-gh prefix: the earlier e2e- prefix also matched the standing e2e-bootstrap stack and only its age had protected it. configure-aws-credentials goes to v5. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A fresh customer account gets both subscribed by default. The sandbox account is permanent in Better Stack (one AwsAccount per organization and AWS account id, kept across source deletions), and each earlier run's stack deletion looked like an external unsubscribe to the sync's reconcile, which then never re-subscribed them. The run now creates explicit subscriptions for the two through the log-group-subscriptions API once X-Ray has created aws/spans; the run's own log group still relies on auto-subscribe. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… both Two log groups are created before the stack: one named after the run and one always named /e2e/static, which every run deletes and recreates. The sync must auto-subscribe the new one on its own. The static group, aws/spans and the CloudTrail group must stay unsubscribed, because the sandbox account record is permanent in Better Stack (T-21948) and a deleted and recreated group counts as explicitly unsubscribed (T-21949); that step names both issues and fails when either is fixed. The three are then subscribed through the log-group-subscriptions API, and 20 lines are written into each of the two groups and counted per group. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… stored trace id
The mapper stores an X-Ray span as {dt, resource, span: {...}}, so the
trace id and name live under span. Spans are counted by their names and
the sample's stored trace ids must equal the X-Ray trace id in its
32-hex form. CloudTrail delivers management events within 15 minutes
and the trail is minutes old at that point, so the read-back waits up
to 25 minutes and, on a timeout, saves the newest CloudTrail and span
rows for the summary.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…he API subscriptions CloudTrail writes its events into /aws/cloudtrail/better-stack and the subscription filter is in place, but CloudWatch Logs forwards none of CloudTrail's batches to the Firehose, while events written into the same group by hand are forwarded and a CloudTrail record pushed into the Firehose by hand reaches the source (T-21951). The read-back no longer waits for CloudTrail; it asserts that no CloudTrail row arrived and fails, naming the issue, once rows start flowing. The frozen-subscription check and the API subscriptions are one step now. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Production accounts with older stacks do receive CloudTrail rows (T-21951 updated); the sandbox only ever sees a stack's first half hour. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every run deletes the template's IAM roles and the next one recreates them under the same names, while AWS keeps using sessions of the deleted roles for up to an hour. CloudWatch Logs holds the subscription role's session per log group name, so delivery from aws/spans, /aws/cloudtrail/better-stack and /e2e/static failed with a non-retryable error, the filter paused for 10 minutes and skipped what arrived meanwhile, even for a log group recreated with a new filter. CloudTrail holds its delivery role's session the same way and wrote nothing into its log group. Measured in the sandbox account: stale filters recovered exactly one hour after CloudWatch Logs had assumed the role, and a stack deployed an hour after the previous one forwarded all 123 CloudTrail events with no delivery error. A run now waits until 65 minutes after the latest e2e-gh* stack deletion, then refreshes its AWS credentials. The CloudTrail check requires this run's PutRetentionPolicy event as exactly one row instead of freezing CloudTrail at none, the read-back allows 20 minutes and prints each group's incoming, forwarded and delivery-error counts when something is missing. The sweep also deletes /aws/application-signals/data, which X-Ray Transaction Search creates outside the stack. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The hour-long wait goes. A step measures how long ago the latest e2e-gh* stack was deleted. More than 65 minutes ago, the read-back is strict as before and waits for the static group, aws/spans and the CloudTrail event. Within that hour it waits only for the run's own log group and the metric; the static group, aws/spans or CloudTrail delivering nothing becomes a warning in the log and the job summary, with the forwarding metrics printed. Any other wrong count still fails, and the span trace id is checked whenever the spans arrived. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PetrHeinz
marked this pull request as ready for review
October 16, 2026 10:26
This workflow only ever assigns Petr, so the assignee input, the Pawel and Collectors secrets and the branch choosing between them go. The issue lands in the Telemetry team, state Plan, project Ingestion for everything, priority High, assigned to Petr. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The read-back only counted metric rows and the sample showed name and tags, so wrong values would have passed. The three datapoints now carry 1, 2 and 3 in three consecutive minutes. The mapper stores each minute's aggregate as the metric plus _max, _min, _sum and _count, and all 15 points must hold exactly what was sent (1 for _count), comparing the lowest and highest stored value per point and grouping by minute, since AWS does not document whether the metric stream stamps a minute's start. The sample shows the metric's three minutes with their values. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The bootstrap stack is deployed once per account and already exists, so the template does not need to live in this repository; the header still names the standing e2e-bootstrap stack. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A new
E2Eworkflow deploys the template into a throwaway AWS account the way a customer sets it up and reads the resulting telemetry back from Better Stack. It runs on every pull request and push to main with the template from the checkout, and daily with the published S3 template, which must then equal main.What a run does:
awssource in the E2E testing team, warms it up until the ingesters accept its token, and pre-creates two log groups: one named after the run, and/e2e/static, which every run recreates under the same namecloudformation/full/better-stack-full.yamlwith that source'sClusterId, token and id, pastes theIntegrationRoleArnandExternalIdoutputs back into the source, and waits until the sync has put theBetterStackLogssubscription filter on the run's log group/e2e/static,aws/spansand the CloudTrail group unsubscribed, because Better Stack remembers them from earlier runs, then subscribes them through the API. This is current behaviour, and the run fails with a pointer to the internal ticket once it changes.PutRetentionPolicycall, then reads all of them back through the team's SQL API connection with exact counts. It counts again a minute later to catch duplicate delivery and checks that the stored trace id matches the X-Ray one.aws/spans,/aws/application-signals/dataand the/e2e/*log groups, and fails if it cannot list or delete somethingA run within an hour of the previous run's stack deletion checks the static group,
aws/spansand CloudTrail leniently. It waits only for the run's own log group and the metric, and when one of those three delivered nothing, it adds a warning to the log and the job summary instead of failing. Any other wrong count still fails. The template names its IAM roles per account, so every run recreates them under the same names, and AWS keeps using sessions of the deleted roles for up to an hour:aws/spans, the CloudTrail group and/e2e/statichave the same names in every run./aws/cloudtrail/better-stackthe same way, and writes nothing there until that session expires.Runs in quick succession lose exactly this data: the run-named group always arrives, while the fixed-name groups fail at random. A run more than an hour after the previous one checks everything strictly. Customers keep their roles and are not affected. A customer who deletes and redeploys the stack would lose up to an hour of logs from the groups that were subscribed before.
When something does not arrive within 20 minutes, the run prints the incoming, forwarded and delivery-error counts of each subscribed log group.
The account is
better-stack-e2e-aws-stack(251917137055), a member of the Better Stack organization that holds nothing else. AWS access is GitHub OIDC through thegithub-actions-e2erole of a one-time stack that is already deployed in the account, so no AWS keys live in GitHub. The role has administrator access because the template creates IAM roles, Lambdas, Firehose streams, CloudTrail and S3, and the account is otherwise empty. The template's role and bucket names are fixed per account, so a concurrency group keeps it to one deploy at a time. Pull requests from forks are skipped, since they get no OIDC token.The job summary shows the counts, sample rows and the cleanup. Secrets
TEST_TEAM_TELEMETRY_API,TEST_TEAM_CONNECTION_USERNAMEandTEST_TEAM_CONNECTION_PASSWORDare set. TheLINEAR_*secrets are set as well: a failure on main or on the schedule opens a High-priority issue in the Telemetry team's Plan state, in the Ingestion for everything project, assigned to Petr.🤖 Generated with Claude Code