@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,693 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: tas-cookbook
|
|
3
|
+
title: TAS cookbook — operations reference and recipe catalog
|
|
4
|
+
applies_to: tas
|
|
5
|
+
tags: [reference, recipes, authoring]
|
|
6
|
+
related: [tas-quickstart, gotchas, discovery-flow, run-query-vs-run-partial]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# TAS cookbook
|
|
10
|
+
|
|
11
|
+
Full operation reference for TAS (`/tas/graph/query`) authoring, plus a
|
|
12
|
+
recipe catalog. Use after `tas-quickstart.md` when you need the breadth of
|
|
13
|
+
ops or a concrete pattern to start from. The schema's `.describe()`
|
|
14
|
+
metadata is the canonical wire spec — this cookbook organizes it by
|
|
15
|
+
purpose.
|
|
16
|
+
|
|
17
|
+
## TAS at a glance
|
|
18
|
+
|
|
19
|
+
A TAS query returns a graph (`vertices` + `edges`) shaped by a single
|
|
20
|
+
recursive **filter tree**. Every filter node is `{ "op": "<NAME>", ... }` —
|
|
21
|
+
a discriminated union on `op`. Most ops can wrap an `input` filter
|
|
22
|
+
(recursive composition); leaf ops (`ALL`, `LAYER`, `LUCENE`, `VARIABLE`)
|
|
23
|
+
do not.
|
|
24
|
+
|
|
25
|
+
```mermaid
|
|
26
|
+
flowchart LR
|
|
27
|
+
envelope["TasQuery envelope { filter, projection, limit, variables, ... }"] --> root["root filter (composite)"]
|
|
28
|
+
root --> leaves["leaves: ALL / ATTRIBUTE / LAYER / VERTEX / LUCENE / VARIABLE"]
|
|
29
|
+
root --> composers["composers: AND / OR / NOT"]
|
|
30
|
+
root --> shapers["shapers / collectors: TRAVERSE / TAKE_VERTICES / TAKE_EDGES / FOLLOW_PATH / COLLECT_*"]
|
|
31
|
+
composers --> root
|
|
32
|
+
shapers --> root
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Top-level envelope
|
|
36
|
+
|
|
37
|
+
Common fields:
|
|
38
|
+
|
|
39
|
+
| Field | Type | Purpose |
|
|
40
|
+
|-------|------|---------|
|
|
41
|
+
| `filter` | TasFilter | Root filter tree (required in practice) |
|
|
42
|
+
| `limit` | number | Cap returned vertices |
|
|
43
|
+
| `offset` | number | Pagination offset |
|
|
44
|
+
| `projection` | `"DETAILED" \| "BRIEF" \| "NO_TYPE"` | Vertex/edge attribute breadth |
|
|
45
|
+
| `projectionFilter` | `{ attributes: string[], attributeValueAsFields?: ... }` | Project specific attributes only |
|
|
46
|
+
| `order` | `[{ name, comparator, caseInsensitive, desc }]` | Sort order |
|
|
47
|
+
| `variables` | `[{ name, input: filter }]` | Named sub-filters reusable via `{op: "VARIABLE", name}` |
|
|
48
|
+
| `universe` | TasFilter | Restrict the working set before `filter` |
|
|
49
|
+
| `postFilter` | TasFilter | Filter applied after `filter` |
|
|
50
|
+
| `stateFilter` | VertexStateFilter | Restrict by vertex state |
|
|
51
|
+
| `includeStatus` | boolean | Adds a `states[]` array to the response (does NOT filter topology — see [Status section](#status--includestatus-and-the-states-response-array)). |
|
|
52
|
+
| `includeServices` | boolean | Adds service-attribution metadata to each vertex |
|
|
53
|
+
| `authorizationView` | string | Apply an auth view restriction |
|
|
54
|
+
|
|
55
|
+
`projection` only changes attribute breadth (`DETAILED` is the default for
|
|
56
|
+
"give me everything"). Use `projectionFilter.attributes[]` to project a
|
|
57
|
+
specific subset.
|
|
58
|
+
|
|
59
|
+
## Leaf filters
|
|
60
|
+
|
|
61
|
+
### `ALL`
|
|
62
|
+
Match every vertex. Use with a small `limit` for sampling.
|
|
63
|
+
|
|
64
|
+
```json
|
|
65
|
+
{ "op": "ALL" }
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### `ATTRIBUTE`
|
|
69
|
+
The workhorse — match by one or more attribute expressions. The list of
|
|
70
|
+
expressions is AND-ed.
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"op": "ATTRIBUTE",
|
|
75
|
+
"expressions": [
|
|
76
|
+
{ "name": "type", "values": ["HOST"], "operator": "IN" }
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`AttributeExpression` fields:
|
|
82
|
+
|
|
83
|
+
| Field | Notes |
|
|
84
|
+
|-------|-------|
|
|
85
|
+
| `name` | Attribute name (e.g. `type`, `name`, `hostname`, `k8s_namespace`) |
|
|
86
|
+
| `pointer` | JSON pointer for nested attribute lookup |
|
|
87
|
+
| `values` | Comparison values (regex pattern strings for `MATCHES`) |
|
|
88
|
+
| `operator` | `IN \| NOT_IN \| MATCHES \| NOT_MATCHES \| GE \| GT \| LE \| LT` |
|
|
89
|
+
| `comparator` | `LEXICAL \| NUMBER \| DATETIME` (default LEXICAL) |
|
|
90
|
+
| `caseInsensitive` | for MATCHES |
|
|
91
|
+
| `layer` | Optional: scope expression to a layer |
|
|
92
|
+
|
|
93
|
+
There is no `TYPE` or `ID` filter op — type is just an attribute named `type`,
|
|
94
|
+
and id selection is done via the `VERTEX` op (below).
|
|
95
|
+
|
|
96
|
+
### `LAYER`
|
|
97
|
+
Restrict to a layer (`externalId` first segment, by convention).
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{ "op": "LAYER", "value": "ATC" }
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Or multiple layers:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{ "op": "LAYER", "values": ["ATC", "INFRASTRUCTURE", "APM_INFRASTRUCTURE"] }
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Discover real layer names via `corpus_get("queries", "50-discover-custom-layers")`,
|
|
110
|
+
or by inspecting `externalId` prefixes on an `ALL` query.
|
|
111
|
+
|
|
112
|
+
### `VERTEX`
|
|
113
|
+
Select by id or external id.
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{ "op": "VERTEX", "vertexId": [12345, 67890] }
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{ "op": "VERTEX", "externalId": ["ATC:tx:checkout"] }
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### `LUCENE`
|
|
124
|
+
Lucene-style query string (only on tenants with Lucene indexing — see
|
|
125
|
+
gotchas).
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{ "op": "LUCENE", "query": "name:Kubernetes*" }
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### `VARIABLE`
|
|
132
|
+
Reference a named sub-filter declared in the top-level `variables[]` array.
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{ "op": "VARIABLE", "name": "k8s_hosts" }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### `SERVICE`
|
|
139
|
+
Restrict to vertices participating in a named service (or services).
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"op": "SERVICE",
|
|
144
|
+
"values": ["payments-api"],
|
|
145
|
+
"includeServiceHierarchy": true
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Composition
|
|
150
|
+
|
|
151
|
+
### `AND` / `OR`
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
{ "op": "AND", "input": [filterA, filterB, ...] }
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{ "op": "OR", "input": [filterA, filterB, ...] }
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### `NOT`
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
{ "op": "NOT", "input": filterA }
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
`AND`/`OR` take an **array** in `input`; `NOT` takes a **single** filter.
|
|
168
|
+
Empty `AND`/`OR` arrays are rejected — see `gotchas.md`.
|
|
169
|
+
|
|
170
|
+
### Variable reuse (`variables[]` + `VARIABLE`)
|
|
171
|
+
|
|
172
|
+
Declare named sub-filters at the top level, then reference them in the main
|
|
173
|
+
filter tree. Useful when the same vertex set is reused as a starting point.
|
|
174
|
+
|
|
175
|
+
```json
|
|
176
|
+
{
|
|
177
|
+
"variables": [
|
|
178
|
+
{ "name": "k8s_hosts", "input": { "op": "ATTRIBUTE", "expressions": [ ... ] } }
|
|
179
|
+
],
|
|
180
|
+
"filter": {
|
|
181
|
+
"op": "TRAVERSE",
|
|
182
|
+
"input": { "op": "VARIABLE", "name": "k8s_hosts" },
|
|
183
|
+
"traverse": [{ "direction": "ANY", "repeat": 1 }]
|
|
184
|
+
},
|
|
185
|
+
...
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
There is no `ASSIGN` / `USE` op — the top-level `variables[]` array is the
|
|
190
|
+
mechanism.
|
|
191
|
+
|
|
192
|
+
## Graph shaping
|
|
193
|
+
|
|
194
|
+
These wrap a base filter (`input`) and reshape its result.
|
|
195
|
+
|
|
196
|
+
### `TRAVERSE`
|
|
197
|
+
Walk the graph from a starting set. Each `Traverse` step has `direction`,
|
|
198
|
+
`repeat` (max hops), and optional `vertexFilter` / `edgeFilter` / `next`
|
|
199
|
+
(nested traversal).
|
|
200
|
+
|
|
201
|
+
```json
|
|
202
|
+
{
|
|
203
|
+
"op": "TRAVERSE",
|
|
204
|
+
"input": { "op": "ATTRIBUTE", "expressions": [...] },
|
|
205
|
+
"traverse": [{ "direction": "ANY", "repeat": 2 }],
|
|
206
|
+
"includeInput": true
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
`direction`: `FORWARD | BACKWARD | ANY`. `includeInput: true` keeps the
|
|
211
|
+
starting vertices in the result; without it you only get the traversal
|
|
212
|
+
targets.
|
|
213
|
+
|
|
214
|
+
Multi-step (chained) traversal:
|
|
215
|
+
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"op": "TRAVERSE",
|
|
219
|
+
"input": { "op": "ATTRIBUTE", "expressions": [...] },
|
|
220
|
+
"traverse": [
|
|
221
|
+
{ "direction": "FORWARD", "repeat": 1,
|
|
222
|
+
"next": [{ "direction": "BACKWARD", "repeat": 2 }] }
|
|
223
|
+
]
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### `TAKE_VERTICES` / `TAKE_EDGES` / `TAKE_FLOWS`
|
|
228
|
+
Restrict the result to only vertices, only edges, or only flow records:
|
|
229
|
+
|
|
230
|
+
```json
|
|
231
|
+
{ "op": "TAKE_EDGES", "input": { "op": "TRAVERSE", ... } }
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Common pattern: traverse then `TAKE_EDGES` to get just the edges between two
|
|
235
|
+
sets of vertices.
|
|
236
|
+
|
|
237
|
+
### `FOLLOW_PATH`
|
|
238
|
+
Directional path-following with hop limits and flow filtering. Useful for
|
|
239
|
+
"upstream / downstream" queries.
|
|
240
|
+
|
|
241
|
+
```json
|
|
242
|
+
{
|
|
243
|
+
"op": "FOLLOW_PATH",
|
|
244
|
+
"input": filter,
|
|
245
|
+
"type": "DOWN",
|
|
246
|
+
"downHops": 3,
|
|
247
|
+
"followToLayers": ["INFRASTRUCTURE"]
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
`type`: `UP | DOWN | BOTH | UP_THEN_DOWN | DOWN_THEN_UP | FULL | COVERAGE`.
|
|
252
|
+
|
|
253
|
+
### `STATUS`
|
|
254
|
+
Restrict the input set by current vertex state (alerts, metrics, etc.).
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"op": "STATUS",
|
|
259
|
+
"input": filter,
|
|
260
|
+
"statusFilter": { "op": "ALERT", ... }
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
You can also use the top-level `stateFilter` field for the same effect.
|
|
265
|
+
|
|
266
|
+
> ⚠️ The `statusFilter`'s `STATE` leaf op (filtering by numeric status code) is
|
|
267
|
+
> currently a server-side no-op — `state[]` is silently ignored. Use the two-query
|
|
268
|
+
> client-side filter pattern in `cookbooks/gotchas` instead. The other state-filter
|
|
269
|
+
> ops (`ALERT`, `METRIC`, `VERTEX_ID`, `NAMESPACE`, `MANAGEMENT_MODULE`) work
|
|
270
|
+
> as expected.
|
|
271
|
+
|
|
272
|
+
### `ADD_FLOWS` / `ADD_WIRES` / `ADD_WIRE_CONTEXT` / `ADD_TRANSITIONING_EDGES`
|
|
273
|
+
Augment the result with related flow/wire/transitioning-edge information
|
|
274
|
+
without changing the base vertex set.
|
|
275
|
+
|
|
276
|
+
- `ADD_FLOWS` — adds flow records (`direction: FORWARD | BACKWARD | ANY`).
|
|
277
|
+
- `ADD_WIRES` — adds wire connection records.
|
|
278
|
+
- `ADD_WIRE_CONTEXT` — adds wire context records with service context.
|
|
279
|
+
- `ADD_TRANSITIONING_EDGES` — adds edges whose endpoints are currently
|
|
280
|
+
transitioning state.
|
|
281
|
+
|
|
282
|
+
All four wrap an `input` filter and return the original vertex/edge result
|
|
283
|
+
enriched with the additional domain records.
|
|
284
|
+
|
|
285
|
+
### `COVERAGE`
|
|
286
|
+
Compute coverage information over the input set. Use `COVERAGE` with TAS-level
|
|
287
|
+
alert/health context filters.
|
|
288
|
+
|
|
289
|
+
### `JOIN`
|
|
290
|
+
Join two filter results. `type`: `INNER | LEFT | RIGHT | NOT`. Use sparingly —
|
|
291
|
+
most TAS queries are tree-shaped, not join-shaped.
|
|
292
|
+
|
|
293
|
+
```json
|
|
294
|
+
{ "op": "JOIN", "input": filterA, "rightInput": filterB, "type": "INNER" }
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### `LEGACY`
|
|
298
|
+
Escape hatch for server-side legacy filter syntax. Use only when a modern
|
|
299
|
+
equivalent does not exist — the string is executed as an internal legacy query.
|
|
300
|
+
|
|
301
|
+
```json
|
|
302
|
+
{ "op": "LEGACY", "query": "..." }
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### `PROJECT`
|
|
306
|
+
Return a pre-computed projection result by name. Rarely needed outside
|
|
307
|
+
server-generated queries.
|
|
308
|
+
|
|
309
|
+
```json
|
|
310
|
+
{ "op": "PROJECT", "name": "some-projection" }
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## Collectors
|
|
314
|
+
|
|
315
|
+
Specialized filters that return aggregated information about the input set
|
|
316
|
+
rather than the vertices/edges themselves. Each result is keyed by `id` in the
|
|
317
|
+
`analytics[]` array of the `TasGraph` response.
|
|
318
|
+
|
|
319
|
+
| Op | Key field(s) | What it returns |
|
|
320
|
+
|----|--------------|----------------|
|
|
321
|
+
| `COLLECT_ATTRIBUTES` | `attributeName` (single string) | Distinct values of one attribute across the matched vertex set, with per-value count and (optionally) the vertex IDs that carry each value. Stack multiple instances inside an `AND` to collect several attributes in one round-trip. |
|
|
322
|
+
| `COLLECT_ATTRIBUTE_NAMES` | — | Distinct attribute names present on the matched vertex set. |
|
|
323
|
+
| `COLLECT_VERTEX_ID` | — | List of vertex IDs in the result set. |
|
|
324
|
+
| `COLLECT_COUNTS` | — | Vertex + edge counts (with optional per-type breakdown). |
|
|
325
|
+
| `COLLECT_GROUPING_INFO` | `grouping: [{name, layer}, ...]` | Hierarchical grouping breakdown along one or more grouping dimensions, with per-group counts and alert stats. |
|
|
326
|
+
| `COLLECT_CARD_INFO` | `tier`, `attributeName` | Card-shaped summary for one APM tier, grouped by a single attribute. |
|
|
327
|
+
| `COLLECT_EXPERIENCE_ATTRIBUTES` | `attributeName`, `selector` | Same shape as `COLLECT_ATTRIBUTES`, restricted to APM experience or business-transaction vertices. |
|
|
328
|
+
|
|
329
|
+
**Field-name landmine:** `COLLECT_ATTRIBUTES` is `attributeName` (singular). The `grouping[]` array shape lives on `COLLECT_GROUPING_INFO` — these are distinct ops with distinct payload shapes. Using `groupings`/`grouping` on `COLLECT_ATTRIBUTES` returns HTTP 500.
|
|
330
|
+
|
|
331
|
+
Collectors wrap an `input` filter. The `id` field on each collector maps to a
|
|
332
|
+
key in `TasGraph.analytics[]` — use multiple collectors inside an `AND` to
|
|
333
|
+
collect several summaries in a single round-trip.
|
|
334
|
+
|
|
335
|
+
```json
|
|
336
|
+
{
|
|
337
|
+
"op": "AND",
|
|
338
|
+
"input": [
|
|
339
|
+
{ "op": "ALL" },
|
|
340
|
+
{ "op": "COLLECT_COUNTS", "id": "counts", "input": { "op": "ALL" } },
|
|
341
|
+
{ "op": "COLLECT_ATTRIBUTE_NAMES", "id": "attrNames", "input": { "op": "ALL" } }
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
The schema's `.describe()` metadata documents the per-collector field details
|
|
347
|
+
(see `tas/response.ts` schemas via the package's `.d.ts`).
|
|
348
|
+
|
|
349
|
+
## Status — `includeStatus` and the `states[]` response array
|
|
350
|
+
|
|
351
|
+
Setting `includeStatus: true` at the envelope level adds a `states[]`
|
|
352
|
+
array to the response alongside `vertices[]` / `edges[]`. **This is
|
|
353
|
+
purely additive** — the toggle does NOT filter the topology; it just
|
|
354
|
+
attaches state information for the vertices already in the result.
|
|
355
|
+
|
|
356
|
+
To filter topology BY state, use the `STATUS` op (or top-level
|
|
357
|
+
`stateFilter`) — those narrow the vertex set; `includeStatus` controls
|
|
358
|
+
whether the state rows are also serialized in the response. Most
|
|
359
|
+
callers want both: filter via `STATUS`, then `includeStatus: true` to
|
|
360
|
+
inspect the state alongside the matched topology.
|
|
361
|
+
|
|
362
|
+
### `states[]` shape
|
|
363
|
+
|
|
364
|
+
Each entry is a per-`(vertex, alert OR metric)` row, so a single
|
|
365
|
+
vertex can have multiple state rows:
|
|
366
|
+
|
|
367
|
+
```ts
|
|
368
|
+
type VertexStateResponseItem = {
|
|
369
|
+
vertexId: number;
|
|
370
|
+
alertId?: number; // populated for alert-driven state rows
|
|
371
|
+
metricId?: number; // populated for metric-driven state rows
|
|
372
|
+
stateExternalId?: {
|
|
373
|
+
vertexId: number;
|
|
374
|
+
alert?: string; // e.g. "sa://sa_status" — see rolled-up alert below
|
|
375
|
+
metric?: string;
|
|
376
|
+
};
|
|
377
|
+
status: number; // numeric severity — see mapping below
|
|
378
|
+
data?: {
|
|
379
|
+
alarm?: { total, critical, major, minor, information };
|
|
380
|
+
services?: Record<string, unknown>;
|
|
381
|
+
stateUpdated?: boolean;
|
|
382
|
+
};
|
|
383
|
+
startTime: number; // epoch ms when this state began
|
|
384
|
+
endTime: number; // epoch ms when it ended; far-future ⇒ ongoing
|
|
385
|
+
};
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Numeric `status` mapping
|
|
389
|
+
|
|
390
|
+
Per-tenant DXO2 convention (verified empirically — used by both
|
|
391
|
+
`states[].status` and `STATUS.statusFilter`'s `STATE` op `state[]`):
|
|
392
|
+
|
|
393
|
+
| `status` | Label |
|
|
394
|
+
|---|---|
|
|
395
|
+
| 0 | UNKNOWN |
|
|
396
|
+
| 1 | OK |
|
|
397
|
+
| 2 | MINOR |
|
|
398
|
+
| 3 | MAJOR |
|
|
399
|
+
| 4 | CRITICAL |
|
|
400
|
+
|
|
401
|
+
(See `cookbooks/gotchas` for the caveat that the canonical schema
|
|
402
|
+
under-documents this — and that the `STATE` filter op itself is
|
|
403
|
+
currently a server-side no-op until that's fixed.)
|
|
404
|
+
|
|
405
|
+
### The rolled-up `sa://sa_status` alert
|
|
406
|
+
|
|
407
|
+
Every vertex carries a synthetic aggregate alert with
|
|
408
|
+
`stateExternalId.alert === "sa://sa_status"`. Its `status` is the
|
|
409
|
+
**worst severity across all of that vertex's individual alerts and
|
|
410
|
+
metrics** — i.e. the value the platform UI shows on the status badge.
|
|
411
|
+
Per-individual-alert and per-individual-metric rows can disagree with
|
|
412
|
+
this rollup (a vertex can have one CRITICAL alert and OK metrics; the
|
|
413
|
+
rollup is CRITICAL).
|
|
414
|
+
|
|
415
|
+
The rollup row's `data.alarm` block summarizes per-tier counts:
|
|
416
|
+
`{ total, critical, major, minor, information }`. Useful for
|
|
417
|
+
"how many alarms of each tier does this vertex carry" without
|
|
418
|
+
reading every per-alert row.
|
|
419
|
+
|
|
420
|
+
### Reading state for a specific vertex
|
|
421
|
+
|
|
422
|
+
Match `states[].vertexId` against the vertex's `id`. Filter to the
|
|
423
|
+
rolled-up severity by also checking
|
|
424
|
+
`stateExternalId.alert === "sa://sa_status"`. Per-source severity is
|
|
425
|
+
the inverse — exclude that alert id and look at the per-alert /
|
|
426
|
+
per-metric rows.
|
|
427
|
+
|
|
428
|
+
### Worked example: "what's the rolled-up status of these vertices?"
|
|
429
|
+
|
|
430
|
+
```json
|
|
431
|
+
{
|
|
432
|
+
"filter": { "op": "VERTEX", "externalId": ["<your-id-1>", "<your-id-2>"] },
|
|
433
|
+
"includeStatus": true,
|
|
434
|
+
"limit": 50,
|
|
435
|
+
"projection": "DETAILED"
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
Response (sketch):
|
|
440
|
+
|
|
441
|
+
```json
|
|
442
|
+
{
|
|
443
|
+
"vertices": [{ "id": 5435, "externalId": "<your-id-1>", "attributes": { ... } }],
|
|
444
|
+
"states": [{
|
|
445
|
+
"vertexId": 5435,
|
|
446
|
+
"alertId": 774,
|
|
447
|
+
"stateExternalId": { "vertexId": 5435, "alert": "sa://sa_status" },
|
|
448
|
+
"status": 3,
|
|
449
|
+
"data": { "alarm": { "total": 1, "critical": 0, "major": 1, "minor": 0, "information": 0 } },
|
|
450
|
+
"startTime": 1768820848440,
|
|
451
|
+
"endTime": 1782097233000
|
|
452
|
+
}]
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
`status: 3` ⇒ MAJOR; `data.alarm.major: 1` confirms the underlying
|
|
457
|
+
alarm count.
|
|
458
|
+
|
|
459
|
+
### Common patterns
|
|
460
|
+
|
|
461
|
+
- **"Show me everything currently CRITICAL"** — the filter-server-side
|
|
462
|
+
path via `STATE` op is a no-op today. Use the two-query pattern
|
|
463
|
+
documented in `cookbooks/gotchas`: pull candidates with
|
|
464
|
+
`includeStatus: true`, client-filter to vertices whose rollup row
|
|
465
|
+
has `status === 4`, then issue a second query (e.g. TRAVERSE from
|
|
466
|
+
those externalIds) for downstream context.
|
|
467
|
+
- **"What alarms does this vertex have right now?"** — issue a
|
|
468
|
+
`VERTEX(externalId=[...])` filter with `includeStatus: true` and
|
|
469
|
+
read every `states[]` row whose `vertexId` matches; skip the
|
|
470
|
+
`sa://sa_status` row to enumerate per-source alerts.
|
|
471
|
+
- **"How long has this been bad?"** — `(endTime - startTime)` for the
|
|
472
|
+
most recent rollup row (or per-source row if you want the specific
|
|
473
|
+
alert's duration). A far-future `endTime` (e.g. `7505567987654`)
|
|
474
|
+
means the state is ongoing.
|
|
475
|
+
|
|
476
|
+
## Recipe catalog
|
|
477
|
+
|
|
478
|
+
Each recipe describes a goal in plain English and gives the minimum filter
|
|
479
|
+
shape. Each links to a worked example shipped in the corpus —
|
|
480
|
+
`corpus_get("queries", "<id>")` returns the full payload + per-op
|
|
481
|
+
descriptions.
|
|
482
|
+
|
|
483
|
+
### "Give me a sample of vertices to learn what's there"
|
|
484
|
+
`corpus_get("queries", "01-discover-vertices")`
|
|
485
|
+
|
|
486
|
+
```json
|
|
487
|
+
{ "filter": { "op": "ALL" }, "limit": 20, "projection": "DETAILED" }
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### "Find vertices of type X (or several types)"
|
|
491
|
+
`corpus_get("queries", "02-discover-services")`
|
|
492
|
+
|
|
493
|
+
```json
|
|
494
|
+
{
|
|
495
|
+
"filter": {
|
|
496
|
+
"op": "ATTRIBUTE",
|
|
497
|
+
"expressions": [
|
|
498
|
+
{ "name": "type", "values": ["HOST", "AGENT"], "operator": "IN" }
|
|
499
|
+
]
|
|
500
|
+
},
|
|
501
|
+
"limit": 100, "projection": "DETAILED"
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### "Find vertices whose attribute matches a regex"
|
|
506
|
+
`corpus_get("queries", "10-filter-attribute-matches")`
|
|
507
|
+
|
|
508
|
+
```json
|
|
509
|
+
{
|
|
510
|
+
"filter": {
|
|
511
|
+
"op": "ATTRIBUTE",
|
|
512
|
+
"expressions": [
|
|
513
|
+
{ "name": "name", "values": [".*tixchange.*"],
|
|
514
|
+
"operator": "MATCHES", "caseInsensitive": true }
|
|
515
|
+
]
|
|
516
|
+
},
|
|
517
|
+
"limit": 50, "projection": "DETAILED"
|
|
518
|
+
}
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
### "Find vertices in a specific layer"
|
|
522
|
+
`corpus_get("queries", "13-filter-layer")`
|
|
523
|
+
|
|
524
|
+
```json
|
|
525
|
+
{ "filter": { "op": "LAYER", "value": "ATC" }, "limit": 50, "projection": "DETAILED" }
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### "Find vertices in any layer except a known set" (find unknown layers)
|
|
529
|
+
`corpus_get("queries", "50-discover-custom-layers")`
|
|
530
|
+
|
|
531
|
+
```json
|
|
532
|
+
{
|
|
533
|
+
"filter": {
|
|
534
|
+
"op": "NOT",
|
|
535
|
+
"input": { "op": "LAYER",
|
|
536
|
+
"values": ["ATC", "INFRASTRUCTURE", "APM_INFRASTRUCTURE"] }
|
|
537
|
+
},
|
|
538
|
+
"limit": 200, "projection": "DETAILED"
|
|
539
|
+
}
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### "Multi-condition AND (type AND name pattern)"
|
|
543
|
+
`corpus_get("queries", "11-filter-and-compose")`
|
|
544
|
+
|
|
545
|
+
```json
|
|
546
|
+
{
|
|
547
|
+
"filter": {
|
|
548
|
+
"op": "AND",
|
|
549
|
+
"input": [
|
|
550
|
+
{ "op": "ATTRIBUTE", "expressions": [{ "name": "type",
|
|
551
|
+
"values": ["BUSINESSTRANSACTION"], "operator": "IN" }] },
|
|
552
|
+
{ "op": "ATTRIBUTE", "expressions": [{ "name": "name",
|
|
553
|
+
"values": ["/checkout.shtml", "/signon.shtml"], "operator": "IN" }] }
|
|
554
|
+
]
|
|
555
|
+
},
|
|
556
|
+
"limit": 20, "projection": "DETAILED"
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
### "OR with a NOT (type X OR (type Y but not name matching ...))"
|
|
561
|
+
`corpus_get("queries", "12-filter-or-not")`
|
|
562
|
+
|
|
563
|
+
```json
|
|
564
|
+
{
|
|
565
|
+
"filter": {
|
|
566
|
+
"op": "OR",
|
|
567
|
+
"input": [
|
|
568
|
+
{ "op": "ATTRIBUTE", "expressions": [{ "name": "type",
|
|
569
|
+
"values": ["k8s_POD"], "operator": "IN" }] },
|
|
570
|
+
{ "op": "AND", "input": [
|
|
571
|
+
{ "op": "ATTRIBUTE", "expressions": [{ "name": "type",
|
|
572
|
+
"values": ["AGENT"], "operator": "IN" }] },
|
|
573
|
+
{ "op": "NOT", "input": { "op": "ATTRIBUTE", "expressions": [
|
|
574
|
+
{ "name": "name", "values": [".*Logstash.*"],
|
|
575
|
+
"operator": "MATCHES", "caseInsensitive": true } ] } }
|
|
576
|
+
] }
|
|
577
|
+
]
|
|
578
|
+
},
|
|
579
|
+
"limit": 50, "projection": "DETAILED"
|
|
580
|
+
}
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### "N-hop neighborhood from a starting set"
|
|
584
|
+
`corpus_get("queries", "14-filter-traverse")`
|
|
585
|
+
|
|
586
|
+
```json
|
|
587
|
+
{
|
|
588
|
+
"filter": {
|
|
589
|
+
"op": "TRAVERSE",
|
|
590
|
+
"input": { "op": "ATTRIBUTE", "expressions": [{ "name": "type",
|
|
591
|
+
"values": ["k8s_CLUSTER"], "operator": "IN" }] },
|
|
592
|
+
"traverse": [{ "direction": "ANY", "repeat": 2 }],
|
|
593
|
+
"includeInput": true
|
|
594
|
+
},
|
|
595
|
+
"limit": 100, "projection": "DETAILED"
|
|
596
|
+
}
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
### "Just the edges between a starting set and its neighborhood"
|
|
600
|
+
`corpus_get("queries", "15-filter-take-vertices-edges")`
|
|
601
|
+
|
|
602
|
+
```json
|
|
603
|
+
{
|
|
604
|
+
"filter": {
|
|
605
|
+
"op": "TAKE_EDGES",
|
|
606
|
+
"input": {
|
|
607
|
+
"op": "TRAVERSE",
|
|
608
|
+
"input": { "op": "ATTRIBUTE", "expressions": [{ "name": "type",
|
|
609
|
+
"values": ["k8s_CLUSTER"], "operator": "IN" }] },
|
|
610
|
+
"traverse": [{ "direction": "ANY", "repeat": 2 }],
|
|
611
|
+
"includeInput": true
|
|
612
|
+
}
|
|
613
|
+
},
|
|
614
|
+
"limit": 100, "projection": "DETAILED"
|
|
615
|
+
}
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
### "Project only the attributes I care about"
|
|
619
|
+
`corpus_get("queries", "16-filter-projection")`
|
|
620
|
+
|
|
621
|
+
```json
|
|
622
|
+
{
|
|
623
|
+
"filter": { "op": "ATTRIBUTE", "expressions": [
|
|
624
|
+
{ "name": "type", "values": ["k8s_POD"], "operator": "IN" } ] },
|
|
625
|
+
"limit": 30,
|
|
626
|
+
"projectionFilter": {
|
|
627
|
+
"attributes": ["name", "type", "hostname", "k8s_namespace", "k8s_status"]
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
### "Reuse the same starting set in two places"
|
|
633
|
+
`corpus_get("queries", "18-filter-variable-reuse")`
|
|
634
|
+
|
|
635
|
+
```json
|
|
636
|
+
{
|
|
637
|
+
"variables": [
|
|
638
|
+
{ "name": "k8s_hosts", "input": { "op": "ATTRIBUTE", "expressions": [
|
|
639
|
+
{ "name": "type", "values": ["HOST"], "operator": "IN" } ] } }
|
|
640
|
+
],
|
|
641
|
+
"filter": {
|
|
642
|
+
"op": "TRAVERSE",
|
|
643
|
+
"input": { "op": "VARIABLE", "name": "k8s_hosts" },
|
|
644
|
+
"traverse": [{ "direction": "ANY", "repeat": 1 }],
|
|
645
|
+
"includeInput": true
|
|
646
|
+
},
|
|
647
|
+
"limit": 50, "projection": "DETAILED"
|
|
648
|
+
}
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
### "Sort results and include status info"
|
|
652
|
+
`corpus_get("queries", "19-filter-order-statefilter")`
|
|
653
|
+
|
|
654
|
+
```json
|
|
655
|
+
{
|
|
656
|
+
"filter": { "op": "ATTRIBUTE", "expressions": [
|
|
657
|
+
{ "name": "type", "values": ["AGENT"], "operator": "IN" } ] },
|
|
658
|
+
"order": [{ "name": "name", "desc": false, "caseInsensitive": true }],
|
|
659
|
+
"includeStatus": true,
|
|
660
|
+
"limit": 20, "projection": "DETAILED"
|
|
661
|
+
}
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
Response carries `states[]` alongside `vertices[]`. To read the
|
|
665
|
+
rolled-up severity per vertex, find each vertex's `states[]` row
|
|
666
|
+
where `stateExternalId.alert === "sa://sa_status"` and read
|
|
667
|
+
`status` (0=UNKNOWN, 1=OK, 2=MINOR, 3=MAJOR, 4=CRITICAL). See the
|
|
668
|
+
Status section above for the full shape and common patterns.
|
|
669
|
+
|
|
670
|
+
### "Free-text Lucene query (where supported)"
|
|
671
|
+
`corpus_get("queries", "17-filter-lucene")` — may return HTTP 400 on tenants
|
|
672
|
+
without Lucene indexing.
|
|
673
|
+
|
|
674
|
+
```json
|
|
675
|
+
{ "filter": { "op": "LUCENE", "query": "name:Kubernetes*" },
|
|
676
|
+
"limit": 20, "projection": "DETAILED" }
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
## Authoring tips
|
|
680
|
+
|
|
681
|
+
- Start broad (`ALL` with small `limit`) to discover vocabulary, then
|
|
682
|
+
progressively narrow with `ATTRIBUTE` and `LAYER`.
|
|
683
|
+
- For "find X and its dependencies", build it as `TRAVERSE` over a base
|
|
684
|
+
`ATTRIBUTE` filter.
|
|
685
|
+
- For "find edges between X and Y", build `TRAVERSE` then wrap in `TAKE_EDGES`.
|
|
686
|
+
- When the same set is reused (e.g. base set and its neighborhood), declare
|
|
687
|
+
it in `variables[]` and reference via `{op: "VARIABLE", name}`.
|
|
688
|
+
- Default `projection: "DETAILED"` if you do not yet know which attributes
|
|
689
|
+
you need; switch to `projectionFilter.attributes[]` once you do.
|
|
690
|
+
- Verify sub-trees with `run_partial_query` (see `run-query-vs-run-partial.md`)
|
|
691
|
+
rather than authoring throwaway test queries.
|
|
692
|
+
- See `gotchas.md` for the common `expressions` (array, not `expression`),
|
|
693
|
+
`input` (not `filters`), and layer-name pitfalls.
|