-
Notifications
You must be signed in to change notification settings - Fork 3
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 in-memory representation of a result is logdag.showdag.LogDAG. It wraps:
-
args— a(conf, dt_range, area)triple that identifies the result. -
graph— anetworkx.DiGraphwhere nodes are integer event IDs and edges represent estimated causal dependencies. -
_evmap— anEventDefinitionMapthat maps each node integer to itsEventDefinition(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.
All show-* commands print results to stdout. Pass -c <config> plus the
argname to select the DAG you want.
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.
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).
Print edges grouped by connected component. Useful for identifying clusters of correlated events.
logdag show-subgraphs -c logdag.conf <argname>
Accepts --filter / -f.
Summarise all DAG results for a config (node count and edge count per window).
logdag show-list -c logdag.conf
List every node in a DAG with its human-readable label.
logdag show-node-list -c logdag.conf <argname>
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.
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
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 require pygraphviz for plot-dag and matplotlib for
plot-node-ts.
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 the time-series of selected nodes.
logdag plot-node-ts -c logdag.conf <argname> <node_id> [<node_id> ...] -o ts.png
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.
apply_filter in showdag.py enforces two ordering rules regardless of the
order in which -f flags appear:
-
to_undirectedis always applied first. -
no_isolatedis always applied last.
All other filters are applied in the order they are specified on the command line.
Passed to ate_prune as the cutoff value. Has no effect for filters that do
not use a threshold.
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).
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())