@@ -5,9 +5,10 @@ A New Relic Terraform utility with two modes:
55- ** import mode** (default) — scan accounts via NerdGraph and generate
66 [ Terraform import blocks] ( https://developer.hashicorp.com/terraform/language/import )
77 ready for ` terraform plan -generate-config-out=resources.tf ` .
8- - ** audit mode** — scan accounts for hardcoded entity IDs and GUIDs that will
9- break after an account migration, and print an annotated report with migration
10- suggestions.
8+ - ** audit mode** — scan accounts for two categories of problems: hardcoded entity
9+ IDs and GUIDs that will break after an account migration, and alert configuration
10+ issues (disabled conditions, empty policies, policies with no notification, legacy
11+ metric conditions) that indicate silent or ineffective monitoring.
1112
1213---
1314
@@ -27,20 +28,34 @@ No Terraform state is created or modified until you explicitly run `terraform ap
2728
2829### Audit mode
2930
30- New Relic generates a unique ` entityGuid ` for every monitored entity (APM services,
31- infrastructure hosts, dashboards, alerts, etc.). Dashboards and alert conditions often
32- reference entities by these GUIDs or by numeric IDs such as ` appId ` or ` hostId ` . These
33- IDs are ** account-specific** — they change when resources are migrated to a new account,
34- breaking any assets that reference them.
31+ Audit mode produces two categories of findings.
32+
33+ ** Hardcoded ID references** — New Relic generates a unique ` entityGuid ` for every
34+ monitored entity (APM services, infrastructure hosts, dashboards, alerts, etc.).
35+ Dashboards and alert conditions often reference entities by these GUIDs or by numeric
36+ IDs such as ` appId ` or ` hostId ` . These IDs are ** account-specific** — they change when
37+ resources are migrated to a new account, silently breaking any asset that references them.
38+
39+ ** Alert configuration health** — Beyond migration risk, audit mode also flags structural
40+ problems in your alert setup that cause monitoring to be ineffective regardless of
41+ migration:
42+
43+ - Conditions that are disabled and therefore never fire.
44+ - Policies with no conditions, which can never generate an alert.
45+ - Policies whose conditions are active but have no notification workflow routing their
46+ alerts — violations open and close silently with nobody notified.
47+ - Legacy APM/Browser/Mobile metric conditions that predate NRQL alerting and should
48+ be recreated as NRQL conditions for long-term support and flexibility.
3549
3650Audit mode:
3751
38- 1 . Fetches all dashboards, NRQL alert conditions, workloads, service levels, and
39- workflows for each account.
40- 2 . Scans their NRQL queries, widget configurations, entity lists, and filter expressions
41- for hardcoded ` entityGuid ` , ` appId ` , ` hostId ` , ` entityId ` , and ` monitorId ` references.
42- 3 . Resolves each found ID to an entity name via NerdGraph.
43- 4 . Prints a grouped report with a migration suggestion per finding.
52+ 1 . Fetches dashboards, NRQL alert conditions, workloads, service levels, workflows,
53+ alert policies, and legacy metric conditions for each account.
54+ 2 . Scans NRQL queries, widget configurations, entity lists, and filter expressions
55+ for hardcoded ID references, and checks alert policies and conditions for
56+ configuration problems.
57+ 3 . Resolves each found entity ID to a name via NerdGraph.
58+ 4 . Prints a grouped report and optionally writes a CSV file (` --csv ` ).
4459
4560---
4661
@@ -120,14 +135,20 @@ terraform apply
120135
121136# --- Audit mode ---
122137
123- # Audit all accessible accounts for hardcoded entity IDs
138+ # Full audit: hardcoded ID refs + alert config health
124139nr-tf-util --mode audit
125140
126- # Audit a single account
127- nr-tf-util --mode audit --account-id 2883194
141+ # Audit a single account and export findings to CSV
142+ nr-tf-util --mode audit --account-id 2883194 --csv findings.csv
128143
129- # Audit only dashboards and NRQL conditions
130- nr-tf-util --mode audit --skip workloads --skip service_levels --skip workflows
144+ # Skip legacy-condition and uncovered-policy checks
145+ nr-tf-util --mode audit --skip legacy_conditions --skip uncovered_alert_policies
146+
147+ # ID-reference checks only (skip all config health checks)
148+ nr-tf-util --mode audit \
149+ --skip disabled_conditions \
150+ --skip legacy_conditions \
151+ --skip uncovered_alert_policies
131152```
132153
133154---
@@ -156,6 +177,12 @@ nr-tf-util --mode audit --skip workloads --skip service_levels --skip workflows
156177| ` --out ` | ` ./output ` | Root directory for output. One subdirectory is created per account. |
157178| ` --dry-run ` | ` false ` | Print what would be written without writing any files. |
158179
180+ ### Audit mode flags
181+
182+ | Flag | Default | Description |
183+ | ---| ---| ---|
184+ | ` --csv ` | — | Write findings to a CSV file (e.g. ` --csv findings.csv ` ). |
185+
159186---
160187
161188## Regions
@@ -201,6 +228,8 @@ Only files with at least one resource are written.
201228
202229### Asset types scanned
203230
231+ #### Hardcoded ID reference checks
232+
204233| Asset type | ` --skip ` value | What is scanned |
205234| ---| ---| ---|
206235| Dashboards | ` dashboards ` | NRQL queries in every widget (` rawConfiguration ` ) |
@@ -209,6 +238,20 @@ Only files with at least one resource are written.
209238| Service levels | ` service_levels ` | Monitored entity GUID + events WHERE clauses |
210239| Workflows | ` workflows ` | Issue filter predicate values |
211240
241+ #### Alert configuration health checks
242+
243+ | Check | ` --skip ` value | What is flagged | Rationale |
244+ | ---| ---| ---| ---|
245+ | Disabled NRQL conditions | ` disabled_conditions ` | Conditions with ` enabled=false ` | A disabled condition never fires. It should be re-enabled if monitoring is still needed, or removed to keep the policy readable. |
246+ | Legacy metric conditions | ` legacy_conditions ` | APM/Browser/Mobile metric conditions (non-NRQL) | These predate NRQL alerting and are no longer the recommended format. NRQL conditions offer finer control, support streaming alerts, and will receive future New Relic improvements; legacy conditions will not. |
247+ | Policies with no conditions | ` uncovered_alert_policies ` | Alert policies that have zero conditions | An empty policy can never generate an alert. It is dead configuration that clutters the policy list and may give a false sense of coverage. |
248+ | Policies with no notification | ` uncovered_alert_policies ` | Policies with at least one enabled condition but no aiWorkflow routing their alerts | When a condition fires, New Relic creates a violation and opens an issue — but if no workflow routes that issue to a destination, nobody is notified. This is one of the most common causes of silent alerting failures. |
249+
250+ > ** Note on notification detection:** The tool checks for aiWorkflows that explicitly
251+ > target a policy via ` labels.policyIds ` predicates, or for a catch-all workflow
252+ > (` VIEW_ALL ` filter type). Workflows that match by policy * name* or other attributes
253+ > are not detected as coverage — review those policies manually.
254+
212255### Hardcoded ID patterns detected
213256
214257| ID type | Example | Why it breaks |
@@ -233,11 +276,24 @@ The audit report includes a per-finding suggestion:
233276| ` monitorId ` | yes | ` Monitor ID changes on migration; after re-import reference '<name>' by name ` |
234277| any | no | Entity could not be resolved — may have been deleted or is in another account |
235278
279+ ### CSV export
280+
281+ Pass ` --csv <file> ` to write all findings to a CSV file alongside the text report.
282+ The CSV has 12 columns:
283+
284+ ```
285+ account_id, account_name, asset_type, asset_id, asset_name,
286+ location, id_type, id_value, resolved, entity_name, entity_type, suggestion
287+ ```
288+
289+ Configuration health findings (disabled conditions, empty policies, etc.) appear as
290+ rows with blank ` id_type ` , ` id_value ` , ` entity_name ` , and ` entity_type ` columns.
291+
236292### Sample audit output
237293
238294```
239295══════════════════════════════════════════════════════════════
240- Account: Production (2883194) findings: 5 assets affected: 3
296+ Account: Production (2883194) findings: 7 assets affected: 5
241297──────────────────────────────────────────────────────────────
242298
243299 DASHBOARD "APM Overview" (id: MTIzNDU2N3xWS...)
@@ -249,21 +305,28 @@ Account: Production (2883194) findings: 5 assets affected: 3
249305 entityGuid MTIzNDU2N3x... → Checkout Service (APPLICATION)
250306 suggestion: GUID is account-specific; after migration find 'Checkout Service' by name to get the new GUID
251307
252- NRQL_CONDITION "High Error Rate — Checkout" (id: 2883194:444555)
253- └─ condition query
254- appId 99887766 → Checkout Service (APPLICATION)
255- suggestion: Replace with: appName = 'Checkout Service'
308+ NRQL_CONDITION "Latency P99 — Deprecated" (id: 2883194:555)
309+ └─ condition configuration
310+ Condition is disabled — enable it or remove it to reduce policy noise
311+
312+ ALERT_CONDITION "Response Time" (id: 2883194:10)
313+ └─ policy: APM Alerts
314+ Legacy APM_APP_METRIC condition — recreate as a NRQL alert condition for long-term support
315+
316+ ALERT_POLICY "Infra Monitoring" (id: 77701)
317+ └─ policy conditions
318+ Policy has no conditions — it will never generate alerts
256319
257- WORKLOAD "Payments Team" (id: 9988776)
258- └─ static entity list
259- entityGuid MTIzOTky... → payments-db (HOST)
260- suggestion: GUID is account-specific; after migration find 'payments-db' by name to get the new GUID
320+ ALERT_POLICY "Checkout Alerts" (id: 77702)
321+ └─ policy notification
322+ Policy has active conditions but no workflow is routing its alerts — they will fire silently
261323
262324══════════════════════════════════════════════════════════════
263325Overall summary
264- Accounts : 1
265- Findings : 5 total (5 resolved, 0 unresolved)
266- Assets : 3 affected
326+ Accounts : 1
327+ Hardcoded ID refs : 2 total (2 resolved, 0 unresolved)
328+ Config issues : 5
329+ Assets affected : 5
267330```
268331
269332---
0 commit comments