.agents/skills/project-create-topology/topology-function-schema.md
Active for new topology Function work. Existing deployed topology producers are to be migrated to this contract.
Topology Functions return normal Function envelopes with type: "topology" and
data.schema_version: "netdata.topology.v1".
The production schema is defined by:
src/plugins.d/FUNCTION_TOPOLOGY_SCHEMA.jsonsrc/plugins.d/FUNCTION_TOPOLOGY_DEVELOPER_GUIDE.mdThe schema is generic across topology domains. It applies to network connections, streaming, SNMP, vSphere, and future topology producers.
Topology payloads separate these planes:
Graph links are projections. Evidence rows are the facts used by Cloud aggregation, matching, and detailed drilldowns.
Mode requests use __topology_mode when a producer has a real detailed vs
aggregated output difference. Valid values are detailed and aggregated.
Mode-invariant topologies should not expose a selector only to return identical
payloads. Mode-capable producers declare data.view.supported_modes; absent
or single-value supported_modes means the topology is mode-invariant for UI
control purposes. The Cloud topology aggregator consumes detailed payloads for
mode-capable producers before returning an aggregated view, so producers must
preserve correlation-grade evidence in detailed mode.
Large sections use compact columnar tables with:
rowscolumnsvaluesSupported column codecs are:
constvaluesdictEvery decoded column must produce exactly rows values. Producers should use
shared helpers for table building, dictionary encoding, validation, and
deterministic sorting rather than hand-rolling encoders in each plugin.
Column type json is allowed only for actor-owned or custom detail cells that
must preserve nested producer-owned values. It is not the default for
relationship evidence, because high-cardinality evidence needs typed scalar,
reference, array, or dictionary-backed columns for compactness and aggregation
semantics.
Actor types declare:
identity;merge_identity;parent_identity;aggregation_scopes.search policy over actor table columns and actor label keys.presentation with UI-owned tokens, safe label policy, size policy,
actor repulsion policy, and graph port-bullet policy.Link types declare:
orientation: directed, undirected, hierarchical, or
observed_bidirectional;direction_role: none, flow, dependency, ownership, or
observation;semantic_role: normal, discovery, ownership, traffic,
correlation, or control;presentation with UI-owned color, line style, width, curve, arrow,
tokenized layout strength/distance, and one variable visual channel.Port types are optional and declare graph port-bullet presentation only. Actor/link modal composition is declared separately under actor/link type presentation and table type presentation. Modal recipes are selectors and projections over existing facts; they are not duplicate row stores.
Helper actors that represent grouping constructs may use distinct actor types
instead of overloading a generic segment type. Each such type must declare
its own identity, merge identity, presentation, modal sections, legend entry,
and aggregation behavior. Consumers must use the declared type metadata and
must not infer semantics only from a type id containing words such as
segment, subnet, or network.
Cloud aggregation may only canonicalize endpoint order when link type policy explicitly allows unordered aggregation. Direction-significant links must preserve direction.
Relationship evidence is not actor custom data.
Evidence tables carry matchable relationship facts such as socket tuples, streaming hops, LLDP/CDP observations, or vSphere inventory edges. Actor-detail tables carry actor-owned data such as streaming path inventory or local status tables. Table metadata must state role and aggregation policy.
Production payloads must not duplicate the same evidence under every actor only to populate drilldown modals. The UI and aggregator derive drilldown views from shared evidence and typed table references.
Actor labels use a compact actor-owned table, normally
tables.actor.actor_labels, with rows shaped as:
actor, key, value, source?, kind?, value_index?
key, value, source, and kind are logical strings and may be encoded as
string or string_ref. Producers should prefer string_ref when they already
maintain a local dictionary; aggregators and UI adapters must normalize both
encodings as equivalent label strings.
Host/node actors should expose the complete host label set when available.
Non-node actors should expose useful producer-known labels and metadata, such
as process command line, user, group, namespace, interface role, or
virtualization object properties. Repeated values are repeated rows ordered by
value_index, not JSON arrays. Facts needed for identity, correlation,
grouping, sorting, filtering, or aggregation must remain typed canonical
columns too.
actor_labels inherits the topology Function sensitive-data classification.
Consumers must preserve the same access-control assumptions as the source
Function because labels may include command lines, users, host labels, system
contact/location fields, or other operator-controlled metadata.
Actor modal identification is producer-selected through
presentation.modal.labels.identification.fields[]. Each field references an
existing actor_labels.key, provides the label to render near the actor title,
and may limit the number of displayed values with max_values. The full Labels
tab remains complete; identification is a curated header projection, not a
second table.
Presentation belongs in the production netdata.topology.v1 payload, not in
Function info, except for old-schema compatibility during rollout.
Function info responses are metadata responses. They may omit data and
advertise only parameters, help text, and timing. The topology JSON schema
applies to full topology responses, not metadata-only info responses.
Type definitions carry type-local presentation:
types.actor_types.<id>.presentationtypes.link_types.<id>.presentationtypes.port_types.<id>.presentationGraph-level data.presentation carries legend order, actor-click highlight
behavior, port tooltip field labels, and scale-key definitions.
Actor and link type presentation may also carry modal composition:
presentation.modal.labels describes the actor label table, usually
actor_labels;presentation.modal.mini_topology describes a depth-1 modal graph preview
built from incident links and opposite actors;presentation.modal.sections[] describes table sections over existing
actors, links, evidence, actor detail tables, or relationship tables.Table types may carry presentation defaults for table label, order, default
visibility, and column display metadata. Table type presentation does not
replace actor/link modal sections; it gives reusable defaults for existing
table rows.
Modal sections require non-empty id, non-empty label, a source, and at
least one column. empty_label is section-only empty-state text. Modal columns
require non-empty id, non-empty label, and a projection. badge_map,
align, and sortable are presentation hints over projected values and must
not introduce new facts.
label_lookup uses label_key and optionally an actor_column; omitted
actor_column means the selected modal actor. json_path always requires both
the JSON column and the scalar path to extract.
Presentation uses closed UI-owned tokens. Producers must not emit raw SVG, raw CSS, coordinates, component names, raw force-layout physics, or viewport state.
Closed token values are part of the schema contract:
primary, secondary, accent, self, neutral, muted,
dim, derived, info, structural, warning, success, danger,
blue, green, orange, purple, cyan, yellow, teal, gray;normal, muted, faded;thin, normal, thick, emphasis;weakest, weaker, normal, stronger,
strongest;closest, closer, normal, farther,
farthest;weakest, weaker, normal, stronger,
strongest;compact, normal, emphasized;normal, discovery, ownership, traffic,
correlation, control;router, switch, firewall, access_point, server, storage,
load_balancer, printer, phone, ups, camera, process, agent,
netdata-agent, parent, remote-endpoint, local-endpoint, segment,
self, ip, cloud, container, docker, kubernetes, lxc,
nspawn, podman, systemd, user, vm, database, service,
datacenter, cluster, host, network, datastore,
datastore_cluster, resource_pool, device, endpoint, correlation,
interface, group, unknown.The UI owns token rendering and must treat producer labels as plain text. If a new producer emits a schema-valid token that an older UI does not know, the UI must use a safe fallback and record diagnostics.
Actor label_policy is the only approved way to choose display labels from
actor rows. Canonical identity is not display text. The UI must reject array
values by default so aggregated identities do not become long actor names.
Label-policy columns must be safe scalar actor-table columns. Producers must
not reference secrets, tokens, customer-identifying fields, or unbounded arrays
from label_policy.columns.
Actor search is the only approved way to choose graph search content for v1.
search.columns[] references scalar actor-table columns. search.label_keys[]
references values in the actor label table, normally actor_labels.key. Set
search.enabled: false for helper actors that should not be searchable. The UI
must not traverse producer-specific details, match, attributes, or label
paths when rendering v1.
Link types may define one variable visual channel using variable.channel,
variable.scale_key, and variable.value_column. Producers emit raw domain
values, such as socket counts or traffic bytes. Cloud or the UI scales values
per scale_key across the visible graph. variable.min and variable.max
are visual tokens for the chosen channel: width variables use width tokens,
opacity variables use opacity tokens.
Link types may also define tokenized force-layout hints using
presentation.layout.strength and presentation.layout.distance. These are
relative UI-owned tokens, not numeric physics. Current producer tuning keeps
strength at normal and varies only distance where the topology needs
semantic separation. Do not reintroduce non-normal strength tokens for graph
polish unless a later product decision explicitly re-enables force-strength
tuning.
Actor types may define tokenized force-layout hints using
presentation.layout.repulsion. Repulsion is separate from link strength:
repulsion pushes actors apart, while link strength pulls endpoints together.
Producers must not emit raw charge values. Actor size may define a type-level
size.scale token for deliberate fixed emphasis, such as current/self actors;
the UI must not infer this from actor type names or labels.
link_types.<id>.semantic_role is behavior metadata, not visual styling. It
drives UI behavior such as discovery-link filtering, ownership/coherence
treatment, traffic emphasis, and correlation treatment without hardcoded
protocol or type-name checks. Link appearance still comes from
presentation.
When link presentation.arrow is auto or omitted, the UI derives arrows from
orientation and direction_role:
undirected -> no arrow;observed_bidirectional -> no arrow;direction_role: none -> no arrow;direction_role: observation -> no arrow;directed with flow or dependency -> forward from src_actor to
dst_actor;hierarchical with ownership -> forward from src_actor to dst_actor;observed_bidirectional means observation completeness, not "draw both
arrows". Producers that need reverse or both arrows must set
presentation.arrow explicitly.
direction_role is required by the v1 schema. Missing direction_role is
schema-invalid and must not produce an inferred arrow from orientation alone.
The UI should render auto as no arrow and emit the normal missing-field
diagnostic for that invalid input.
For schema-valid values, the auto semantic diagnostic boundary is:
directed+flow, directed+dependency,
hierarchical+ownership, undirected+none, undirected+observation,
observed_bidirectional+none, or observed_bidirectional+observation;directed+none, directed+observation,
directed+ownership, hierarchical+none, hierarchical+flow,
hierarchical+dependency, hierarchical+observation, undirected+flow,
undirected+dependency, undirected+ownership,
observed_bidirectional+flow, observed_bidirectional+dependency, or
observed_bidirectional+ownership.Initial UI-owned mappings are:
size.scale: compact=0.85, normal=1.0, emphasized=1.18;layout.repulsion: weakest=-200, weaker=-300, normal=-450,
stronger=-700, strongest=-1000.These numeric values are not schema and may be tuned after visual QA.
size.scale composes with size.mode; it does not override data-driven
sizing. Missing optional fields use neutral defaults (scale: normal,
repulsion: normal) and must not trigger v1 UI fallback heuristics.
Actor port bullets require explicit ports.sources[] when
show_bullets: true. The source may be links, evidence, or an
actor_table. Source column names are table-local and must remain unchanged
during Cloud aggregation. Type ids inside row values and default_type values
are rewritten only when they refer to type registries. ports.sources[].evidence
is an evidence type id. name_column must reference a scalar display column,
not a raw actor/link/evidence reference, array, or JSON cell.
ports.sources[].value_column is optional and must reference a numeric source
column. When present, the UI sums values for matching bullet keys and uses the
sum for bullet multiplicity, overflow, and sizing. Aggregated producers should
use this instead of sending repeated rows only to drive presentation.
Modal/table composition uses closed source, projection, cell, and visibility
tokens. Supported source kinds are actors, links, evidence,
actor_table, and relationship_table. Supported projections include direct
column values, actor-ref labels, opposite actor labels, formatted endpoints,
selected-side endpoints, label-table lookups, coalesced columns, constants,
and explicitly declared scalar JSON paths. Supported cell types include text,
number, badge, actor link, timestamp, duration, endpoint, array count, and
debug JSON. Raw JSON belongs behind debug visibility or an explicit scalar
projection; it must not be the default polished actor modal rendering.
Selected-side endpoint projections must be self-contained: the projection
names source and destination actor-ref columns, plus at least one source-side
endpoint column and one destination-side endpoint column.
selection.actor_click.mode: highlight_path requires path_table,
path_actor_column, and path_order_column. path_actor_column identifies
path members. When one table contains different paths for different clicked
actors, path_owner_column identifies the actor that owns each path row.
highlight_connections requires no path table.
Presentation conflict policy:
label_policy belongs to the actor type presentation and follows the same
namespace/deduplicate rule;profile_version is diagnostic. It may help choose a preferred display
profile later, but it is not a comparable semantic-version contract and must
not be used to drop facts or rows.Correlation is producer-visible graph semantics, not aggregator state. Producers must not encode correlation as hidden flags on real actors, and must not expose aggregator internal states such as absorbed, candidate, equivalence class, or rewrite plan. The final aggregated output is always a normal topology payload.
Correlation can resolve several shapes:
data.correlation.rules defines how independent payloads of the same topology
kind can be correlated. Each rule defines:
class: resolve_loose_side, replace_actor, or
merge_enrich_actor;action: absorb for exact matches that remove visible correlation actors
or consume loose-side placeholders and rewrite incident correlation
relationships, or link for partial/broader matches that keep the visible
correlation/materialized actor and add a weak correlation link;priority: lower numbers run first;key_space: namespace for exact string-key matching;key: a declarative template built from point/claim table columns and
literals;point_actor_types: actor types that are visible correlation points when the
input graph materializes points;claim_actor_types: actor types that may satisfy the point;correlation_link_types: link types that connect real actors to
correlation actors and may be consumed/replaced by the rule;output_link_type: link type emitted for rewritten absorb links or visible
partial correlation links.data.correlation.points is a compact table of visible correlation actors and keys.
data.correlation.claims is a compact table of real actors and keys they can
satisfy. Both tables require actor, rule, and the key columns referenced by
their rules.
The aggregator is intentionally agnostic. It builds normalized keys from declared columns and literals, applies rule priority, and handles ambiguity conservatively. It must not need new code to understand every future IP, port, MAC, chassis id, object id, label, or topology-domain key.
No match keeps the visible correlation actor or loose-side materialization visible. Ambiguous matches remain unresolved and produce diagnostics. NAT or other alias evidence can be modeled by adding extra point/claim rows for the same actor and rule; aliases add facts without mutating the original observation.
Correlation links must be semantic link types even for single-node payloads. The legend must include visible correlation actors and links when they are visible, so users can distinguish unresolved, partial, inferred, and resolved graph relationships.
Refreshable traffic, state, error, packet, or utilization data is represented by overlay templates and per-actor/per-link refs.
Templates define the query mechanism once. Refs provide only template ids, one
owner reference, and selector parameters. The refs table uses schema ids for
column names, so template ids, selector params, and refs column ids must match
the topology $defs/id contract: start with a letter and then use only letters,
digits, _, ., :, or -.
The refs-table convention is:
template: string or string_ref template name resolving to
data.types.overlay_templates;actor with type actor_ref or link
with type link_ref; every row must have a non-null owner value;Selector params must not use reserved refs-table convention column names:
template, actor, or link.
No other actor_ref or link_ref columns are valid in overlay refs. Consumers
can identify ownership from the fixed actor / link column ids instead of
scanning all columns by type.
The template column and all selector-param columns required by a row's
resolved template must be string or string_ref. Required selector-param row
values must resolve to non-empty strings. Selector-param columns used by other
templates may be nullable and null on rows whose template does not require them.
Future selectors that need ip_ref, mac_ref, or empty-string matching must
relax this contract explicitly.
For provider: "netdata.metrics", selector params are interpreted as:
node_id: node-scope selector, not a chart label;collect_job: chart label _collect_job;Aggregated actors or links merge overlay refs according to the template merge
policy. merge.refs controls ref-list handling, currently append or set.
merge.values controls how multiple matching metric values collapse, currently
sum, min, max, avg, last, or none.
Production payloads carry canonical topology facts, not compatibility reconstruction instructions. Projection code for parity with deployed compatibility consumers is test or rollout code only.
Agent/backend contracts and docs should point new work to
netdata.topology.v1. Temporary compatibility handling belongs in isolated
Cloud frontend adapters during rollout.
Topology producer changes must include:
FUNCTION_TOPOLOGY_SCHEMA.json;Cloud topology aggregation service readiness also requires service-level
fixtures for every topology kind covered by this contract. network-connections
is the high-cardinality benchmark, but the service is not considered ready if
the UI can use it for only some topology kinds while bypassing it for others.
topology:network-connections now emits netdata.topology.v1 directly from
the C network-viewer Function. Aggregated mode is the default and emits compact
actor, graph-link, and actor-owned socket_ports tables. Detailed mode adds a
shared socket relationship-evidence table for exact tuple matching and
drilldowns. Process actor size uses the actor row socket_count metric, while
process port bullets read the socket_ports.socket_count value column so an
aggregated port row can represent several sockets. The producer no longer emits
the superseded old-schema presentation object or duplicated actor-nested socket
modal tables. It now emits compact graph presentation metadata in type
definitions plus data.presentation, and repeated string columns use
dictionary encoding when it reduces raw payload size.
topology:network-connections enforces a producer-side fixed response budget of
64 MiB. When a requested live topology would exceed that budget, the Function
returns a normal Function error with HTTP status 413 instead of emitting a
partial topology. This keeps the producer below the plugins.d deferred-response
hard stop and preserves the contract that evidence is never silently truncated.
Network-connections distinguishes unresolved endpoint links from aggregator
correlation output. endpoint_socket connects a process to a visible unresolved
endpoint actor and must not use the farthest layout distance because that makes
single-node maps zoom out unnecessarily. correlated_socket is the output link
type after exact endpoint absorption by an aggregator and may use farthest
distance to keep independent topology clusters from blending.
Network-connections modal composition is producer-declared. Self/node actors use
a Processes section over ownership graph links filtered by link type.
Network-connections socket link types use direction_role: "dependency" and
are client-to-server: src_actor is the client/dependant and dst_actor is the
server/dependency target. Non-node actors therefore use two primary sections in
both aggregated and detailed mode:
Dependencies, filtered to rows where the selected actor is src_actor, and
Dependants, filtered to rows where the selected actor is dst_actor.
Aggregated mode reads these sections from tables.relationship.connections;
detailed mode reads them from evidence.socket. socket_ports is an actor
inventory for process port bullets only; it is not a standalone modal tab for
network-connections.
Network-connections supports three actor grouping levels: process_name,
pid, and container. group_by:pid emits one process actor per PID and may
emit raw variable fields as scalar actor columns: PID, UID, network namespace,
command line, cgroup status/path/name, and detailed container metadata.
group_by:process_name emits grouped process actors; fields that can vary
across grouped PIDs must be represented as merged/set-valued actor labels or
columns with declared set aggregation, not as arbitrary scalar replacements.
group_by:container emits actors grouped by canonical container_name;
runtime-specific actor types such as Docker containers, Kubernetes containers,
VMs, systemd services, user slices, and process fallbacks are producer-declared
actor types that share the container aggregation scope. Systemd services use
the service unit name. user.slice/user-UID.slice paths use a composed user
actor only when cgroups did not return a usable container name: the grouped
actor name is the process UID's resolved username, or user${UID} when username
resolution is unavailable, while leaf scopes stay in cgroup/detail evidence.
Rootless Docker and any other known cgroup with a container label or cgroup name
keep the cgroups-provided container identity instead of being absorbed into the
user actor. Known host/root processes fall back to process name, and unresolved
retry-later lookups remain explicit pending/unknown container identity instead
of being fabricated as final process-name containers. The three aggregation
scopes use evidence_policy: "preserve".
Network-connections topology keeps cgroup metric-monitoring rules separate from
topology display classification rules. apps.plugin exposes per-PID facts;
network-connections may compose user-activity actors from those facts for the
dependency map. Topology producers may derive
systemd_unit_name, systemd_unit_kind, actor_kind, specific actor types,
and display icons from cgroup path/orchestrator rule modules without widening
the netipc orchestrator enum for each display subtype.
Network-connections actor modals expose producer-declared actor-owned
processes and cgroups tables in addition to labels and relationship
sections. processes contains contributing PID/process/user/namespace/command
rows. cgroups contains contributing PID cgroup status/path/name,
container/service name, effective display orchestrator, actor kind, Kubernetes,
Docker/Podman, and systemd unit fields. These are topology schema tables, not
Cloud/UI hardcoded container views.
The Function info response advertises v: 3, and data requests consume the
selected grouping from the v3 POST payload shape
{"selections":{"group_by":["..."]}}; legacy function-string aliases such as
group_by:pid and processes:by_pid remain accepted for compatibility.
The orchestrator column renders netipc orchestrators as systemd, docker,
k8s, kvm, lxc, podman, or nspawn. It additionally renders
APPS_LOOKUP host-root cgroup status as host_root; this is a producer-local
topology value, not a netipc enum member.
Free-form cgroup labels are denied by default in Function output. Operators
opt in with labels:<pattern> using pipe-separated simple_pattern tokens.
The whitelist is applied at network-viewer Function emission only; upstream
cgroup caches and IPC payloads carry raw labels. Raw cgroup paths are scalar
actor columns only in group_by:pid; grouped views preserve them as
deduplicated actor-label values when available.
topology:snmp now emits netdata.topology.v1 from the Function handler
through an adapter over the existing SNMP topology engine output. The adapter
preserves actors, links, L2 observation evidence, bounded L3 adjacency
evidence, actor metadata, and actor custom detail tables. Remaining SNMP
refinement is to promote interface metric lookup fragments into first-class
overlay templates/refs.
SNMP l3_subnet links are logical L3 adjacency, not physical or L2 adjacency.
They use orientation: observed_bidirectional, direction_role: observation,
and semantic_role: normal. The producer emits them only between resolved
managed SNMP device actors; unresolved or ambiguous L3 endpoints remain
diagnostic/suppression state and must not create IP-only graph actors.
SNMP l3_subnet evidence must preserve the relationship facts needed for
drilldown and aggregation, including a link_ref, source/destination actors,
source/destination interface IPs, subnet, network, netmask, prefix, source, and
logical inference/attachment metadata. The evidence is an actor-modal source
for L3 adjacency drilldowns.
SNMP ospf_adjacency links are logical OSPF control-plane adjacency, not
physical, L2, discovery, or port-neighbor evidence. They use
orientation: observed_bidirectional, direction_role: observation, and
semantic_role: control. Their graph presentation should use a dashed line
style and purple color slot so operators do not read them as physical cabling
or generic success/health state. The producer emits
graph links only for full OSPF neighbors between resolved managed SNMP device
actors. Non-full or unresolved OSPF neighbor rows remain diagnostic actor-owned
detail rows and must not create loose router/IP graph actors.
Current SNMP OSPF topology scope is OSPFv2 non-virtual neighbors from
ospfNbrTable; OSPFv3 and OSPF virtual-neighbor tables are future scope unless
a later topology feature explicitly adds their distinct semantics.
When ospf_adjacency and l3_subnet describe the same resolved actor pair and
endpoint/subnet relationship, OSPF is the stronger protocol-specific signal for
the graph. The producer may suppress the matching l3_subnet graph link while
preserving typed OSPF evidence and actor-owned neighbor detail rows.
SNMP modal composition must be port-centric for managed device actors. A managed
device modal uses actor-label identification for important device facts, a
primary Ports section over actor_ports, and a Port Neighbors section over
actor_port_links. It may also expose an L3 Adjacencies section sourced from
l3_subnet relationship evidence. Generic graph-link Links sections are
reserved for endpoint, segment, or custom actors that do not own port inventory.
SNMP actor_ports exposes real port identity and status as typed columns:
SNMP if_index as the visible numeric port ID when known, source port_id,
display name, if_name, if_descr, if_alias, MAC, speed, status, mode,
role, VLAN, FDB, link, and neighbor counts. It must never fabricate numeric
port IDs; row order and generated sequences must not be used. if_index must
come from the device/SNMP facts and must align with actor_port_links.if_index.
SNMP actor_ports may also carry compact expanded-row neighbor columns such as
nullable neighbor_actor and neighbor_port_name, derived from graph-link
endpoint facts. These columns make the port row clickable without duplicating
raw LLDP/CDP/FDB/ARP/STP evidence.
SNMP actor_port_links is a compact actor-owned modal index over existing graph
links and evidence. It has one row per incident actor side and carries the local
if_index/port name, remote actor, remote port facts, protocol, link type,
state, evidence count, confidence, inference, attachment mode, and timestamps.
It exists so device modals can align neighbor rows with the same port identity
shown in actor_ports; it is not a second copy of raw evidence.
SNMP actor_port_links must remain port-neighbor oriented. It must not include
l3_subnet or ospf_adjacency links, because shared-subnet and
routing-protocol L3 adjacency do not prove a physical or L2 port neighbor.
SNMP protocol-neighbor detail sections, such as OSPF neighbors, should be actor-owned detail tables. They may include unresolved or non-full neighbor observations for diagnostics even when no graph link is emitted.
SNMP polished UI must not depend on raw actor_metadata and endpoint JSON.
Important scalar/count summary values live in typed actor or actor-detail
columns and are also available through actor_labels. Nested neighbors, VLANs,
unknown custom port attributes, and endpoint objects stay in expanded or debug
sections unless a structured child table is defined. Link endpoint port labels
must come only from real port fields such as port_name, if_name,
if_descr, or source port_id; actor labels such as display_name or
sys_name must not be used as port-name fallbacks.
topology:streaming now emits netdata.topology.v1 directly from the C
Function. It models streaming agents as compact actor rows, streaming/virtual/
stale relationships as directed graph links with matching evidence types, and
keeps stream_path, retention, inbound, and outbound modal data as typed
actor-detail or relationship-summary tables. Streaming also emits graph
presentation metadata for highlight-path behavior, legend, link styles, and
port bullets. Streaming hops remain signed so stale path values are not
corrupted.
Streaming parent actor size is data-driven by the actor row
retained_node_count metric, not by graph degree or direct child count. This
count represents nodes for which the parent has retained DB data, including
self, virtual nodes, stale nodes, and transit descendants when they have
retention state. The parent actor type must declare presentation.size: {"mode":"metric","metric_column":"retained_node_count"}. Parent port bullets
represent child or vnode streams attached to the parent side of streaming graph
links, so the parent ports.sources[] entry over links must use
actor_column: "dst_actor" with a scalar child/node display column such as
port_name.
Streaming modal composition emits actor_labels, complete host labels where
available, host/system metadata labels needed by old summaries, and typed
OS/architecture/CPU columns. The actor modal header must select important
identity/status labels from actor_labels, including hostname, node type,
stream status, ingest status, health status, retained-node count where
applicable, direct-child count where applicable, OS/platform labels, and Agent
version. Existing stream_path, retention, and inbound tables have the
right actor-ref shape for recipe-based table rendering. The outbound table
must use the parent-owned shape described below; a table that only records the
selected actor's own upstream destination is insufficient for parent operator
workflows.
Streaming actor modal identification is role-specific. Host-like actors
(parent, child, and stale) should expose operational status plus
OS/hardware/platform labels such as OS, OS version, kernel, architecture, CPU
model, cores, RAM, virtualization, container, cloud provider/type/region, and
Agent version. Parents additionally expose retained_node_count and
child_count so the visual size and direct attachments are both explainable.
Vnode actors should expose inventory/device labels such as vnode type, vendor,
model, address, location, sys object id, LLDP system name, and status. Long
stable identifiers such as machine_guid and node_id remain in the full
Labels tab by default unless a future product decision explicitly promotes them.
Streaming actor modals must keep those tables as the single source of truth and must not duplicate rows only for modal display. The default visible sections are:
Stream path: rows from stream_path filtered by actor, ordered by
path_index. The table shows the selected actor's own path only; virtual
nodes and children have their own actors and therefore their own path rows.
since and first_time must be populated from the best canonical source
available for every path row. Synthetic path rows added only for rendering or
highlighting must still carry timestamps when the producer can derive them
from the adjacent path edge, the selected actor's ingest status, or database
first-time status. They may be null only when the Agent genuinely does not
know the value.Retained nodes: rows from the same retention table filtered by
observer_actor; this view answers which nodes' data the selected actor
maintains. The table must include self, virtual nodes, direct children,
transit descendants, and stale/archived hosts when those hosts are present in
the Agent root index and have retention state. It must show retained node,
node type, retention status, from/to timestamps, duration, metrics, instances,
and contexts. db_from and db_to may be null only when the database status
genuinely has no time range.Received nodes: rows from inbound filtered by parent_actor; this view
represents children, virtual nodes, stale nodes, and descendants received or
transiting through the selected parent. source_actor is the immediate actor
from which the selected parent receives the row. For direct local receipt,
source_actor should be the child/vnode actor itself; it should be null only
when the immediate source is genuinely unknown.Outbound streams: rows from outbound filtered by the sending parent
actor, not by the streamed node actor. This view answers which node payloads
the selected parent currently streams, and where it streams each one. Each row
must include the streamed node actor, destination actor when known, status,
age, hops, TLS, compression, and useful stream/replication/count metrics when
available. In clustered-parent setups, the selected parent must list self,
virtual nodes, direct children, and transit descendants that are sent to each
upstream destination.The old Retention for node default section is not part of the current
streaming modal contract. The canonical retention table still keeps both
actor and observer_actor so Cloud aggregation can preserve multiple
retaining parents for the same node. If a future modal needs a selected-node
"who retains me" view, it must be explicitly named Retained by and must not
replace the parent-owned Retained nodes view.