@dx-do/cli 6.0.1 → 6.0.4
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 +12 -6
- package/dist-node/{03-discover-sources.nassql.data-store-by6sqk23.json5 → 03-discover-sources.nassql.data-store-d6hb6wf7.json5} +4 -3
- package/dist-node/{20-nassql-from-metadata-basic.nassql.data-store-zdf1gp1v.json5 → 20-nassql-from-metadata-basic.nassql.data-store-mq1hn0qz.json5} +4 -2
- package/dist-node/34-nassql-entity-to-metric-ids.nassql-jn6t8zxs.md +76 -0
- package/dist-node/34-nassql-entity-to-metric-ids.nassql.data-store-t8ecm336.json5 +69 -0
- package/dist-node/34-nassql-entity-to-metric-ids.nassql.data-store-tmd-9vbg6p76.json +4 -0
- package/dist-node/40-metadata-filter-by-typeenum.metadata-kmcc85ac.md +66 -0
- package/dist-node/40-metadata-filter-by-typeenum.metadata.data-store-b4erpx6h.json5 +52 -0
- package/dist-node/40-metadata-filter-by-typeenum.metadata.data-store-tmd-3zg3n0j1.json +4 -0
- package/dist-node/41-metadata-frontend-durations.metadata-n2ba62j7.md +50 -0
- package/dist-node/41-metadata-frontend-durations.metadata.data-store-kpkhaf6c.json5 +48 -0
- package/dist-node/41-metadata-frontend-durations.metadata.data-store-tmd-c685fc9v.json +4 -0
- package/dist-node/42-metadata-metric-id-to-entities.metadata-qg0p7y71.md +67 -0
- package/dist-node/42-metadata-metric-id-to-entities.metadata.data-store-tmd-zd99v6pz.json +4 -0
- package/dist-node/42-metadata-metric-id-to-entities.metadata.data-store-vwv8dq0e.json5 +52 -0
- package/dist-node/{SKILL-1xn7r9nt.md → SKILL-86r2cm61.md} +26 -2
- package/dist-node/{agentic-mcp-rycd2gh8.md → agentic-mcp-9nz7zh8d.md} +2 -1
- package/dist-node/alarms-cookbook-xrwbrdte.md +160 -0
- package/dist-node/alarms-quickstart-fhg59mr2.md +100 -0
- package/dist-node/{chunk-RNMHSXZF-pdwasrg7.js → chunk-4L5DIG2E-9p3rrkp9.js} +1 -1
- package/dist-node/{chunk-VV2FJEMA-3rvtkmga.js → chunk-4Q347M53-e6wyjnpc.js} +2 -2
- package/dist-node/{chunk-Q2JA73UH-akkb8bh3.js → chunk-6TL6OWJA-jrr526kw.js} +1 -1
- package/dist-node/chunk-7G4RSOZU-nnmp25yx.js +3753 -0
- package/dist-node/{chunk-YVD3UK5I-9pxr1jka.js → chunk-JYKZ5EMU-6jq5egbw.js} +3 -3
- package/dist-node/{chunk-5VSFINOX-ewzpx7wh.js → chunk-OV4PNSIK-pqs8y3nm.js} +3 -3
- package/dist-node/{chunk-JRM4BLOM-rg32z8w4.js → chunk-P6TRLBVU-rxz4tacs.js} +1 -1
- package/dist-node/{chunk-4I3HBO6U-2ebgf7kh.js → chunk-TFFMCZCS-rhchxvk7.js} +1 -1
- package/dist-node/{chunk-4PMCLJMS-0mqvr4m4.js → chunk-W5FHICA2-x50sz7wk.js} +1 -1
- package/dist-node/{discovery-flow-fw79kbx4.md → discovery-flow-m0zp07e3.md} +13 -0
- package/dist-node/{gotchas-8ab64kcd.md → gotchas-p696dmam.md} +131 -0
- package/dist-node/{index-104hyb1m.html → index-dfkxebky.html} +1 -1
- package/dist-node/{index-mbzg9rhc.json → index-mf7znaf7.json} +30 -0
- package/dist-node/{index-g3hh5wez.json → index-x07qhy6g.json} +53 -0
- package/dist-node/{investigator-flow-jc2s0n46.md → investigator-flow-dcyk8v51.md} +36 -2
- package/dist-node/main-4VTFKCWX-6x4n4v8m.js +13 -0
- package/dist-node/main.js +26106 -18435
- package/dist-node/{metrics-grounding-2h4kkbe3.md → metrics-grounding-8vhfqya9.md} +59 -4
- package/dist-node/{mm-cookbook-23jpw721.md → mm-cookbook-fdwbt989.md} +1 -1
- package/dist-node/{nassql-cookbook-n8kc0mff.md → nassql-cookbook-kp525xra.md} +41 -1
- package/dist-node/{nassql-quickstart-090e0yex.md → nassql-quickstart-mth22qd3.md} +3 -1
- package/package.json +1 -1
- package/dist-node/chunk-72HYG3XZ-kf7hy4vs.js +0 -3625
- package/dist-node/main-SGLYO5YX-ht69eb0y.js +0 -13
|
@@ -10,7 +10,7 @@ related: [metric-source-names, mm-cookbook, mm-quickstart, entity-relationships,
|
|
|
10
10
|
|
|
11
11
|
`mm-quickstart` and `mm-cookbook` cover the *mechanics* of authoring metric-metadata queries. This cookbook covers the **semantics** — what a metric *means* in DXO2's entity model, how to navigate from a metric back to the producing agent (or accept that no entity exists), and how to handle the most common surprise: metrics for resources that have no topology vertex.
|
|
12
12
|
|
|
13
|
-
## Metric identity,
|
|
13
|
+
## Metric identity, five ways
|
|
14
14
|
|
|
15
15
|
The same metric is referred to by different names depending on which surface you're on:
|
|
16
16
|
|
|
@@ -20,6 +20,7 @@ The same metric is referred to by different names depending on which surface you
|
|
|
20
20
|
| MM `SourceNameSpecifier` + `AttributeNameSpecifier` | Metrics-Metadata query input |
|
|
21
21
|
| `<resource>:<metric>` | User shorthand — the `metric.path` ending after the last `:` is the metric name; the prefix is the "resource" |
|
|
22
22
|
| `metric.attribute` (older) | Older API field — alias for the path's leaf segment |
|
|
23
|
+
| `metric.attributes.external_ids` | TAS-compatible vertex externalIds carried on every metric descriptor — the entity-association field. An array because a metric can be associated with multiple vertices. Round-trips with `FROM_TOPOLOGY`'s `VERTEX` filter without reformatting. See worked examples `42-metadata-metric-id-to-entities` (metricId → externalIds) and `34-nassql-entity-to-metric-ids` (externalId → metricIds). |
|
|
23
24
|
|
|
24
25
|
Concretely, a metric like `Beans|Nass Reactive Client|Store|Flush|Unregistered Queue:Concurrent Invocations` carries:
|
|
25
26
|
|
|
@@ -60,11 +61,65 @@ The metric *value* is sometimes the only place identity lives — e.g. a `queue_
|
|
|
60
61
|
|
|
61
62
|
When this pattern repeats for the same customer / same kind of resource, **inventorize** materializes a vertex per resource so future queries can use vertex traversal. See `lexicon/inventorize`.
|
|
62
63
|
|
|
63
|
-
## Metric `type` is
|
|
64
|
+
## Metric `type` is a bitmask — what the bits mean
|
|
64
65
|
|
|
65
|
-
Every metric carries a numeric `type` field
|
|
66
|
+
Every metric carries a numeric `type` field. It is **not** an enum value — it is a 32-bit integer composed by bitwise-OR of one or more named `typeEnum` values. A `type` of `268436481` decodes to `MONITOR_INT_DURATION` combined with `TYPE_INFO_FRONTEND` (`0x401 | 0x10000000`).
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
### Bit-region layout
|
|
69
|
+
|
|
70
|
+
| Region mask | Purpose |
|
|
71
|
+
|---|---|
|
|
72
|
+
| `0x0000000F` | underlying type — INT (1), LONG (2), DOUBLE (4), STRING (5) |
|
|
73
|
+
| `0x000000F0` | type-property bits (server-internal flags) |
|
|
74
|
+
| `0x000FFF00` | numeric-info bits — DURATION (0x400), RATE (0x200), COUNTER (0x100), PERCENTAGE (0x1000), INTERVAL_COUNTER (0x2000), SATURATION (0x4000) |
|
|
75
|
+
| `0x00F00000` | counter-info bits (server-internal counter flags) |
|
|
76
|
+
| `0x0F000000` | metric flags — TYPE_FUTURE (0x01000000), TYPE_VIRTUAL (0x02000000), TYPE_TAGS (0x04000000) |
|
|
77
|
+
| `0xF0000000` | metric-type info — TYPE_INFO_FRONTEND (0x10000000), TYPE_INFO_BACKEND (0x20000000), TYPE_INFO_BUSINESS_TRANSACTION (0x40000000) |
|
|
78
|
+
|
|
79
|
+
### `typeEnum` value table
|
|
80
|
+
|
|
81
|
+
| typeEnum | hex | decimal |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| `MONITOR_INT_DURATION` | `0x00000401` | 1025 |
|
|
84
|
+
| `MONITOR_LONG_DURATION` | `0x00000402` | 1026 |
|
|
85
|
+
| `MONITOR_INT_RATE` | `0x00000201` | 513 |
|
|
86
|
+
| `MONITOR_LONG_RATE` | `0x00000202` | 514 |
|
|
87
|
+
| `MONITOR_PERCENTAGE` | `0x00001001` | 4097 |
|
|
88
|
+
| `MONITOR_INT_INTERVAL_COUNTER` | `0x00002001` | 8193 |
|
|
89
|
+
| `MONITOR_LONG_INTERVAL_COUNTER` | `0x00002002` | 8194 |
|
|
90
|
+
| `MONITOR_DOUBLE_INTERVAL_COUNTER` | `0x00002004` | 8196 |
|
|
91
|
+
| `MONITOR_INT_SATURATION` | `0x00004001` | 16385 |
|
|
92
|
+
| `MONITOR_LONG_SATURATION` | `0x00004002` | 16386 |
|
|
93
|
+
| `MONITOR_STRING` | `0x00000005` | 5 |
|
|
94
|
+
| `MONITOR_INT_COUNTER` | `0x00000101` | 257 |
|
|
95
|
+
| `MONITOR_LONG_COUNTER` | `0x00000102` | 258 |
|
|
96
|
+
| `MONITOR_DOUBLE_COUNTER` | `0x00000104` | 260 |
|
|
97
|
+
| `TYPE_FUTURE` | `0x01000000` | 16777216 |
|
|
98
|
+
| `TYPE_VIRTUAL` | `0x02000000` | 33554432 |
|
|
99
|
+
| `TYPE_TAGS` | `0x04000000` | 67108864 |
|
|
100
|
+
| `TYPE_INFO_FRONTEND` | `0x10000000` | 268435456 |
|
|
101
|
+
| `TYPE_INFO_BACKEND` | `0x20000000` | 536870912 |
|
|
102
|
+
| `TYPE_INFO_BUSINESS_TRANSACTION` | `0x40000000` | 1073741824 |
|
|
103
|
+
|
|
104
|
+
To check bit math: `composeMetricTypeBits(['MONITOR_INT_DURATION', 'TYPE_INFO_FRONTEND'])` from `@dx-do/client` returns `268436481`. The reverse is `decodeMetricTypeBits(n)`, which returns `{ matched, residual }` — a non-zero residual means the integer carries server-internal bits outside the user-facing typeEnum API (see `gotchas.md` — undocumented `MONITOR_DOUBLE_*` variants).
|
|
105
|
+
|
|
106
|
+
### Filtering metrics by typeEnum
|
|
107
|
+
|
|
108
|
+
Use the `TYPE` AttributeNameSpecifier:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"op": "TYPE",
|
|
113
|
+
"bitMask": 1024,
|
|
114
|
+
"bitMatch": 1024,
|
|
115
|
+
"operator": "EQ",
|
|
116
|
+
"specifier": { "op": "ALL" }
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
This catches every metric where bit 10 is set — i.e. any DURATION variant (INT, LONG, or undocumented DOUBLE). For an exact typeEnum filter set `bitMask = bitMatch = composeMetricTypeBits([...])`. The `specifier` field is required by the server even though the schema marks it optional — see `gotchas.md`.
|
|
121
|
+
|
|
122
|
+
The visual MM query editor's TYPE-op chips picker writes both fields (and the inner `specifier`) automatically when you select typeEnum names. For "any of this semantic class regardless of INT / LONG / DOUBLE", pick from the **`ANY_*` group** at the top of the dropdown — e.g. `ANY_DURATION` produces the bit-10-only mask above, `ANY_RATE` produces bit 9, etc. The `MONITOR_*` chips remain pinned to a specific underlying type; picking both `MONITOR_INT_DURATION` and `MONITOR_LONG_DURATION` is **not** the same as `ANY_DURATION` — the chips combine with AND semantics, so that pair composes to a mask no real metric satisfies. Use `ANY_DURATION` for the "INT or LONG or DOUBLE" intent.
|
|
68
123
|
|
|
69
124
|
## Pattern recognition: deciding when to inventorize
|
|
70
125
|
|
|
@@ -59,7 +59,7 @@ so each component has its own specifier sub-language with its own ops.
|
|
|
59
59
|
| `OR` | `{ op: "OR", specifiers: [...] }` | Union |
|
|
60
60
|
| `NOT` | `{ op: "NOT", specifier: ... }` | Complement |
|
|
61
61
|
| `SPEC` | `{ op: "SPEC", sourceNameSpecifier?, folderNameSpecifier?, attributeNameSpecifier? }` | Structured match (the workhorse) |
|
|
62
|
-
| `ID` | `{ op: "ID", ids: ["m-id-1", ...] }` | By metric id |
|
|
62
|
+
| `ID` | `{ op: "ID", ids: ["m-id-1", ...] }` | By metric id. The response's `metric.attributes.external_ids` array carries TAS-compatible vertex externalIds — the entity-association field. See worked example `42-metadata-metric-id-to-entities` for the metricId → entity round-trip. |
|
|
63
63
|
| `ATTRIBUTE` | `{ op: "ATTRIBUTE", expressions: [...] }` | By metric-attribute expression |
|
|
64
64
|
| `GROUP` | `{ op: "GROUP", id?, managementModuleId? }` | By management module / group |
|
|
65
65
|
| `SERVICE` | `{ op: "SERVICE", values: [...] }` | By named service |
|
|
@@ -26,7 +26,7 @@ flowchart LR
|
|
|
26
26
|
src["source: FROM_TOPOLOGY / FROM_METADATA / FROM / FROM_DATA"] --> joins["joins (optional): JOIN_TOPOLOGY / JOIN_METADATA / JOIN_DATA"]
|
|
27
27
|
joins --> transforms["transforms: GROUP / FILTER / WINDOW / MAP_STRING / FORMAT_TIME / DISTINCT / ORDER"]
|
|
28
28
|
transforms --> aggs["aggregations: COUNT / SUM / MEAN / TOP / BOTTOM / FIRST / LAST / QUANTILE / AGG"]
|
|
29
|
-
aggs --> shape["shape: KEEP (
|
|
29
|
+
aggs --> shape["shape: KEEP (optional; last if used)"]
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
Mental model: a **dataframe pipeline**. Source ops produce rows with named
|
|
@@ -186,6 +186,14 @@ After a `FROM_TOPOLOGY` source, join in metric metadata for those vertices.
|
|
|
186
186
|
`joinType`: `INNER` (default) | `LEFT`. Use `LEFT` when you want to keep
|
|
187
187
|
vertices that have no metrics (rows with null metric columns are retained).
|
|
188
188
|
|
|
189
|
+
**Scope to one entity (metric inventory for a named vertex).** A common
|
|
190
|
+
recipe — `FROM_TOPOLOGY` filtered to one `externalId` with `VERTEX`,
|
|
191
|
+
followed by `JOIN_METADATA(ALL)` and `KEEP vertex.externalId, metric.id`
|
|
192
|
+
— enumerates every metric an entity emits. Worked example:
|
|
193
|
+
`34-nassql-entity-to-metric-ids`. The inverse direction (metricId →
|
|
194
|
+
the externalIds of associated entities) is `42-metadata-metric-id-to-entities`,
|
|
195
|
+
via the `metric.attributes.external_ids` array on every metric descriptor.
|
|
196
|
+
|
|
189
197
|
### `JOIN_TOPOLOGY`
|
|
190
198
|
|
|
191
199
|
Inverse: after a metadata source, join the topology for the metrics' source
|
|
@@ -260,9 +268,41 @@ Filter rows by a `QueryFilterPredicateSpec`. Predicate ops:
|
|
|
260
268
|
|
|
261
269
|
String-based filter expression for cases the predicate spec cannot express.
|
|
262
270
|
|
|
271
|
+
Operators: `&&` (AND), `||` (OR), `!` (NOT), `== != < <= > >=`, `matches` (regex). String literals use single quotes.
|
|
272
|
+
|
|
273
|
+
The visual editor's FILTER_EXPR helper offers these same examples as one-click templates — keep them synchronized when either side gains a new pattern. (Longer-term, the editor should load examples from this file rather than maintaining its own list.)
|
|
274
|
+
|
|
275
|
+
Worked examples:
|
|
276
|
+
|
|
277
|
+
```json
|
|
278
|
+
{ "op": "FILTER_EXPR", "spec": "metric_count > 100" }
|
|
279
|
+
```
|
|
280
|
+
*Numeric threshold — keep rows where a numeric column passes a threshold.*
|
|
281
|
+
|
|
282
|
+
```json
|
|
283
|
+
{ "op": "FILTER_EXPR", "spec": "metric.source matches '.*prod.*'" }
|
|
284
|
+
```
|
|
285
|
+
*String regex on a metric attribute — anchor with `^…$` for a full match; otherwise treated as substring.*
|
|
286
|
+
|
|
263
287
|
```json
|
|
264
288
|
{ "op": "FILTER_EXPR", "spec": "metric_count > 100 && metric.source matches '.*prod.*'" }
|
|
265
289
|
```
|
|
290
|
+
*Compound (AND) — combine clauses with `&&` (AND) or `||` (OR).*
|
|
291
|
+
|
|
292
|
+
```json
|
|
293
|
+
{ "op": "FILTER_EXPR", "spec": "used > capacity * 0.9" }
|
|
294
|
+
```
|
|
295
|
+
*Column-vs-column — both sides can reference columns and arithmetic.*
|
|
296
|
+
|
|
297
|
+
```json
|
|
298
|
+
{ "op": "FILTER_EXPR", "spec": "!(metric.source matches '.*staging.*')" }
|
|
299
|
+
```
|
|
300
|
+
*Negation — wrap any expression with `!(…)` to negate it.*
|
|
301
|
+
|
|
302
|
+
```json
|
|
303
|
+
{ "op": "FILTER_EXPR", "spec": "metric.environment == 'prod'" }
|
|
304
|
+
```
|
|
305
|
+
*String equality — single quotes for string literals; `==` for equality, `!=` for inequality.*
|
|
266
306
|
|
|
267
307
|
### `ORDER`
|
|
268
308
|
|
|
@@ -28,7 +28,7 @@ The `FROM_METADATA` vs `FROM` confusion is the most-confused single distinction
|
|
|
28
28
|
|
|
29
29
|
## Schema landmines (READ FIRST)
|
|
30
30
|
|
|
31
|
-
1. **`KEEP
|
|
31
|
+
1. **`KEEP`, when used, must be the LAST op.** KEEP itself is **optional** — many pipelines end with `AGG` / `COUNT` / `TOP` / `BOTTOM` / `DESCRIBE` and have no KEEP at all. But anything that follows a KEEP returns HTTP 400. If you do project, put KEEP at the end and do GROUP / FILTER / sorting before it.
|
|
32
32
|
2. **`TOP` and `BOTTOM` use `n`, not `count`.** `{op:"TOP", column:"x", n:10}` — schema field is exactly `n`. The intuitive `count: 10` parses but rejects.
|
|
33
33
|
3. **`GROUP`, `ORDER`, `KEEP` cannot have empty `columns`.** Schema enforces `.min(1)`. Same for `FILTER`'s `AND`/`OR` `spec` arrays.
|
|
34
34
|
4. **`JOIN_TOPOLOGY` does NOT take a `querySpecifier`** — it joins by pipeline data via `externalIdColumn`, not by a TAS specifier. Surprising compared to JOIN_METADATA.
|
|
@@ -39,6 +39,8 @@ The `FROM_METADATA` vs `FROM` confusion is the most-confused single distinction
|
|
|
39
39
|
9. **TOP and BOTTOM have asymmetric `sortAscending` defaults.** TOP defaults to `false` (largest first); BOTTOM defaults to `true` (smallest first). Setting `sortAscending: true` on TOP is legal but produces BOTTOM-equivalent ordering — switch the op for clarity.
|
|
40
40
|
10. **`GROUP` only drops non-grouped columns when followed by an aggregator.** `GROUP → AGG` collapses to grouping-key + `as` outputs; `GROUP → BOTTOM/TOP/ORDER/KEEP/FILTER` (no aggregator) preserves the upstream column shape. Use `KEEP` after GROUP if you want pruning without aggregation.
|
|
41
41
|
11. **Diagnostic: verify a FROM matches anything before pulling on the full pipeline.** Run `[FROM, KEEP({columns:["metric.id"]})]` in isolation; zero data rows → the specifier matches no metric in this tenant. The data-store editor's "Run JUST this step" control on FROM / FROM_METADATA does this for you.
|
|
42
|
+
12. **`COUNT` after `GROUP` requires an explicit `as`.** Schema marks `as` optional with default `"count"`, but the server returns HTTP 400 for a bare `{op:"COUNT"}` immediately after `GROUP`. Always set `as` on COUNT (e.g. `{op:"COUNT", as:"n"}`). Treat `as` as required in practice. See `cookbooks/gotchas` for the full schema-vs-server discrepancy note.
|
|
43
|
+
13. **TAS ATTRIBUTE expression `name` is `type`, NOT `_type`.** `_type` is a storage-side / NASSQL specifier convention; using it inside a TAS ATTRIBUTE filter is accepted by the schema (the schema allows any string) but silently returns zero rows. Same for `hostname`, `agentType`, etc. — use the user-facing attribute key, not the storage field. See `cookbooks/gotchas`.
|
|
42
44
|
|
|
43
45
|
## The envelope
|
|
44
46
|
|