@dx-do/cli 5.2.49 → 6.0.1
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.
- package/README.md +24 -6
- package/dist-node/01-discover-vertices.tas-pwngv2fz.md +31 -0
- package/dist-node/01-discover-vertices.tas.data-store-svjfrm1f.json5 +29 -0
- package/dist-node/01-discover-vertices.tas.data-store-tmd-w650nfzt.json +4 -0
- package/dist-node/02-discover-services.tas-867m0m88.md +30 -0
- package/dist-node/02-discover-services.tas.data-store-jz0gx5vn.json5 +40 -0
- package/dist-node/02-discover-services.tas.data-store-tmd-eq264m6y.json +4 -0
- package/dist-node/03-discover-sources.nassql-4tgp9jvv.md +34 -0
- package/dist-node/03-discover-sources.nassql.data-store-by6sqk23.json5 +63 -0
- package/dist-node/03-discover-sources.nassql.data-store-tmd-n3gy57wm.json +4 -0
- package/dist-node/04-discover-metadata-columns.nassql-vhzb0mrq.md +26 -0
- package/dist-node/04-discover-metadata-columns.nassql.data-store-c9zr7p0q.json5 +35 -0
- package/dist-node/04-discover-metadata-columns.nassql.data-store-tmd-4ygrjvty.json +4 -0
- package/dist-node/10-filter-attribute-matches.tas-tafqmtw1.md +33 -0
- package/dist-node/10-filter-attribute-matches.tas.data-store-tmd-m2sendv0.json +4 -0
- package/dist-node/10-filter-attribute-matches.tas.data-store-whdc6vbc.json5 +35 -0
- package/dist-node/11-filter-and-compose.tas-m8856738.md +29 -0
- package/dist-node/11-filter-and-compose.tas.data-store-dh5meyk8.json5 +56 -0
- package/dist-node/11-filter-and-compose.tas.data-store-tmd-mfn8a16f.json +4 -0
- package/dist-node/12-filter-or-not.tas-21zab96s.md +35 -0
- package/dist-node/12-filter-or-not.tas.data-store-7vjr4fnd.json5 +83 -0
- package/dist-node/12-filter-or-not.tas.data-store-tmd-am9smwe5.json +4 -0
- package/dist-node/13-filter-layer.tas-r1ff5anv.md +29 -0
- package/dist-node/13-filter-layer.tas.data-store-5mneyz77.json5 +30 -0
- package/dist-node/13-filter-layer.tas.data-store-tmd-9qmhyfzr.json +4 -0
- package/dist-node/14-filter-traverse.tas-da9jene0.md +38 -0
- package/dist-node/14-filter-traverse.tas.data-store-p0vxtfvj.json5 +63 -0
- package/dist-node/14-filter-traverse.tas.data-store-tmd-5hepg5wf.json +4 -0
- package/dist-node/15-filter-take-vertices-edges.tas-m160qc7z.md +35 -0
- package/dist-node/15-filter-take-vertices-edges.tas.data-store-drmcme43.json5 +46 -0
- package/dist-node/15-filter-take-vertices-edges.tas.data-store-tmd-8fewsp5s.json +4 -0
- package/dist-node/16-filter-projection.tas-dh39mcx8.md +31 -0
- package/dist-node/16-filter-projection.tas.data-store-tmd-3r8anggx.json +4 -0
- package/dist-node/16-filter-projection.tas.data-store-xjbdry1x.json5 +36 -0
- package/dist-node/17-filter-lucene.tas-gyvtzwaa.md +29 -0
- package/dist-node/17-filter-lucene.tas.data-store-1knw6srt.json5 +39 -0
- package/dist-node/17-filter-lucene.tas.data-store-tmd-5cf3tygg.json +5 -0
- package/dist-node/18-filter-variable-reuse.tas-89fq0y6x.md +46 -0
- package/dist-node/18-filter-variable-reuse.tas.data-store-by35113t.json5 +55 -0
- package/dist-node/18-filter-variable-reuse.tas.data-store-tmd-ak7aprgk.json +4 -0
- package/dist-node/19-filter-order-statefilter.tas-hm3z71qj.md +36 -0
- package/dist-node/19-filter-order-statefilter.tas.data-store-ra9hj1rz.json5 +51 -0
- package/dist-node/19-filter-order-statefilter.tas.data-store-tmd-wqer9xy2.json +4 -0
- package/dist-node/20-nassql-from-metadata-basic.nassql-szr2xax1.md +28 -0
- package/dist-node/20-nassql-from-metadata-basic.nassql.data-store-tmd-c7drxs1m.json +4 -0
- package/dist-node/20-nassql-from-metadata-basic.nassql.data-store-zdf1gp1v.json5 +42 -0
- package/dist-node/21-nassql-from-metadata-regex.nassql-78jnsn3e.md +30 -0
- package/dist-node/21-nassql-from-metadata-regex.nassql.data-store-ckzsv7h1.json5 +53 -0
- package/dist-node/21-nassql-from-metadata-regex.nassql.data-store-tmd-zgr6r9my.json +4 -0
- package/dist-node/22-nassql-from-topology.nassql-a71qw9r0.md +42 -0
- package/dist-node/22-nassql-from-topology.nassql.data-store-81m23nge.json5 +58 -0
- package/dist-node/22-nassql-from-topology.nassql.data-store-tmd-vhpjy6c7.json +4 -0
- package/dist-node/23-nassql-join-topology-metadata.nassql-hywxhcg2.md +35 -0
- package/dist-node/23-nassql-join-topology-metadata.nassql.data-store-da7q90n2.json5 +76 -0
- package/dist-node/23-nassql-join-topology-metadata.nassql.data-store-tmd-rr8wt9qa.json +4 -0
- package/dist-node/24-nassql-from-data-window-mean.nassql-q6qsgdxw.md +33 -0
- package/dist-node/24-nassql-from-data-window-mean.nassql.data-store-j7xmg7fc.json5 +81 -0
- package/dist-node/24-nassql-from-data-window-mean.nassql.data-store-tmd-qgzz2f7v.json +4 -0
- package/dist-node/25-nassql-group-order-top.nassql-awgnwn3r.md +30 -0
- package/dist-node/25-nassql-group-order-top.nassql.data-store-cmrn300b.json5 +48 -0
- package/dist-node/25-nassql-group-order-top.nassql.data-store-tmd-7xpqeh7c.json +4 -0
- package/dist-node/26-nassql-filter-predicate.nassql-2t27h5ev.md +41 -0
- package/dist-node/26-nassql-filter-predicate.nassql.data-store-k2rgp609.json5 +59 -0
- package/dist-node/26-nassql-filter-predicate.nassql.data-store-tmd-m4dddgwm.json +4 -0
- package/dist-node/27-nassql-distinct-keep.nassql-6z55dvk3.md +24 -0
- package/dist-node/27-nassql-distinct-keep.nassql.data-store-mrx00ys5.json5 +52 -0
- package/dist-node/27-nassql-distinct-keep.nassql.data-store-tmd-0p9hy42g.json +4 -0
- package/dist-node/28-nassql-format-time.nassql-6wraqgdk.md +30 -0
- package/dist-node/28-nassql-format-time.nassql.data-store-tmd-bbbqhz1x.json +4 -0
- package/dist-node/28-nassql-format-time.nassql.data-store-tvy8y2cs.json5 +59 -0
- package/dist-node/29-nassql-describe-log.nassql-t9vnxeb0.md +31 -0
- package/dist-node/29-nassql-describe-log.nassql.data-store-tmd-q4mtczy8.json +4 -0
- package/dist-node/29-nassql-describe-log.nassql.data-store-x16y4crx.json5 +51 -0
- package/dist-node/30-nassql-map-string.nassql-f2tdknzs.md +30 -0
- package/dist-node/30-nassql-map-string.nassql.data-store-t8ahcabn.json5 +53 -0
- package/dist-node/30-nassql-map-string.nassql.data-store-tmd-a6xq0bdx.json +4 -0
- package/dist-node/31-nassql-join-data-sum.nassql-p16y3xk6.md +26 -0
- package/dist-node/31-nassql-join-data-sum.nassql.data-store-dje7wm6v.json5 +64 -0
- package/dist-node/31-nassql-join-data-sum.nassql.data-store-tmd-c1pyx1qw.json +4 -0
- package/dist-node/32-nassql-bottom-aggregation.nassql-hpgfn77p.md +26 -0
- package/dist-node/32-nassql-bottom-aggregation.nassql.data-store-tmd-p0ssj1vc.json +4 -0
- package/dist-node/32-nassql-bottom-aggregation.nassql.data-store-v9580caa.json5 +43 -0
- package/dist-node/33-nassql-cross-domain-pipeline.nassql-fm0ynphf.md +45 -0
- package/dist-node/33-nassql-cross-domain-pipeline.nassql.data-store-tmd-18881drs.json +4 -0
- package/dist-node/33-nassql-cross-domain-pipeline.nassql.data-store-vqs9hkx4.json5 +79 -0
- package/dist-node/3rdpartylicenses-hx59bakt.txt +885 -0
- package/dist-node/50-discover-custom-layers.tas-2hvvpkzw.md +66 -0
- package/dist-node/50-discover-custom-layers.tas.data-store-h85zgna9.json5 +36 -0
- package/dist-node/50-discover-custom-layers.tas.data-store-tmd-hagn9eak.json +4 -0
- package/dist-node/51-collect-counts-everything.tas-nz0ksgdc.md +46 -0
- package/dist-node/51-collect-counts-everything.tas.data-store-eypcjah8.json5 +48 -0
- package/dist-node/51-collect-counts-everything.tas.data-store-tmd-4pcj94s9.json +4 -0
- package/dist-node/52-collect-counts-bulk.tas-eerw4z8s.md +54 -0
- package/dist-node/52-collect-counts-bulk.tas.data-store-scedtw1m.json5 +65 -0
- package/dist-node/52-collect-counts-bulk.tas.data-store-tmd-csyzj189.json +4 -0
- package/dist-node/53-collect-attributes-by-type.tas-cw0285hx.md +71 -0
- package/dist-node/53-collect-attributes-by-type.tas.data-store-fvjge4yr.json5 +65 -0
- package/dist-node/53-collect-attributes-by-type.tas.data-store-tmd-274qrd8f.json +4 -0
- package/dist-node/README-ghxecaz0.md +84 -0
- package/dist-node/SKILL-1xn7r9nt.md +104 -0
- package/dist-node/agent-25q752kd.md +55 -0
- package/dist-node/agent_connection_and_status-0dq7zkpc.md +62 -0
- package/dist-node/agent_source_collector-6s06n3rs.md +40 -0
- package/dist-node/agentic-mcp-rycd2gh8.md +140 -0
- package/dist-node/application-dfva8tz0.md +48 -0
- package/dist-node/application-m0q2vaxj.md +74 -0
- package/dist-node/attribute_resource_metric_name-pxrceab5.md +56 -0
- package/dist-node/browseragent-snippet.template-9megjp8a.html +12 -0
- package/dist-node/bulkvertexpatch-1a4qy5vb.md +78 -0
- package/dist-node/bundle.pbd-38r15kyd.template +13 -0
- package/dist-node/bundle.profile-1wpzpt3d.template +2 -0
- package/dist-node/business_transaction-mbqz5ex9.md +61 -0
- package/dist-node/chunk-4I3HBO6U-2ebgf7kh.js +127 -0
- package/dist-node/chunk-4PMCLJMS-0mqvr4m4.js +1 -0
- package/dist-node/chunk-5VSFINOX-ewzpx7wh.js +5 -0
- package/dist-node/chunk-72HYG3XZ-kf7hy4vs.js +3625 -0
- package/dist-node/chunk-JRM4BLOM-rg32z8w4.js +1 -0
- package/dist-node/chunk-Q2JA73UH-akkb8bh3.js +14 -0
- package/dist-node/chunk-RNMHSXZF-pdwasrg7.js +1358 -0
- package/dist-node/chunk-VV2FJEMA-3rvtkmga.js +321 -0
- package/dist-node/chunk-YVD3UK5I-9pxr1jka.js +695 -0
- package/dist-node/configuration-1vczsdex.md +104 -0
- package/dist-node/dashboards-x0xddksy.md +17 -0
- package/dist-node/database_or_inferred-8vqf5gyr.md +75 -0
- package/dist-node/default-licensing-config-0p879qpb.template +122 -0
- package/dist-node/dependency-3b0neg5x.md +40 -0
- package/dist-node/description.md-qwc2bj9r.template +30 -0
- package/dist-node/discovery-flow-fw79kbx4.md +116 -0
- package/dist-node/dxi_service-13prnpd5.md +59 -0
- package/dist-node/entity-relationships-cevz61kj.md +142 -0
- package/dist-node/gotchas-8ab64kcd.md +389 -0
- package/dist-node/host-es6fxtgx.md +46 -0
- package/dist-node/host-j3qqrm5f.md +55 -0
- package/dist-node/index-104hyb1m.html +13 -0
- package/dist-node/index-7fp2dfas.json +178 -0
- package/dist-node/index-g3hh5wez.json +403 -0
- package/dist-node/index-mbzg9rhc.json +270 -0
- package/dist-node/index-qffdhwgm.json +2479 -0
- package/dist-node/inferred-w998vfq1.md +41 -0
- package/dist-node/installInstructions.md-k9ghf3dr.template +21 -0
- package/dist-node/inventorize-xc9h9bjr.md +34 -0
- package/dist-node/investigation-planning-6kcm01h9.md +149 -0
- package/dist-node/investigator-flow-jc2s0n46.md +186 -0
- package/dist-node/k8s_deployment_and_namespace-69c29152.md +88 -0
- package/dist-node/k8s_pod_and_container-9h4v6cmj.md +64 -0
- package/dist-node/main-SGLYO5YX-ht69eb0y.js +13 -0
- package/dist-node/main.js +397415 -0
- package/dist-node/marketplace-srdmzxkj.json +15 -0
- package/dist-node/metric-source-names-6cbczyks.md +75 -0
- package/dist-node/metrics-grounding-2h4kkbe3.md +130 -0
- package/dist-node/mm-cookbook-23jpw721.md +231 -0
- package/dist-node/mm-quickstart-x2adfc16.md +106 -0
- package/dist-node/nassql-cookbook-n8kc0mff.md +812 -0
- package/dist-node/nassql-quickstart-090e0yex.md +149 -0
- package/dist-node/plugin-c3bavxvf.json +18 -0
- package/dist-node/polyfills-A7ZF72EO-mp884a0b.js +2 -0
- package/dist-node/prerendered-routes-523d8gat.json +3 -0
- package/dist-node/primeicons-4GST5W3O-jac3wxrf.woff2 +0 -0
- package/dist-node/primeicons-DHQU4SEP-760n99pp.svg +345 -0
- package/dist-node/primeicons-GEFHGEHP-rc4kaa3b.ttf +0 -0
- package/dist-node/primeicons-P53SE5CV-4saz3d5j.woff +0 -0
- package/dist-node/primeicons-RSSEDYLY-4d4vbd67.eot +0 -0
- package/dist-node/query-vs-analysis-separation-sag1ezcq.md +97 -0
- package/dist-node/run-query-vs-run-partial-6138pc94.md +80 -0
- package/dist-node/service-5pz5nhzf.md +133 -0
- package/dist-node/service-hierarchies-87a4ynpj.md +178 -0
- package/dist-node/service-k4f5mkbq.md +51 -0
- package/dist-node/servlet_or_frontend-1kjcb7ar.md +76 -0
- package/dist-node/src-apm-mfnsq6vw.svg +4 -0
- package/dist-node/src-axa-nn28yqmj.svg +4 -0
- package/dist-node/src-dxim-fv7ne4qa.svg +4 -0
- package/dist-node/styles-23VUPSCU-9ehggc1f.css +1 -0
- package/dist-node/tas-cookbook-0y4826rp.md +693 -0
- package/dist-node/tas-quickstart-wgcvwffc.md +138 -0
- package/dist-node/time-format-0595g01j.md +41 -0
- package/dist-node/toggles.pbd-9wscbmng.template +2 -0
- package/dist-node/type-host-agbhmn6v.svg +6 -0
- package/dist-node/type-metric-p9b90bpx.svg +4 -0
- package/dist-node/type-service-k7f1x71k.svg +4 -0
- package/dist-node/ui-0b5grqrg.md +113 -0
- package/dist-node/universe-b9nhf325.md +47 -0
- package/dist-node/universe-fzpwzvxr.md +91 -0
- package/dist-node/universes-and-scopes-1cb9pfk7.md +105 -0
- package/dist-node/vertex_entity_node-mm3yp9d0.md +31 -0
- 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>
|