@dx-do/cli 5.2.49 → 5.2.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/README.md +24 -6
  2. package/dist-node/01-discover-vertices.tas-pwngv2fz.md +31 -0
  3. package/dist-node/01-discover-vertices.tas.data-store-svjfrm1f.json5 +29 -0
  4. package/dist-node/01-discover-vertices.tas.data-store-tmd-w650nfzt.json +4 -0
  5. package/dist-node/02-discover-services.tas-867m0m88.md +30 -0
  6. package/dist-node/02-discover-services.tas.data-store-jz0gx5vn.json5 +40 -0
  7. package/dist-node/02-discover-services.tas.data-store-tmd-eq264m6y.json +4 -0
  8. package/dist-node/03-discover-sources.nassql-4tgp9jvv.md +34 -0
  9. package/dist-node/03-discover-sources.nassql.data-store-by6sqk23.json5 +63 -0
  10. package/dist-node/03-discover-sources.nassql.data-store-tmd-n3gy57wm.json +4 -0
  11. package/dist-node/04-discover-metadata-columns.nassql-vhzb0mrq.md +26 -0
  12. package/dist-node/04-discover-metadata-columns.nassql.data-store-c9zr7p0q.json5 +35 -0
  13. package/dist-node/04-discover-metadata-columns.nassql.data-store-tmd-4ygrjvty.json +4 -0
  14. package/dist-node/10-filter-attribute-matches.tas-tafqmtw1.md +33 -0
  15. package/dist-node/10-filter-attribute-matches.tas.data-store-tmd-m2sendv0.json +4 -0
  16. package/dist-node/10-filter-attribute-matches.tas.data-store-whdc6vbc.json5 +35 -0
  17. package/dist-node/11-filter-and-compose.tas-m8856738.md +29 -0
  18. package/dist-node/11-filter-and-compose.tas.data-store-dh5meyk8.json5 +56 -0
  19. package/dist-node/11-filter-and-compose.tas.data-store-tmd-mfn8a16f.json +4 -0
  20. package/dist-node/12-filter-or-not.tas-21zab96s.md +35 -0
  21. package/dist-node/12-filter-or-not.tas.data-store-7vjr4fnd.json5 +83 -0
  22. package/dist-node/12-filter-or-not.tas.data-store-tmd-am9smwe5.json +4 -0
  23. package/dist-node/13-filter-layer.tas-r1ff5anv.md +29 -0
  24. package/dist-node/13-filter-layer.tas.data-store-5mneyz77.json5 +30 -0
  25. package/dist-node/13-filter-layer.tas.data-store-tmd-9qmhyfzr.json +4 -0
  26. package/dist-node/14-filter-traverse.tas-da9jene0.md +38 -0
  27. package/dist-node/14-filter-traverse.tas.data-store-p0vxtfvj.json5 +63 -0
  28. package/dist-node/14-filter-traverse.tas.data-store-tmd-5hepg5wf.json +4 -0
  29. package/dist-node/15-filter-take-vertices-edges.tas-m160qc7z.md +35 -0
  30. package/dist-node/15-filter-take-vertices-edges.tas.data-store-drmcme43.json5 +46 -0
  31. package/dist-node/15-filter-take-vertices-edges.tas.data-store-tmd-8fewsp5s.json +4 -0
  32. package/dist-node/16-filter-projection.tas-dh39mcx8.md +31 -0
  33. package/dist-node/16-filter-projection.tas.data-store-tmd-3r8anggx.json +4 -0
  34. package/dist-node/16-filter-projection.tas.data-store-xjbdry1x.json5 +36 -0
  35. package/dist-node/17-filter-lucene.tas-gyvtzwaa.md +29 -0
  36. package/dist-node/17-filter-lucene.tas.data-store-1knw6srt.json5 +39 -0
  37. package/dist-node/17-filter-lucene.tas.data-store-tmd-5cf3tygg.json +5 -0
  38. package/dist-node/18-filter-variable-reuse.tas-89fq0y6x.md +46 -0
  39. package/dist-node/18-filter-variable-reuse.tas.data-store-by35113t.json5 +55 -0
  40. package/dist-node/18-filter-variable-reuse.tas.data-store-tmd-ak7aprgk.json +4 -0
  41. package/dist-node/19-filter-order-statefilter.tas-hm3z71qj.md +36 -0
  42. package/dist-node/19-filter-order-statefilter.tas.data-store-ra9hj1rz.json5 +51 -0
  43. package/dist-node/19-filter-order-statefilter.tas.data-store-tmd-wqer9xy2.json +4 -0
  44. package/dist-node/20-nassql-from-metadata-basic.nassql-szr2xax1.md +28 -0
  45. package/dist-node/20-nassql-from-metadata-basic.nassql.data-store-tmd-c7drxs1m.json +4 -0
  46. package/dist-node/20-nassql-from-metadata-basic.nassql.data-store-zdf1gp1v.json5 +42 -0
  47. package/dist-node/21-nassql-from-metadata-regex.nassql-78jnsn3e.md +30 -0
  48. package/dist-node/21-nassql-from-metadata-regex.nassql.data-store-ckzsv7h1.json5 +53 -0
  49. package/dist-node/21-nassql-from-metadata-regex.nassql.data-store-tmd-zgr6r9my.json +4 -0
  50. package/dist-node/22-nassql-from-topology.nassql-a71qw9r0.md +42 -0
  51. package/dist-node/22-nassql-from-topology.nassql.data-store-81m23nge.json5 +58 -0
  52. package/dist-node/22-nassql-from-topology.nassql.data-store-tmd-vhpjy6c7.json +4 -0
  53. package/dist-node/23-nassql-join-topology-metadata.nassql-hywxhcg2.md +35 -0
  54. package/dist-node/23-nassql-join-topology-metadata.nassql.data-store-da7q90n2.json5 +76 -0
  55. package/dist-node/23-nassql-join-topology-metadata.nassql.data-store-tmd-rr8wt9qa.json +4 -0
  56. package/dist-node/24-nassql-from-data-window-mean.nassql-q6qsgdxw.md +33 -0
  57. package/dist-node/24-nassql-from-data-window-mean.nassql.data-store-j7xmg7fc.json5 +81 -0
  58. package/dist-node/24-nassql-from-data-window-mean.nassql.data-store-tmd-qgzz2f7v.json +4 -0
  59. package/dist-node/25-nassql-group-order-top.nassql-awgnwn3r.md +30 -0
  60. package/dist-node/25-nassql-group-order-top.nassql.data-store-cmrn300b.json5 +48 -0
  61. package/dist-node/25-nassql-group-order-top.nassql.data-store-tmd-7xpqeh7c.json +4 -0
  62. package/dist-node/26-nassql-filter-predicate.nassql-2t27h5ev.md +41 -0
  63. package/dist-node/26-nassql-filter-predicate.nassql.data-store-k2rgp609.json5 +59 -0
  64. package/dist-node/26-nassql-filter-predicate.nassql.data-store-tmd-m4dddgwm.json +4 -0
  65. package/dist-node/27-nassql-distinct-keep.nassql-6z55dvk3.md +24 -0
  66. package/dist-node/27-nassql-distinct-keep.nassql.data-store-mrx00ys5.json5 +52 -0
  67. package/dist-node/27-nassql-distinct-keep.nassql.data-store-tmd-0p9hy42g.json +4 -0
  68. package/dist-node/28-nassql-format-time.nassql-6wraqgdk.md +30 -0
  69. package/dist-node/28-nassql-format-time.nassql.data-store-tmd-bbbqhz1x.json +4 -0
  70. package/dist-node/28-nassql-format-time.nassql.data-store-tvy8y2cs.json5 +59 -0
  71. package/dist-node/29-nassql-describe-log.nassql-t9vnxeb0.md +31 -0
  72. package/dist-node/29-nassql-describe-log.nassql.data-store-tmd-q4mtczy8.json +4 -0
  73. package/dist-node/29-nassql-describe-log.nassql.data-store-x16y4crx.json5 +51 -0
  74. package/dist-node/30-nassql-map-string.nassql-f2tdknzs.md +30 -0
  75. package/dist-node/30-nassql-map-string.nassql.data-store-t8ahcabn.json5 +53 -0
  76. package/dist-node/30-nassql-map-string.nassql.data-store-tmd-a6xq0bdx.json +4 -0
  77. package/dist-node/31-nassql-join-data-sum.nassql-p16y3xk6.md +26 -0
  78. package/dist-node/31-nassql-join-data-sum.nassql.data-store-dje7wm6v.json5 +64 -0
  79. package/dist-node/31-nassql-join-data-sum.nassql.data-store-tmd-c1pyx1qw.json +4 -0
  80. package/dist-node/32-nassql-bottom-aggregation.nassql-hpgfn77p.md +26 -0
  81. package/dist-node/32-nassql-bottom-aggregation.nassql.data-store-tmd-p0ssj1vc.json +4 -0
  82. package/dist-node/32-nassql-bottom-aggregation.nassql.data-store-v9580caa.json5 +43 -0
  83. package/dist-node/33-nassql-cross-domain-pipeline.nassql-fm0ynphf.md +45 -0
  84. package/dist-node/33-nassql-cross-domain-pipeline.nassql.data-store-tmd-18881drs.json +4 -0
  85. package/dist-node/33-nassql-cross-domain-pipeline.nassql.data-store-vqs9hkx4.json5 +79 -0
  86. package/dist-node/3rdpartylicenses-hx59bakt.txt +885 -0
  87. package/dist-node/50-discover-custom-layers.tas-2hvvpkzw.md +66 -0
  88. package/dist-node/50-discover-custom-layers.tas.data-store-h85zgna9.json5 +36 -0
  89. package/dist-node/50-discover-custom-layers.tas.data-store-tmd-hagn9eak.json +4 -0
  90. package/dist-node/51-collect-counts-everything.tas-nz0ksgdc.md +46 -0
  91. package/dist-node/51-collect-counts-everything.tas.data-store-eypcjah8.json5 +48 -0
  92. package/dist-node/51-collect-counts-everything.tas.data-store-tmd-4pcj94s9.json +4 -0
  93. package/dist-node/52-collect-counts-bulk.tas-eerw4z8s.md +54 -0
  94. package/dist-node/52-collect-counts-bulk.tas.data-store-scedtw1m.json5 +65 -0
  95. package/dist-node/52-collect-counts-bulk.tas.data-store-tmd-csyzj189.json +4 -0
  96. package/dist-node/53-collect-attributes-by-type.tas-cw0285hx.md +71 -0
  97. package/dist-node/53-collect-attributes-by-type.tas.data-store-fvjge4yr.json5 +65 -0
  98. package/dist-node/53-collect-attributes-by-type.tas.data-store-tmd-274qrd8f.json +4 -0
  99. package/dist-node/README-ghxecaz0.md +84 -0
  100. package/dist-node/SKILL-1xn7r9nt.md +104 -0
  101. package/dist-node/agent-25q752kd.md +55 -0
  102. package/dist-node/agent_connection_and_status-0dq7zkpc.md +62 -0
  103. package/dist-node/agent_source_collector-6s06n3rs.md +40 -0
  104. package/dist-node/agentic-mcp-rycd2gh8.md +140 -0
  105. package/dist-node/application-dfva8tz0.md +48 -0
  106. package/dist-node/application-m0q2vaxj.md +74 -0
  107. package/dist-node/attribute_resource_metric_name-pxrceab5.md +56 -0
  108. package/dist-node/browseragent-snippet.template-9megjp8a.html +12 -0
  109. package/dist-node/bulkvertexpatch-1a4qy5vb.md +78 -0
  110. package/dist-node/bundle.pbd-38r15kyd.template +13 -0
  111. package/dist-node/bundle.profile-1wpzpt3d.template +2 -0
  112. package/dist-node/business_transaction-mbqz5ex9.md +61 -0
  113. package/dist-node/chunk-4I3HBO6U-2ebgf7kh.js +127 -0
  114. package/dist-node/chunk-4PMCLJMS-0mqvr4m4.js +1 -0
  115. package/dist-node/chunk-5VSFINOX-ewzpx7wh.js +5 -0
  116. package/dist-node/chunk-72HYG3XZ-kf7hy4vs.js +3625 -0
  117. package/dist-node/chunk-JRM4BLOM-rg32z8w4.js +1 -0
  118. package/dist-node/chunk-Q2JA73UH-akkb8bh3.js +14 -0
  119. package/dist-node/chunk-RNMHSXZF-pdwasrg7.js +1358 -0
  120. package/dist-node/chunk-VV2FJEMA-3rvtkmga.js +321 -0
  121. package/dist-node/chunk-YVD3UK5I-9pxr1jka.js +695 -0
  122. package/dist-node/configuration-1vczsdex.md +104 -0
  123. package/dist-node/dashboards-x0xddksy.md +17 -0
  124. package/dist-node/database_or_inferred-8vqf5gyr.md +75 -0
  125. package/dist-node/default-licensing-config-0p879qpb.template +122 -0
  126. package/dist-node/dependency-3b0neg5x.md +40 -0
  127. package/dist-node/description.md-qwc2bj9r.template +30 -0
  128. package/dist-node/discovery-flow-fw79kbx4.md +116 -0
  129. package/dist-node/dxi_service-13prnpd5.md +59 -0
  130. package/dist-node/entity-relationships-cevz61kj.md +142 -0
  131. package/dist-node/gotchas-8ab64kcd.md +389 -0
  132. package/dist-node/host-es6fxtgx.md +46 -0
  133. package/dist-node/host-j3qqrm5f.md +55 -0
  134. package/dist-node/index-104hyb1m.html +13 -0
  135. package/dist-node/index-7fp2dfas.json +178 -0
  136. package/dist-node/index-g3hh5wez.json +403 -0
  137. package/dist-node/index-mbzg9rhc.json +270 -0
  138. package/dist-node/index-qffdhwgm.json +2479 -0
  139. package/dist-node/inferred-w998vfq1.md +41 -0
  140. package/dist-node/installInstructions.md-k9ghf3dr.template +21 -0
  141. package/dist-node/inventorize-xc9h9bjr.md +34 -0
  142. package/dist-node/investigation-planning-6kcm01h9.md +149 -0
  143. package/dist-node/investigator-flow-jc2s0n46.md +186 -0
  144. package/dist-node/k8s_deployment_and_namespace-69c29152.md +88 -0
  145. package/dist-node/k8s_pod_and_container-9h4v6cmj.md +64 -0
  146. package/dist-node/main-SGLYO5YX-ht69eb0y.js +13 -0
  147. package/dist-node/main.js +397415 -0
  148. package/dist-node/marketplace-srdmzxkj.json +15 -0
  149. package/dist-node/metric-source-names-6cbczyks.md +75 -0
  150. package/dist-node/metrics-grounding-2h4kkbe3.md +130 -0
  151. package/dist-node/mm-cookbook-23jpw721.md +231 -0
  152. package/dist-node/mm-quickstart-x2adfc16.md +106 -0
  153. package/dist-node/nassql-cookbook-n8kc0mff.md +812 -0
  154. package/dist-node/nassql-quickstart-090e0yex.md +149 -0
  155. package/dist-node/plugin-c3bavxvf.json +18 -0
  156. package/dist-node/polyfills-A7ZF72EO-mp884a0b.js +2 -0
  157. package/dist-node/prerendered-routes-523d8gat.json +3 -0
  158. package/dist-node/primeicons-4GST5W3O-jac3wxrf.woff2 +0 -0
  159. package/dist-node/primeicons-DHQU4SEP-760n99pp.svg +345 -0
  160. package/dist-node/primeicons-GEFHGEHP-rc4kaa3b.ttf +0 -0
  161. package/dist-node/primeicons-P53SE5CV-4saz3d5j.woff +0 -0
  162. package/dist-node/primeicons-RSSEDYLY-4d4vbd67.eot +0 -0
  163. package/dist-node/query-vs-analysis-separation-sag1ezcq.md +97 -0
  164. package/dist-node/run-query-vs-run-partial-6138pc94.md +80 -0
  165. package/dist-node/service-5pz5nhzf.md +133 -0
  166. package/dist-node/service-hierarchies-87a4ynpj.md +178 -0
  167. package/dist-node/service-k4f5mkbq.md +51 -0
  168. package/dist-node/servlet_or_frontend-1kjcb7ar.md +76 -0
  169. package/dist-node/src-apm-mfnsq6vw.svg +4 -0
  170. package/dist-node/src-axa-nn28yqmj.svg +4 -0
  171. package/dist-node/src-dxim-fv7ne4qa.svg +4 -0
  172. package/dist-node/styles-23VUPSCU-9ehggc1f.css +1 -0
  173. package/dist-node/tas-cookbook-0y4826rp.md +693 -0
  174. package/dist-node/tas-quickstart-wgcvwffc.md +138 -0
  175. package/dist-node/time-format-0595g01j.md +41 -0
  176. package/dist-node/toggles.pbd-9wscbmng.template +2 -0
  177. package/dist-node/type-host-agbhmn6v.svg +6 -0
  178. package/dist-node/type-metric-p9b90bpx.svg +4 -0
  179. package/dist-node/type-service-k7f1x71k.svg +4 -0
  180. package/dist-node/ui-0b5grqrg.md +113 -0
  181. package/dist-node/universe-b9nhf325.md +47 -0
  182. package/dist-node/universe-fzpwzvxr.md +91 -0
  183. package/dist-node/universes-and-scopes-1cb9pfk7.md +105 -0
  184. package/dist-node/vertex_entity_node-mm3yp9d0.md +31 -0
  185. package/package.json +1 -1
@@ -0,0 +1,142 @@
1
+ ---
2
+ id: entity-relationships
3
+ title: Entity relationships — five kinds, knowing which is in play
4
+ applies_to: all
5
+ tags: [reference, authoring]
6
+ related: [investigation-planning, service-hierarchies, universes-and-scopes, metrics-grounding]
7
+ ---
8
+
9
+ # Entity relationships
10
+
11
+ DXO2 has multiple, overlapping ways for two entities to be related. Most user questions about "X and Y" implicitly want one of these — but it's not always the same one. This cookbook enumerates the five kinds and how to use each.
12
+
13
+ ## 1. TAS edges (the actual graph)
14
+
15
+ Edges between vertices are the most concrete relationship: directed, attribute-bearing, queryable via TAS `TRAVERSE`. Each edge has a `semantic` attribute that hints at the kind of relationship.
16
+
17
+ **The semantics observed on real tenants** (from a survey of 6,513 edges):
18
+
19
+ | `semantic` | Count | Meaning |
20
+ |---|---|---|
21
+ | `contains` | ~50% | Structural containment (cluster contains namespace contains deployment, host contains process, etc.) |
22
+ | `agent-monitors` | ~22% | The AGENT on the source side observes the entity on the target side |
23
+ | (no semantic) | ~17% | A non-trivial fraction of edges have NO `semantic` attribute |
24
+ | `composed_of` | ~4% | Compositional (deployment composed of replicaset, service composed of pods) |
25
+ | `runs_on` | ~4% | Runtime placement (pod runs on node) |
26
+ | `orchestrates` | small | Workload-controller relationships in k8s |
27
+ | `declares`, `consists_of` | small | Less-common variants of containment |
28
+ | `Related To` | small | Loose / generic — tenant-specific |
29
+ | `collectsData`, `isConnectedL2`, `isadjacentto` | small | Integration-specific |
30
+
31
+ **The 17% unlabeled edges matter.** Filtering by `semantic` will *miss* them. Default to NOT filtering by semantic unless you're sure the data you want has it.
32
+
33
+ ### Where TAS edges come from
34
+
35
+ Four mechanisms produce edges:
36
+
37
+ 1. **Single-agent multi-entity emission** — an agent that monitors several entities at once also emits the edges between them (e.g. the k8s agent emits the entire pod/deployment/namespace tree).
38
+ 2. **Agent correlation telemetry** — an APM agent watching app-to-app calls emits backend-call edges.
39
+ 3. **Platform-side inference rules** — the platform deduces edges from attribute patterns (e.g. matching IP addresses, matching `applicationName`).
40
+ 4. **Manual / integration imports** — NetOps integrations produce their own edge structure.
41
+
42
+ Different mechanisms give different reliability. Inferred edges are sometimes brittle.
43
+
44
+ ### Authoring against TAS edges
45
+
46
+ ```js
47
+ // Find what depends on X (outgoing edges from X)
48
+ { "filter": { "op": "AND", "input": [
49
+ { "op": "ATTRIBUTE", "expressions": [{ "name": "name", "values": ["X"], "operator": "EQ" }] },
50
+ { "op": "TRAVERSE", "depth": 1, "direction": "OUTBOUND" }
51
+ ] }, "limit": 50 }
52
+ ```
53
+
54
+ Use `direction: "INBOUND"` for "what does X belong to" and `"BIDIRECTIONAL"` when you don't know which side you're on.
55
+
56
+ ## 2. Service membership (DXO2 services)
57
+
58
+ Two entities can be members of the same DXO2 service even when no edge connects them directly. Service membership is an organizational relationship layered over the topology.
59
+
60
+ - **Same service, no edge** → likely related (the customer chose to group them).
61
+ - **Parent service** → child entities are part of a larger logical unit.
62
+ - **Sibling services** → loosely related; sometimes via parent dependency.
63
+ - **Niece / nephew (children of sibling services)** → the loosest meaningful tie.
64
+
65
+ Service-level mechanics live in `cookbooks/service-hierarchies`. Use the `service-dependency-graph` API for the runtime view of inter-service dependencies.
66
+
67
+ ### The `serviceNames` shortcut
68
+
69
+ The platform indexes service membership directly on each entity via a **`serviceNames`** attribute — an array like `["NA_Billing", "NA_Provisioning"]`. It's kept current automatically (typically within ~1 min of entity creation, ~2 min of new-service creation), so it's a reliable, **single-query** answer to "what services does this entity belong to" — far faster than a hierarchy walk.
70
+
71
+ **Gotcha**: the attribute is **not in the default projection**. Pass `includeServices: true` on the TAS query envelope and `serviceNames` shows up in `vertex.attributes`. Without the flag, the field is silently absent and an agent will incorrectly conclude the entity has no service membership.
72
+
73
+ ```json
74
+ {
75
+ "filter": { "op": "ATTRIBUTE", "expressions": [{ "name": "name", "values": ["host-001"], "operator": "EQ" }] },
76
+ "limit": 5,
77
+ "projection": "DETAILED",
78
+ "includeServices": true
79
+ }
80
+ ```
81
+
82
+ The companion flag is `includeStatus: true`, which surfaces the `state` / `status` attribute (similarly omitted by default). Set both when you want a single-shot "identity + service membership + health" snapshot. See `entities/service` for the full pattern.
83
+
84
+ A common analysis pattern:
85
+
86
+ 1. User asks about entity X.
87
+ 2. Find the service(s) X belongs to — **read X's `serviceNames` (with `includeServices: true`)**, don't walk the hierarchy.
88
+ 3. Pull other members of those services for "things related to X" — `op: SERVICE` filter.
89
+ 4. Walk parent and dependent services for the broader picture.
90
+
91
+ ## 3. Universe membership (APM Universe vs O2 Universe)
92
+
93
+ Two entities in the same universe are in the same **scope**. They aren't necessarily related — universe is a coarser axis than service — but the universe boundary is meaningful when answering "what's nearby":
94
+
95
+ - **APM Universe** typically contains telemetry sources and the entities they produce.
96
+ - **O2 Universe** typically contains platform-side and integration-imported data.
97
+
98
+ When a user asks "where is X" or "what universe is X in", the answer is one of two universe kinds. See `lexicon/universe` and `cookbooks/universes-and-scopes`.
99
+
100
+ ## 4. Attribute similarity
101
+
102
+ Two entities sharing an IP address, hostname, or FQDN value are almost always related, even if no edge connects them. This is the canonical pattern when:
103
+
104
+ - **`HOST` and `Host` for the same physical machine** — APM and NetOps records of the same box. No edge between them. Match on `acnHostName`, `acnOtherHostNames`, `dx_hostname_list`, `NetworkAddress`, IP attributes.
105
+ - **Source/destination IP pairs in network metrics** — different attribute names, same IP value, different vertices.
106
+ - **An AGENT and the HOST it runs on** — usually edge-connected, but the `SystemFQHostName` attribute on the AGENT directly names the host even without traversal.
107
+
108
+ Authoring pattern:
109
+
110
+ 1. Collect candidate identity attributes for each entity (use the entity catalog's `typical_attributes` field — see `entities/catalog.json5`).
111
+ 2. For each candidate attribute, query for other entities with a similar value.
112
+ 3. Cross-reference matches with their types — a match between a `HOST` and a `k8s_NODE` of the same hostname is high-signal; a match between two unrelated `Host_Device`s with the same vendor model number is noise.
113
+
114
+ ## 5. Metric-name- and metric-value-implied
115
+
116
+ Sometimes the relationship is hidden inside the **metric data itself**, not in the topology graph:
117
+
118
+ - A metric named `JDBC_Pool|<host>|<pool>:Active Connections` implies a connection-pool resource at that host. There's no `JDBC_CONNECTION_POOL` vertex — the resource exists only in the metric path.
119
+ - A metric VALUE can be a string. `queue_name=queue://host/queuename` reveals which queue host is in use.
120
+ - Some agents put resource identity in path segments; some put it in metric values; both can be the only signal.
121
+
122
+ This is the **metric-first** investigation strategy. See `cookbooks/metrics-grounding`. If a metric pattern recurs, an inventorize rule can materialize the implied resource as a vertex (`lexicon/inventorize`).
123
+
124
+ ## Picking the right kind to ask
125
+
126
+ When a user asks about "the X that A uses" / "what's related to A":
127
+
128
+ 1. **Try TAS edges first** when both endpoints are likely vertices and the relationship is explicit (call graph, containment).
129
+ 2. **Service membership** when the user is asking about organizational closeness.
130
+ 3. **Universe membership** for "is it even in scope" questions.
131
+ 4. **Attribute similarity** when bridging integrations (APM ↔ NetOps, k8s ↔ infra agent on the same node).
132
+ 5. **Metric-implied** when the resource genuinely has no vertex (JMX-style).
133
+
134
+ Most real questions touch more than one kind. The rule of thumb: **start with the most explicit kind that could plausibly answer**, fall back to broader/looser kinds if it doesn't.
135
+
136
+ ## See also
137
+
138
+ - `cookbooks/investigation-planning` — the planning loop that uses this taxonomy.
139
+ - `cookbooks/service-hierarchies` — service membership in depth.
140
+ - `cookbooks/universes-and-scopes` — universe membership in depth.
141
+ - `cookbooks/metrics-grounding` — the metric-implied case.
142
+ - `cookbooks/tas-cookbook` — TAS TRAVERSE syntax and operators.
@@ -0,0 +1,389 @@
1
+ ---
2
+ id: gotchas
3
+ title: Empirical gotchas — things the schema docs alone don't tell you
4
+ applies_to: all
5
+ tags: [reference, validation]
6
+ related: [tas-quickstart, nassql-quickstart, mm-quickstart]
7
+ ---
8
+
9
+ # Gotchas
10
+
11
+ A list of behaviors that tripped up real query authoring (human or agent).
12
+ Each entry includes the symptom, the cause, and how the schema guards
13
+ against it (where possible).
14
+
15
+ These are **bundled, universal** gotchas — behaviors of the DXO2 server
16
+ that every customer encounters. They ship with each release.
17
+
18
+ **Capturing your own findings**: when you discover a behavior specific
19
+ to *your* tenant (or a recipe that worked for you), leave the reasoning
20
+ in the **JSON5 description** on the relevant op or at the query top-level.
21
+ Agents reading your query via `get_query` get that context for free, and
22
+ it round-trips into the file as a `/* */` block comment. Tenant-specific
23
+ knowledge belongs on the queries themselves.
24
+
25
+ If you find a gotcha that applies to *every* customer, that's a candidate
26
+ for inclusion here — file an issue or PR against `packages/corpus/cookbooks/`
27
+ in the dx-do source repo.
28
+
29
+ ---
30
+
31
+ ## TAS — empty AND / OR rejected by server
32
+
33
+ **Symptom**: `400 Bad Request` from `/tas/graph/query`.
34
+ **Cause**: `{"op":"AND","input":[]}` is semantically meaningless (empty
35
+ boolean composite). Server rejects.
36
+ **Schema guard**: `TasAndFilterSchema.input` and `TasOrFilterSchema.input`
37
+ have `.min(1)` — caught at SPA validation before submit.
38
+
39
+ ---
40
+
41
+ ## NASSQL — empty FILTER AND / OR rejected
42
+
43
+ **Symptom**: same as above — server 400.
44
+ **Cause**: `{"op":"AND","spec":[]}` inside a `FILTER` predicate.
45
+ **Schema guard**: `QueryFilterAndSpecSchema.spec` and `QueryFilterOrSpecSchema.spec`
46
+ have `.min(1)`.
47
+
48
+ ---
49
+
50
+ ## NASSQL — GROUP / ORDER / KEEP cannot be empty
51
+
52
+ **Symptom**: server 400 or noop.
53
+ **Cause**: `{"op":"GROUP","columns":[]}` has no grouping key, etc.
54
+ **Schema guard**: All three ops' `columns` field has `.min(1)`.
55
+
56
+ ---
57
+
58
+ ## MM — `ID` specifier requires non-empty `ids`
59
+
60
+ **Symptom**: `400 Bad Request` from MM endpoint.
61
+ **Cause**: `{"op":"ID"}` or `{"op":"ID","ids":[]}` — server requires
62
+ explicit IDs.
63
+ **Schema guard**: `QueryIdSpecifierSchema.ids` has `.min(1)`. Read IDs
64
+ from a previous MM query's leftmost result column, or pass them
65
+ explicitly when chaining queries.
66
+
67
+ ---
68
+
69
+ ## MM — empty AND / OR specifier rejected (4 levels deep)
70
+
71
+ **Symptom**: server 400.
72
+ **Cause**: Same pattern as TAS / NASSQL but applies at all four MM tree
73
+ levels (top-level, source-name, folder-name, attribute-name). Empty
74
+ boolean composites are always wrong.
75
+ **Schema guard**: All eight `*AndSpecifierSchema` / `*OrSpecifierSchema`
76
+ variants have `.min(1)` on `specifiers`.
77
+
78
+ ---
79
+
80
+ ## NASSQL FROM_TOPOLOGY — querySpecifier ignores most fields
81
+
82
+ **Symptom**: top-level `limit` / `projection` / `time` set on
83
+ `FROM_TOPOLOGY.querySpecifier` either silently drop or 400.
84
+ **Cause**: Although the field types as `TasQuerySchema` (full envelope),
85
+ the server only honors `filter`. Pipeline-level `limit` (on the top-level
86
+ `QueryRequest`) is what caps row count.
87
+ **Workaround**: don't put `limit`, `projection`, `time` etc. inside
88
+ `querySpecifier`. Author the TAS filter directly; place row-capping on
89
+ the outer NASSQL envelope.
90
+ **Schema guard**: documented in JSDoc on `QueryFromTopologySpecSchema` and
91
+ `TasQuerySchema`.
92
+
93
+ ---
94
+
95
+ ## NASSQL JOIN_TOPOLOGY — no querySpecifier exists
96
+
97
+ **Symptom**: agents try to add `querySpecifier` to JOIN_TOPOLOGY and
98
+ the schema rejects.
99
+ **Cause**: Unlike FROM_TOPOLOGY, JOIN_TOPOLOGY has no specifier field.
100
+ The topology context is inherited from the upstream pipeline data via
101
+ `externalIdColumn`.
102
+ **Workaround**: to constrain the topology side of a join, do a separate
103
+ FROM_TOPOLOGY into an aliased branch and JOIN against that branch.
104
+ **Schema guard**: documented in JSDoc on `QueryJoinTopologySpecSchema`.
105
+
106
+ ---
107
+
108
+ ## MM — unbounded ALL queries return tens of MB
109
+
110
+ **Symptom**: queries with `{"specifier":{"op":"ALL"}}` and no `clamp`
111
+ return huge responses, sometimes crashing browser tabs.
112
+ **Cause**: server returns ALL matching metrics by default.
113
+ **Workaround**: always set `clamp: 500` (or a similar bound) for new
114
+ specifiers. Raise only if needed.
115
+ **Schema guard**: documented in JSDoc on `MetadataMetricQuerySchema`. New
116
+ MM queries created via `create_query` default `clamp: 500`.
117
+
118
+ ---
119
+
120
+ ## TAS — ATTRIBUTE without a `layer` matches across all layers
121
+
122
+ **Symptom**: results include unexpected vertex types.
123
+ **Cause**: TAS attributes are layer-scoped. `{"op":"ATTRIBUTE",
124
+ "expressions":[{"name":"hostname",...}]}` without a `layer` matches
125
+ hostname-bearing attributes on every layer that has them.
126
+ **Workaround**: set `ATTRIBUTE.layer` to scope the match. The op-level
127
+ `layer` is inherited into each expression row's `layer` field unless
128
+ overridden explicitly per-expression.
129
+ **Schema guard**: none — empty `layer` is valid and intentional in some
130
+ queries (cross-layer search).
131
+
132
+ ---
133
+
134
+ ## NASSQL — pipeline ordering matters
135
+
136
+ **Symptom**: `WINDOW` / `GROUP` / aggregation sequence produces wrong
137
+ results or fails validation.
138
+ **Cause**: NASSQL ops don't reorder themselves. `GROUP` before `WINDOW`
139
+ behaves differently from `WINDOW` before `GROUP`.
140
+ **Workaround**: standard ordering is `FROM* → FILTER → WINDOW → GROUP →
141
+ AGG → ORDER → KEEP`. Use `run_partial_query` with `upToStep: N` to
142
+ verify after each insertion.
143
+ **Schema guard**: none — the schema is order-agnostic, the runtime is not.
144
+
145
+ ---
146
+
147
+ ## Discovery — `discovery_metrics` is capped at 1000 names
148
+
149
+ **Symptom**: agents can't find a metric they know exists on a large tenant.
150
+ **Cause**: `getMetricsHandler` caps the unique name list at 1000 to
151
+ keep the response payload reasonable.
152
+ **Workaround**: if you know the metric ID, use `ID` specifier directly
153
+ without depending on the discovery cache.
154
+ **Schema guard**: documented in `getMetricsHandler` JSDoc.
155
+
156
+ ---
157
+
158
+ ## `create_query` — `shortName` is prefixed with an auto-numbered bucket
159
+
160
+ **Symptom**: agent passes `shortName: "all-hosts"` to `create_query` and the saved query's id comes back as `15-all-hosts` (or some other small integer).
161
+ **Cause**: `create_query` auto-assigns a numeric prefix per query-type bucket — the next free integer in `~/.dxdo/queries/<alias>/` for queries of the same type. Allows stable sorting and visual ordering in any tool that lists the saved queries.
162
+ **Workaround**: nothing to do — this is by design. When chaining `create_query` → `get_query` / `update_query` / `signal_handoff_to_ui`, use the RETURNED `id` (which includes the prefix), NOT the `shortName` you passed in. Pre-assigning your own prefix via the `prefix` argument bypasses the bucket counter.
163
+ **Schema guard**: documented in `create_query` tool description; the response body always includes the assigned id.
164
+
165
+ ---
166
+
167
+ ## NASSQL — `metric.source` REGEX needs the `<domain>|` prefix
168
+
169
+ **Symptom**: a NASSQL `FROM` query with a `sourceNameSpecifier` REGEX like `.*<host-name>.*` returns zero rows even though the host clearly exists and is reporting metrics.
170
+ **Cause**: `metric.source` strings are pipe-delimited multi-segment values shaped `<domain>|<host>|<bus>|<role>` (e.g. `SuperDomain|host-001|Infrastructure|Agent`). The naive `.*<host>.*` pattern doesn't account for the `<domain>|` prefix or the literal `|` separators (which are regex meta-characters needing escape). A pattern that *looks* like it should match doesn't.
171
+ **Workaround**: see `cookbooks/metric-source-names` for the full shape + canonical regex patterns + the empirical-discovery move (`run_partial_query` with `FROM_METADATA upToStep:0` to inspect actual source values before authoring the FROM regex).
172
+ **Schema guard**: none — the regex is opaque to schema validation; empty results are silent.
173
+
174
+ ## NASSQL — verify a FROM is matching anything before pulling on the whole pipeline
175
+
176
+ **Symptom**: a NASSQL query runs end-to-end but produces nulls or
177
+ zero rows in unexpected places — most often after an aggregator over
178
+ multiple FROMs where one of them silently matches no metric. The
179
+ end-to-end result is "valid but empty" with no error message pointing
180
+ at which FROM is the empty branch.
181
+
182
+ **Diagnostic**: run each FROM (or FROM_METADATA) **in isolation** as a
183
+ two-step pipeline:
184
+
185
+ ```json
186
+ {
187
+ "query": [
188
+ { "op": "FROM", "querySpecifier": <THE_SPECIFIER>, "alias": "probe" },
189
+ { "op": "KEEP", "columns": ["metric.id"] }
190
+ ],
191
+ "limit": 50
192
+ }
193
+ ```
194
+
195
+ The result is `[["metric.id"], <id1>, <id2>, …]`. Zero data rows means
196
+ the specifier matches nothing in this tenant. Common causes:
197
+
198
+ - An `ATTRIBUTE` predicate inside `attributeNameSpecifier` that filters
199
+ by a value the tenant doesn't actually store in that form (e.g.
200
+ `is_Custom_health IN ["true"]` when the tenant stores it as a boolean
201
+ type, not the string `"true"`).
202
+ - A REGEX `pattern` that doesn't match any actual `metric.path` /
203
+ `metric.source`.
204
+ - A `sourceNameSpecifier` `EXACT` name that's stale or misspelled.
205
+
206
+ **Refining the filter**: relax the predicates one at a time
207
+ (start by removing the `ATTRIBUTE` predicate while keeping the
208
+ REGEX) and re-run the isolation pipeline. When rows come back, sample
209
+ a few `metric.id` values, look up their attributes via Metrics-Metadata,
210
+ and see how the filter you originally wanted should be expressed against
211
+ the tenant's actual data shape.
212
+
213
+ **Tooling**: the data-store visual editor surfaces a "Run JUST this
214
+ step" control on `FROM` / `FROM_METADATA` headers that runs the
215
+ two-step probe above and shows the result in the Debug pane — same
216
+ diagnostic, no JSON5 editing required.
217
+
218
+ **Schema guard**: none — empty results are always valid; the server has
219
+ no way to tell that empty wasn't intended.
220
+
221
+ ---
222
+
223
+ ## NASSQL — `GROUP` only drops non-grouped columns when followed by an aggregator
224
+
225
+ **Symptom**: a `GROUP` step appears to have done nothing — non-grouped
226
+ columns are still present in the output of the next step (verified via
227
+ `DESCRIBE` or by running partial up-to-this-step).
228
+
229
+ **Cause**: `GROUP` itself doesn't immediately prune the column set. It
230
+ registers the grouping key for the *next aggregator* in the pipeline:
231
+
232
+ - `GROUP → AGG` / `→ COUNT` / `→ SUM` / `→ MEAN` / `→ MIN` / `→ MAX`
233
+ / `→ FIRST` / `→ LAST` / `→ QUANTILE` / `→ NASS_AGG` → output
234
+ collapses to *grouping key columns* + each aggregator's `as` outputs;
235
+ every other column is dropped here.
236
+ - `GROUP → BOTTOM` / `→ TOP` / `→ ORDER` / `→ KEEP` / `→ FILTER` (no
237
+ aggregator between) → upstream columns survive unchanged. `GROUP` has
238
+ no row-level effect; it only registered a key that would have applied
239
+ if an aggregator had followed.
240
+
241
+ **Workaround / authoring rule**: if you need column-pruning behavior
242
+ without an aggregator, follow `GROUP` with `KEEP` instead. If you need
243
+ the per-group reduction, ensure an aggregator is in the pipeline
244
+ between `GROUP` and any `KEEP` / output projection. Running partial
245
+ up-to-this-step on the first column-input field after `GROUP` is the
246
+ fastest way to verify which column shape you actually have at that
247
+ boundary.
248
+
249
+ **Repeated GROUP overrides** the previous user-grouping key — useful
250
+ when you want to GROUP-aggregate-then-GROUP-aggregate again on a
251
+ different key.
252
+
253
+ **Schema guard**: none — both flows are server-valid; surprise comes
254
+ from the column shape, not from a hard error.
255
+
256
+ ---
257
+
258
+ ## NASSQL — `alias` does NOT prefix output column names
259
+
260
+ **Symptom**: a `FROM` step with `alias: "health"` is documented to namespace
261
+ its output columns as `health.data.value` / `health.metric.source` / etc.,
262
+ but running the pipeline up to that step and inspecting `rows[0]` shows the
263
+ columns are still flat — `data.value`, `metric.source`, `metric.path`. The
264
+ prefixed name (`health.data.value`) doesn't appear on any row, so a
265
+ downstream `KEEP { columns: ["health.data.value"] }` returns nothing.
266
+
267
+ **Cause**: aliases are a **logical reference scope** consumed by downstream
268
+ ops that resolve them at execution time (AGG / SCRIPT / FILTER expressions
269
+ correctly understand `health.data.value`), but the runtime never rewrites
270
+ the row-level column keys with the alias prefix. The canonical schema's
271
+ `.describe()` text on `alias` is misleading — what aliases actually do is
272
+ let multiple FROMs (or JOIN_DATA / JOIN_METADATA) share a column-name
273
+ namespace internally without colliding when the engine merges their row
274
+ sets.
275
+
276
+ **Workaround**:
277
+
278
+ 1. **Reference aliased columns in expressions, not in projections.** AGG's
279
+ inner `column`, FILTER predicates, MAP `fn`, SCRIPT `inputColumns[]`,
280
+ etc. all resolve `<alias>.<col>` correctly.
281
+ 2. **Project the bare column names in `KEEP`.** `KEEP { columns: ["data.value", "metric.source"] }`
282
+ works; `KEEP { columns: ["health.data.value"] }` returns empty.
283
+ 3. **If you need to disambiguate two FROMs that emit the same column
284
+ name in the final result**, use `KEEP`'s positional `as[]` to rename:
285
+ `KEEP { columns: ["data.value", "data.value"], as: ["health_value", "custom_value"] }`.
286
+
287
+ **Schema guard**: none — the `alias` field's `.describe()` text is the
288
+ trap. Tooling that suggests column names should NOT include
289
+ `<alias>.<col>` variants in the suggestion list at the row level; only
290
+ expression contexts (AGG / FILTER / SCRIPT / MAP) accept them.
291
+
292
+ ---
293
+
294
+ ## TAS — `STATUS.statusFilter`'s `STATE` op is currently a server-side no-op
295
+
296
+ **Symptom**: a TAS query of the shape
297
+ ```json
298
+ { "op": "STATUS", "input": filter,
299
+ "statusFilter": { "op": "STATE", "state": [4] } }
300
+ ```
301
+ returns zero vertices even when vertices with the requested numeric status
302
+ demonstrably exist (verified by running `input` alone with `includeStatus: true`
303
+ and reading `states[].status` from the response). Worse: setting `not: true`
304
+ returns *every* input vertex regardless of what's in `state[]` — `not` flips
305
+ an empty match-set to the universal set, masking the underlying breakage.
306
+
307
+ **Cause**: the server-side handler doesn't bind the `STATE` op's `state[]`
308
+ array. The predicate is effectively a no-op. Other leaf ops in the same
309
+ state-filter union (`ALERT`, `METRIC`, `VERTEX_ID`, `NAMESPACE`,
310
+ `MANAGEMENT_MODULE`) appear to work — only `STATE` is affected.
311
+
312
+ **Numeric status reference** (values appearing in `states[].status`):
313
+
314
+ | `status` | Label |
315
+ |---|---|
316
+ | 0 | UNKNOWN |
317
+ | 1 | OK |
318
+ | 2 | MINOR |
319
+ | 3 | MAJOR |
320
+ | 4 | CRITICAL |
321
+
322
+ The rolled-up per-vertex severity (the value the platform UI shows on the
323
+ status badge) lives on the state row whose `stateExternalId.alert` is
324
+ `"sa://sa_status"` — a synthetic aggregate alert that summarizes all of a
325
+ vertex's individual alerts and metrics. Per-alert / per-metric rows report
326
+ their own `status` independently and can disagree with the rollup.
327
+
328
+ **Workaround — split into two queries and filter client-side.** Example
329
+ goal: *for each HOST currently CRITICAL, list any downstream databases
330
+ whose status is not OK.*
331
+
332
+ 1. **Pull candidates with state attached.** Run the source-side topology
333
+ query with `includeStatus: true`. From `states[]`, keep only rows where
334
+ `stateExternalId.alert === "sa://sa_status"`, group by `vertexId`, and
335
+ read `status`. Collect the matching vertices' `externalId` values.
336
+
337
+ ```json
338
+ {
339
+ "limit": 5000,
340
+ "includeStatus": true,
341
+ "filter": {
342
+ "op": "ATTRIBUTE",
343
+ "expressions": [
344
+ { "name": "type", "operator": "IN", "values": ["HOST"] }
345
+ ]
346
+ }
347
+ }
348
+ ```
349
+
350
+ Client-side: keep `externalId`s where the rollup row's `status === 4`.
351
+
352
+ 2. **Pin those externalIds and traverse.** Issue a second query whose
353
+ filter is `VERTEX(externalId: [...])` → `TRAVERSE` (or `FOLLOW_PATH`)
354
+ to the target type, again with `includeStatus: true` so the downstream
355
+ side can be filtered on the client.
356
+
357
+ ```json
358
+ {
359
+ "limit": 5000,
360
+ "includeStatus": true,
361
+ "filter": {
362
+ "op": "TRAVERSE",
363
+ "input": { "op": "VERTEX", "externalId": ["<id-1>", "<id-2>"] },
364
+ "traverse": [{ "direction": "ANY", "repeat": 3 }]
365
+ }
366
+ }
367
+ ```
368
+
369
+ Then client-side: keep vertices whose `type` is the target (e.g.
370
+ database) and whose rollup `states[].status !== 1` (not OK).
371
+
372
+ The rest of `STATUS` is fine — `ALERT(alertId)`, `METRIC(metricId)`,
373
+ `NAMESPACE`, and `MANAGEMENT_MODULE` predicates all narrow as documented.
374
+ Avoid `STATE` until this is resolved.
375
+
376
+ **Schema guard**: none — the server silently accepts the `state[]` field
377
+ and returns empty (or, with `not: true`, universal) results without a
378
+ validation error. Tools that surface the `STATE` op in a form-style
379
+ editor still produce wire-valid JSON, but it won't take effect until the
380
+ platform handler is fixed.
381
+
382
+ ---
383
+
384
+ ## `run_query` — empty payload silently dumps the whole topology
385
+
386
+ **Symptom**: `run_query({type: "tas", payload: {}})` (no filter, no limit) returns a response that looks innocuous in the wire but represents megabytes of topology data.
387
+ **Cause**: `{}` parses as a valid TAS payload — `filter` defaulting to no-filter is equivalent to `{op:"ALL"}`, and `limit` defaults to "no limit." Returns the entire bound tenant's topology. On large tenants that's 10MB+ + may be saved to disk by ui rather than returned inline. The same trap exists in NASSQL (`FROM_METADATA / FROM_TOPOLOGY / FROM` with `op:"ALL"` and no row-reducing op + no top-level `limit`) and in Metrics Metadata (`specifier: {op:"ALL"}` or specifier missing, `clamp` unset).
388
+ **Workaround**: NEVER author a `run_query` payload that scans everything without scoping. For TAS, pair every `op:"ALL"` filter with a sane `limit` (5–100 for sampling). For NASSQL, either narrow the source op's specifier (`SPEC` + `sourceNameSpecifier` / `attributeNameSpecifier`; or a TAS filter for `FROM_TOPOLOGY`), include an aggregation (GROUP+COUNT, TOP/BOTTOM, FILTER), or set top-level `limit`. For MM, narrow the specifier or pass a sane `clamp`. See `corpus_get('queries', '01-discover-vertices')` and `corpus_get('queries', '03-discover-sources')` for canonical bounded-discovery patterns.
389
+ **Schema guard**: server-side preflight refuses three unbounded shapes — TAS `ALL` filter without `limit` ≤ 100; NASSQL pipeline starting with `FROM_*` + ALL-spec, no row-reducer, no `limit` ≤ 200; MM ALL specifier (or missing) without `clamp` ≤ 1000. The error message names the trap and points at the canonical fix. The tool description for `run_query` explicitly warns up front.
@@ -0,0 +1,46 @@
1
+ ---
2
+ id: host
3
+ title: host — uppercase HOST vs mixed-case Host
4
+ aliases: [hosts, machine, server]
5
+ category: topology
6
+ related: [agent]
7
+ tags: [overloaded, disambiguation, core]
8
+ ---
9
+
10
+ # host
11
+
12
+ `HOST` and `Host` are **different vertex types** in DXO2 and frequently coexist on the same tenant:
13
+
14
+ | Type | Source | Layer | Notes |
15
+ |---|---|---|---|
16
+ | `HOST` | APM Infrastructure Agent | INFRASTRUCTURE | The default APM-flavored host record. Has APM-style attributes (`SourceProduct`, `agent`, `acn_loganalytics_key`). |
17
+ | `Host` | NetOps / Spectrum | INFRASTRUCTURE_UIM | NetOps-style record. Has Spectrum-style attributes (`alias`, `CSType`, `ProbeName`, `correlationNames`). |
18
+ | `Host_Device` | NetOps / Spectrum | NETWORK_SPECTRUM | A NetOps host record that also has device-level info attached. |
19
+ | `LPAR_HOST` | Mainframe integration | INFRASTRUCTURE | IBM LPAR-style logical host. |
20
+ | `k8s_NODE` | Kubernetes agent | INFRASTRUCTURE | Worker node in a Kubernetes cluster — k8s-flavored counterpart to `HOST`. |
21
+
22
+ ## Why this matters
23
+
24
+ A query filtering on `type=HOST` excludes NetOps `Host` records entirely. On a tenant that monitors with both APM *and* NetOps, that's roughly half the actual machine inventory. To fetch all hosts regardless of source, filter:
25
+
26
+ ```
27
+ ATTRIBUTE type IN ["HOST", "Host", "Host_Device", "LPAR_HOST"]
28
+ ```
29
+
30
+ (Optionally include `k8s_NODE` if k8s nodes-as-hosts make sense for the question.)
31
+
32
+ ## How users phrase it
33
+
34
+ - "the host" / "this server" / "the box" — usually want the union; default to all flavors and let the answer explain.
35
+ - "the APM host" → just `HOST`.
36
+ - "the NetOps host" → `Host` / `Host_Device`.
37
+ - "the node" → ambiguous; in k8s shops `k8s_NODE`, otherwise `HOST`.
38
+
39
+ ## Cross-flavor matching
40
+
41
+ `HOST` and `Host` for the same physical machine are **separate vertices** with **no edge between them**. To match across, use attribute similarity on `acnHostName`, `acnOtherHostNames`, `dx_hostname_list`, or IP address. See `cookbooks/entity-relationships`.
42
+
43
+ ## See also
44
+
45
+ - `entities/host` — APM HOST detail.
46
+ - `cookbooks/entity-relationships` — attribute-similarity matching across flavors.
@@ -0,0 +1,55 @@
1
+ ---
2
+ id: host
3
+ title: HOST — physical or virtual machine in the topology
4
+ layer: INFRASTRUCTURE
5
+ synonyms: [machine, node, server]
6
+ related_entities: [agent, k8s_node]
7
+ related_cookbooks: [tas-quickstart]
8
+ tags: [infrastructure, core]
9
+ ---
10
+
11
+ # HOST
12
+
13
+ ## What it is
14
+
15
+ A HOST vertex represents one machine — physical, VM, container host, or a cloud-managed compute resource — that is reporting telemetry or has been discovered by an agent. Hostnames, IPs, MAC addresses, OS-level inventory all hang off the HOST as attributes.
16
+
17
+ ## Where it lives
18
+
19
+ `type=HOST` vertices live in the **INFRASTRUCTURE** layer.
20
+
21
+ **NOT in APM_INFRASTRUCTURE.** That layer holds AGENT, AGENT_CONNECTION, DXI_SERVICE, and other APM-specific telemetry concepts. This is a common confusion: "APM hosts" naturally suggests `APM_INFRASTRUCTURE` but you'll get back agents, not hosts.
22
+
23
+ To find HOSTs that participate in APM, filter `INFRASTRUCTURE.HOST` by `SourceProduct=APM`.
24
+
25
+ ## Common uses
26
+
27
+ - **Inventory queries** — list all hosts on the tenant, optionally filtered by `SourceProduct`, `agent`, `dx_hostname`, etc.
28
+ - **Traversal seed** — TRAVERSE from a HOST to find its agents (forward edges) or its k8s pods (forward edges to k8s entities).
29
+ - **Cardinality estimation** — counting HOSTs gives a rough sense of monitored fleet size.
30
+
31
+ ## Useful attributes
32
+
33
+ - `hostname` / `dx_hostname` — primary name (canonical: `dx_hostname`).
34
+ - `dx_ip_address` / `dx_ip_address_list` — IP(s) the host has been seen with.
35
+ - `SourceProduct` — array of products that report telemetry from this host (`APM`, `DXIM`, etc.). Useful for filtering.
36
+ - `agent` — array of agent identity strings on this host.
37
+ - `category` — high-level grouping ("System", etc.).
38
+ - `compacted` / `hidden` — internal flags; rarely useful for filtering.
39
+
40
+ ## Common synonyms / mistakes
41
+
42
+ - "machine", "node", "server" — all map to HOST in user vocabulary.
43
+ - **"k8s host" / "k8s node"** — different! `k8s_NODE` is its own type. A `k8s_NODE` is the in-cluster representation; the HOST is the underlying VM. Some tenants surface both for the same physical machine.
44
+ - "physical host" — there's no separate type; HOST covers physical and virtual.
45
+
46
+ ## Related entities
47
+
48
+ - **AGENT** (in APM_INFRASTRUCTURE) — typically reachable via TRAVERSE from a HOST.
49
+ - **k8s_NODE** (in INFRASTRUCTURE) — Kubernetes-cluster-side view of a node. May co-exist with HOST.
50
+
51
+ ## See also
52
+
53
+ - `cookbooks/tas-quickstart` — the layer + ATTRIBUTE pattern that returns HOSTs.
54
+ - `queries/01-discover-vertices` — sample TAS query that returns 20 vertices including HOSTs.
55
+ - `queries/02-discover-services` — pulls HOSTs alongside other top-level types.
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en" data-beasties-container>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>dx-do · query builder</title>
6
+ <base href="/">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <link rel="icon" type="image/x-icon" href="favicon.ico">
9
+ <style>@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}:root{color-scheme:dark;--dx-accent:#86efac;--dx-accent-strong:#34d399;--dx-accent-soft:rgba(134, 239, 172, .1);--dx-accent-amber:#fbbf24;--dx-glow:0 0 12px rgba(134, 239, 172, .4);--dx-glow-amber:0 0 12px rgba(251, 191, 36, .35);--dx-bg-canvas:#0a0a0a;--dx-bg-canvas-vignette:radial-gradient( ellipse at center, #161616 0%, #0a0a0a 70% );--dx-sidebar-bg:rgba(18, 18, 20, .94);--dx-sidebar-border:rgba(255, 255, 255, .06);--dx-text:#e5e5e5;--dx-text-muted:#a3a3a3;--dx-text-subtle:#737373}html,body{margin:0;padding:0;height:100vh;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;background:var(--dx-bg-canvas);color:var(--dx-text)}.dx-app-body{background:var(--dx-bg-canvas);color:var(--dx-text)}</style><link rel="stylesheet" href="styles-23VUPSCU.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles-23VUPSCU.css"></noscript></head>
10
+ <body class="dx-app-body">
11
+ <dx-app></dx-app>
12
+ <link rel="modulepreload" href="chunk-JRM4BLOM.js"><link rel="modulepreload" href="chunk-YVD3UK5I.js"><link rel="modulepreload" href="chunk-Q2JA73UH.js"><link rel="modulepreload" href="chunk-RNMHSXZF.js"><link rel="modulepreload" href="chunk-5VSFINOX.js"><script src="polyfills-A7ZF72EO.js" type="module"></script><script src="main-SGLYO5YX.js" type="module"></script></body>
13
+ </html>