@dx-do/cli 5.2.48 → 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.
- 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,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: tas-quickstart
|
|
3
|
+
title: TAS quickstart — author a topology query
|
|
4
|
+
applies_to: tas
|
|
5
|
+
tags: [getting-started, authoring]
|
|
6
|
+
related: [gotchas, discovery-flow]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# TAS quickstart
|
|
10
|
+
|
|
11
|
+
TAS = topology graph queries. Returns `{ vertices, edges }` shaped by a single
|
|
12
|
+
recursive **filter tree**. Every node is `{ "op": "<NAME>", ... }` — a
|
|
13
|
+
discriminated union on `op`. Most ops can wrap an `input` filter; leaf ops
|
|
14
|
+
(`ALL`, `LAYER`, `LUCENE`, `VARIABLE`) cannot.
|
|
15
|
+
|
|
16
|
+
## Schema landmines (READ FIRST)
|
|
17
|
+
|
|
18
|
+
The five things that bite first-time TAS authors:
|
|
19
|
+
|
|
20
|
+
1. **There is no `EQ` op.** Equality goes through `ATTRIBUTE` with `operator: IN` (one or more values), or through `LUCENE` with `field:value` syntax. Reaching for `{op:"EQ"}` is the most common day-1 mistake.
|
|
21
|
+
2. **`AND` / `OR` cannot be empty.** `{op:"AND", input:[]}` returns HTTP 400. Always at least one child. Schema validation rejects empty arrays before the request reaches the server.
|
|
22
|
+
3. **`NOT` takes a single `input`, not an array.** `{op:"NOT", input: <filter>}` — NOT `input: [<filter>]`. The latter parses but is rejected.
|
|
23
|
+
4. **`{op:"ALL"}` without `limit` returns the entire topology.** Often megabytes; sometimes refused. Always pair `ALL` with a sensible `limit` (5–100 for sampling).
|
|
24
|
+
5. **Field name is `input`, not `filters`/`children`.** The recursive child slot is always called `input` (singular for NOT, array for AND/OR/TRAVERSE-input).
|
|
25
|
+
|
|
26
|
+
Two more, schema-shape:
|
|
27
|
+
|
|
28
|
+
6. **`LUCENE` is tenant-config-dependent** — not enabled on every tenant. If you're authoring a query that should work everywhere, prefer `ATTRIBUTE` + `MATCHES` instead.
|
|
29
|
+
7. **`LAYER` filter has both `value` (singular string) and `values` (array)** — pick the one that matches the count of layers you want to match. Both work; mixing them is invalid.
|
|
30
|
+
|
|
31
|
+
## The envelope
|
|
32
|
+
|
|
33
|
+
```jsonish
|
|
34
|
+
{
|
|
35
|
+
"filter": { ... }, // root filter tree (required in practice)
|
|
36
|
+
"limit": 20, // cap returned vertices
|
|
37
|
+
"projection": "DETAILED", // attribute breadth: DETAILED | BRIEF | NO_TYPE
|
|
38
|
+
"includeServices": true, // surface the `serviceNames` attribute on each vertex
|
|
39
|
+
"includeStatus": true, // adds a `states[]` array to the response (NOT an attribute on each vertex — see the Status section in tas-cookbook)
|
|
40
|
+
"time": 1700000000000, // optional point-in-time epoch ms
|
|
41
|
+
"order": [...], // optional sort
|
|
42
|
+
"universe": { ... }, // optional filter applied first
|
|
43
|
+
"postFilter": { ... } // optional filter applied after
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Default `projection` is implementation-defined; explicitly set `DETAILED`
|
|
48
|
+
when you want all attributes back.
|
|
49
|
+
|
|
50
|
+
**`includeServices: true` is the cheapest way to learn what services an entity belongs to** — every entity carries a `serviceNames: string[]` attribute that the platform pre-populates (typically within ~1 min of entity creation, ~2 min of new-service creation). Without this flag, the field is silently absent and you'll wrongly conclude the entity has no service membership. Pair with `includeStatus: true` for an identity + membership + health snapshot in one query.
|
|
51
|
+
|
|
52
|
+
**`includeStatus: true` adds a `states[]` array to the response, separate from `vertices[]` / `edges[]`.** It does NOT add a `status` attribute to each vertex — read severity by joining `states[].vertexId` against `vertices[].id`. Each state row is per-`(vertex, alert OR metric)`; a single vertex typically has multiple state rows. The rolled-up severity (what the platform UI shows) lives on the row whose `stateExternalId.alert === "sa://sa_status"`. Numeric `status` values: `0=UNKNOWN`, `1=OK`, `2=MINOR`, `3=MAJOR`, `4=CRITICAL`. Full response shape, common patterns, and the "show me everything currently CRITICAL" workaround in `cookbooks/tas-cookbook` ("Status — `includeStatus` and the `states[]` response array" section).
|
|
53
|
+
|
|
54
|
+
## The 8 ops you'll use most
|
|
55
|
+
|
|
56
|
+
| Op | Purpose | Has `input`? |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| `ALL` | Match every vertex. Use with `limit` for sampling. | No |
|
|
59
|
+
| `ATTRIBUTE` | Match by attribute expressions. The workhorse. | Yes |
|
|
60
|
+
| `LAYER` | Restrict to one or more layers. | No |
|
|
61
|
+
| `LUCENE` | Free-text Lucene query. | No |
|
|
62
|
+
| `AND` / `OR` | Compose. Each takes `input: TasFilter[]`. **Cannot be empty.** | Yes (children) |
|
|
63
|
+
| `NOT` | Negate. Takes `input: TasFilter`. | Yes |
|
|
64
|
+
| `TRAVERSE` | Walk edges. Takes a `traverse: [...]` array. | Yes |
|
|
65
|
+
|
|
66
|
+
## Discovery first, then author
|
|
67
|
+
|
|
68
|
+
Before authoring anything specific, call:
|
|
69
|
+
|
|
70
|
+
- `discovery_layers` → list of available layers (e.g. `INFRASTRUCTURE`, `CONNECTOR`, `AGENT`)
|
|
71
|
+
- `discovery_attributes(layer)` → attribute names known on that layer
|
|
72
|
+
- `discovery_attribute_values(layer, attribute)` → distinct values for IN-style filters
|
|
73
|
+
|
|
74
|
+
Without this, you'll guess attribute names that don't exist on this tenant.
|
|
75
|
+
|
|
76
|
+
**Authoring an `ATTRIBUTE` filter (or any other op)?** Call `query_schema` with the op first to confirm the canonical field names — `{type: "tas", op: "ATTRIBUTE"}` returns a 4 KB summary listing the 5 properties (op, input, expressions, layer, mode) with descriptions. Cheaper than a guess + server-validation retry, and prevents the textbook `_type` vs `type` mistake. The summary is inline-readable; reach for `full: true` only when nested validation detail (enum values past 6 entries, recursive sub-shapes) actually matters.
|
|
77
|
+
|
|
78
|
+
## Pattern: layer + attribute filter
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"filter": {
|
|
83
|
+
"op": "AND",
|
|
84
|
+
"input": [
|
|
85
|
+
{ "op": "LAYER", "values": ["INFRASTRUCTURE"] },
|
|
86
|
+
{ "op": "ATTRIBUTE", "expressions": [
|
|
87
|
+
{ "name": "type", "operator": "IN", "values": ["HOST"] }
|
|
88
|
+
]}
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
"limit": 20,
|
|
92
|
+
"projection": "DETAILED"
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Pattern: traverse from one set to its neighbours
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"filter": {
|
|
101
|
+
"op": "TRAVERSE",
|
|
102
|
+
"input": { "op": "ATTRIBUTE", "expressions": [...] },
|
|
103
|
+
"traverse": [
|
|
104
|
+
{ "vertex": { "op": "ALL" }, "edge": { "op": "ALL" }, "direction": "FORWARD" }
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## ATTRIBUTE expression details
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"name": "hostname", // attribute name
|
|
115
|
+
"operator": "MATCHES", // IN | NOT_IN | MATCHES | NOT_MATCHES | GE | GT | LE | LT
|
|
116
|
+
"values": ["api-*"], // values array (IN/NOT_IN take arrays of values)
|
|
117
|
+
"comparator": "LEXICAL", // LEXICAL | NUMBER | DATETIME (changes value typing)
|
|
118
|
+
"caseInsensitive": false
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
For `comparator: "NUMBER"`, `values` are JSON numbers, not strings.
|
|
123
|
+
|
|
124
|
+
## Iteration
|
|
125
|
+
|
|
126
|
+
Once a draft is in place, use `run_partial_query` with `at: ["filter", "input", N]`
|
|
127
|
+
to verify a sub-tree without authoring a separate test query. The wrapped
|
|
128
|
+
envelope inherits `limit`, `projection`, `time`, `universe`, `order`, `offset`
|
|
129
|
+
from the parent payload — so "run just this branch" sees what would be seen
|
|
130
|
+
at the top.
|
|
131
|
+
|
|
132
|
+
## See also
|
|
133
|
+
|
|
134
|
+
- `tas-cookbook.md` — full op reference, recipe catalog, composition patterns
|
|
135
|
+
- `gotchas.md` — FROM_TOPOLOGY's restricted querySpecifier, ATTRIBUTE.layer constraint
|
|
136
|
+
- `discovery-flow.md` — full discovery pattern
|
|
137
|
+
- `run-query-vs-run-partial.md` — when to use which execution mode
|
|
138
|
+
- Live examples: `corpus_list("queries", {type: "tas"})` — fetch full payloads with `corpus_get("queries", "<id>")`. Good starting points: `01-discover-vertices`, `02-discover-services`, `10-filter-attribute-matches`, `11-filter-and-compose`.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
## Let's just say it out loud: time formatting from the command line sucks.
|
|
2
|
+
|
|
3
|
+
But there are some easy consistent options for many time range commands including
|
|
4
|
+
|
|
5
|
+
* metric data
|
|
6
|
+
* agent get-trace-summaries
|
|
7
|
+
|
|
8
|
+
The absolutely easiest way, IMO is `ISO Durations`.
|
|
9
|
+
|
|
10
|
+
The commands above take
|
|
11
|
+
|
|
12
|
+
* endTime + relativeStartTime
|
|
13
|
+
* startTime + relativeEndTime
|
|
14
|
+
|
|
15
|
+
## Let's start with examples:
|
|
16
|
+
|
|
17
|
+
### Time period ends 1day+3 hours ago, and begins 2 hours before that.
|
|
18
|
+
```
|
|
19
|
+
endTime=P1DT3H relativeStartDuration=PT2H
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Time period starts 1week+7hours ago and ends 30 minutes after that.
|
|
23
|
+
```
|
|
24
|
+
startTime=P1WT3H relativeEndDuration=PT30M
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
* If you specify a partial for endTime or startTime, that is relative to NOW.
|
|
28
|
+
* relativeStartDuration/relativeEndDuration is relative to the endTime/startTime.
|
|
29
|
+
* There is no need to specify a negative
|
|
30
|
+
|
|
31
|
+
* P = REQUIRED START INDICATOR FOR ISO8601 Partial
|
|
32
|
+
* Y = years
|
|
33
|
+
* M = months
|
|
34
|
+
* W = weeks
|
|
35
|
+
* D = days
|
|
36
|
+
* T = delineator between dates and times, necessary to disambiguate between months and minutes
|
|
37
|
+
* H = hours
|
|
38
|
+
* M = minutes
|
|
39
|
+
* S = seconds
|
|
40
|
+
|
|
41
|
+
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
2
|
+
<rect x="3" y="5" width="18" height="11" rx="1.5"/>
|
|
3
|
+
<line x1="3" y1="13" x2="21" y2="13"/>
|
|
4
|
+
<line x1="8" y1="20" x2="16" y2="20"/>
|
|
5
|
+
<line x1="12" y1="16" x2="12" y2="20"/>
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
2
|
+
<circle cx="12" cy="12" r="3.2"/>
|
|
3
|
+
<path d="M12 4v3M12 17v3M4 12h3M17 12h3M6.3 6.3l2.1 2.1M15.6 15.6l2.1 2.1M6.3 17.7l2.1-2.1M15.6 8.4l2.1-2.1"/>
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# `dx-do ui start` — visual query builder
|
|
2
|
+
|
|
3
|
+
Start a local Fastify + Angular server that lets you author and run **TAS / NASSQL / Metrics-Metadata** queries against a bound DXO2 tenant in your browser. The same server hosts the MCP endpoint at `/mcp` (see `dx-do help agentic-mcp` for the MCP surface).
|
|
4
|
+
|
|
5
|
+
> **Experimental.** `ui start` is currently gated. To run it, either:
|
|
6
|
+
> - pass `--enable-experimental-commands` on the dx-do invocation
|
|
7
|
+
> - export `DXDO_ENABLE_EXPERIMENTAL_COMMANDS=true` in your environment
|
|
8
|
+
>
|
|
9
|
+
> Both forms work the same way; the env var is the easiest if you'll be running ui repeatedly.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
DXDO_ENABLE_EXPERIMENTAL_COMMANDS=true dx-do ui start [config=<alias>]
|
|
15
|
+
[port=<n>]
|
|
16
|
+
[open=true|false]
|
|
17
|
+
[mcp=true|false]
|
|
18
|
+
[module.<id>=off|read|write ...]
|
|
19
|
+
[dev=true|false]
|
|
20
|
+
[mcpOnly=true|false]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
All flags are optional. With no flags the server picks a free port, opens your browser, prompts you to pick a tenant config, and starts the MCP at `/mcp`.
|
|
24
|
+
|
|
25
|
+
## What you get
|
|
26
|
+
|
|
27
|
+
* **Visual editors** for the three datastore query types — TAS topology queries, NASSQL metric pipelines, and Metrics-Metadata specifiers. Each editor renders the payload tree with op-specific controls and discovery-driven dropdowns.
|
|
28
|
+
* **Tenant picker** (the *configuration alias* pill in the top bar). Switch tenants mid-session without restarting; everything re-binds.
|
|
29
|
+
* **Save to disk** under `~/.dxdo/queries/<alias>/` as a *file triplet* (see below). Saved queries appear in the left rail and can be edited / re-run later.
|
|
30
|
+
* **Discovery panel** — auto-loaded layer / service / metric / attribute lists for the bound tenant, cached per session. Refresh with the refresh button when the tenant changes underneath you.
|
|
31
|
+
* **Catalog browser** — read-only access to the universal worked-example queries and cookbooks shipped with `@dx-do/corpus`. Useful when you want a starting point for authoring.
|
|
32
|
+
* **MCP endpoint at `/mcp`** for AI agents — same 17-tool default surface as `dx-do agentic mcp`, gated by the same module flags. Use `mcp=false` to skip MCP entirely.
|
|
33
|
+
|
|
34
|
+
## Basic workflow
|
|
35
|
+
|
|
36
|
+
1. **Start**: `dx-do ui start config=demo-prod` (browser opens automatically).
|
|
37
|
+
2. **Pick a query type** in the left rail or open an existing one.
|
|
38
|
+
3. **Edit** in the visual tree, in the JSON5 tab, or both (they round-trip).
|
|
39
|
+
4. **Run** with the ▶ button. Use the per-op ▶ buttons for partial runs (TAS sub-filters; NASSQL up-to-step).
|
|
40
|
+
5. **Save** with **⌘S** / **Ctrl+S**. The file triplet is written to disk and the left-rail entry refreshes.
|
|
41
|
+
|
|
42
|
+
## Query persistence — the file triplet
|
|
43
|
+
|
|
44
|
+
Each saved query is **three sibling files** under `~/.dxdo/queries/<alias>/`:
|
|
45
|
+
|
|
46
|
+
| File | Contents |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `<id>.<type>.data-store.json5` | Payload + path-keyed inline descriptions persisted as JSON5 `/* */` block comments. |
|
|
49
|
+
| `<id>.<type>.data-store-tmd.json` | Test metadata: short description, tags, `expectedFailure`, `skip`. |
|
|
50
|
+
| `<id>.<type>.md` | Companion markdown — long-form intent, expected output, gotchas. |
|
|
51
|
+
|
|
52
|
+
`<type>` is `tas`, `nassql`, or `metadata`. The id includes a numeric prefix (e.g. `01-discover-vertices`) which orders the left rail. Files round-trip: hand-edit the JSON5 in your editor and the SPA picks up the changes on focus.
|
|
53
|
+
|
|
54
|
+
## Inline descriptions — three tiers
|
|
55
|
+
|
|
56
|
+
Every op in your query can carry an inline note. The notes persist as JSON5 block comments and round-trip through the visual / JSON5 tabs without flapping.
|
|
57
|
+
|
|
58
|
+
* **Top-level** — file-leading comment, describes the whole query. Above the visual tree.
|
|
59
|
+
* **Per-op** — above each op's header (in the visual tree). Bound to a JSONPath like `$.filter` or `$.query[2]`.
|
|
60
|
+
* **Per-record** — above each AttributeExpression / specifier inside an op (e.g. `$.filter.expressions[0]`).
|
|
61
|
+
|
|
62
|
+
These descriptions are how you ground future agents reading your saved query via MCP — leave reasoning here and the next agent gets it for free via `get_query`.
|
|
63
|
+
|
|
64
|
+
## Right pane — Source / Results / Debug
|
|
65
|
+
|
|
66
|
+
The right pane is tabbed:
|
|
67
|
+
|
|
68
|
+
* **Source** — pretty-printed JSON of the parsed payload. The default tab.
|
|
69
|
+
* **Results** — full-run output. Auto-activates when ▶ produces a result.
|
|
70
|
+
* **Debug** — partial-run output. Auto-activates when a per-op ▶ runs. Shows a scope breadcrumb (e.g. `$.filter.input[1]` for TAS, `steps 1–3` for NASSQL).
|
|
71
|
+
|
|
72
|
+
Tabs report `<n>ms / stale / error`. Editing the payload flips Results and Debug to **stale** until you re-run.
|
|
73
|
+
|
|
74
|
+
## Flags
|
|
75
|
+
|
|
76
|
+
| Flag | Default | Effect |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| `config=<alias>` | (prompts in UI) | Pre-bind to `~/.dxdo/<alias>.dxo2.config.json`. |
|
|
79
|
+
| `port=<n>` | free port (4321 in `dev=true`) | Bind to a specific port. |
|
|
80
|
+
| `open=false` | `true` | Suppress the auto-open browser. |
|
|
81
|
+
| `mcpOnly=true` | `false` | Don't open browser; surface the MCP URL in the startup log. |
|
|
82
|
+
| `mcp=false` | `true` | Skip registering `/mcp` on the HTTP server entirely. |
|
|
83
|
+
| `module.<id>=off\|read\|write` | `ui=write`, others `read` | Per-module MCP permissions. See `dx-do help agentic-mcp` for the module corpus. |
|
|
84
|
+
| `dev=true` | `false` | Bind port 4321; enable CORS for `http://localhost:4200` (the Angular dev server). |
|
|
85
|
+
|
|
86
|
+
## MCP module flags
|
|
87
|
+
|
|
88
|
+
The same `module.<id>=...` flags accepted by `dx-do agentic mcp` work here — they control the HTTP `/mcp` endpoint instead of stdio. Examples:
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
# Lock external agents to read-only on user queries even though the SPA can still write.
|
|
92
|
+
dx-do ui start config=demo-prod module.ui=read
|
|
93
|
+
|
|
94
|
+
# Disable the MCP entirely (SPA only).
|
|
95
|
+
dx-do ui start config=demo-prod mcp=false
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The startup log line shows the resolved per-module levels so you can confirm at a glance.
|
|
99
|
+
|
|
100
|
+
## Stopping
|
|
101
|
+
|
|
102
|
+
**Ctrl+C** terminates the server. The Fastify shutdown hook closes open connections cleanly.
|
|
103
|
+
|
|
104
|
+
## Where things live on disk
|
|
105
|
+
|
|
106
|
+
* **Tenant configs** — `~/.dxdo/<alias>.dxo2.config.json`
|
|
107
|
+
* **Saved queries** — `~/.dxdo/queries/<alias>/[<folder>/]<id>.<type>.<ext>`
|
|
108
|
+
* **Catalog (read-only)** — bundled inside `@dx-do/corpus` (no user-side files)
|
|
109
|
+
|
|
110
|
+
## Related
|
|
111
|
+
|
|
112
|
+
* `dx-do help agentic-mcp` — same MCP surface, stdio transport, no SPA.
|
|
113
|
+
* `dx-do help configuration` — how `~/.dxdo/<alias>.dxo2.config.json` files are loaded and validated.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: universe
|
|
3
|
+
title: universe — APM Universe vs O2 Universe
|
|
4
|
+
aliases: [universes, view, scope]
|
|
5
|
+
category: scoping
|
|
6
|
+
related: [service, application]
|
|
7
|
+
tags: [overloaded, core]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# universe
|
|
11
|
+
|
|
12
|
+
DXO2 has **two flavors of universe**, and the difference matters for which API to call and what data to expect:
|
|
13
|
+
|
|
14
|
+
- **APM Universe** — ApmUniverseService territory. Tends to hold telemetry sources (the agents that produce metrics) and their associated entities. Created and managed by the APM side of the platform.
|
|
15
|
+
- **O2 Universe** (a.k.a. Platform Universe) — O2UniverseService territory. A catch-all for organization, especially data integrated from non-APM sources (NetOps, log analytics, custom integrations). Created and managed on the O2/platform side.
|
|
16
|
+
|
|
17
|
+
Both are **scoping mechanisms** — like a workspace for a slice of tenant data.
|
|
18
|
+
|
|
19
|
+
## Why this matters
|
|
20
|
+
|
|
21
|
+
- The two flavors have **different APIs and different vertex shapes**. If you query the wrong service, you'll get an empty list and not realize it.
|
|
22
|
+
- Some system-default universes exist on every tenant and are usually NOT what the user wants when they say "in universe X" — e.g. `UNsaasProd`, `VIEWALL`. Exclude these from offered choices unless the user explicitly references them.
|
|
23
|
+
|
|
24
|
+
## Disambiguation rule
|
|
25
|
+
|
|
26
|
+
1. If the user names a universe by id or label, search **both** APM and O2 universes.
|
|
27
|
+
2. The MCP tool `discovery_universes` returns the union (in two distinguishable lists).
|
|
28
|
+
3. Default to the matching universe; if both have a universe of that name, prefer the user-created one and confirm.
|
|
29
|
+
|
|
30
|
+
## When to scope by universe vs by service
|
|
31
|
+
|
|
32
|
+
- **Universe** = primary scope for *what data exists* (a slice of the tenant).
|
|
33
|
+
- **Service** = secondary scope for *organizational/business meaning* on top of a universe.
|
|
34
|
+
|
|
35
|
+
When a user says "the production environment", that's usually a universe (or a service inside a universe). "The X application" usually maps to a service or DXO2 application within whatever universe makes sense.
|
|
36
|
+
|
|
37
|
+
## How users phrase it
|
|
38
|
+
|
|
39
|
+
- "in the APM universe" / "the metric universe" → APM Universe.
|
|
40
|
+
- "the platform universe" / "everything we ingest" → O2 Universe.
|
|
41
|
+
- "the production view" / "the prod scope" → either; needs disambiguation.
|
|
42
|
+
|
|
43
|
+
## See also
|
|
44
|
+
|
|
45
|
+
- `cookbooks/universes-and-scopes` — full mechanics.
|
|
46
|
+
- `lexicon/service` — the next-axis-down.
|
|
47
|
+
- `entities/universe` — entity-shape detail.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: universe
|
|
3
|
+
title: Universe — the primary scoping mechanism for tenant data
|
|
4
|
+
synonyms: [view, scope, segregation]
|
|
5
|
+
related_entities: [service, dxi_service]
|
|
6
|
+
related_cookbooks: [universes-and-scopes, investigator-flow]
|
|
7
|
+
tags: [scoping, core, organizational-axis]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Universe
|
|
11
|
+
|
|
12
|
+
## What it is
|
|
13
|
+
|
|
14
|
+
A **Universe** is the primary scoping mechanism in DXO2 — a named, access-controlled view over a slice of the tenant's topology and metrics. When a user asks an investigative question on a typical tenant, *the first ambiguity to resolve is which universe(s) they mean*. Universes are how customers segregate environments (prod vs staging), regions (NA vs EMEA vs APJ), product lines, lines of business, or any other organizational axis they care about.
|
|
15
|
+
|
|
16
|
+
There are **two distinct kinds of universes** in DXO2 with materially different shapes — confusing them silently is one of the bigger ways an investigator can hand back a wrong answer:
|
|
17
|
+
|
|
18
|
+
- **APM Universe** (legacy-shaped, APM-flavoured)
|
|
19
|
+
- **O2 Universe** (modern, "Platform" / O2-flavoured)
|
|
20
|
+
|
|
21
|
+
Both kinds can coexist on the same tenant. Many tenants have only one kind; some have both.
|
|
22
|
+
|
|
23
|
+
## APM Universes
|
|
24
|
+
|
|
25
|
+
The original universe concept, scoped to APM (Application Performance Management) data.
|
|
26
|
+
|
|
27
|
+
**Shape**: each universe has a single `viewId` + `label`, and a fixed `views` object with three slots:
|
|
28
|
+
|
|
29
|
+
- `views.tas` — a TAS filter (in legacy form: `{ vertices, items, joins }`) defining which entities are visible.
|
|
30
|
+
- `views.nass` — a NASS filter built from EXACT-name and REGEX specifiers.
|
|
31
|
+
- `views.mm` — a metric-metadata filter (just a `string[]`).
|
|
32
|
+
|
|
33
|
+
Plus per-view permissions, attributes (counts like `TAS_AGENT_COUNT` / `TAS_ATC_COUNT` / `NASS_COUNT`), and an `access` block of users + groups with role-based permissions.
|
|
34
|
+
|
|
35
|
+
**How to enumerate**: from an MCP-driven agent, call `discovery_universes` (returns both kinds in one call as `{apm, o2}`, in the user-facing `name`-first shape). From the CLI: `dx-do apm-universe list`. Programmatically: `ApmUniverseService.retrieveAllUniverses()`.
|
|
36
|
+
|
|
37
|
+
**APM-flavoured signals**: legacy TAS filter shape (`legacy.vertices`, `legacy.items`, `legacy.joins`); presence of `attributes.TAS_AGENT_COUNT`; user/group permissions include `nass`/`tas`/`mm` keys.
|
|
38
|
+
|
|
39
|
+
## O2 Universes
|
|
40
|
+
|
|
41
|
+
The newer Platform / O2-style universe. Same conceptual role (named, access-controlled view) but a flexible multi-view shape:
|
|
42
|
+
|
|
43
|
+
**Shape**: each universe has `viewId` + `label`/`description` (in `attributes`), and a `views: O2UniverseView[]` array — each entry is one of:
|
|
44
|
+
|
|
45
|
+
- `{ type: 'tas', filter: { filter: TASFilter, includeMetricFilter?, projection?, projectionFilter? }, permissions }`
|
|
46
|
+
- `{ type: 'nass', filter: { filter: TASFilter, serviceFilter? }, permissions }`
|
|
47
|
+
- `{ type: 'es', filter: unknown, permissions }`
|
|
48
|
+
|
|
49
|
+
A single O2 universe can carry zero, one, or many of each view type. The TAS filter inside is the *modern* TAS schema (op-discriminated tree), not the legacy form. Per-view permissions are independent.
|
|
50
|
+
|
|
51
|
+
**How to enumerate**: same as above — `discovery_universes` returns both kinds in one call. CLI: `dx-do o2-universe list`. Programmatically: `O2UniverseService.retrieveAllUniverses()`.
|
|
52
|
+
|
|
53
|
+
**O2-flavoured signals**: modern TAS filter shape (`op: 'AND'`, `op: 'ATTRIBUTE'`, etc.); `viewId` + `attributes.label`; multiple views in an array; the universe-to-service relationship surfaced via `getServiceNameToUniverseLabelMap()` (see "Universes and services" below).
|
|
54
|
+
|
|
55
|
+
## Investigative checklist (the load-bearing pattern)
|
|
56
|
+
|
|
57
|
+
When a user asks an entity- or metric-shaped investigative question (*"are there any hosts with high CPU right now?"*, *"show me the top services by error rate"*, *"what alarms fired overnight?"*), **before authoring any query**:
|
|
58
|
+
|
|
59
|
+
1. **Enumerate**: how many APM universes? how many O2 universes? how many top-level services?
|
|
60
|
+
2. **Surface**: tell the user what you see, in a single sentence. *"On this tenant I see 3 APM universes (Prod, Staging, NA-EMEA-Combined), 7 O2 universes (mostly per-region), and 142 services."*
|
|
61
|
+
3. **Ask**: did they mean *all* of it, a specific universe, a specific service?
|
|
62
|
+
4. **Default carefully**: if the user replies "all hosts", confirm whether they mean "literally all" (cross-universe) or "all in the universe I'm currently looking at" — the answer is materially different on a tenant with multiple universes.
|
|
63
|
+
|
|
64
|
+
This is one or two extra round-trips. It's worth it; the alternative is producing a query against the wrong scope and burning the user's time on a result they have to re-do.
|
|
65
|
+
|
|
66
|
+
## Universes and services
|
|
67
|
+
|
|
68
|
+
On many O2 tenants, a universe maps to a *service* (or a service maps to a universe — the relationship is bidirectional). `O2UniverseService.getServiceNameToUniverseLabelMap()` and `getUniverseLabelToServiceNameMap()` exist for exactly this lookup. When a user names a service in their question (*"the Mobile Service"*), check whether there's a universe of the same name first — if so, the universe-scoped query is usually what they want.
|
|
69
|
+
|
|
70
|
+
See `entities/service` for the service axis (which has its own hierarchy and subservice-traversal nuances).
|
|
71
|
+
|
|
72
|
+
## Common synonyms / mistakes
|
|
73
|
+
|
|
74
|
+
- **"View" / "scope"** — colloquial synonyms. Worth confirming which kind of universe.
|
|
75
|
+
- **"Universe" without qualifier** — on a multi-universe-kind tenant, ALWAYS clarify APM vs O2. They have different filter shapes, different access models, and different downstream behavior.
|
|
76
|
+
- **Confusing universe with service** — common, especially because they often share names. A *universe* is the view-defining filter; a *service* is one of the things that view typically scopes around. They're orthogonal axes that frequently collapse together in tenant naming.
|
|
77
|
+
- **Treating `attributes.label` and `viewId` interchangeably** — the user reads the label; the API takes the viewId. Always look up the viewId via the universe list, don't hardcode it. The `discovery_universes` MCP tool surfaces these as `name` (label) and `id` (viewId) — speak to users in `name` always, reach for `id` only when assembling an outgoing API call.
|
|
78
|
+
|
|
79
|
+
## Useful CLI commands
|
|
80
|
+
|
|
81
|
+
- `dx-do apm-universe list` — APM universes on the bound tenant.
|
|
82
|
+
- `dx-do o2-universe list` — O2 universes on the bound tenant.
|
|
83
|
+
- `dx-do o2-universe services` — service↔universe mapping.
|
|
84
|
+
- `dx-do apm-universe detail` / `o2-universe export` — full universe shape including filters.
|
|
85
|
+
|
|
86
|
+
## See also
|
|
87
|
+
|
|
88
|
+
- `entities/service` — the secondary scoping axis (often interacts with universes).
|
|
89
|
+
- `entities/dxi_service` — APM-internal service abstraction (different from the service axis).
|
|
90
|
+
- `cookbooks/universes-and-scopes` — the canonical investigator pattern for universe-aware querying.
|
|
91
|
+
- `cookbooks/investigator-flow` — the broader scope-clarification checklist.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: universes-and-scopes
|
|
3
|
+
title: Universes and scopes — APM vs O2 disambiguation
|
|
4
|
+
applies_to: all
|
|
5
|
+
tags: [investigator, scoping, reference]
|
|
6
|
+
related: [investigator-flow, service-hierarchies]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Universes and scopes
|
|
10
|
+
|
|
11
|
+
## Why this matters
|
|
12
|
+
|
|
13
|
+
On any tenant with more than one universe, "show me the hosts" is ambiguous. The user almost always has a specific universe in mind but doesn't realize they're asking against an undefined scope. Authoring a query against the wrong scope is silently wrong — the user gets answers that look real but represent the wrong slice.
|
|
14
|
+
|
|
15
|
+
This cookbook covers the universe-disambiguation half of the scope-clarification step (`cookbooks/investigator-flow` step 1).
|
|
16
|
+
|
|
17
|
+
## Two kinds of universes
|
|
18
|
+
|
|
19
|
+
DXO2 has **APM Universes** and **O2 Universes** (Platform). Both can coexist on a tenant. They have different shapes, different APIs, and different downstream behavior. See `entities/universe` for the schema-level details.
|
|
20
|
+
|
|
21
|
+
| | APM Universe | O2 Universe |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| Shape | Fixed `views: { tas, nass, mm }` | Flexible `views[]` (TAS / NASS / ES, multi-instance) |
|
|
24
|
+
| TAS filter form | Legacy (`vertices`, `items`, `joins`) | Modern op-discriminated tree |
|
|
25
|
+
| NASS filter form | EXACT/REGEX specifiers | TAS filter + optional ServiceFilter |
|
|
26
|
+
| Enumerate (CLI) | `dx-do apm-universe list` | `dx-do o2-universe list` |
|
|
27
|
+
| Service↔universe map | (per-universe; check the universe's `views` for service references) | Provided by the O2 universe metadata; surfaced via `discovery_universes` once available |
|
|
28
|
+
|
|
29
|
+
There is no shared "universe list" MCP tool today — `discovery_universes` is forthcoming. Until then, shell out to the CLI commands above.
|
|
30
|
+
|
|
31
|
+
## How to detect "which kind does the user mean"
|
|
32
|
+
|
|
33
|
+
When the user mentions a universe name without qualifying it:
|
|
34
|
+
|
|
35
|
+
1. **Check both lists.** A name might be unique to APM, unique to O2, or duplicated across both (rare but possible).
|
|
36
|
+
2. **If unique to one** — proceed with that universe; mention which kind in your handoff sentence so the user can correct you if wrong.
|
|
37
|
+
3. **If duplicated** — ask. *"There's an APM universe and an O2 universe both called 'Prod' — which one?"*
|
|
38
|
+
4. **If neither matches** — ask if they're naming a service instead. Universes and services often have overlapping names (see "Universe-service collisions" below).
|
|
39
|
+
|
|
40
|
+
When the user uses APM-flavoured language (*"agents in this universe"*, *"the APM Prod universe"*, *"agent counts"*) — bias toward APM Universe.
|
|
41
|
+
|
|
42
|
+
When the user uses O2-flavoured language (*"the O2 view"*, *"the platform universe"*, *"NASS view permissions"*) — bias toward O2 Universe.
|
|
43
|
+
|
|
44
|
+
## Universe-service collisions
|
|
45
|
+
|
|
46
|
+
On many O2-style tenants, **a universe and a service share the same name** because the universe was created from the service's filter (or vice versa). When the user says *"the Mobile Service"*:
|
|
47
|
+
|
|
48
|
+
- Is there a universe labelled "Mobile Service"? Cross-check the O2 universe list (`dx-do o2-universe list`) for a matching label.
|
|
49
|
+
- If yes, the universe-scoped query is usually the right move — universes already encode the relevant filter.
|
|
50
|
+
- If no, fall back to a service-scoped TAS query (see `cookbooks/service-hierarchies`).
|
|
51
|
+
|
|
52
|
+
If the user has both a universe and a service of the same name, that's an artifact of how their tenant was set up; the universe usually has the more curated definition.
|
|
53
|
+
|
|
54
|
+
## Authoring queries scoped to a universe
|
|
55
|
+
|
|
56
|
+
A universe is a collection of *filter definitions* — to scope a TAS or NASSQL query to a universe, you replicate the universe's filter into your query.
|
|
57
|
+
|
|
58
|
+
### From an O2 Universe
|
|
59
|
+
|
|
60
|
+
For an O2 Universe with a TAS view, retrieve the universe (e.g. via `dx-do o2-universe get <id>`), pull the TAS view's filter, and AND it with the user's intent filter:
|
|
61
|
+
|
|
62
|
+
```jsonish
|
|
63
|
+
{
|
|
64
|
+
"filter": {
|
|
65
|
+
"op": "AND",
|
|
66
|
+
"input": [
|
|
67
|
+
<universe's TAS filter>,
|
|
68
|
+
<the user's intent filter>
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
"limit": 100,
|
|
72
|
+
"projection": "DETAILED"
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
For a NASS view, the universe carries `{ filter: TASFilter, serviceFilter?: ServiceFilter }` — for NASSQL queries, use the TAS filter as the input to `FROM_TOPOLOGY`.
|
|
77
|
+
|
|
78
|
+
### From an APM Universe
|
|
79
|
+
|
|
80
|
+
The APM Universe carries a *legacy*-shaped TAS filter (`legacy.vertices`, `legacy.items`, `legacy.joins`). The DXO2 server typically accepts both forms; if the canonical TAS schema (op-discriminated) doesn't accept the legacy shape directly, you may need to translate it. A simpler practical approach: use the universe's `nass` filter (EXACT-name specifiers) as the input to `FROM_TOPOLOGY` in a NASSQL query when possible.
|
|
81
|
+
|
|
82
|
+
## System-default universes — exclude when inferring org shape
|
|
83
|
+
|
|
84
|
+
Two universe IDs are tenant-creation defaults (not user-modeled scopes). They appear on every tenant; their presence tells you nothing about how the customer organizes their data:
|
|
85
|
+
|
|
86
|
+
- **`UNsaasProd`** — the APM default universe (often labelled "Your Applications").
|
|
87
|
+
- **`VIEWALL`** — the O2 default universe (often labelled "All Access").
|
|
88
|
+
|
|
89
|
+
When inferring the *organizational shape* of a tenant for an investigator's scope-clarification step, **filter these out** of the universe list. The user-created universes that remain are the ones that reflect the customer's intent (per-region, per-product, per-environment, etc.). If after filtering there are zero or one user-created universes, the tenant is universe-light — fall back on the service axis for org structure.
|
|
90
|
+
|
|
91
|
+
(For *executing* a query against a universe, the system defaults are still valid scopes; they just don't help you understand "how is this tenant organized.")
|
|
92
|
+
|
|
93
|
+
## Investigator-flow integration
|
|
94
|
+
|
|
95
|
+
In step 1 of `cookbooks/investigator-flow`, surface the user-created universe count alongside the service count: *"On this tenant: 11 APM universes / 6 O2 universes (excluding the system defaults `UNsaasProd` and `VIEWALL`), 106 services across 24 root branches."* Then state the org-shape inference and ask one targeted question: *"Services look fully populated here, so I'd lean on the service axis — were you thinking of a specific service, or all of them?"*
|
|
96
|
+
|
|
97
|
+
If the user answers with a name that maps to a universe: scope the query to that universe.
|
|
98
|
+
|
|
99
|
+
If the user answers with a name that maps to a service: use `cookbooks/service-hierarchies` for the SERVICE filter pattern (preferred when both axes are populated — see `cookbooks/investigator-flow` § "Scope-axis precedence").
|
|
100
|
+
|
|
101
|
+
## See also
|
|
102
|
+
|
|
103
|
+
- `entities/universe` — the schema-level reference.
|
|
104
|
+
- `cookbooks/service-hierarchies` — the service-axis half of scope clarification.
|
|
105
|
+
- `cookbooks/investigator-flow` — the broader investigator decision tree.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: vertex_entity_node
|
|
3
|
+
title: vertex / entity / node — same thing, three names
|
|
4
|
+
aliases: [topology node, graph node]
|
|
5
|
+
category: topology
|
|
6
|
+
related: []
|
|
7
|
+
tags: [overloaded]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# vertex / entity / node
|
|
11
|
+
|
|
12
|
+
Three words for the same DXO2 concept: a record in the topology graph that represents a thing the platform tracks (a host, a transaction, a service, a database, …).
|
|
13
|
+
|
|
14
|
+
- **vertex** — the most precise term. Used in TAS APIs (`vertices`, `vertex.attr.type`).
|
|
15
|
+
- **entity** — used in cookbooks, docs, conversation. The corpus catalog section is `entities/`.
|
|
16
|
+
- **node** — used in Kubernetes shops to mean the worker node, but in graph contexts can mean the same as vertex. Avoid in DXO2 docs; prefer "vertex" for TAS and "entity" for narrative.
|
|
17
|
+
|
|
18
|
+
## Conventions
|
|
19
|
+
|
|
20
|
+
- TAS query authoring → "vertex" (matches the API).
|
|
21
|
+
- Entity catalog browsing / cookbook prose → "entity".
|
|
22
|
+
- Talking to a Kubernetes user → "node" almost always means `k8s_NODE`. Don't conflate.
|
|
23
|
+
|
|
24
|
+
## Edges
|
|
25
|
+
|
|
26
|
+
The companion concept — relationships between vertices — is just **edge** (no overload). Edges have attributes including `semantic` (`contains`, `agent-monitors`, `runs_on`, etc.). Some edges have no `semantic` value at all; see `cookbooks/entity-relationships`.
|
|
27
|
+
|
|
28
|
+
## See also
|
|
29
|
+
|
|
30
|
+
- `entities/` — the catalog section.
|
|
31
|
+
- `cookbooks/entity-relationships` — edge taxonomy.
|