Repository navigation
feat(datadog): loud MacroDB prod CPU and wait alerts #6904
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d1e36b7
d394564
f3f5469
ae52a27
55c7e14
5950fae
1cf290f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| name: Sync MacroDB Datadog alerts | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| push: | ||
| paths: | ||
| - 'infra/stacks/datadog-macrodb-alerts/monitors.ts' | ||
| - 'infra/stacks/datadog-macrodb-alerts/sync.ts' | ||
| - '.github/workflows/sync-macrodb-datadog-alerts.yml' | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alert sync runs on every branchMedium Severity The sync workflow triggers on Reviewed by Cursor Bugbot for commit 55c7e14. Configure here.
Comment on lines
+5
to
+9
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🛡️ Detected with Advanced Tier | 🟠 Major | ⚡ Quick win Sensitive Data Exposure Reachability: External Restrict production sync to an approved branch. A push to any same-repository branch that changes a listed file runs that branch’s As per path instructions, “Ensure workflow triggers are appropriate (push vs PR vs manual).” 🤖 Prompt for AI Agents |
||
|
|
||
| concurrency: | ||
| group: sync-macrodb-datadog-alerts | ||
| cancel-in-progress: false | ||
|
|
||
| jobs: | ||
| sync: | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| steps: | ||
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - uses: oven-sh/setup-bun@v2 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🛡️ Detected with Advanced Tier | 🟠 Major | ⚡ Quick win Security Misconfiguration Reachability: Internal Pin The As per path instructions, “Check for pinned action versions (use SHA, not tags).” 🤖 Prompt for AI Agents |
||
| with: | ||
| bun-version: 1.2.0 | ||
|
|
||
| - name: Upsert MacroDB Datadog monitors | ||
| working-directory: infra/stacks/datadog-macrodb-alerts | ||
| env: | ||
| DD_API_KEY: ${{ secrets.DD_API_KEY }} | ||
| DD_APP_KEY: ${{ secrets.DD_APP_KEY }} | ||
| DD_SITE: us5.datadoghq.com | ||
| run: bun run sync.ts | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| config: | ||
| aws:region: us-east-1 | ||
| datadog:validate: "false" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| config: | ||
| aws:region: us-east-1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| name: datadog-macrodb-alerts | ||
| runtime: nodejs | ||
| description: Datadog monitors for MacroDB primary and read replica |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import * as datadog from '@pulumi/datadog'; | ||
| import * as pulumi from '@pulumi/pulumi'; | ||
| import { MACRODB_PROD_MONITORS } from './monitors'; | ||
|
|
||
| const stack = pulumi.getStack(); | ||
|
|
||
| if (stack === 'prod') { | ||
| for (const spec of MACRODB_PROD_MONITORS) { | ||
| new datadog.Monitor(spec.id, { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: set -eu
printf '%s\n' '--- changed files ---'
git diff --name-status ddddcb44d4bdb201a3c92aaf4e1f6fffba5fd298 5950fae30badddb8313cefbb78e7af0d16add9ef
printf '%s\n' '--- target stack ---'
git show 5950fae30badddb8313cefbb78e7af0d16add9ef:infra/stacks/datadog-macrodb-alerts/index.ts | nl -ba
printf '%s\n' '--- sync candidates ---'
git ls-tree -r --name-only 5950fae30badddb8313cefbb78e7af0d16add9ef | rg '(^|/)(sync|datadog|macrodb).*\.ts$|datadog-macrodb-alerts'
printf '%s\n' '--- sync references ---'
rg -n -i 'sync|upsert|create.*monitor|monitor.*create|managed.?tag|MACRODB_PROD_MONITORS' infra --glob '*.ts' || trueRepository: macro-inc/macro Length of output: 21185 🏁 Script executed: git show 5950fae30badddb8313cefbb78e7af0d16add9ef:infra/stacks/datadog-macrodb-alerts/index.ts | nl -ba
git ls-tree -r --name-only 5950fae30badddb8313cefbb78e7af0d16add9ef | grep -E '(^|/)(sync|datadog|macrodb).*\.ts$|datadog-macrodb-alerts' || true
grep -RInE 'sync|upsert|create.*monitor|monitor.*create|managed.?tag|MACRODB_PROD_MONITORS' infra --include='*.ts' || trueRepository: macro-inc/macro Length of output: 17023 🏁 Script executed: set -eu
for f in \
infra/stacks/datadog-macrodb-alerts/sync.ts \
.github/workflows/sync-macrodb-datadog-alerts.yml \
infra/stacks/datadog-macrodb-alerts/package.json; do
printf '\n--- %s ---\n' "$f"
git show 5950fae30badddb8313cefbb78e7af0d16add9ef:"$f" | nl -ba
doneRepository: macro-inc/macro Length of output: 6510 Use one owner for the Datadog monitors.
🤖 Prompt for AI Agents |
||
| name: spec.name, | ||
| type: spec.type, | ||
| query: spec.query, | ||
| message: spec.message, | ||
| tags: spec.tags, | ||
| priority: String(spec.priority), | ||
| monitorThresholds: { | ||
| critical: spec.thresholds.critical, | ||
| warning: spec.thresholds.warning, | ||
| criticalRecovery: spec.thresholds.criticalRecovery, | ||
| warningRecovery: spec.thresholds.warningRecovery, | ||
| }, | ||
| requireFullWindow: spec.requireFullWindow, | ||
| evaluationDelay: spec.evaluationDelay, | ||
| notifyNoData: spec.notifyNoData, | ||
| noDataTimeframe: spec.noDataTimeframe, | ||
| includeTags: true, | ||
| newGroupDelay: 60, | ||
| timeoutH: 0, | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| export const monitorCount = stack === 'prod' ? MACRODB_PROD_MONITORS.length : 0; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we really need to export this? |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,170 @@ | ||
| /** | ||
| * MacroDB prod alert registry. | ||
| * | ||
| * Each entry becomes one Datadog metric monitor. Deploy only on the prod stack. | ||
| * Notifications target the Macro Alerts channel via @webhook-macro-alert-hook. | ||
| */ | ||
|
|
||
| export type MonitorSpec = { | ||
| /** Pulumi resource name. Stable across deploys. */ | ||
| id: string; | ||
| name: string; | ||
| type: 'query alert'; | ||
| query: string; | ||
| message: string; | ||
| tags: string[]; | ||
| thresholds: { | ||
| critical: string; | ||
| warning?: string; | ||
| criticalRecovery?: string; | ||
| warningRecovery?: string; | ||
| }; | ||
| priority: number; | ||
| requireFullWindow?: boolean; | ||
| evaluationDelay?: number; | ||
| notifyNoData?: boolean; | ||
| noDataTimeframe?: number; | ||
| }; | ||
|
|
||
| /** RDS instance identifiers for MacroDB prod primary and read replica. */ | ||
| export const MACRODB_PROD_DB_IDS = | ||
| 'dbinstanceidentifier:macro-db-prod OR dbinstanceidentifier:macro-db-prod-read-replica'; | ||
|
|
||
| /** | ||
| * DBM `database_instance` tags (FQDNs) for MacroDB prod primary and read replica. | ||
| */ | ||
| export const MACRODB_PROD_DATABASE_INSTANCES = | ||
| 'database_instance:macro-db-prod.ctkwyjgndnfr.us-east-1.rds.amazonaws.com OR database_instance:macro-db-prod-read-replica.ctkwyjgndnfr.us-east-1.rds.amazonaws.com'; | ||
|
|
||
| export const MACRODB_PROD_READ_REPLICA_DATABASE_INSTANCE = | ||
| 'database_instance:macro-db-prod-read-replica.ctkwyjgndnfr.us-east-1.rds.amazonaws.com'; | ||
|
|
||
| const ALERTS_CHANNEL = '@webhook-macro-alert-hook'; | ||
|
|
||
| const COMMON_TAGS = [ | ||
| 'env:prod', | ||
| 'service:macrodb', | ||
| 'team:infra', | ||
| 'managed:datadog-macrodb-alerts', | ||
| ]; | ||
|
|
||
| function alertMessage(body: string): string { | ||
| return `{{#is_alert}} | ||
| 🚨 ${body} | ||
|
|
||
| ${ALERTS_CHANNEL} | ||
| {{/is_alert}} | ||
| {{#is_warning}} | ||
| ⚠️ ${body} | ||
|
|
||
| ${ALERTS_CHANNEL} | ||
| {{/is_warning}} | ||
| {{#is_recovery}} | ||
| ✅ Recovered: ${body} | ||
|
|
||
| ${ALERTS_CHANNEL} | ||
| {{/is_recovery}}`; | ||
|
Comment on lines
+51
to
+66
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Route replica-lag no-data alerts to the webhook. The replica-lag monitor enables 🤖 Prompt for AI Agents |
||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No-data alerts skip webhookMedium Severity The replica lag monitor sets Additional Locations (1)Reviewed by Cursor Bugbot for commit 55c7e14. Configure here. |
||
|
|
||
| /** | ||
| * Prod MacroDB monitors. | ||
| * | ||
| * Thresholds come from 7d baselines (primary CPU avg ~4% / max ~14%, replica | ||
| * max ~36%, lock-wait spikes, blocked_connections mostly 0 with rare spikes, | ||
| * replica lag usually <1s with rare multi-second bumps). Existing UI monitor | ||
| * "[PROD] RDS High CPU Utilization" stays at 95%/1h and is too quiet; these | ||
| * fire earlier into Alerts. | ||
| */ | ||
| export const MACRODB_PROD_MONITORS: MonitorSpec[] = [ | ||
| { | ||
| id: 'macrodb-cpu-high', | ||
| name: '[PROD] MacroDB CPU high', | ||
| type: 'query alert', | ||
| query: `avg(last_10m):avg:aws.rds.cpuutilization{${MACRODB_PROD_DB_IDS}} by {dbinstanceidentifier}.weighted() > 70`, | ||
| message: alertMessage( | ||
| 'MacroDB {{dbinstanceidentifier.name}} CPU is {{value}}% (threshold {{threshold}}%). Check DBM activity and top queries.' | ||
| ), | ||
| tags: [...COMMON_TAGS, 'signal:cpu'], | ||
| thresholds: { | ||
| critical: '70', | ||
| warning: '50', | ||
| }, | ||
| priority: 2, | ||
| requireFullWindow: true, | ||
| evaluationDelay: 60, | ||
| notifyNoData: false, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CPU monitor skips CloudWatch evaluationsHigh Severity The CPU monitor queries Reviewed by Cursor Bugbot for commit 55c7e14. Configure here. |
||
| }, | ||
| { | ||
| id: 'macrodb-lock-waits-high', | ||
| name: '[PROD] MacroDB lock waits high', | ||
| type: 'query alert', | ||
| query: `avg(last_10m):sum:postgresql.activity.waits{(${MACRODB_PROD_DATABASE_INSTANCES}) AND wait_event_type:Lock} by {database_instance} > 15`, | ||
| message: alertMessage( | ||
| 'MacroDB {{database_instance.name}} has {{value}} sessions in Lock waits (threshold {{threshold}}). Check blockers and long transactions in DBM.' | ||
| ), | ||
| tags: [...COMMON_TAGS, 'signal:lock-waits'], | ||
| thresholds: { | ||
| critical: '15', | ||
| warning: '8', | ||
| }, | ||
| priority: 1, | ||
| requireFullWindow: false, | ||
| evaluationDelay: 60, | ||
| notifyNoData: false, | ||
| }, | ||
| { | ||
| id: 'macrodb-blocked-connections', | ||
| name: '[PROD] MacroDB blocked connections', | ||
| type: 'query alert', | ||
| query: `avg(last_10m):avg:postgresql.activity.blocked_connections{${MACRODB_PROD_DATABASE_INSTANCES}} by {database_instance} > 5`, | ||
| message: alertMessage( | ||
| 'MacroDB {{database_instance.name}} has {{value}} blocked connections (threshold {{threshold}}). Lock contention is active.' | ||
| ), | ||
| tags: [...COMMON_TAGS, 'signal:blocked-connections'], | ||
| thresholds: { | ||
| critical: '5', | ||
| warning: '2', | ||
| }, | ||
| priority: 1, | ||
| requireFullWindow: false, | ||
| evaluationDelay: 60, | ||
| notifyNoData: false, | ||
| }, | ||
| { | ||
| id: 'macrodb-io-waits-high', | ||
| name: '[PROD] MacroDB IO waits high', | ||
| type: 'query alert', | ||
| query: `avg(last_15m):sum:postgresql.activity.waits{(${MACRODB_PROD_DATABASE_INSTANCES}) AND wait_event_type:IO} by {database_instance} > 25`, | ||
| message: alertMessage( | ||
| 'MacroDB {{database_instance.name}} has {{value}} sessions in IO waits (threshold {{threshold}}). Check storage IOPS, WAL, and heavy queries.' | ||
| ), | ||
| tags: [...COMMON_TAGS, 'signal:io-waits'], | ||
| thresholds: { | ||
| critical: '25', | ||
| warning: '15', | ||
| }, | ||
| priority: 2, | ||
| requireFullWindow: true, | ||
| evaluationDelay: 60, | ||
| notifyNoData: false, | ||
| }, | ||
| { | ||
| id: 'macrodb-replication-lag', | ||
| name: '[PROD] MacroDB read replica lag', | ||
| type: 'query alert', | ||
| query: `avg(last_5m):avg:postgresql.replication_delay{${MACRODB_PROD_READ_REPLICA_DATABASE_INSTANCE}} > 60`, | ||
| message: alertMessage( | ||
| 'MacroDB read replica lag is {{value}}s (threshold {{threshold}}s). Reads may be stale; check replica CPU/IO and primary WAL pressure.' | ||
| ), | ||
| tags: [...COMMON_TAGS, 'signal:replication-lag'], | ||
| thresholds: { | ||
| critical: '60', | ||
| warning: '15', | ||
| }, | ||
| priority: 2, | ||
| requireFullWindow: true, | ||
| evaluationDelay: 60, | ||
| notifyNoData: true, | ||
| noDataTimeframe: 20, | ||
| }, | ||
| ]; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "name": "datadog-macrodb-alerts-stack", | ||
| "version": "0.0.0", | ||
| "private": true, | ||
| "license": "MIT", | ||
| "main": "index.ts" | ||
| } |


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be generated using our xtask stuff