@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,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dx-do",
|
|
3
|
+
"owner": {
|
|
4
|
+
"name": "Ki Alam",
|
|
5
|
+
"url": "https://github.com/zoobroker"
|
|
6
|
+
},
|
|
7
|
+
"description": "DXO2 plugins for Claude Code — one per activity (investigate, operate, admin, …). All share the dx-do-query MCP server and the @dx-do/catalog grounding content.",
|
|
8
|
+
"plugins": [
|
|
9
|
+
{
|
|
10
|
+
"name": "investigate",
|
|
11
|
+
"source": "./investigate",
|
|
12
|
+
"description": "Investigate a DXO2 tenant — guided discovery, query authoring, and UI/analyzer handoff."
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: metric-source-names
|
|
3
|
+
title: Metric source naming convention — the `<domain>|<host>|<bus>|<role>` shape
|
|
4
|
+
applies_to: nassql
|
|
5
|
+
tags: [reference, naming, gotcha]
|
|
6
|
+
related: [nassql-quickstart, mm-quickstart, gotchas, discovery-flow]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Metric source naming
|
|
10
|
+
|
|
11
|
+
`metric.source` values are **pipe-delimited multi-segment strings** that identify the producer of a metric datapoint. Getting the regex shape wrong is the single most common reason an otherwise-correct NASSQL FROM pipeline returns zero rows. This cookbook covers the canonical shapes and the empirical-discovery move you should reach for when an unfamiliar tenant doesn't match what you expect.
|
|
12
|
+
|
|
13
|
+
## The general shape
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
<domain>|<host-or-agent-id>|<bus>|<role>[|<extra-segments>...]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- **`<domain>`** — the source family. The most common value is `SuperDomain` (the default for Infrastructure-agent metrics). Other domains seen in the wild: `SystemEdge`, custom enterprise domains. **This is the segment most agents forget about** — they jump straight to the host name and write `.*<host>.*`, which doesn't match anything because every source starts with a domain prefix.
|
|
20
|
+
- **`<host-or-agent-id>`** — usually the host name, sometimes a synthetic agent identifier. May be a bare hostname (`host-001`) or fully-qualified (`host-001.us-west1-b.c.example.internal`). The form depends on how the agent was registered.
|
|
21
|
+
- **`<bus>`** — the metric bus / category (`Infrastructure`, `TopProcess`, `BusinessTransaction`, etc.).
|
|
22
|
+
- **`<role>`** — the producer role within that bus (`Agent`, `TopNProcessByCPU`, etc.). For Infrastructure agents this is literally `Agent`.
|
|
23
|
+
|
|
24
|
+
## Canonical examples
|
|
25
|
+
|
|
26
|
+
| Source string | Shape |
|
|
27
|
+
|---|---|
|
|
28
|
+
| `SuperDomain\|host-001\|Infrastructure\|Agent` | 4-segment Infrastructure-agent (the most common shape). |
|
|
29
|
+
| `SystemEdge\|host-001.us-west1-b.c.example.internal\|TopProcess\|TopNProcessByCPU\|3:Parent PID Number` | 5-segment SystemEdge probe with a sub-category. |
|
|
30
|
+
|
|
31
|
+
## Regex authoring rules
|
|
32
|
+
|
|
33
|
+
When you write a `metric.source` REGEX in a `sourceNameSpecifier`:
|
|
34
|
+
|
|
35
|
+
1. **`|` is a regex meta-character.** Always escape it as `\|` in the pattern. A bare `|` will match anything (it's regex-OR).
|
|
36
|
+
2. **Don't omit the leading segment.** A pattern like `.*host-001.*` is a common reflex — but it implicitly requires the host name to appear *somewhere*, which means it ALSO has to match the leading `<domain>|` prefix, which it does NOT (because there's no `.*` consuming the domain part). Either anchor with the domain (`^SuperDomain\|host-001\|...`) or use a wildcard explicitly between segments.
|
|
37
|
+
3. **Anchor or don't — be deliberate.** Anchored (`^...$`) is faster and unambiguous. Unanchored (`.*...`) is forgiving but may pull in unintended sources from other buses.
|
|
38
|
+
4. **Wildcards across segments use `.`, not `\|`.** `.*host-001.Infrastructure.Agent` (with bare `.` between segments) is a valid loose pattern — works because `.` matches the literal `|` along with anything else. Slightly wasteful but readable.
|
|
39
|
+
|
|
40
|
+
## The empirical-discovery move
|
|
41
|
+
|
|
42
|
+
When you don't know the source-name shape on a tenant — **do not guess from host names**. Run a FROM_METADATA probe and inspect actual source values:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"query": [
|
|
47
|
+
{"op": "FROM_METADATA",
|
|
48
|
+
"querySpecifier": {"op": "SPEC",
|
|
49
|
+
"sourceNameSpecifier": {"op": "REGEX", "pattern": ".*<host-or-id-fragment>.*"},
|
|
50
|
+
"attributeNameSpecifier": {"op": "REGEX", "pattern": ".*"}}},
|
|
51
|
+
{"op": "KEEP", "columns": ["metric.source", "metric.path"]}
|
|
52
|
+
],
|
|
53
|
+
"limit": 20
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Use `run_partial_query` with `upToStep: 0` for the cheapest possible probe (just the FROM_METADATA call, no transforms). Read the actual `metric.source` values back, then write your real query against the discovered shape.
|
|
58
|
+
|
|
59
|
+
This is also the fastest way to figure out which **`<domain>`** values exist on a tenant — especially when an enterprise customer has provisioned non-`SuperDomain` agents.
|
|
60
|
+
|
|
61
|
+
## Common mistakes (from the foray)
|
|
62
|
+
|
|
63
|
+
| What the agent tried | Why it returned empty | The fix |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `.*host-001.*` against `metric.source` | No `SuperDomain\|` prefix consumed; pattern doesn't span the literal `|` separators correctly. | `^SuperDomain\|host-001\|.*` or `.*host-001.Infrastructure.Agent` |
|
|
66
|
+
| `.*<bare-host>.*` with `\|` in pattern as `|` (unescaped) | The `|` parses as regex-OR, blowing up the intended structure. | Escape as `\|` or use bare `.`. |
|
|
67
|
+
| Probing source names with `run_query` (full execute) instead of a partial | Wastes a full pipeline run for what's actually a one-step inspection. | `run_partial_query` with `upToStep: 0`. |
|
|
68
|
+
|
|
69
|
+
## See also
|
|
70
|
+
|
|
71
|
+
- `nassql-quickstart` — the FROM / FROM_METADATA / FROM_DATA decision (this cookbook covers the source-pattern shape that those ops consume).
|
|
72
|
+
- `mm-quickstart` — Metrics Metadata specifiers (the `sourceNameSpecifier` field is the same shape).
|
|
73
|
+
- `gotchas` — promotes the empty-payload trap + auto-numbered shortName + this cookbook's source-pattern trap to the top.
|
|
74
|
+
- `discovery-flow` — the broader discovery hierarchy.
|
|
75
|
+
- `entities/agent` — the entity that *produces* these source names.
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: metrics-grounding
|
|
3
|
+
title: Metrics grounding — the semantic layer beyond MM mechanics
|
|
4
|
+
applies_to: metadata
|
|
5
|
+
tags: [reference, authoring]
|
|
6
|
+
related: [metric-source-names, mm-cookbook, mm-quickstart, entity-relationships, investigation-planning]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Metrics grounding
|
|
10
|
+
|
|
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
|
+
|
|
13
|
+
## Metric identity, four ways
|
|
14
|
+
|
|
15
|
+
The same metric is referred to by different names depending on which surface you're on:
|
|
16
|
+
|
|
17
|
+
| Name | Where you see it |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `metric.source` + `metric.path` | NASSQL `FROM_METADATA` columns |
|
|
20
|
+
| MM `SourceNameSpecifier` + `AttributeNameSpecifier` | Metrics-Metadata query input |
|
|
21
|
+
| `<resource>:<metric>` | User shorthand — the `metric.path` ending after the last `:` is the metric name; the prefix is the "resource" |
|
|
22
|
+
| `metric.attribute` (older) | Older API field — alias for the path's leaf segment |
|
|
23
|
+
|
|
24
|
+
Concretely, a metric like `Beans|Nass Reactive Client|Store|Flush|Unregistered Queue:Concurrent Invocations` carries:
|
|
25
|
+
|
|
26
|
+
- `metric.source` = `SuperDomain|host-001|Custom Metric Process|Custom Metric Agent` (the producer).
|
|
27
|
+
- `metric.path` = the pipe-delimited folder breadcrumb ending with `:Concurrent Invocations`.
|
|
28
|
+
- User shorthand: `Unregistered Queue:Concurrent Invocations` (resource = breadcrumb tail; metric name = post-`:`).
|
|
29
|
+
|
|
30
|
+
For the field-level rules see `lexicon/attribute_resource_metric_name`.
|
|
31
|
+
|
|
32
|
+
## The agent ↔ metric bridge
|
|
33
|
+
|
|
34
|
+
Most metrics tie back to an **AGENT vertex** via a known path. The bridge:
|
|
35
|
+
|
|
36
|
+
1. From a topology vertex (HOST, BUSINESSTRANSACTION, k8s_POD), TRAVERSE `agent-monitors` (incoming) → AGENT vertex.
|
|
37
|
+
2. From the AGENT, the `agentName` attribute (or part of `metric.source`) connects to MM.
|
|
38
|
+
3. Query MM by `metric.source` matching a regex of the agent's identity, or use `discovery_metrics_for_entity` (which builds the canonical metric query body for a vertex).
|
|
39
|
+
|
|
40
|
+
The AGENT is the *producer*; metrics flow from it. If you only have a metric and you want to find its agent: split `metric.source` on `|`, look at the second-to-last segment (often the `agent` identity), and search AGENT vertices.
|
|
41
|
+
|
|
42
|
+
## Orphaned-by-design metrics
|
|
43
|
+
|
|
44
|
+
**Not every metric has a topology vertex.** This is the single biggest grounding gap a query agent runs into. The canonical example: **JMX metrics**.
|
|
45
|
+
|
|
46
|
+
A JMX-instrumented JVM exposes hundreds of MBeans — connection pools, thread pools, cache regions, queue stats, GC details. The platform's JMX agent forwards these as metrics under the JVM's source. But:
|
|
47
|
+
|
|
48
|
+
- There is usually **one** `JMX_SYSTEM` vertex per monitored JVM, not one vertex per pool.
|
|
49
|
+
- There is **no `JDBC_CONNECTION_POOL` vertex type** by default.
|
|
50
|
+
- The pool, queue, or cache identity exists *only in the metric path*.
|
|
51
|
+
|
|
52
|
+
If a user asks "how are the database connection pools for application X doing", the wrong move is "search for `type=JDBC_CONNECTION_POOL`" — that returns nothing. The right move is:
|
|
53
|
+
|
|
54
|
+
1. Find the application X (DXO2 service / k8s_DEPLOYMENT / `applicationName` — see `cookbooks/investigation-planning`).
|
|
55
|
+
2. Find the agents producing metrics for X — typically a Java APM agent and a JMX agent.
|
|
56
|
+
3. Query MM under those agents for paths matching pool-flavored regex: `.*JDBC.*Pool.*` or `.*Connection Pool.*` or similar.
|
|
57
|
+
4. Group/aggregate by the pool segment of the path to get per-pool numbers.
|
|
58
|
+
|
|
59
|
+
The metric *value* is sometimes the only place identity lives — e.g. a `queue_name` metric that's a string `queue://host-2/orders`. In that case, NASSQL `FROM_DATA` to extract values, then group/filter on the value.
|
|
60
|
+
|
|
61
|
+
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
|
+
## Metric `type` is opaque (for now)
|
|
64
|
+
|
|
65
|
+
Every metric carries a numeric `type` field with values like `0`, `1`, `2`, `3`. The numeric ID indicates the metric's data shape (gauge, counter, rate, etc.) and informs how it should be aggregated and displayed.
|
|
66
|
+
|
|
67
|
+
**The numeric → semantic mapping is not yet documented in the corpus.** Treat `metric.type` as opaque: when you need to aggregate or order, prefer empirical inspection of values via `run_partial_query` rather than assuming a particular type means a particular aggregation. A future grounding pass will close this gap.
|
|
68
|
+
|
|
69
|
+
## Pattern recognition: deciding when to inventorize
|
|
70
|
+
|
|
71
|
+
If you see all three of these for the same resource pattern, inventorizing is probably right:
|
|
72
|
+
|
|
73
|
+
1. The user keeps asking about the resource by name — it's part of their vocabulary.
|
|
74
|
+
2. The metrics for the resource are reliable and stable (same source, same path shape, same regular intervals).
|
|
75
|
+
3. There's no existing vertex type that matches.
|
|
76
|
+
|
|
77
|
+
In that case, an **inventorize rule** (`inventory create-inventorize-rule`) materializes a vertex per match. The vertex gets a `CUSTOM_INVENTORIZE_<N>` type by default; you can give it a more specific name. After the rule runs, future queries can use the new type as a first-class anchor.
|
|
78
|
+
|
|
79
|
+
## Practical authoring patterns
|
|
80
|
+
|
|
81
|
+
### Pattern 1 — find metrics for a known vertex
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
discovery_metrics_for_entity(vertexId="<id>")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Returns the canonical metric query body the platform's mapping configuration says applies. Use this when you have the vertex.
|
|
88
|
+
|
|
89
|
+
### Pattern 2 — find metrics matching a name pattern
|
|
90
|
+
|
|
91
|
+
```js
|
|
92
|
+
// MM query
|
|
93
|
+
{
|
|
94
|
+
"querySpecifier": {
|
|
95
|
+
"op": "AND",
|
|
96
|
+
"input": [
|
|
97
|
+
{ "op": "ATTRIBUTE_NAME", "values": [".*Connection Pool.*"], "queryType": "REGEX" }
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
"limit": 200
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Use this for orphaned metrics. Adjust the regex to taste.
|
|
105
|
+
|
|
106
|
+
### Pattern 3 — find which agent produced a metric
|
|
107
|
+
|
|
108
|
+
```js
|
|
109
|
+
// NASSQL
|
|
110
|
+
{ "query": [
|
|
111
|
+
{ "op": "FROM_METADATA", "querySpecifier": { ... }, "alias": "m" },
|
|
112
|
+
{ "op": "GROUP", "columns": ["metric.source"] },
|
|
113
|
+
{ "op": "COUNT", "as": "n" }
|
|
114
|
+
], "limit": 50 }
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Group by source to see the producer distribution. Then look up each source as an AGENT.
|
|
118
|
+
|
|
119
|
+
### Pattern 4 — compare multiple agents reporting the "same" metric
|
|
120
|
+
|
|
121
|
+
A backend or BT may show up under multiple agents. To compare, NASSQL `FROM_DATA` joined to `FROM_TOPOLOGY` (or grouped by `metric.source`) gives per-agent slices. Sum/average for the unified view.
|
|
122
|
+
|
|
123
|
+
## See also
|
|
124
|
+
|
|
125
|
+
- `cookbooks/metric-source-names` — pipe-delimited source name anatomy.
|
|
126
|
+
- `cookbooks/mm-cookbook` — full specifier vocabulary.
|
|
127
|
+
- `cookbooks/investigation-planning` — when to reach for metric-first vs entity-first.
|
|
128
|
+
- `lexicon/attribute_resource_metric_name` — the four-name terminology.
|
|
129
|
+
- `lexicon/inventorize` — promoting metric patterns into vertices.
|
|
130
|
+
- `entities/jmx_system` — the canonical orphaned-metrics case.
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: mm-cookbook
|
|
3
|
+
title: Metrics Metadata cookbook — specifier reference and recipe catalog
|
|
4
|
+
applies_to: metadata
|
|
5
|
+
tags: [reference, recipes, authoring]
|
|
6
|
+
related: [mm-quickstart, nassql-cookbook, gotchas]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Metrics Metadata cookbook
|
|
10
|
+
|
|
11
|
+
Full specifier-vocabulary reference for Metrics Metadata
|
|
12
|
+
(`/metadata/queryMetric`) authoring, plus a recipe catalog. The same
|
|
13
|
+
`QuerySpecifier` vocabulary documented here is also embedded inside NASSQL
|
|
14
|
+
`FROM_METADATA` and `JOIN_METADATA` ops — so this cookbook is required
|
|
15
|
+
reading for NASSQL authors too.
|
|
16
|
+
|
|
17
|
+
Use after `mm-quickstart.md` when you need the full sub-specifier
|
|
18
|
+
breakdown or a concrete pattern to start from.
|
|
19
|
+
|
|
20
|
+
## Specifier mental model
|
|
21
|
+
|
|
22
|
+
A `QuerySpecifier` describes a **set of metric metadata records**. It is a
|
|
23
|
+
discriminated union on `op`. The richest op is `SPEC`, which has three
|
|
24
|
+
sub-specifier slots:
|
|
25
|
+
|
|
26
|
+
```mermaid
|
|
27
|
+
flowchart TB
|
|
28
|
+
spec["QuerySpecifier (op-discriminated)"] --> simple["leaves: ALL / NONE / ID / GROUP / SERVICE / ATTRIBUTE"]
|
|
29
|
+
spec --> compose["composers: AND / OR / NOT"]
|
|
30
|
+
spec --> structured["SPEC { sourceNameSpecifier, folderNameSpecifier, attributeNameSpecifier }"]
|
|
31
|
+
structured --> sourceSpec["SourceNameSpecifier (ALL / EXACT / REGEX / PART / AND / OR / NOT)"]
|
|
32
|
+
structured --> attrSpec["AttributeNameSpecifier (ALL / EXACT / REGEX / FOLDER / CHILDREN / TYPE / OPERATOR / NUMERIC / ATTRIBUTE / AND / OR / NOT)"]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Why three: a metric is keyed by `<source>` + `<folder/path>` + `<attribute>`,
|
|
36
|
+
so each component has its own specifier sub-language with its own ops.
|
|
37
|
+
|
|
38
|
+
## Top-level envelope
|
|
39
|
+
|
|
40
|
+
| Field | Type | Purpose |
|
|
41
|
+
|-------|------|---------|
|
|
42
|
+
| `specifier` | `QuerySpecifier` | What metrics to match; omit = `ALL` |
|
|
43
|
+
| `clamp` | number | Cap on result count. **Default new queries to ≤ 500.** Large tenants return MB without this. |
|
|
44
|
+
| `time` | number | Reference time (epoch ms); default = now |
|
|
45
|
+
| `range` | number | Time range in ms around `time` to include recently-inactive metrics |
|
|
46
|
+
| `includeLive` | boolean | Include currently-active live metrics not yet persisted |
|
|
47
|
+
| `includeProfile` | boolean | Include profiling info per metric descriptor |
|
|
48
|
+
| `profileLevel` | string | Granularity of profiling when `includeProfile=true` |
|
|
49
|
+
| `authorizationView` | string | Auth-view restriction |
|
|
50
|
+
| `queryHints` | `QueryHint[]` | `{ "hint": "ForceRange" }` forces time-range search even without an explicit `queryRange` |
|
|
51
|
+
|
|
52
|
+
## Top-level `QuerySpecifier` ops
|
|
53
|
+
|
|
54
|
+
| Op | Shape | Purpose |
|
|
55
|
+
|----|-------|---------|
|
|
56
|
+
| `ALL` | `{ op: "ALL", includeFolders?, includeMetrics? }` | Every metric |
|
|
57
|
+
| `NONE` | `{ op: "NONE" }` | Empty set |
|
|
58
|
+
| `AND` | `{ op: "AND", specifiers: [...] }` | Intersection |
|
|
59
|
+
| `OR` | `{ op: "OR", specifiers: [...] }` | Union |
|
|
60
|
+
| `NOT` | `{ op: "NOT", specifier: ... }` | Complement |
|
|
61
|
+
| `SPEC` | `{ op: "SPEC", sourceNameSpecifier?, folderNameSpecifier?, attributeNameSpecifier? }` | Structured match (the workhorse) |
|
|
62
|
+
| `ID` | `{ op: "ID", ids: ["m-id-1", ...] }` | By metric id |
|
|
63
|
+
| `ATTRIBUTE` | `{ op: "ATTRIBUTE", expressions: [...] }` | By metric-attribute expression |
|
|
64
|
+
| `GROUP` | `{ op: "GROUP", id?, managementModuleId? }` | By management module / group |
|
|
65
|
+
| `SERVICE` | `{ op: "SERVICE", values: [...] }` | By named service |
|
|
66
|
+
|
|
67
|
+
Note: `AND`/`OR` use `specifiers` (array), `NOT` uses `specifier` (single).
|
|
68
|
+
**Do not** confuse with NASSQL `FILTER` predicates which use `spec`.
|
|
69
|
+
|
|
70
|
+
## SourceNameSpecifier ops
|
|
71
|
+
|
|
72
|
+
Used inside `SPEC.sourceNameSpecifier`.
|
|
73
|
+
|
|
74
|
+
| Op | Shape | Purpose |
|
|
75
|
+
|----|-------|---------|
|
|
76
|
+
| `ALL` | `{ op: "ALL" }` | Any source |
|
|
77
|
+
| `NONE` | `{ op: "NONE" }` | No source |
|
|
78
|
+
| `EXACT` | `{ op: "EXACT", names: [...], ignoreCase? }` | Exact source-name match |
|
|
79
|
+
| `REGEX` | `{ op: "REGEX", pattern, ignoreCase? }` | Regex match |
|
|
80
|
+
| `PART` | `{ op: "PART", part, partValue?, operator? }` | Match a specific dot-separated segment (0-indexed) |
|
|
81
|
+
| `AND` / `OR` | `{ op, specifiers: [...] }` | Boolean composition |
|
|
82
|
+
| `NOT` | `{ op: "NOT", specifier: ... }` | Complement |
|
|
83
|
+
|
|
84
|
+
`PART.operator`: `EQ | NE | GE | GT | LE | LT`.
|
|
85
|
+
|
|
86
|
+
See `metric-source-names.md` for the canonical `<domain>|<host>|<bus>|<role>`
|
|
87
|
+
shape that source strings follow, and the regex-authoring rules that
|
|
88
|
+
prevent zero-row results.
|
|
89
|
+
|
|
90
|
+
## AttributeNameSpecifier ops
|
|
91
|
+
|
|
92
|
+
Used inside `SPEC.attributeNameSpecifier`. Richer than the source side
|
|
93
|
+
because metric attribute names form a hierarchy:
|
|
94
|
+
|
|
95
|
+
| Op | Shape | Purpose |
|
|
96
|
+
|----|-------|---------|
|
|
97
|
+
| `ALL` / `NONE` | `{ op }` | Any / no attribute |
|
|
98
|
+
| `EXACT` | `{ op: "EXACT", names: [...], type?, ignoreCase? }` | Exact attribute name |
|
|
99
|
+
| `REGEX` | `{ op: "REGEX", pattern, ignoreCase? }` | Regex match |
|
|
100
|
+
| `FOLDER` | `{ op: "FOLDER", specifier: FolderNameSpecifier }` | Match by folder |
|
|
101
|
+
| `CHILDREN` | `{ op: "CHILDREN", prefix?, recursive? }` | Match attribute children of prefix |
|
|
102
|
+
| `TYPE` | `{ op: "TYPE", specifier?, bitMask?, bitMatch?, operator? }` | Match by type bits |
|
|
103
|
+
| `OPERATOR` | `{ op: "OPERATOR", name?, fullPath?, operator? }` | Match by operator |
|
|
104
|
+
| `NUMERIC` | `{ op: "NUMERIC" }` | Match any numeric attribute |
|
|
105
|
+
| `ATTRIBUTE` | `{ op: "ATTRIBUTE", expressions: [...] }` | Match by metric-attribute expression |
|
|
106
|
+
| `AND` / `OR` | `{ op, specifiers: [...] }` | Boolean composition |
|
|
107
|
+
| `NOT` | `{ op: "NOT", specifier: ... }` | Complement |
|
|
108
|
+
|
|
109
|
+
The simplest combinators are `EXACT` and `REGEX`, which cover the majority
|
|
110
|
+
of real queries.
|
|
111
|
+
|
|
112
|
+
## FolderNameSpecifier
|
|
113
|
+
|
|
114
|
+
A sub-language for folder paths, used inside an
|
|
115
|
+
`AttributeNameSpecifier` of op `FOLDER`.
|
|
116
|
+
|
|
117
|
+
| Op | Shape | Purpose |
|
|
118
|
+
|----|-------|---------|
|
|
119
|
+
| `ALL` / `NONE` | `{ op }` | Any / no folder |
|
|
120
|
+
| `EXACT` | `{ op: "EXACT", names: [...], ignoreCase? }` | Exact folder name |
|
|
121
|
+
| `REGEX` | `{ op: "REGEX", pattern, ignoreCase? }` | Regex match |
|
|
122
|
+
| `CHILDREN` | `{ op: "CHILDREN", prefix?, recursive? }` | Children of prefix path |
|
|
123
|
+
| `AND` / `OR` | `{ op, specifiers: [...] }` | Boolean composition |
|
|
124
|
+
| `NOT` | `{ op: "NOT", specifier: ... }` | Complement |
|
|
125
|
+
|
|
126
|
+
Metric attribute names are organized in a virtual folder hierarchy using
|
|
127
|
+
dots as separators. `prefix` is a dot-delimited parent path.
|
|
128
|
+
|
|
129
|
+
## Recipe catalog
|
|
130
|
+
|
|
131
|
+
### "All metrics on the tenant (smoke / count)"
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"specifier": { "op": "ALL" },
|
|
136
|
+
"clamp": 10,
|
|
137
|
+
"range": 480000,
|
|
138
|
+
"includeLive": true
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### "Metrics with source matching a regex"
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"specifier": {
|
|
147
|
+
"op": "SPEC",
|
|
148
|
+
"sourceNameSpecifier": { "op": "REGEX", "pattern": ".*Infrastructure.*" }
|
|
149
|
+
},
|
|
150
|
+
"clamp": 100
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### "Metrics with attribute matching a regex"
|
|
155
|
+
|
|
156
|
+
```json
|
|
157
|
+
{
|
|
158
|
+
"specifier": {
|
|
159
|
+
"op": "SPEC",
|
|
160
|
+
"attributeNameSpecifier": { "op": "REGEX", "pattern": ".*CPU.*Utilization.*" }
|
|
161
|
+
},
|
|
162
|
+
"clamp": 100
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### "Metrics for a specific source name (exact)"
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"specifier": {
|
|
171
|
+
"op": "SPEC",
|
|
172
|
+
"sourceNameSpecifier": { "op": "EXACT", "names": ["Infrastructure|host01|CPU"] }
|
|
173
|
+
},
|
|
174
|
+
"clamp": 50
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### "Cross-product: source regex AND attribute regex"
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"specifier": {
|
|
183
|
+
"op": "SPEC",
|
|
184
|
+
"sourceNameSpecifier": { "op": "REGEX", "pattern": ".*Infrastructure.*" },
|
|
185
|
+
"attributeNameSpecifier": { "op": "REGEX", "pattern": ".*CPU.*" }
|
|
186
|
+
},
|
|
187
|
+
"clamp": 200
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### "Either of two sources, but exclude a noisy attribute"
|
|
192
|
+
|
|
193
|
+
```json
|
|
194
|
+
{
|
|
195
|
+
"specifier": {
|
|
196
|
+
"op": "AND",
|
|
197
|
+
"specifiers": [
|
|
198
|
+
{ "op": "SPEC",
|
|
199
|
+
"sourceNameSpecifier": { "op": "OR", "specifiers": [
|
|
200
|
+
{ "op": "REGEX", "pattern": ".*Infrastructure.*" },
|
|
201
|
+
{ "op": "REGEX", "pattern": ".*APM.*" } ] } },
|
|
202
|
+
{ "op": "NOT",
|
|
203
|
+
"specifier": { "op": "SPEC",
|
|
204
|
+
"attributeNameSpecifier": { "op": "REGEX", "pattern": ".*Heap.*" } } }
|
|
205
|
+
]
|
|
206
|
+
},
|
|
207
|
+
"clamp": 100
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### "Metrics by id"
|
|
212
|
+
|
|
213
|
+
```json
|
|
214
|
+
{ "specifier": { "op": "ID", "ids": ["m-id-1", "m-id-2"] } }
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Authoring tips
|
|
218
|
+
|
|
219
|
+
- For NASSQL embedding, **always wrap REGEX in `SPEC`**. A bare
|
|
220
|
+
`{ op: "REGEX", ... }` is not a valid `QuerySpecifier`. See `gotchas.md`.
|
|
221
|
+
- Use `AND` / `OR` / `NOT` at the **`QuerySpecifier`** level for
|
|
222
|
+
whole-spec composition, not inside the sub-specifiers.
|
|
223
|
+
- The sub-specifiers (`SourceNameSpecifier`, `AttributeNameSpecifier`)
|
|
224
|
+
have their **own** `AND` / `OR` / `NOT` ops scoped to that
|
|
225
|
+
sub-language — useful for "source = (X regex OR Y regex)".
|
|
226
|
+
- `clamp` caps the result count at the metadata service; use it in
|
|
227
|
+
addition to (or instead of) any pagination on the calling code.
|
|
228
|
+
- When the metric-source vocabulary is unknown, run the `FROM_METADATA` +
|
|
229
|
+
`GROUP source` + `COUNT` discovery NASSQL query first
|
|
230
|
+
(`corpus_get("queries", "03-discover-sources")`) to learn real source
|
|
231
|
+
names. See `metric-source-names.md` for the source-string shape.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: mm-quickstart
|
|
3
|
+
title: Metrics Metadata quickstart — author a metric specifier
|
|
4
|
+
applies_to: metadata
|
|
5
|
+
tags: [getting-started, authoring]
|
|
6
|
+
related: [nassql-quickstart, gotchas]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Metrics Metadata quickstart
|
|
10
|
+
|
|
11
|
+
MM = metric metadata queries. Returns `{ metrics, folders }` arrays of
|
|
12
|
+
descriptors. The query body is a single recursive **specifier tree**.
|
|
13
|
+
|
|
14
|
+
## The envelope
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"specifier": { "op": "ALL", "includeMetrics": true },
|
|
19
|
+
"clamp": 500, // strongly recommended — see Gotcha below
|
|
20
|
+
"time": 1700000000000,
|
|
21
|
+
"range": 86400000,
|
|
22
|
+
"includeLive": false,
|
|
23
|
+
"includeProfile": false,
|
|
24
|
+
"profileLevel": null,
|
|
25
|
+
"authorizationView": null
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Gotcha — set `clamp`
|
|
30
|
+
|
|
31
|
+
Without a `clamp`, the server returns ALL matching metrics. On a real
|
|
32
|
+
tenant that's tens of thousands of descriptors / multiple MB. **Default
|
|
33
|
+
`clamp: 500`** for new MM queries, raise only when needed.
|
|
34
|
+
|
|
35
|
+
## Top-level specifier ops (10)
|
|
36
|
+
|
|
37
|
+
| Op | Purpose |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `ALL` | Match everything. Use `includeFolders` / `includeMetrics`. |
|
|
40
|
+
| `NONE` | Match nothing. |
|
|
41
|
+
| `AND` / `OR` | Compose specifiers. **Cannot be empty.** |
|
|
42
|
+
| `NOT` | Negate. |
|
|
43
|
+
| `SPEC` | Compose three sub-specifiers (source-name + folder-name + attribute-name). |
|
|
44
|
+
| `ID` | Match specific metric IDs. **`ids` cannot be empty.** |
|
|
45
|
+
| `ATTRIBUTE` | Match by attribute expressions. |
|
|
46
|
+
| `GROUP` | Match a metric group / module. |
|
|
47
|
+
| `SERVICE` | Restrict by service name(s). |
|
|
48
|
+
|
|
49
|
+
## SPEC — composing the three sub-specifier trees
|
|
50
|
+
|
|
51
|
+
`SPEC` is the powerful pattern. It combines:
|
|
52
|
+
|
|
53
|
+
- `sourceNameSpecifier` — match the source layer name
|
|
54
|
+
- `folderNameSpecifier` — match the folder hierarchy
|
|
55
|
+
- `attributeNameSpecifier` — match the attribute name
|
|
56
|
+
|
|
57
|
+
Each is its own recursive tree with AND/OR/NOT/EXACT/REGEX. AttributeName
|
|
58
|
+
also has CHILDREN, FOLDER, TYPE, OPERATOR, NUMERIC, ATTRIBUTE.
|
|
59
|
+
|
|
60
|
+
Example — APM-sourced CPU metrics in a specific folder:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"specifier": {
|
|
65
|
+
"op": "SPEC",
|
|
66
|
+
"sourceNameSpecifier": { "op": "EXACT", "names": ["APM"] },
|
|
67
|
+
"folderNameSpecifier": { "op": "CHILDREN", "prefix": "Hosts", "recursive": true },
|
|
68
|
+
"attributeNameSpecifier": { "op": "REGEX", "pattern": "^cpu\\..*" }
|
|
69
|
+
},
|
|
70
|
+
"clamp": 500
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## ID — pinpoint specific metrics
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"specifier": {
|
|
79
|
+
"op": "ID",
|
|
80
|
+
"ids": ["NOB-BE-qP-n5EevJ0B", "ABC-12-..."]
|
|
81
|
+
},
|
|
82
|
+
"clamp": 100
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`ids` is required-non-empty. Reading metric IDs from a previous MM query's
|
|
87
|
+
result table (the leftmost column of the metric results) is the typical
|
|
88
|
+
pattern.
|
|
89
|
+
|
|
90
|
+
## Iteration
|
|
91
|
+
|
|
92
|
+
MM has no partial-run primitive (single specifier — no obvious slice
|
|
93
|
+
point). Run the full query, narrow the specifier, run again.
|
|
94
|
+
|
|
95
|
+
## Discovery
|
|
96
|
+
|
|
97
|
+
`discovery_metrics` returns up to 1000 metric attribute names known on
|
|
98
|
+
the tenant. Useful to validate `ATTRIBUTE` expression names before
|
|
99
|
+
running.
|
|
100
|
+
|
|
101
|
+
## See also
|
|
102
|
+
|
|
103
|
+
- `mm-cookbook.md` — full specifier reference, recipe catalog, sub-specifier composition
|
|
104
|
+
- `gotchas.md` — `ID.ids` empty-array surprise (now caught by .min(1))
|
|
105
|
+
- `nassql-quickstart.md` — for embedding MM specifiers in NASSQL FROM_METADATA / JOIN_METADATA
|
|
106
|
+
- Live examples: `corpus_list("queries", {type: "metadata"})` — fetch full payloads with `corpus_get("queries", "<id>")`.
|