Skip to content

Viewing and Filtering DAGs

sat edited this page Jul 15, 2026 · 1 revision

Viewing and Filtering DAGs

After running logdag make-dag, each produced DAG is stored as a file under the output directory. The logdag CLI provides a set of show-* and plot-* subcommands for inspecting those results. All of them accept the same -c <config> flag and most accept a <argname> positional argument that identifies a specific time-window/area combination.

See also: CLI Commands · Overview and Pipeline


The LogDAG container (showdag.py)

The in-memory representation of a result is logdag.showdag.LogDAG. It wraps:

  • args — a (conf, dt_range, area) triple that identifies the result.
  • graph — a networkx.DiGraph where nodes are integer event IDs and edges represent estimated causal dependencies.
  • _evmap — an EventDefinitionMap that maps each node integer to its EventDefinition (host, source type, template ID or SNMP key, group tag).

Key methods:

Method Description
load() Deserialise the graph from disk (pickle or JSON, per [dag] output_dag_format).
dump() Serialise back to disk.
nodes() / edges() Iterate over graph elements. edges() deduplicates bidirectional edges by default.
node_str(node) Human-readable label: <id>@<host>:<gid>[:<group>].
edge_str(edge) A -> B for directed edges, A <-> B for bidirectional.
node_evdef(node) Returns the EventDefinition for a node.
edge_evdef(edge) Returns the two EventDefinition objects for an edge.
node_ts(nodes) Loads the binned time-series DataFrame for the given node IDs.
connected_subgraphs() Returns connected components (as sets of node IDs).
relabel(graph) Returns a copy with node IDs replaced by string labels.
edge_isdirected(edge) True if the reverse edge is absent.

LogDAG is also used programmatically in the logdag.visual and logdag.eval packages.


show-* commands

All show-* commands print results to stdout. Pass -c <config> plus the argname to select the DAG you want.

show-edge

Show detailed information about one or more edges that match given conditions.

logdag show-edge -c logdag.conf <argname> <condition> [<condition> ...]

Conditions are key=value strings (e.g. host=web01, gid=42). Add --detail / -d to print the raw log lines (or numeric values) that support each endpoint.

show-edge-list

Print every edge in a DAG, one per line.

logdag show-edge-list -c logdag.conf <argname>

Add --detail / -d for per-edge supporting data. Accepts --filter / -f (see Filtering below).

show-subgraphs

Print edges grouped by connected component. Useful for identifying clusters of correlated events.

logdag show-subgraphs -c logdag.conf <argname>

Accepts --filter / -f.

show-list

Summarise all DAG results for a config (node count and edge count per window).

logdag show-list -c logdag.conf

show-node-list

List every node in a DAG with its human-readable label.

logdag show-node-list -c logdag.conf <argname>

show-stats

Print aggregate statistics across all DAG results:

  • total nodes, total edges
  • directed edge count, undirected edge count
logdag show-stats -c logdag.conf

Add --xhost to also report edge counts broken down by same-host vs. cross-host edges.

show-stats-by-threshold

Print edge counts at multiple ATE (average treatment effect) thresholds. Useful for LiNGAM results where edges carry a weight.

logdag show-stats-by-threshold -c logdag.conf

show-node-ts

Print the binned time-series of one or more nodes in CSV format.

logdag show-node-ts -c logdag.conf <argname> <node_id> [<node_id> ...]

plot-* commands

Plot commands require pygraphviz for plot-dag and matplotlib for plot-node-ts.

plot-dag

Render a DAG to an image file using Graphviz (layout: circo).

logdag plot-dag -c logdag.conf <argname> -o output.png

Accepts --filter / -f. Without an output path the filename is printed to stdout.

plot-node-ts

Plot the time-series of selected nodes.

logdag plot-node-ts -c logdag.conf <argname> <node_id> [<node_id> ...] -o ts.png

Filtering DAG views

Many subcommands accept one or more -f / --filter flags. Filters are applied sequentially to the graph before display or plotting.

logdag show-edge-list -c logdag.conf <argname> -f directed -f no_isolated

Available filter names (from showdag_filter.FUNCTIONS):

Filter Effect
no_isolated Remove nodes that have no edges (applied last, regardless of position).
to_undirected Convert the graph to an undirected graph (applied first).
directed Keep only directed edges (edges with no reverse counterpart).
undirected Keep only undirected (bidirectional) edges.
across_host Keep only edges where the two endpoints belong to different hosts.
within_host Keep only edges where both endpoints share the same host.
subgraph_with_log Keep only connected components that contain at least one log-source edge.
subgraph_with_snmp Keep only connected components that contain at least one SNMP-source edge.
ate_prune Remove edges whose absolute ATE weight is below --threshold. Effective for LiNGAM results; ignored (returns an empty graph) when edges carry no weight.

Additionally, any filter of the form key=value is treated as an edge search: only edges where key matches value in either endpoint's EventDefinition are kept.

Order of application

apply_filter in showdag.py enforces two ordering rules regardless of the order in which -f flags appear:

  1. to_undirected is always applied first.
  2. no_isolated is always applied last.

All other filters are applied in the order they are specified on the command line.

--threshold / -t

Passed to ate_prune as the cutoff value. Has no effect for filters that do not use a threshold.


Programmatic use

You can load and inspect a LogDAG directly in Python:

from logdag import arguments, showdag

conf = arguments.open_logdag_config("logdag.conf")
args = arguments.name2args("area_20230101", conf)   # argname -> (conf, dt_range, area)

ldag = showdag.LogDAG(args)
ldag.load()

# Print all edges
for edge in ldag.edges():
    print(ldag.edge_str(edge))

# Apply a filter
g = showdag.apply_filter(ldag, ["directed", "no_isolated"])
for edge in ldag.edges(graph=g):
    print(ldag.edge_str(edge, graph=g))

arguments.open_logdag_config and arguments.name2args require a running Python environment with amulog and logdag installed (logenv venv).


Iterating over all results

showdag.iter_results(conf, area=None) is a convenience generator that loads every stored LogDAG for a config, optionally filtered by area:

from logdag import arguments, showdag

conf = arguments.open_logdag_config("logdag.conf")
for ldag in showdag.iter_results(conf, area="all"):
    print(ldag.name, "nodes:", ldag.number_of_nodes())

Clone this wiki locally