Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
a9b7c80
feat(aws): stream CloudWatch metrics to Maple through Firehose
Makisuo Oct 22, 2026
933bbe8
Merge remote-tracking branch 'origin/feat/aws-principal' into feat/aw…
Makisuo Oct 22, 2026
2b7d415
fix(aws): empty the failed-deliveries bucket before deleting a metric…
Makisuo Oct 22, 2026
62955b6
test(aws): run the setup and cleanup scripts against a fake aws CLI
Makisuo Oct 22, 2026
be10f32
fix(aws): retry a metric stream delete request AWS refused
Makisuo Oct 22, 2026
301b9ce
Merge branch 'feat/aws-principal' into feat/aws-metric-stream
Makisuo Oct 22, 2026
3c97f7f
test(aws): give the removal stub the metric stream fields; delete cop…
Makisuo Oct 22, 2026
60371d0
Merge branch 'feat/aws-principal' into feat/aws-metric-stream
Makisuo Oct 22, 2026
0f7b24e
fix(ingest): snake_case CloudWatch dimension attribute keys
Makisuo Oct 22, 2026
876ce20
Merge branch 'feat/aws-principal' into feat/aws-metric-stream
Makisuo Oct 22, 2026
a687d03
Merge branch 'feat/aws-principal' into feat/aws-metric-stream
Makisuo Oct 22, 2026
1644280
Merge branch 'feat/aws-principal' into feat/aws-metric-stream
Makisuo Oct 22, 2026
6b56dd3
fix(aws): turning a metric stream off revokes its secret
Makisuo Oct 22, 2026
cbf2055
Merge branch 'feat/aws-principal' into feat/aws-metric-stream
Makisuo Oct 22, 2026
1dc226f
fix(ingest): drop empty CloudWatch requests and resources while decoding
Makisuo Oct 22, 2026
f86f917
fix(ingest): cap metric points per CloudWatch delivery
Makisuo Oct 22, 2026
6564daf
Merge branch 'feat/aws-principal' into feat/aws-metric-stream
Makisuo Oct 22, 2026
8657243
fix(ingest): also drop empty scope metrics while decoding
Makisuo Oct 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions apps/api/src/routes/v2/integrations-aws.http.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ describe("v2 aws integration over HTTP", () => {
verified_at: null,
last_checked_at: null,
last_check_error: null,
metric_stream: null,
metrics_last_received_at: null,
metrics_last_error: null,
created_at: expect.stringMatching(/^\d{4}-\d{2}-\d{2}T.*Z$/),
})
const id: string = created.body.id
Expand Down Expand Up @@ -218,6 +221,16 @@ describe("v2 aws integration over HTTP", () => {
modules: ["cost"],
})
expect(planned.status).toBe(400)
const elsewhere = await harness.request("POST", CONNECTIONS, admin.secret, {
account_id: "123456789012",
metric_stream: { regions: ["mars-north-1a"], namespaces: ["AWS/ECS"] },
})
expect(elsewhere.status).toBe(400)
const nothing = await harness.request("POST", CONNECTIONS, admin.secret, {
account_id: "123456789012",
metric_stream: { regions: ["us-east-1"], namespaces: [] },
})
expect(nothing.status).toBe(400)
await harness.dispose()
})

Expand Down
8 changes: 8 additions & 0 deletions apps/api/src/routes/v2/integrations-aws.http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,16 @@ const toV2Connection = (connection: AwsConnection): V2AwsConnection => ({
verified_at: isoTimestampOrNull(connection.verifiedAt),
last_checked_at: isoTimestampOrNull(connection.lastCheckedAt),
last_check_error: connection.lastCheckError,
metric_stream: connection.metricStream,
metrics_last_received_at: isoTimestampOrNull(connection.metricsLastReceivedAt),
metrics_last_error: connection.metricsLastError,
created_at: isoTimestamp(connection.createdAt),
})

const auditMetadata = (connection: AwsConnection) => ({
account_id: connection.accountId,
modules: connection.modules,
metric_stream: connection.metricStream,
})

export const HttpV2AwsIntegrationsLive = HttpApiBuilder.group(MapleApiV2, "awsIntegration", (handlers) =>
Expand All @@ -64,6 +68,7 @@ export const HttpV2AwsIntegrationsLive = HttpApiBuilder.group(MapleApiV2, "awsIn
const connection = yield* aws.create(tenant.orgId, tenant.userId, {
accountId: payload.account_id,
modules: payload.modules ?? [],
metricStream: payload.metric_stream ?? null,
})
yield* recordHttpAudit("aws_connection.created", {
resourceId: connection.id,
Expand All @@ -78,6 +83,7 @@ export const HttpV2AwsIntegrationsLive = HttpApiBuilder.group(MapleApiV2, "awsIn
yield* requireAdmin(tenant.roles, adminOnly)
const connection = yield* aws.update(tenant.orgId, params.id, {
modules: payload.modules,
metricStream: payload.metric_stream,
})
yield* recordHttpAudit("aws_connection.updated", {
resourceId: connection.id,
Expand All @@ -99,6 +105,8 @@ export const HttpV2AwsIntegrationsLive = HttpApiBuilder.group(MapleApiV2, "awsIn
cleanup_script: setup.cleanupScript,
cloudformation_template: setup.cloudformationTemplate,
terraform: setup.terraform,
metrics_stack_name: setup.metricsStackName,
metrics_cloudformation_template: setup.metricsCloudformationTemplate,
}
}),
)
Expand Down
Loading
Loading