Consolidate logging

- Make log event handler work
- Move terminal event log into an addon
- Clean various log related errors and duplications
This commit is contained in:
Aldo Cortesi 2016-10-04 13:00:15 +11:00
parent 2bd8686629
commit 7fe09f4d26
12 changed files with 81 additions and 46 deletions

View File

@ -0,0 +1,23 @@
from __future__ import absolute_import, print_function, division
import click
from mitmproxy import utils
class TermLog:
def __init__(self):
self.options = None
def configure(self, options, updated):
self.options = options
def log(self, e):
if self.options.verbosity >= utils.log_tier(e.level):
click.secho(
e.msg,
file=self.options.tfile,
fg=dict(error="red", warn="yellow").get(e.level),
dim=(e.level == "debug"),
err=(e.level == "error")
)

View File

@ -28,21 +28,26 @@ Events = frozenset([
"requestheaders", "requestheaders",
"response", "response",
"responseheaders", "responseheaders",
"error",
"websocket_handshake", "websocket_handshake",
"next_layer", "next_layer",
"error",
"log",
"start",
"configure", "configure",
"done", "done",
"log",
"start",
"tick", "tick",
]) ])
class LogEntry(object):
def __init__(self, msg, level):
self.msg = msg
self.level = level
class Log(object): class Log(object):
def __init__(self, master): def __init__(self, master):
self.master = master self.master = master
@ -90,11 +95,16 @@ class Master(object):
mitmproxy_ctx.master = None mitmproxy_ctx.master = None
mitmproxy_ctx.log = None mitmproxy_ctx.log = None
def tell(self, mtype, m):
m.reply = DummyReply()
self.event_queue.put((mtype, m))
def add_log(self, e, level): def add_log(self, e, level):
""" """
level: debug, info, warn, error level: debug, info, warn, error
""" """
pass with self.handlecontext():
self.addons("log", LogEntry(e, level))
def add_server(self, server): def add_server(self, server):
# We give a Channel to the server which can be used to communicate with the master # We give a Channel to the server which can be used to communicate with the master

View File

@ -3,15 +3,12 @@ from __future__ import absolute_import, print_function, division
from typing import Optional # noqa from typing import Optional # noqa
import typing # noqa import typing # noqa
import click
from mitmproxy import controller from mitmproxy import controller
from mitmproxy import exceptions from mitmproxy import exceptions
from mitmproxy import flow from mitmproxy import flow
from mitmproxy import builtins from mitmproxy import builtins
from mitmproxy import utils
from mitmproxy import options from mitmproxy import options
from mitmproxy.builtins import dumper from mitmproxy.builtins import dumper, termlog
from netlib import tcp from netlib import tcp
@ -42,6 +39,7 @@ class DumpMaster(flow.FlowMaster):
self.has_errored = False self.has_errored = False
self.addons.add(*builtins.default_addons()) self.addons.add(*builtins.default_addons())
self.addons.add(dumper.Dumper()) self.addons.add(dumper.Dumper())
self.addons.add(termlog.TermLog())
# This line is just for type hinting # This line is just for type hinting
self.options = self.options # type: Options self.options = self.options # type: Options
self.set_stream_large_bodies(options.stream_large_bodies) self.set_stream_large_bodies(options.stream_large_bodies)
@ -79,17 +77,10 @@ class DumpMaster(flow.FlowMaster):
except exceptions.FlowReadException as e: except exceptions.FlowReadException as e:
raise DumpError(str(e)) raise DumpError(str(e))
def add_log(self, e, level="info"): @controller.handler
if level == "error": def log(self, e):
if e.level == "error":
self.has_errored = True self.has_errored = True
if self.options.verbosity >= utils.log_tier(level):
click.secho(
e,
file=self.options.tfile,
fg=dict(error="red", warn="yellow").get(level),
dim=(level == "debug"),
err=(level == "error")
)
@controller.handler @controller.handler
def request(self, f): def request(self, f):

View File

@ -190,7 +190,7 @@ class FlowMaster(controller.Master):
@controller.handler @controller.handler
def log(self, l): def log(self, l):
self.add_log(l.msg, l.level) pass
@controller.handler @controller.handler
def clientconnect(self, root_layer): def clientconnect(self, root_layer):

View File

@ -1,11 +1,11 @@
from __future__ import absolute_import, print_function, division from __future__ import absolute_import, print_function, division
from .config import ProxyConfig from .config import ProxyConfig
from .root_context import RootContext, Log from .root_context import RootContext
from .server import ProxyServer, DummyServer from .server import ProxyServer, DummyServer
__all__ = [ __all__ = [
"ProxyServer", "DummyServer", "ProxyServer", "DummyServer",
"ProxyConfig", "ProxyConfig",
"RootContext", "Log", "RootContext"
] ]

View File

@ -5,6 +5,7 @@ import sys
import six import six
import netlib.exceptions import netlib.exceptions
from mitmproxy import controller
from mitmproxy import exceptions from mitmproxy import exceptions
from mitmproxy import protocol from mitmproxy import protocol
from mitmproxy.proxy import modes from mitmproxy.proxy import modes
@ -118,7 +119,7 @@ class RootContext(object):
for i in subs: for i in subs:
full_msg.append(" -> " + i) full_msg.append(" -> " + i)
full_msg = "\n".join(full_msg) full_msg = "\n".join(full_msg)
self.channel.tell("log", Log(full_msg, level)) self.channel.tell("log", controller.LogEntry(full_msg, level))
@property @property
def layers(self): def layers(self):
@ -126,9 +127,3 @@ class RootContext(object):
def __repr__(self): def __repr__(self):
return "RootContext" return "RootContext"
class Log(object):
def __init__(self, msg, level="info"):
self.msg = msg
self.level = level

View File

@ -9,6 +9,7 @@ import six
import netlib.exceptions import netlib.exceptions
from mitmproxy import exceptions from mitmproxy import exceptions
from mitmproxy import models from mitmproxy import models
from mitmproxy import controller
from mitmproxy.proxy import modes from mitmproxy.proxy import modes
from mitmproxy.proxy import root_context from mitmproxy.proxy import root_context
from netlib import tcp from netlib import tcp
@ -155,4 +156,4 @@ class ConnectionHandler(object):
def log(self, msg, level): def log(self, msg, level):
msg = "{}: {}".format(repr(self.client_conn.address), msg) msg = "{}: {}".format(repr(self.client_conn.address), msg)
self.channel.tell("log", root_context.Log(msg, level)) self.channel.tell("log", controller.LogEntry(msg, level))

View File

@ -0,0 +1,17 @@
from .. import mastertest
from six.moves import cStringIO as StringIO
from mitmproxy.builtins import termlog
from mitmproxy import controller
from mitmproxy import dump
class TestTermLog(mastertest.MasterTest):
def test_simple(self):
t = termlog.TermLog()
sio = StringIO()
t.configure(dump.Options(tfile = sio, verbosity = 2), set([]))
t.log(controller.LogEntry("one", "info"))
assert "one" in sio.getvalue()
t.log(controller.LogEntry("two", "debug"))
assert "two" not in sio.getvalue()

View File

@ -1,37 +1,37 @@
import mitmproxy import mitmproxy
log = [] record = []
def clientconnect(cc): def clientconnect(cc):
mitmproxy.ctx.log("XCLIENTCONNECT") mitmproxy.ctx.log("XCLIENTCONNECT")
log.append("clientconnect") record.append("clientconnect")
def serverconnect(cc): def serverconnect(cc):
mitmproxy.ctx.log("XSERVERCONNECT") mitmproxy.ctx.log("XSERVERCONNECT")
log.append("serverconnect") record.append("serverconnect")
def request(f): def request(f):
mitmproxy.ctx.log("XREQUEST") mitmproxy.ctx.log("XREQUEST")
log.append("request") record.append("request")
def response(f): def response(f):
mitmproxy.ctx.log("XRESPONSE") mitmproxy.ctx.log("XRESPONSE")
log.append("response") record.append("response")
def responseheaders(f): def responseheaders(f):
mitmproxy.ctx.log("XRESPONSEHEADERS") mitmproxy.ctx.log("XRESPONSEHEADERS")
log.append("responseheaders") record.append("responseheaders")
def clientdisconnect(cc): def clientdisconnect(cc):
mitmproxy.ctx.log("XCLIENTDISCONNECT") mitmproxy.ctx.log("XCLIENTDISCONNECT")
log.append("clientdisconnect") record.append("clientdisconnect")
def error(cc): def error(cc):
mitmproxy.ctx.log("XERROR") mitmproxy.ctx.log("XERROR")
log.append("error") record.append("error")

View File

@ -4,7 +4,7 @@ from . import tutils
import netlib.tutils import netlib.tutils
from mitmproxy.flow import master from mitmproxy.flow import master
from mitmproxy import flow, proxy, models, controller, options from mitmproxy import flow, proxy, models, options
class TestMaster: class TestMaster:
@ -15,9 +15,6 @@ class MasterTest:
def cycle(self, master, content): def cycle(self, master, content):
f = tutils.tflow(req=netlib.tutils.treq(content=content)) f = tutils.tflow(req=netlib.tutils.treq(content=content))
l = proxy.Log("connect")
l.reply = controller.DummyReply()
master.log(l)
master.clientconnect(f.client_conn) master.clientconnect(f.client_conn)
master.serverconnect(f.server_conn) master.serverconnect(f.server_conn)
master.request(f) master.request(f)

View File

@ -44,8 +44,9 @@ class TestMaster(flow.FlowMaster):
def clear_log(self): def clear_log(self):
self.tlog = [] self.tlog = []
def add_log(self, message, level=None): @controller.handler
self.tlog.append(message) def log(self, e):
self.tlog.append(e.msg)
class ProxyThread(threading.Thread): class ProxyThread(threading.Thread):