This page walks through a minimal, end-to-end example of shipping unified analysis (UA) page documents with an extension. It uses a single generic node type, CUSTOM_NODE, exposed by an extension named custom:my-extension.
You ship four documents:
| File | Document type | Purpose |
|---|---|---|
|
| Top-level Inventory Explorer category that groups related extensions. |
|
| Subtype under the category, representing this extension. |
|
| Subtype that lists all |
|
| Detail screen shown when a user opens a single |
The three InvExTypeDefinition documents nest into a hierarchy; the EntityDetailsDefinition then renders the individual entity page:
Example category (category-inventory.screen.json)└── Example extension (extension-inventory.screen.json)└── Example nodes (custom_node-inventory.screen.json)
Each document declares a target that binds it to an app, and — for nested types — to its parent invExType. See Targeting for the full field reference.
Place all four documents in your extension's screens directory:
src/extension/├── extension.yaml└── screens/├── category-inventory.screen.json├── extension-inventory.screen.json├── custom_node-inventory.screen.json└── custom_node-entitydetails.screen.json
and declare them in the extension.yaml file:
name: custom:my-extensionversion: 1.0.0minDynatraceVersion: "1.343"author:name: Joe Doedocuments:screens:- path: screens/category-inventory.screen.json- path: screens/extension-inventory.screen.json- path: screens/custom_node-inventory.screen.json- path: screens/custom_node-entitydetails.screen.json
When the extension is built and activated in Dynatrace, the documents will be automatically imported to your environment.
The category is the top-level entry in the Inventory Explorer. It has no invExType in its target, which marks it as a new top-level type. Multiple extensions can register subtypes under the same category, so keep the id and displayName generic.
category-inventory.screen.json
{"version": "1.3.0","type": "InvExTypeDefinition","target": {"app": "dynatrace.infraops"},"content": {"id": "example-category","displayName": "Example category","content": {"type": "vertical-layout","items": []}}}
The extension document nests under the category by setting target.invExType to the category id (example-category). Its own id is the string that child node types point to.
extension-inventory.screen.json
{"version": "1.3.0","type": "InvExTypeDefinition","target": {"app": "dynatrace.infraops","invExType": "example-category"},"content": {"id": "custom:my-extension","displayName": "Example extension","content": {"type": "vertical-layout","items": []}}}
This document lists every CUSTOM_NODE entity in a table. It nests under the extension via target.invExType, and metadata.nodeType binds it to the Smartscape node type. The dql-table fetches nodes with smartscapeNodes and renders one row per entity; interactiveRows: "id" makes each row link to the entity details page.
custom_node-inventory.screen.json
{"version": "1.3.0","type": "InvExTypeDefinition","target": {"app": "dynatrace.infraops","invExType": "custom:my-extension"},"metadata": {"nodeType": "CUSTOM_NODE"},"content": {"id": "CUSTOM_NODE-inventory","displayName": "Example nodes","filtering": {"type": "filtering","id": "text-filtering","filters": [{"id": "name-filter","title": "Name","fieldIds": ["name"]}]},"content": {"type": "vertical-layout","items": [{"type": "dql-table","id": "CUSTOM_NODE-default-table","title": "Example nodes","interactiveRows": "id","dqlQuery": {"idField": "id","query": "smartscapeNodes CUSTOM_NODE\n| fieldsAdd status, version"},"columns": [{"id": "name","field": "name","displayName": "Name","defaultColumn": true,"sortable": true},{"id": "status","field": "status","displayName": "Status","sortable": true},{"id": "version","field": "version","displayName": "Version","sortable": true}]}]}}}
The details document renders the page for a single entity. Its target.nodeType binds it to CUSTOM_NODE, and every query filters on the selected entity with toSmartscapeId($(entityId)). This example defines two tabs: a metadata properties tab and an Overview tab with one chart.
custom_node-entitydetails.screen.json
{"version": "1.3.0","type": "EntityDetailsDefinition","target": {"app": "dynatrace.infraops","nodeType": "CUSTOM_NODE"},"content": {"type": "details","id": "example-node-details","content": {"type": "tabs","items": [{"type": "tab","id": "example-node-properties","title": "Properties","content": [{"type": "vertical-layout","items": [{"type": "metadata","id": "example-node-metadata","dqlQuery": "smartscapeNodes CUSTOM_NODE\n| fields id, name, status, version\n| filter id == toSmartscapeId($(entityId))"}]}]},{"type": "tab","id": "example-node-overview","title": "Overview","content": [{"type": "vertical-layout","items": [{"type": "chart-group","id": "example-node-charts","charts": [{"id": "example-node-uptime-chart","displayName": "Uptime","dqlQuery": "timeseries uptime = avg(`my_extension.uptime`),\n by: {`dt.smartscape.custom_node`},\n filter: {`dt.smartscape.custom_node` == toSmartscapeId($(entityId))}","visualization": {"type": "TIMESERIES_CHART","variant": "line"}}]}]}]}]}}}
After you build and activate the extension:
CUSTOM_NODE entities.
ExtensionsInfrastructure Observability