Logpresso Graph

Download 110
Last updated Sep 29, 2026

App Extension

App Extension

Other Logpresso apps can register their own node/relationship types, automatic loading builders, and threat intel tabs into the graph. Place a sonar_graph.json manifest at the app bundle root (src/main/resources in a Maven project) and it is registered automatically when the app starts and unregistered when it stops. No API calls are needed.

Note
This page is a summary for app developers. For the full field-by-field specification,
see docs/app-registration.md in the sonar-graph repository.

Manifest Structure

{
  "manifest_version": "1.0.0",
  "node_defs":  { "<type>": { ... } },
  "edge_defs":  { "<relationship>": { ... } },
  "builders":   [ { ... } ],
  "ip_intels":  { "<key>": { ... } }
}

All four sections are optional. An app that only provides threat intel tabs needs just ip_intels.

node_defs — Node Types

Besides names/descriptions (en·ko·ja) and attrs (attribute definitions with types, enums, and ranges), a node type can declare its value format:

  • value_examples — per-locale value examples, shown as the input placeholder in the Knowledge Graph's Add Node screen.
  • value_pattern — a regular expression the value must match, validated both in the UI and by the batch commands.
"myapp-scanner": {
  "type": "myapp-scanner",
  "names": { "en": "Scanner", "ko": "스캐너" },
  "descriptions": { "en": "Scanner appliance keyed by serial", "ko": "시리얼로 식별되는 스캐너 장비" },
  "value_examples": { "en": "SN-2024-0001" },
  "value_pattern": "^SN-\\d{4}-\\d{4}$",
  "attrs": {}
}

edge_defs — Relationship Types

Declare the allowed source/target type combinations with pairs. They drive the "Connectable node types" guidance in the Knowledge Graph connection screen and are also enforced on writes. A relationship without pairs is generic and accepts any combination.

"scanned-by": {
  "type": "scanned-by",
  "names": { "en": "Scanned By", "ko": "스캔 수행" },
  "descriptions": { "en": "ipv4-addr scanned by myapp-scanner", "ko": "IP가 스캐너에 의해 점검됨" },
  "attrs": {},
  "pairs": [ { "src": "ipv4-addr", "dst": "myapp-scanner" } ]
}

builders — Automatic Loading

A declarative batch that runs a query on a cron schedule to populate the graph. The schedule is registered when the app starts and disabled when it stops.

"builders": [
  {
    "cron_schedule": "0 5/30 * * * ?",
    "names": { "en": "Sync scanners", "ko": "스캐너 동기화" },
    "descriptions": { "en": "Sync scanner inventory", "ko": "스캐너 인벤토리 동기화" },
    "query": "myapp-scanners | eval type=\"myapp-scanner\", value=serial | sonar-set-node-batch run=t"
  }
]

ip_intels — Threat Intel Tabs

Adds tabs to IP cards in the Threat Intel screen. The target IP is injected into the $(&quot;ip&quot;) placeholder of query. A single type renders as a property sheet, a multiple type as a table. The app's icon appears next to the tab name automatically.

"ip_intels": {
  "myapp-ports": {
    "type": "multiple",
    "names": { "en": "Open Ports", "ko": "열린 포트" },
    "descriptions": { "en": "Ports detected for the IP", "ko": "탐지된 열린 포트" },
    "query": "myapp-open-ports ip=$(\"ip\")",
    "fields": [
      { "key": "port", "names": { "en": "Port", "ko": "포트" } },
      { "key": "service", "names": { "en": "Service", "ko": "서비스" } }
    ]
  }
}

Cautions

  • Type names have no namespace. Registering the same type name lets the later-loaded app overwrite it, so prefix app-specific types (e.g. myapp-).
  • Malformed JSON is ignored silently. If registration seems to do nothing, use the checks below.
  • Builders run only when the app is installed in Sonar.

Verifying Registration

sonar-graph-node-defs locale=ko
sonar-graph-edge-defs locale=ko

Check that your types appear in the results. Verify builders with sonar-graph-builders, and threat intel tabs by opening an IP card in the Threat Intel screen.