Merge pull request #2923 from cortesi/moreopts

Options: split verbosity, add some docs to Loader.add_option
This commit is contained in:
Aldo Cortesi 2018-02-26 09:45:24 +13:00 committed by GitHub
commit f02896862d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 44 additions and 35 deletions

View File

@ -92,6 +92,13 @@ class Loader:
help: str, help: str,
choices: typing.Optional[typing.Sequence[str]] = None choices: typing.Optional[typing.Sequence[str]] = None
) -> None: ) -> None:
"""
Add an option to mitmproxy.
Help should be a single paragraph with no linebreaks - it will be
reflowed by tools. Information on the data type should be omitted -
it will be generated and added by tools as needed.
"""
if name in self.master.options: if name in self.master.options:
existing = self.master.options._options[name] existing = self.master.options._options[name]
same_signature = ( same_signature = (

View File

@ -14,13 +14,20 @@ class TermLog:
def __init__(self, outfile=None): def __init__(self, outfile=None):
self.outfile = outfile self.outfile = outfile
def load(self, loader):
loader.add_option(
"termlog_verbosity", str, 'info',
"Log verbosity.",
choices=log.LogTierOrder
)
def log(self, e): def log(self, e):
if log.log_tier(e.level) == log.log_tier("error"): if log.log_tier(e.level) == log.log_tier("error"):
outfile = self.outfile or realstderr outfile = self.outfile or realstderr
else: else:
outfile = self.outfile or realstdout outfile = self.outfile or realstdout
if log.log_tier(ctx.options.verbosity) >= log.log_tier(e.level): if log.log_tier(ctx.options.termlog_verbosity) >= log.log_tier(e.level):
click.secho( click.secho(
e.msg, e.msg,
file=outfile, file=outfile,

View File

@ -57,5 +57,14 @@ class Log:
self.master.add_log(text, level) self.master.add_log(text, level)
LogTierOrder = [
"error",
"warn",
"info",
"alert",
"debug",
]
def log_tier(level): def log_tier(level):
return dict(error=0, warn=1, info=2, alert=2, debug=3).get(level) return dict(error=0, warn=1, info=2, alert=2, debug=3).get(level)

View File

@ -3,23 +3,10 @@ from typing import Optional, Sequence
from mitmproxy import optmanager from mitmproxy import optmanager
from mitmproxy.net import tls from mitmproxy.net import tls
log_verbosity = [
"error",
"warn",
"info",
"alert",
"debug",
]
CA_DIR = "~/.mitmproxy" CA_DIR = "~/.mitmproxy"
LISTEN_PORT = 8080 LISTEN_PORT = 8080
# Some help text style guidelines:
#
# - Should be a single paragraph with no linebreaks. Help will be reflowed by
# tools.
# - Avoid adding information about the data type - we can generate that.
class Options(optmanager.OptManager): class Options(optmanager.OptManager):
@ -42,6 +29,7 @@ class Options(optmanager.OptManager):
mode = None # type: str mode = None # type: str
rawtcp = None # type: bool rawtcp = None # type: bool
server = None # type: bool server = None # type: bool
showhost = None # type: bool
spoof_source_address = None # type: bool spoof_source_address = None # type: bool
ssl_insecure = None # type: bool ssl_insecure = None # type: bool
ssl_verify_upstream_trusted_ca = None # type: Optional[str] ssl_verify_upstream_trusted_ca = None # type: Optional[str]
@ -56,8 +44,6 @@ class Options(optmanager.OptManager):
# FIXME: Options that must be migrated to addons, but are complicated # FIXME: Options that must be migrated to addons, but are complicated
# because they're used by more than one addon, or because they're # because they're used by more than one addon, or because they're
# embedded in the core code somehow. # embedded in the core code somehow.
showhost = None # type: bool
verbosity = None # type: str
view_filter = None # type: Optional[str] view_filter = None # type: Optional[str]
def __init__(self, **kwargs) -> None: def __init__(self, **kwargs) -> None:
@ -70,11 +56,6 @@ class Options(optmanager.OptManager):
"showhost", bool, False, "showhost", bool, False,
"Use the Host header to construct URLs for display." "Use the Host header to construct URLs for display."
) )
self.add_option(
"verbosity", str, 'info',
"Log verbosity.",
choices=log_verbosity
)
# Proxy options # Proxy options
self.add_option( self.add_option(

View File

@ -7,6 +7,7 @@ from mitmproxy import command
from mitmproxy import exceptions from mitmproxy import exceptions
from mitmproxy import flow from mitmproxy import flow
from mitmproxy import http from mitmproxy import http
from mitmproxy import log
from mitmproxy import contentviews from mitmproxy import contentviews
from mitmproxy.utils import strutils from mitmproxy.utils import strutils
import mitmproxy.types import mitmproxy.types
@ -81,6 +82,11 @@ class ConsoleAddon:
"The default content view mode.", "The default content view mode.",
choices = [i.name.lower() for i in contentviews.views] choices = [i.name.lower() for i in contentviews.views]
) )
loader.add_option(
"console_eventlog_verbosity", str, 'info',
"EventLog verbosity.",
choices=log.LogTierOrder
)
loader.add_option( loader.add_option(
"console_layout", str, "single", "console_layout", str, "single",
"Console layout.", "Console layout.",

View File

@ -21,7 +21,7 @@ class EventLog(urwid.ListBox, layoutwidget.LayoutWidget):
master.events.sig_add.connect(self.add_event) master.events.sig_add.connect(self.add_event)
master.events.sig_refresh.connect(self.refresh_events) master.events.sig_refresh.connect(self.refresh_events)
self.master.options.subscribe(self.refresh_events, ["verbosity"]) self.master.options.subscribe(self.refresh_events, ["console_eventlog_verbosity"])
self.refresh_events() self.refresh_events()
super().__init__(self.walker) super().__init__(self.walker)
@ -44,7 +44,7 @@ class EventLog(urwid.ListBox, layoutwidget.LayoutWidget):
return super().keypress(size, key) return super().keypress(size, key)
def add_event(self, event_store, entry: log.LogEntry): def add_event(self, event_store, entry: log.LogEntry):
if log.log_tier(self.master.options.verbosity) < log.log_tier(entry.level): if log.log_tier(self.master.options.console_eventlog_verbosity) < log.log_tier(entry.level):
return return
txt = "%s: %s" % (entry.level, str(entry.msg)) txt = "%s: %s" % (entry.level, str(entry.msg))
if entry.level in ("error", "warn", "alert"): if entry.level in ("error", "warn", "alert"):

View File

@ -87,7 +87,7 @@ class ConsoleMaster(master.Master):
) )
def sig_add_log(self, event_store, entry: log.LogEntry): def sig_add_log(self, event_store, entry: log.LogEntry):
if log.log_tier(self.options.verbosity) < log.log_tier(entry.level): if log.log_tier(self.options.console_eventlog_verbosity) < log.log_tier(entry.level):
return return
if entry.level in ("error", "warn", "alert"): if entry.level in ("error", "warn", "alert"):
if self.first_tick: if self.first_tick:

View File

@ -46,10 +46,10 @@ def process_options(parser, opts, args):
if args.quiet or args.options or args.commands: if args.quiet or args.options or args.commands:
# also reduce log verbosity if --options or --commands is passed, # also reduce log verbosity if --options or --commands is passed,
# we don't want log messages from regular startup then. # we don't want log messages from regular startup then.
args.verbosity = 'error' args.termlog_verbosity = 'error'
args.flow_detail = 0 args.flow_detail = 0
if args.verbose: if args.verbose:
args.verbosity = 'debug' args.termlog_verbosity = 'debug'
args.flow_detail = 2 args.flow_detail = 2
adict = {} adict = {}
@ -104,9 +104,7 @@ def run(
master.server = server master.server = server
master.addons.trigger("configure", opts.keys()) master.addons.trigger("configure", opts.keys())
master.addons.trigger("tick") master.addons.trigger("tick")
remaining = opts.update_known(**unknown) opts.update_known(**unknown)
if remaining and log.log_tier(opts.verbosity) > 1:
print("Ignored options: %s" % remaining)
if args.options: if args.options:
print(optmanager.dump_defaults(opts)) print(optmanager.dump_defaults(opts))
sys.exit(0) sys.exit(0)

View File

@ -310,6 +310,9 @@ class TestXSSScanner():
def __init__(self): def __init__(self):
self.args = [] self.args = []
def info(self, str):
self.args.append(str)
def error(self, str): def error(self, str):
self.args.append(str) self.args.append(str)
return Logger() return Logger()

View File

@ -147,7 +147,7 @@ class TestContentView:
sio = io.StringIO() sio = io.StringIO()
d = dumper.Dumper(sio) d = dumper.Dumper(sio)
with taddons.context(d) as ctx: with taddons.context(d) as ctx:
ctx.configure(d, flow_detail=4, verbosity='debug') ctx.configure(d, flow_detail=4)
d.response(tflow.tflow()) d.response(tflow.tflow())
assert ctx.master.has_log("content viewer failed") assert ctx.master.has_log("content viewer failed")

View File

@ -3,7 +3,6 @@ import pytest
from mitmproxy.addons import termlog from mitmproxy.addons import termlog
from mitmproxy import log from mitmproxy import log
from mitmproxy.options import Options
from mitmproxy.test import taddons from mitmproxy.test import taddons
@ -16,7 +15,8 @@ class TestTermLog:
]) ])
def test_output(self, outfile, expected_out, expected_err, capfd): def test_output(self, outfile, expected_out, expected_err, capfd):
t = termlog.TermLog(outfile=outfile) t = termlog.TermLog(outfile=outfile)
with taddons.context(options=Options(verbosity='info')) as tctx: with taddons.context(t) as tctx:
tctx.options.termlog_verbosity = "info"
tctx.configure(t) tctx.configure(t)
t.log(log.LogEntry("one", "info")) t.log(log.LogEntry("one", "info"))
t.log(log.LogEntry("two", "debug")) t.log(log.LogEntry("two", "debug"))

View File

@ -7,8 +7,6 @@ from ... import tservers
class TestMaster(tservers.MasterTest): class TestMaster(tservers.MasterTest):
def mkmaster(self, **opts): def mkmaster(self, **opts):
if "verbosity" not in opts:
opts["verbosity"] = 'warn'
o = options.Options(**opts) o = options.Options(**opts)
m = console.master.ConsoleMaster(o) m = console.master.ConsoleMaster(o)
m.addons.trigger("configure", o.keys()) m.addons.trigger("configure", o.keys())

View File

@ -11,7 +11,7 @@ from .. import tservers
class TestDumpMaster(tservers.MasterTest): class TestDumpMaster(tservers.MasterTest):
def mkmaster(self, flt, **opts): def mkmaster(self, flt, **opts):
o = options.Options(view_filter=flt, verbosity='error', **opts) o = options.Options(view_filter=flt, **opts)
m = dump.DumpMaster(o, with_termlog=False, with_dumper=False) m = dump.DumpMaster(o, with_termlog=False, with_dumper=False)
return m return m