Back to Netdata

Verify network-connections layout tokens

.agents/skills/project-create-topology/how-tos/verify-network-connections-layout-tokens.md

2.11.06.3 KB
Original Source

Verify network-connections layout tokens

Question

How can a developer verify that a local Cloud-connected Netdata Agent serves topology:network-connections with the expected v1 link layout tokens and correlation rule wiring, without exposing Cloud tokens, agent bearers, node ids, machine GUIDs, claim ids, cookies, or raw endpoint rows?

This is a producer-contract validation recipe. It belongs to the developer topology skill, not to the public/operator query skills.

Inputs

  • Local Agent URL, usually http://127.0.0.1:19999; set AGENT_URL when using a non-default address.
  • NETDATA_CLOUD_TOKEN and NETDATA_CLOUD_HOSTNAME in <repo>/.env.
  • A local Agent that exposes topology:network-connections.

Steps

  1. Capture the local identity tuple in memory and print only presence checks:

    bash
    AGENT_URL="${AGENT_URL:-http://127.0.0.1:19999}"
    AGENT_URL="${AGENT_URL%/}"
    AGENT_HOST="${AGENT_URL#http://}"
    AGENT_HOST="${AGENT_HOST#https://}"
    AGENT_HOST="${AGENT_HOST%%/*}"
    AGENT_SCHEME="http"
    case "$AGENT_URL" in
      https://*) AGENT_SCHEME="https" ;;
    esac
    AGENT_ORIGIN="${AGENT_SCHEME}://${AGENT_HOST}"
    
    INFO_JSON="$(curl --fail -sS --max-time 10 "${AGENT_ORIGIN}/api/v3/info")"
    
    jq '{
      agent_count: (.agents | length),
      node_id_present: ((.agents[0].nd // "") | length > 0),
      machine_guid_present: ((.agents[0].mg // "") | length > 0),
      claim_id_present: ((.agents[0].cloud.claim_id // "") | length > 0),
      cloud_status: .agents[0].cloud.status
    }' <<<"$INFO_JSON"
    
  2. Load the token-safe direct-agent wrappers:

    bash
    source docs/netdata-ai/skills/query-netdata-agents/scripts/_lib.sh
    agents_load_env
    
  3. Query the topology Function through the direct-agent path. Store the raw response only under .local/:

    bash
    NODE_UUID="$(jq -r '.agents[0].nd' <<<"$INFO_JSON")"
    MACHINE_GUID="$(jq -r '.agents[0].mg' <<<"$INFO_JSON")"
    FUNCTION_NAME="topology:network-connections"
    FUNCTION_ENCODED="$(printf '%s' "$FUNCTION_NAME" | jq -sRr @uri)"
    REQUEST_BODY='{"selections":{"group_by":["process_name"],"__topology_mode":["aggregated"],"sockets":["inbound","outbound","listening"],"protocols":["ipv4_tcp","ipv6_tcp","ipv4_udp","ipv6_udp"],"endpoints":["by_ip"]}}'
    OUT="$(agents_audit_dir)/network-connections-aggregated-live.json"
    
    agents_query_agent \
      --node "$NODE_UUID" \
      --host "$AGENT_HOST" \
      --machine-guid "$MACHINE_GUID" \
      POST "/api/v3/function?function=${FUNCTION_ENCODED}&timeout=120000&last=200" \
      "$REQUEST_BODY" \
      > "$OUT"
    
  4. Print a sanitized response summary:

    bash
    jq '{
      status,
      type,
      schema_version: .data.schema_version,
      actor_rows: .data.actors.rows,
      link_rows: .data.links.rows,
      correlation_point_rows: .data.correlation.points.rows,
      correlation_claim_rows: .data.correlation.claims.rows
    }' "$OUT"
    
  5. Verify the producer's link layout tokens:

    bash
    jq '.data.types.link_types
      | with_entries({
          key: .key,
          value: {
            label: .value.presentation.label,
            color_slot: .value.presentation.color_slot,
            line_style: .value.presentation.line_style,
            width: .value.presentation.width,
            variable: .value.presentation.variable,
            layout: .value.presentation.layout
          }
        })' "$OUT"
    
  6. Verify correlation rule wiring without printing endpoint rows:

    bash
    jq '.data.correlation.rules
      | with_entries({
          key: .key,
          value: {
            action: .value.action,
            priority: .value.priority,
            key_space: .value.key_space,
            point_actor_types: .value.point_actor_types,
            claim_actor_types: .value.claim_actor_types,
            correlation_link_types: .value.correlation_link_types,
            output_link_type: .value.output_link_type
          }
        })' "$OUT"
    
  7. Count graph links by type from the compact table:

    bash
    jq -r '
    .data as $d
    | def col($table; $name):
        ($table.columns | map(.id) | index($name)) as $i
        | $table.values[$i];
      def v($c; $i):
        if $c.codec == "const" then $c.value
        elif $c.codec == "values" then $c.values[$i]
        elif $c.codec == "dict" then $c.values[$c.indexes[$i]]
        else null end;
      (col($d.links; "type")) as $typeCol
    | (col($d.links; "socket_count")) as $socketCol
    | [range(0; $d.links.rows)
       | {type: v($typeCol; .), socket_count: (v($socketCol; .) // 0)}]
    | group_by(.type)
    | map({type: .[0].type, links: length, sockets: (map(.socket_count) | add)})
    | sort_by(.type)
    | .[]
    | [.type, .links, .sockets]
    | @tsv
    ' "$OUT"
    

Output

For the current network-connections v1 contract, expect these link types:

  • endpoint_socket: visible unresolved endpoint links, weakest strength, normal distance.
  • correlated_socket: Cloud aggregator output after exact absorption, weakest strength, farthest distance.
  • socket: local/resolved process links, stronger strength, farther distance, variable width by socket_count.
  • ownership: graph-coherence node-to-process links, dotted/faded, normal strength, normal distance.

The socket_exact correlation rule should consume endpoint_socket through correlation_link_types and emit correlated_socket through output_link_type.

Notes / gotchas

  • The wrapper logs masked curl commands on stderr. Cloud tokens, per-agent bearers, node ids, machine GUIDs, and claim ids must not appear in stdout or committed files.
  • Keep the raw Function response under .local/; it may contain hostnames, private addresses, and process names.
  • A rendered graph can still look stretched even when the payload uses endpoint_socket with normal distance. That is a frontend force-layout issue, not proof that the backend emitted farthest.
  • Compact topology tables require decoding the column codec before counting rows by type. Do not assume the high-cardinality rows are emitted as arrays of objects.

Source guides