1from __future__ import print_function
2import sys
3from io import StringIO
4from twisted.python import usage
5
6import foolscap
7from foolscap.logging.tail import TailOptions, LogTail
8from foolscap.logging.gatherer import \
9     CreateGatherOptions, create_log_gatherer, \
10     CreateIncidentGatherOptions, create_incident_gatherer
11from foolscap.logging.dumper import DumpOptions, LogDumper
12from foolscap.logging.web import WebViewerOptions, WebViewer
13from foolscap.logging.filter import FilterOptions, Filter
14from foolscap.logging.incident import ClassifyOptions, IncidentClassifier
15
16class Options(usage.Options):
17    synopsis = "Usage: flogtool (tail|create-gatherer|dump|filter|web-viewer)"
18
19    subCommands = [
20        ("tail", None, TailOptions, "follow logs of the target node"),
21        ("create-gatherer", None, CreateGatherOptions,
22         "Make a .tac which will record all logs to a given directory"),
23        ("create-incident-gatherer", None, CreateIncidentGatherOptions,
24         "Make a .tac which will record all incidents to a given directory"),
25        ("dump", None, DumpOptions,
26         "dump the logs recorded by 'logtool gather'"),
27        ("filter", None, FilterOptions,
28         "produce a new file with a subset of the events from another file"),
29        ("web-viewer", None, WebViewerOptions,
30         "view the logs through a web page"),
31        ("classify-incident", None, ClassifyOptions,
32         "classify a stored Incident file"),
33        ]
34
35    def postOptions(self):
36        if not hasattr(self, 'subOptions'):
37            raise usage.UsageError("must specify a command")
38
39    def opt_help(self):
40        print(self.synopsis)
41        sys.exit(0)
42
43    def opt_version(self):
44        from twisted import copyright
45        print("Foolscap version:", foolscap.__version__)
46        print("Twisted version:", copyright.version)
47        sys.exit(0)
48
49
50def dispatch(command, options):
51    if command == "tail":
52        lt = LogTail(options)
53        return lt.run(options.target_furl)
54
55    elif command == "create-gatherer":
56        return create_log_gatherer(options)
57
58    elif command == "create-incident-gatherer":
59        return create_incident_gatherer(options)
60
61    elif command == "dump":
62        ld = LogDumper()
63        return ld.run(options)
64
65    elif command == "filter":
66        f = Filter()
67        return f.run(options)
68
69    elif command == "web-viewer":
70        wv = WebViewer()
71        return wv.run(options)
72
73    elif command == "classify-incident":
74        ic = IncidentClassifier()
75        return ic.run(options)
76
77    else:
78        print("unknown command '%s'" % command)
79        raise NotImplementedError
80
81def run_flogtool(argv=None, run_by_human=True):
82    if argv:
83        command_name = argv[0]
84    else:
85        command_name = sys.argv[0]
86    config = Options()
87    try:
88        config.parseOptions(argv)
89    except usage.error as e:
90        if not run_by_human:
91            raise
92        print("%s:  %s" % (command_name, e))
93        print()
94        c = getattr(config, 'subOptions', config)
95        print(str(c))
96        sys.exit(1)
97
98    command = config.subCommand
99    so = config.subOptions
100    if not run_by_human:
101        so.stdout = StringIO()
102        so.stderr = StringIO()
103    rc = dispatch(command, so)
104    if rc is None:
105        rc = 0
106    if run_by_human:
107        sys.exit(rc)
108    else:
109        return (so.stdout.getvalue(), so.stderr.getvalue())
110