logdag 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. logdag/__init__.py +2 -0
  2. logdag/__main__.py +610 -0
  3. logdag/arguments.py +338 -0
  4. logdag/cdt_input.py +64 -0
  5. logdag/data/area_def.txt.sample +49 -0
  6. logdag/data/config.conf.default +278 -0
  7. logdag/data/config.conf.old +181 -0
  8. logdag/data/list_rt_if +3 -0
  9. logdag/data/list_rt_info +2 -0
  10. logdag/dtutil.py +393 -0
  11. logdag/eval/__init__.py +0 -0
  12. logdag/eval/__main__.py +512 -0
  13. logdag/eval/match_edge.py +94 -0
  14. logdag/eval/trouble.py +169 -0
  15. logdag/lingam_input.py +107 -0
  16. logdag/log2event.py +624 -0
  17. logdag/makedag.py +143 -0
  18. logdag/mixedlingam_input.py +72 -0
  19. logdag/pc_input.py +183 -0
  20. logdag/pknowledge.py +370 -0
  21. logdag/showdag.py +766 -0
  22. logdag/showdag_filter.py +127 -0
  23. logdag/source/__init__.py +0 -0
  24. logdag/source/__main__.py +217 -0
  25. logdag/source/convert.py +69 -0
  26. logdag/source/evgen_common.py +75 -0
  27. logdag/source/evgen_log.py +272 -0
  28. logdag/source/evgen_snmp.py +665 -0
  29. logdag/source/evpost.py +105 -0
  30. logdag/source/filter_log.py +259 -0
  31. logdag/source/influx.py +224 -0
  32. logdag/source/influx3.py +486 -0
  33. logdag/source/period.py +136 -0
  34. logdag/source/sqlts.py +302 -0
  35. logdag/source/src_amulog.py +134 -0
  36. logdag/source/src_rrd.py +96 -0
  37. logdag/visual/__init__.py +0 -0
  38. logdag/visual/__main__.py +581 -0
  39. logdag/visual/comparison.py +205 -0
  40. logdag/visual/draw.py +22 -0
  41. logdag/visual/edge_search.py +766 -0
  42. logdag-0.2.0.dist-info/METADATA +112 -0
  43. logdag-0.2.0.dist-info/RECORD +47 -0
  44. logdag-0.2.0.dist-info/WHEEL +5 -0
  45. logdag-0.2.0.dist-info/entry_points.txt +5 -0
  46. logdag-0.2.0.dist-info/licenses/LICENSE +11 -0
  47. logdag-0.2.0.dist-info/top_level.txt +1 -0
logdag/__init__.py ADDED
@@ -0,0 +1,2 @@
1
+
2
+ __version__ = '0.2.0'
logdag/__main__.py ADDED
@@ -0,0 +1,610 @@
1
+ #!/usr/bin/env python
2
+ # coding: utf-8
3
+
4
+ import sys
5
+ import logging
6
+
7
+ from . import arguments
8
+ from amulog import cli
9
+ from amulog import common
10
+
11
+ _logger = logging.getLogger(__package__)
12
+ SUBLIB = ["source", "eval", "visual"]
13
+
14
+
15
+ def open_logdag_config(ns):
16
+ from . import arguments
17
+ return arguments.open_logdag_config(ns.conf_path, debug=ns.debug)
18
+
19
+
20
+ def test_makedag(ns):
21
+ from . import makedag
22
+ conf = open_logdag_config(ns)
23
+
24
+ am = arguments.ArgumentManager(conf)
25
+ am.generate(arguments.all_args)
26
+ am.dump()
27
+ makedag.makedag_main(am[0])
28
+
29
+
30
+ def make_args(ns):
31
+ conf = open_logdag_config(ns)
32
+
33
+ am = arguments.ArgumentManager(conf)
34
+ am.generate(arguments.all_args)
35
+ am.init_dirs(conf)
36
+ am.dump()
37
+
38
+
39
+ def make_dag(ns):
40
+ from . import makedag
41
+
42
+ conf = open_logdag_config(ns)
43
+
44
+ am = arguments.ArgumentManager(conf)
45
+ am.generate(arguments.all_args)
46
+ am.init_dirs(conf)
47
+ am.dump()
48
+
49
+ pal = ns.parallel
50
+ if pal > 1:
51
+ import multiprocessing
52
+ timer = common.Timer("makedag task", output=_logger)
53
+ timer.start()
54
+ with multiprocessing.Pool(processes=pal) as pool:
55
+ pool.map(makedag.makedag_pool, am)
56
+ timer.stop()
57
+ else:
58
+ timer = common.Timer("makedag task", output=_logger)
59
+ timer.start()
60
+ for args in am:
61
+ makedag.makedag_pool(args)
62
+ timer.stop()
63
+
64
+
65
+ def make_dag_stdin(ns):
66
+ from . import makedag
67
+
68
+ conf = open_logdag_config(ns)
69
+
70
+ am = arguments.ArgumentManager(conf)
71
+ am.init_dirs(conf)
72
+ args = am.jobname2args(ns.argname, conf)
73
+
74
+ timer = common.Timer("makedag task for {0}".format(ns.argname),
75
+ output=_logger)
76
+ timer.start()
77
+ makedag.makedag_main(args, do_dump=True)
78
+ timer.stop()
79
+
80
+
81
+ def update_event_label(ns):
82
+ conf = open_logdag_config(ns)
83
+ am = arguments.ArgumentManager(conf)
84
+ am.init_dirs(conf)
85
+ args = am.jobname2args(ns.argname, conf)
86
+
87
+ from . import log2event
88
+ evmap = log2event.EventDefinitionMap()
89
+ evmap.load(args)
90
+
91
+ from amulog import config
92
+ from .source import src_amulog
93
+ tmp_args = [config.getterm(conf, "general", "evdb_whole_term"),
94
+ conf["database_amulog"]["source_conf"],
95
+ conf["database_amulog"]["event_gid"]]
96
+ al = src_amulog.AmulogLoader(*tmp_args)
97
+
98
+ for evdef in evmap.iter_evdef():
99
+ assert evdef.source == log2event.SRCCLS_LOG
100
+ evdef.group = al.group(evdef.gid)
101
+
102
+ evmap.dump(args)
103
+
104
+
105
+ def dump_input(ns):
106
+ from . import makedag
107
+
108
+ conf = open_logdag_config(ns)
109
+
110
+ am = arguments.ArgumentManager(conf)
111
+ am.init_dirs(conf)
112
+ args = am.jobname2args(ns.argname, conf)
113
+
114
+ input_df, _ = makedag.make_input(args)
115
+ input_df.to_csv(ns.output)
116
+
117
+
118
+ def dump_events(ns):
119
+ from . import log2event
120
+ conf = open_logdag_config(ns)
121
+
122
+ am = arguments.ArgumentManager(conf)
123
+ am.init_dirs(conf)
124
+ args = am.jobname2args(ns.argname, conf)
125
+
126
+ evmap = log2event.EventDefinitionMap()
127
+ evmap.load(args)
128
+
129
+ if len(evmap) == 0:
130
+ from . import makedag
131
+ input_df, evmap = makedag.make_input(args)
132
+
133
+ for eid, evdef in evmap.items():
134
+ print("eid {0}: {1}".format(eid, evdef))
135
+
136
+
137
+ def show_args(ns):
138
+ conf = open_logdag_config(ns)
139
+
140
+ am = arguments.ArgumentManager(conf)
141
+ try:
142
+ am.load()
143
+ except IOError:
144
+ sys.exit("ArgumentManager object file not found")
145
+
146
+ print(am.show())
147
+
148
+
149
+ def _parse_condition(conditions):
150
+ d = {}
151
+ for arg in conditions:
152
+ if "=" not in arg:
153
+ raise SyntaxError("condition must be key=value: {0}".format(arg))
154
+ key, _, value = arg.partition("=")
155
+ if key == "node":
156
+ d["node"] = int(value)
157
+ elif key == "gid":
158
+ d["gid"] = int(value)
159
+ elif key == "host":
160
+ d["host"] = value
161
+ else:
162
+ # do not silently drop an unknown (e.g. mistyped) key
163
+ raise SyntaxError("unknown condition key: {0}".format(key))
164
+ return d
165
+
166
+
167
+ def show_edge(ns):
168
+ from . import showdag
169
+ conf = open_logdag_config(ns)
170
+ args = arguments.name2args(ns.argname, conf)
171
+
172
+ r = showdag.LogDAG(args)
173
+ r.load()
174
+
175
+ if ns.detail:
176
+ context = "detail"
177
+ elif ns.instruction:
178
+ context = "instruction"
179
+ else:
180
+ context = "edge"
181
+ d_cond = _parse_condition(ns.conditions)
182
+
183
+ print(showdag.show_edge(r, d_cond, context=context,
184
+ load_cache=(not ns.nocache), graph=None))
185
+
186
+
187
+ def show_subgraphs(ns):
188
+ from . import showdag
189
+ conf = open_logdag_config(ns)
190
+ args = arguments.name2args(ns.argname, conf)
191
+
192
+ ldag = showdag.LogDAG(args)
193
+ ldag.load()
194
+ g = showdag.apply_filter(ldag, ns.filters, th=ns.threshold)
195
+
196
+ if ns.detail:
197
+ context = "detail"
198
+ elif ns.instruction:
199
+ context = "instruction"
200
+ else:
201
+ context = "edge"
202
+
203
+ print(showdag.show_subgraphs(ldag, context,
204
+ load_cache=(not ns.nocache), graph=g))
205
+
206
+
207
+ def show_edge_list(ns):
208
+ from . import showdag
209
+ conf = open_logdag_config(ns)
210
+ args = arguments.name2args(ns.argname, conf)
211
+
212
+ r = showdag.LogDAG(args)
213
+ r.load()
214
+ g = showdag.apply_filter(r, ns.filters, th=ns.threshold)
215
+
216
+ if ns.detail:
217
+ context = "detail"
218
+ elif ns.instruction:
219
+ context = "instruction"
220
+ else:
221
+ context = "edge"
222
+
223
+ print(showdag.show_edge_list(r, context,
224
+ load_cache=(not ns.nocache), graph=g))
225
+
226
+
227
+ def show_list(ns):
228
+ from . import showdag
229
+ conf = open_logdag_config(ns)
230
+
231
+ l_func = [lambda r: r.graph.number_of_nodes(),
232
+ lambda r: r.graph.number_of_edges()]
233
+ table = []
234
+ for key, _, data in showdag.stat_groupby(conf, l_func, groupby=ns.groupby):
235
+ table.append([key] + list(data))
236
+ print(common.cli_table(table))
237
+
238
+
239
+ def show_node_list(ns):
240
+ from . import showdag
241
+ conf = open_logdag_config(ns)
242
+ args = arguments.name2args(ns.argname, conf)
243
+
244
+ r = showdag.LogDAG(args)
245
+ r.load()
246
+ for node in r.graph.nodes():
247
+ print("{0}: {1}".format(node, r.node_str(node)))
248
+
249
+
250
+ def show_stats(ns):
251
+ import numpy as np
252
+ from . import showdag
253
+ conf = open_logdag_config(ns)
254
+
255
+ msg = [
256
+ "number of events (nodes)",
257
+ "number of all edges",
258
+ "number of directed edges",
259
+ "number of undirected edges"
260
+ ]
261
+ l_func = [
262
+ lambda r: r.number_of_nodes(),
263
+ lambda r: r.number_of_edges(),
264
+ lambda r: showdag.apply_filter(r, ["directed"]).number_of_edges(),
265
+ lambda r: showdag.apply_filter(r, ["undirected"]).number_of_edges(),
266
+ ]
267
+ if ns.across_host:
268
+ msg += [
269
+ "number of edges across hosts",
270
+ "number of directed edges across hosts",
271
+ "number of undirected edges across hosts",
272
+ ]
273
+ l_func += [
274
+ lambda r: r.number_of_edges(showdag.apply_filter(r, ["across_host"])),
275
+ lambda r: showdag.apply_filter(r, ["directed", "across_host"]).number_of_edges(),
276
+ lambda r: showdag.apply_filter(r, ["undirected", "across_host"]).number_of_edges(),
277
+ ]
278
+
279
+ dt_range = _parse_opt_range(ns)
280
+ data = [v for _, _, v
281
+ in showdag.stat_groupby(conf, l_func, dt_range=dt_range)]
282
+ agg_data = np.sum(data, axis=0)
283
+ print(common.cli_table(list(zip(msg, agg_data)), align="right"))
284
+
285
+
286
+ def show_stats_by_threshold(ns):
287
+ import numpy as np
288
+ from . import showdag
289
+ conf = open_logdag_config(ns)
290
+
291
+ thresholds = np.arange(0, 1, 0.1)
292
+ dt_range = _parse_opt_range(ns)
293
+ data = showdag.stat_by_threshold(conf, thresholds, dt_range=dt_range)
294
+ print(common.cli_table(list(zip(thresholds, data)), align="right"))
295
+
296
+
297
+ def show_group_stats(ns):
298
+ from . import showdag
299
+ conf = open_logdag_config(ns)
300
+
301
+ from collections import defaultdict
302
+ d_node = defaultdict(int)
303
+ d_edge = defaultdict(int)
304
+ d_event = defaultdict(int)
305
+ for ldag in showdag.iter_results(conf):
306
+ l_node = list(ldag.nodes())
307
+ df = ldag.node_ts(l_node)
308
+ for node in l_node:
309
+ evdef = ldag.node_evdef(node)
310
+ d_node[evdef.group] += 1
311
+ d_event[evdef.group] += df[node].sum()
312
+ for edge in ldag.edges():
313
+ src_evdef, dst_evdef = ldag.edge_evdef(edge)
314
+ d_edge[src_evdef.group] += 1
315
+ d_edge[dst_evdef.group] += 1
316
+
317
+ table = [["group", "nodes", "edges", "logs"]]
318
+ for key in d_node.keys():
319
+ table.append([key, str(d_node[key]), str(d_edge[key]), str(d_event[key])])
320
+ print(common.cli_table(table))
321
+
322
+
323
+ def show_node_ts(ns):
324
+ from . import showdag
325
+ conf = open_logdag_config(ns)
326
+
327
+ args = arguments.name2args(ns.argname, conf)
328
+ l_nodeid = [int(n) for n in ns.node_ids]
329
+
330
+ ldag = showdag.LogDAG(args)
331
+ ldag.load()
332
+ df = ldag.node_ts(l_nodeid)
333
+ print(df.to_csv())
334
+
335
+
336
+ def show_netsize(ns):
337
+ from . import showdag
338
+ conf = open_logdag_config(ns)
339
+
340
+ print(showdag.show_netsize_dist(conf))
341
+
342
+
343
+ def show_netsize_list(ns):
344
+ from . import showdag
345
+ conf = open_logdag_config(ns)
346
+
347
+ print(showdag.list_netsize(conf))
348
+
349
+
350
+ def show_full_config(ns):
351
+ from amulog import config
352
+ conf = open_logdag_config(ns)
353
+ config.show_config(conf)
354
+
355
+
356
+ def show_default_config(_):
357
+ from . import arguments
358
+ arguments.show_logdag_default_config()
359
+
360
+
361
+ def plot_dag(ns):
362
+ from . import showdag
363
+ # from . import showdag_filter
364
+ conf = open_logdag_config(ns)
365
+
366
+ args = arguments.name2args(ns.argname, conf)
367
+ output = ns.output
368
+
369
+ r = showdag.LogDAG(args)
370
+ r.load()
371
+ # g = showdag_filter.apply(r, ns.filters, th=ns.threshold)
372
+ g = showdag.apply_filter(r, ns.filters, th=ns.threshold)
373
+ g = r.relabel(graph=g)
374
+ r.graph_nx(output, graph=g)
375
+ print(output)
376
+
377
+
378
+ def plot_node_ts(ns):
379
+ from . import showdag
380
+ conf = open_logdag_config(ns)
381
+
382
+ args = arguments.name2args(ns.argname, conf)
383
+ output = ns.output
384
+
385
+ l_nodeid = [int(n) for n in ns.node_ids]
386
+ showdag.plot_node_ts(args, l_nodeid, output)
387
+ print(output)
388
+
389
+
390
+ def _parse_opt_range(ns):
391
+ date_range_str = ns.dt_range
392
+ if date_range_str is None:
393
+ return None
394
+ else:
395
+ # argparse enforces nargs=2, but keep an explicit check (assert is
396
+ # stripped under -O) for any non-CLI caller
397
+ # argparse enforces nargs=2, but keep an explicit check (assert is
398
+ # stripped under -O) for any non-CLI caller
399
+ if len(date_range_str) != 2:
400
+ raise ValueError("range needs exactly 2 dates (start end)")
401
+ import datetime
402
+ return [datetime.datetime.strptime(s, "%Y-%m-%d") for s in date_range_str]
403
+
404
+
405
+ # def parse_condition(conditions):
406
+ # """
407
+ # Args:
408
+ # conditions (list)
409
+ # """
410
+ # import datetime
411
+ # d = {}
412
+ # for arg in conditions:
413
+ # if not "=" in arg:
414
+ # raise SyntaxError
415
+ # key = arg.partition("=")[0]
416
+ # if key == "gid":
417
+ # d["gid"] = int(arg.partition("=")[-1])
418
+ # elif key == "top_date":
419
+ # date_string = arg.partition("=")[-1]
420
+ # d["dts"] = datetime.datetime.strptime(date_string, "%Y-%m-%d")
421
+ # elif key == "end_date":
422
+ # date_string = arg.partition("=")[-1]
423
+ # d["dte"] = datetime.datetime.strptime(date_string, "%Y-%m-%d")
424
+ # elif key == "date":
425
+ # date_string = arg.partition("=")[-1]
426
+ # d["dts"] = datetime.datetime.strptime(date_string, "%Y-%m-%d")
427
+ # d["dte"] = d["dts"] + datetime.timedelta(days=1)
428
+ # elif key == "host":
429
+ # d["host"] = arg.partition("=")[-1]
430
+ # elif key == "area":
431
+ # d["area"] = arg.partition("=")[-1]
432
+ # else:
433
+ # d[key] = arg.partition("=")[-1]
434
+ # return d
435
+
436
+
437
+ # common argument settings
438
+ OPT_DEBUG = [["--debug"],
439
+ {"dest": "debug", "action": "store_true",
440
+ "help": "set logging level to debug (default: info)"}]
441
+ OPT_CONFIG = [["-c", "--config"],
442
+ {"dest": "conf_path", "metavar": "CONFIG", "action": "store",
443
+ "default": None,
444
+ "help": "configuration file path for amulog"}]
445
+ OPT_PARALLEL = [["-p", "--parallel"],
446
+ {"dest": "parallel", "metavar": "PARALLEL",
447
+ "type": int, "default": 1,
448
+ "help": "number of processes in parallel"}]
449
+ OPT_OUTPUT = [["-o", "--output"],
450
+ {"dest": "output", "metavar": "OUTPUT", "action": "store",
451
+ "default": "output",
452
+ "help": "output filename"}]
453
+ OPT_DIRNAME = [["-d", "--dirname"],
454
+ {"dest": "dirname", "metavar": "DIRNAME", "action": "store",
455
+ "default": ".",
456
+ "help": "directory name for output"}]
457
+ OPT_RANGE = [["-r", "--range"],
458
+ {"dest": "dt_range",
459
+ "metavar": "DATE", "nargs": 2, "default": None,
460
+ "help": ("datetime range, start and end in YY-MM-dd style. "
461
+ "end date is not included."
462
+ "(optional; use all data in default)")}]
463
+ OPT_THRESHOLD = [["-t", "--threshold"],
464
+ {"dest": "threshold", "metavar": "THRESHOLD", "action": "store",
465
+ "type": float, "default": None,
466
+ "help": "threshold for filter ate_prune"}]
467
+ OPT_GID = [["-g", "--gid"],
468
+ {"dest": "gid", "metavar": "GID", "action": "store",
469
+ "type": int, "default": None,
470
+ "help": "log group identifier to search events"}, ]
471
+ OPT_HOSTNAME = [["-n", "--host"],
472
+ {"dest": "host", "metavar": "HOST", "action": "store",
473
+ "default": None,
474
+ "help": "hostname to search events"}]
475
+ OPT_BINSIZE = [["-b", "--binsize"],
476
+ {"dest": "binsize", "metavar": "BINSIZE",
477
+ "action": "store", "default": None,
478
+ "help": "binsize (like 10s)"}]
479
+ OPT_INSTRUCTION = [["--instruction"],
480
+ {"dest": "instruction", "action": "store_true",
481
+ "help": "show event definition with source information"}]
482
+ OPT_DETAIL = [["-d", "--detail"],
483
+ {"dest": "detail", "action": "store_true",
484
+ "help": "show event time-series samples"}]
485
+ OPT_IGNORE_CACHE = [["--nocache"],
486
+ {"dest": "nocache", "action": "store_true",
487
+ "help": "ignore existing cache"}]
488
+ # OPT_LOG_ORG = [["--log-org"],
489
+ # {"dest": "log_org", "action": "store_true",
490
+ # "help": "show original logs from amulog db for log time-series"}]
491
+ OPT_GROUPBY = [["--groupby"],
492
+ {"dest": "groupby", "metavar": "GROUPBY",
493
+ "action": "store", "default": None,
494
+ "help": "aggregate results by given metrics (like day, area)"}]
495
+ OPT_FILTER = [["-f", "--filter"],
496
+ {"dest": "filters", "action": "append",
497
+ "help": ("filters for dag stats or plots. "
498
+ "see showdag_filter.py for more detail")}]
499
+
500
+ ARG_ARGNAME = [["argname"],
501
+ {"metavar": "TASKNAME", "action": "store",
502
+ "help": "argument name"}]
503
+ ARG_EDGESEARCH = [["conditions"],
504
+ {"metavar": "CONDITION", "nargs": "+",
505
+ "help": ("Conditions to search edges."
506
+ "Example: MODE gid=24 host=host01 ..., "
507
+ "Keys: node, gid, host.")}]
508
+
509
+ # argument settings for each modes
510
+ # description, List[args, kwargs], func
511
+ # defined after functions because these settings use functions
512
+ DICT_ARGSET = {
513
+ "make-args": ["Initialize arguments for pc algorithm",
514
+ [OPT_CONFIG, OPT_DEBUG],
515
+ make_args],
516
+ "make-dag": ["Generate causal DAGs",
517
+ [OPT_CONFIG, OPT_DEBUG, OPT_PARALLEL],
518
+ make_dag],
519
+ "make-dag-stdin": ["make-dag interface for pipeline processing",
520
+ [OPT_CONFIG, OPT_DEBUG, ARG_ARGNAME],
521
+ make_dag_stdin],
522
+ "update-event-label": ["Overwrite labels for log events",
523
+ [OPT_CONFIG, OPT_DEBUG, ARG_ARGNAME],
524
+ update_event_label],
525
+ "dump-input": ["Output causal analysis input in pandas csv format",
526
+ [OPT_CONFIG, OPT_DEBUG, OPT_OUTPUT,
527
+ [["-b", "--binary"],
528
+ {"dest": "binary", "action": "store_true",
529
+ "help": "dump binarized dataframe csv"}],
530
+ ARG_ARGNAME],
531
+ dump_input],
532
+ "dump-events": ["Output event node definition in readable format",
533
+ [OPT_CONFIG, OPT_DEBUG, ARG_ARGNAME],
534
+ dump_events],
535
+ "show-args": ["Show arguments recorded in argument file",
536
+ [OPT_CONFIG, OPT_DEBUG],
537
+ show_args],
538
+ "show-edge": ["Show edges related to given conditions",
539
+ [OPT_CONFIG, OPT_DEBUG, OPT_INSTRUCTION,
540
+ OPT_DETAIL, OPT_IGNORE_CACHE,
541
+ ARG_ARGNAME, ARG_EDGESEARCH],
542
+ show_edge],
543
+ "show-edge-list": ["Show all edges in a DAG",
544
+ [OPT_CONFIG, OPT_DEBUG, OPT_THRESHOLD, OPT_INSTRUCTION,
545
+ OPT_DETAIL, OPT_IGNORE_CACHE, OPT_FILTER,
546
+ ARG_ARGNAME],
547
+ show_edge_list],
548
+ "show-subgraphs": ["Show edges in each connected subgraphs",
549
+ [OPT_CONFIG, OPT_DEBUG, OPT_THRESHOLD, OPT_INSTRUCTION,
550
+ OPT_DETAIL, OPT_IGNORE_CACHE, OPT_FILTER,
551
+ ARG_ARGNAME],
552
+ show_subgraphs],
553
+ "show-list": ["Show abstracted results of DAG generation",
554
+ [OPT_CONFIG, OPT_DEBUG, OPT_THRESHOLD, OPT_GROUPBY],
555
+ show_list],
556
+ "show-node-list": ["Show node definitions of the input",
557
+ [OPT_CONFIG, OPT_DEBUG, ARG_ARGNAME],
558
+ show_node_list],
559
+ "show-stats": ["Show sum of nodes and edges",
560
+ [OPT_CONFIG, OPT_DEBUG, OPT_RANGE,
561
+ [["--xhost"],
562
+ {"dest": "across_host", "action": "store_true",
563
+ "help": "show additional stats for edges across multiple hosts"}]],
564
+ show_stats],
565
+ "show-stats-by-threshold": ["Show sum of edges by thresholds",
566
+ [OPT_CONFIG, OPT_DEBUG, OPT_RANGE],
567
+ show_stats_by_threshold],
568
+ "show-group-stats": ["Show stats classified by amulog tags",
569
+ [OPT_CONFIG, OPT_DEBUG],
570
+ show_group_stats],
571
+ "show-node-ts": ["Show time-series of specified nodes in csv format",
572
+ [OPT_CONFIG, OPT_DEBUG,
573
+ ARG_ARGNAME,
574
+ [["node_ids"],
575
+ {"metavar": "NODE_IDs", "nargs": "+",
576
+ "help": "nodes to show"}]],
577
+ show_node_ts],
578
+ "show-netsize": ["Show distribution of connected subgraphs in DAGs",
579
+ [OPT_CONFIG, OPT_DEBUG],
580
+ show_netsize],
581
+ "show-netsize-list": ["Show connected subgraphs in every DAG",
582
+ [OPT_CONFIG, OPT_DEBUG],
583
+ show_netsize_list],
584
+ "show-full-config": ["Show virtual configuration considering defaults",
585
+ [OPT_CONFIG, OPT_DEBUG],
586
+ show_full_config],
587
+ "show-deafult-config": ["Show configuration defaults",
588
+ [],
589
+ show_default_config],
590
+ "plot-dag": ["Generate causal DAG view",
591
+ [OPT_CONFIG, OPT_DEBUG,
592
+ OPT_OUTPUT, OPT_THRESHOLD, OPT_FILTER,
593
+ ARG_ARGNAME],
594
+ plot_dag],
595
+ "plot-node-ts": ["Generate node time-series view",
596
+ [OPT_CONFIG, OPT_DEBUG, OPT_OUTPUT,
597
+ ARG_ARGNAME,
598
+ [["node_ids"],
599
+ {"metavar": "NODE_IDs", "nargs": "+",
600
+ "help": "nodes to show"}]],
601
+ plot_node_ts],
602
+ }
603
+
604
+
605
+ def main():
606
+ cli.main(DICT_ARGSET, sublibs=SUBLIB)
607
+
608
+
609
+ if __name__ == "__main__":
610
+ main()