Changeset 280


Ignore:
Timestamp:
06/25/15 14:27:54 (9 years ago)
Author:
atzm
Message:
  • logging support
Location:
etherws/trunk
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • etherws/trunk/README.rst

    r279 r280  
    128128Advanced Usage 
    129129============== 
     130 
     131Proxy 
     132----- 
     133You can create WebSocket tunnels via HTTP proxy.  Proxy server's address and 
     134port number are specified by generic environment variables: e.g. *$http_proxy* 
     135 
     136See https://docs.python.org/library/urllib.html for more information about 
     137environment variables for the proxy. 
     138 
     139Logging 
     140------- 
     141etherws uses standard logging library.  You can customize the logger using the 
     142*fileConfig* described in https://docs.python.org/library/logging.config.html 
     143 
     144To run *etherws sw* with the custom logger:: 
     145 
     146  # etherws sw --logconf /path/to/logging.ini 
     147 
     148etherws uses a logger stream named "etherws".  And internally Tornado uses 
     149some logger streams described in http://www.tornadoweb.org/en/stable/log.html 
     150 
     151Note: etherws does not write debug logs even if you simply configure loglevel 
     152DEBUG, to avoid performance degradation.  To write debug logs, you can 
     153specify *--debug* option. 
    130154 
    131155Remote Control 
     
    203227======= 
    2042281.3 
     229  - logging support 
    205230  - http proxy support on client connection 
    206231  - fix listport bug on tornado 4.0.x 
  • etherws/trunk/etherws.py

    r278 r280  
    5252import operator 
    5353import argparse 
    54 import traceback 
     54 
     55import logging 
     56import logging.config 
    5557 
    5658import tornado 
     
    6567 
    6668 
    67 class DebugMixIn(object): 
    68     def dprintf(self, msg, func=lambda: ()): 
    69         if self._debug: 
    70             prefix = '[%s] %s - ' % (time.asctime(), self.__class__.__name__) 
    71             sys.stderr.write(prefix + (msg % func())) 
    72  
    73  
    7469class EthernetFrame(object): 
    7570    def __init__(self, data): 
     
    107102 
    108103 
    109 class FDB(DebugMixIn): 
     104class FDB(object): 
    110105    class Entry(object): 
    111106        def __init__(self, port, ageout): 
     
    122117            return self.age > self._ageout 
    123118 
    124     def __init__(self, ageout, debug): 
     119    def __init__(self, ageout, logger, debug): 
    125120        self._ageout = ageout 
     121        self._logger = logger 
    126122        self._debug = debug 
    127123        self._table = {} 
     
    149145 
    150146        self._del_entry(vid, mac) 
    151         self.dprintf('aged out: port:%d; vid:%d; mac:%s\n', 
    152                      lambda: (entry.port.number, vid, mac.encode('hex'))) 
     147 
     148        if self._debug: 
     149            self._logger.debug('fdb aged out: port:%d; vid:%d; mac:%s', 
     150                               entry.port.number, vid, mac.encode('hex')) 
    153151 
    154152    def each(self): 
     
    169167        vid = frame.vid 
    170168        self._set_entry(vid, mac, port) 
    171         self.dprintf('learned: port:%d; vid:%d; mac:%s\n', 
    172                      lambda: (port.number, vid, mac.encode('hex'))) 
     169 
     170        if self._debug: 
     171            self._logger.debug('fdb learned: port:%d; vid:%d; mac:%s', 
     172                               port.number, vid, mac.encode('hex')) 
    173173 
    174174    def delete(self, port): 
     
    176176            if entry.port.number == port.number: 
    177177                self._del_entry(vid, mac) 
    178                 self.dprintf('deleted: port:%d; vid:%d; mac:%s\n', 
    179                              lambda: (port.number, vid, mac.encode('hex'))) 
    180  
    181  
    182 class SwitchingHub(DebugMixIn): 
     178 
     179                if self._debug: 
     180                    self._logger.debug('fdb deleted: port:%d; vid:%d; mac:%s', 
     181                                       port.number, vid, mac.encode('hex')) 
     182 
     183 
     184class SwitchingHub(object): 
    183185    class Port(object): 
    184186        def __init__(self, number, interface): 
     
    189191            self.shut = False 
    190192 
    191     def __init__(self, fdb, debug): 
     193    def __init__(self, fdb, logger, debug): 
    192194        self.fdb = fdb 
     195        self._logger = logger 
    193196        self._debug = debug 
    194197        self._table = {} 
     
    227230            p.tx += 1 
    228231 
    229         if ports: 
    230             self.dprintf('sent: port:%s; vid:%d; %s -> %s\n', 
    231                          lambda: (','.join(str(p.number) for p in ports), 
    232                                   frame.vid, 
    233                                   frame.src_mac.encode('hex'), 
    234                                   frame.dst_mac.encode('hex'))) 
     232        if self._debug and ports: 
     233            self._logger.debug('sent: port:%s; vid:%d; %s -> %s', 
     234                               ','.join(str(p.number) for p in ports), 
     235                               frame.vid, 
     236                               frame.src_mac.encode('hex'), 
     237                               frame.dst_mac.encode('hex')) 
    235238 
    236239    def receive(self, src_interface, frame): 
     
    257260 
    258261        except:  # ex. received invalid frame 
    259             traceback.print_exc() 
     262            self._logger.exception( 
     263                'caught error while forwarding frame: port:%d; frame:%s', 
     264                src_port.number, frame.data.encode('hex')) 
    260265 
    261266    def _privattr(self, name): 
    262         return '_%s_%s_%s' % (self.__class__.__name__, id(self), name) 
     267        return '_%s_%s_%s' % (type(self).__name__, id(self), name) 
    263268 
    264269    def _set_privattr(self, name, obj, value): 
     
    402407                return do_execute() 
    403408        except: 
    404             traceback.print_exc() 
     409            self._logger.exception('caught error while doing authorization') 
    405410 
    406411        return auth_required() 
    407412 
    408413 
    409 class ServerHandler(DebugMixIn, BasicAuthMixIn, WebSocketHandler): 
     414class ServerHandler(BasicAuthMixIn, WebSocketHandler): 
    410415    IFTYPE = 'server' 
    411416    IFOP_ALLOWED = False 
    412417 
    413     def __init__(self, app, req, switch, htpasswd, debug): 
     418    def __init__(self, app, req, switch, htpasswd, logger, debug): 
    414419        super(ServerHandler, self).__init__(app, req) 
    415420        self._switch = switch 
    416421        self._htpasswd = htpasswd 
     422        self._logger = logger 
    417423        self._debug = debug 
    418424 
     
    421427        conn = self.request.connection 
    422428        if hasattr(conn, 'address'): 
    423             return ':'.join(str(e) for e in conn.address) 
     429            return ':'.join(str(e) for e in conn.address[:2]) 
    424430        if hasattr(conn, 'context'): 
    425             return ':'.join(str(e) for e in conn.context.address) 
     431            return ':'.join(str(e) for e in conn.context.address[:2]) 
    426432        return str(conn) 
    427433 
     
    430436            return self._switch.register_port(self) 
    431437        finally: 
    432             self.dprintf('connected: %s\n', lambda: self.request.remote_ip) 
     438            self._logger.info('connected: %s', self.request.remote_ip) 
    433439 
    434440    def on_message(self, message): 
     
    437443    def on_close(self): 
    438444        self._switch.unregister_port(self) 
    439         self.dprintf('disconnected: %s\n', lambda: self.request.remote_ip) 
    440  
    441  
    442 class BaseClientHandler(DebugMixIn): 
     445        self._logger.info('disconnected: %s', self.request.remote_ip) 
     446 
     447 
     448class BaseClientHandler(object): 
    443449    IFTYPE = 'baseclient' 
    444450    IFOP_ALLOWED = False 
    445451 
    446     def __init__(self, ioloop, switch, target, debug, *args, **kwargs): 
     452    def __init__(self, ioloop, switch, target, logger, debug, *args, **kwargs): 
    447453        self._ioloop = ioloop 
    448454        self._switch = switch 
    449455        self._target = target 
     456        self._logger = logger 
    450457        self._debug = debug 
    451458        self._args = args 
     
    491498 
    492499    @property 
     500    def logger(self): 
     501        return self._logger 
     502 
     503    @property 
    493504    def device(self): 
    494505        return self._device 
     
    503514        self.leave_switch() 
    504515        self.unregister_device() 
    505         self.dprintf('disconnected: %s\n', lambda: self.target) 
     516        self.logger.info('disconnected: %s', self.target) 
    506517 
    507518    def register_device(self, device): 
     
    524535                return 
    525536        except: 
    526             traceback.print_exc() 
     537            self.logger.exception('caught error while receiving frame') 
    527538        self.close() 
    528539 
     
    583594            socket.PF_PACKET, socket.SOCK_RAW, socket.htons(self.ETH_P_ALL))) 
    584595        self.device.bind((self.target, self.ETH_P_ALL)) 
    585         self.dprintf('connected: %s\n', lambda: self.target) 
     596        self.logger.info('connected: %s', self.target) 
    586597        return self.join_switch() 
    587598 
     
    659670        self.register_device(TunTapDevice(self.target, IFF_TAP | IFF_NO_PI)) 
    660671        self.device.up() 
    661         self.dprintf('connected: %s\n', lambda: self.target) 
     672        self.logger.info('connected: %s', self.target) 
    662673        return self.join_switch() 
    663674 
     
    702713        self.register_device(websocket.WebSocket(sslopt=self._sslopt)) 
    703714        self.device.connect(self.target, **self._options) 
    704         self.dprintf('connected: %s\n', lambda: self.target) 
     715        self.logger.info('connected: %s', self.target) 
    705716        return self.join_switch() 
    706717 
     
    736747 
    737748 
    738 class ControlServerHandler(DebugMixIn, BasicAuthMixIn, RequestHandler): 
     749class ControlServerHandler(BasicAuthMixIn, RequestHandler): 
    739750    NAMESPACE = 'etherws.control' 
    740751    IFTYPES = { 
     
    744755    } 
    745756 
    746     def __init__(self, app, req, ioloop, switch, htpasswd, debug): 
     757    def __init__(self, app, req, ioloop, switch, htpasswd, logger, debug): 
    747758        super(ControlServerHandler, self).__init__(app, req) 
    748759        self._ioloop = ioloop 
    749760        self._switch = switch 
    750761        self._htpasswd = htpasswd 
     762        self._logger = logger 
    751763        self._debug = debug 
    752764 
     
    758770                'code':    0 - 32700, 
    759771                'message': 'Parse error', 
    760                 'data':    '%s: %s' % (e.__class__.__name__, str(e)), 
     772                'data':    '%s: %s' % (type(e).__name__, str(e)), 
    761773            }) 
    762774 
     
    772784                'code':    0 - 32600, 
    773785                'message': 'Invalid Request', 
    774                 'data':    '%s: %s' % (e.__class__.__name__, str(e)), 
     786                'data':    '%s: %s' % (type(e).__name__, str(e)), 
    775787            }) 
    776788 
     
    784796                'code':    0 - 32601, 
    785797                'message': 'Method not found', 
    786                 'data':    '%s: %s' % (e.__class__.__name__, str(e)), 
     798                'data':    '%s: %s' % (type(e).__name__, str(e)), 
    787799            }) 
    788800 
     
    790802            return self._jsonrpc_response(id_=id_, result=handler(params)) 
    791803        except Exception as e: 
    792             traceback.print_exc() 
     804            self._logger.exception('caught error while processing request') 
    793805            return self._jsonrpc_response(id_=id_, error={ 
    794806                'code':    0 - 32602, 
    795807                'message': 'Invalid params', 
    796                 'data':     '%s: %s' % (e.__class__.__name__, str(e)), 
     808                'data':     '%s: %s' % (type(e).__name__, str(e)), 
    797809            }) 
    798810 
     
    816828        opt = getattr(self, '_optparse_' + type_)(params.get('options', {})) 
    817829        cls = self.IFTYPES[type_] 
    818         interface = cls(self._ioloop, self._switch, target, self._debug, **opt) 
     830        interface = cls(self._ioloop, self._switch, target, 
     831                        self._logger, self._debug, **opt) 
    819832        portnum = interface.open() 
    820833        return {'entries': [self._portstat(self._switch.get_port(portnum))]} 
     
    971984        raise ValueError('Invalid ageout: %s' % args.ageout) 
    972985 
     986    setrealpath(args, 'logconf') 
    973987    setrealpath(args, 'htpasswd', 'sslkey', 'sslcert') 
    974988    setrealpath(args, 'ctlhtpasswd', 'ctlsslkey', 'ctlsslcert') 
     
    9861000    sethtpasswd(args, 'ctlhtpasswd') 
    9871001 
     1002    if args.logconf: 
     1003        logging.config.fileConfig(args.logconf) 
     1004        logger = logging.getLogger('etherws') 
     1005    else: 
     1006        logger = logging.getLogger('etherws') 
     1007        logger.setLevel(logging.DEBUG if args.debug else logging.INFO) 
     1008 
    9881009    ioloop = IOLoop.instance() 
    989     fdb = FDB(args.ageout, args.debug) 
    990     switch = SwitchingHub(fdb, args.debug) 
     1010    fdb = FDB(args.ageout, logger, args.debug) 
     1011    switch = SwitchingHub(fdb, logger, args.debug) 
    9911012 
    9921013    if args.port == args.ctlport and args.host == args.ctlhost: 
     
    10021023                'switch':   switch, 
    10031024                'htpasswd': args.htpasswd, 
     1025                'logger':   logger, 
    10041026                'debug':    args.debug, 
    10051027            }), 
     
    10081030                'switch':   switch, 
    10091031                'htpasswd': args.ctlhtpasswd, 
     1032                'logger':   logger, 
    10101033                'debug':    args.debug, 
    10111034            }), 
     
    10181041            'switch':   switch, 
    10191042            'htpasswd': args.htpasswd, 
     1043            'logger':   logger, 
    10201044            'debug':    args.debug, 
    10211045        })]) 
     
    10271051            'switch':   switch, 
    10281052            'htpasswd': args.ctlhtpasswd, 
     1053            'logger':   logger, 
    10291054            'debug':    args.debug, 
    10301055        })]) 
     
    11991224    parser_sw.add_argument('--debug', action='store_true', default=False, 
    12001225                           help='run as debug mode') 
     1226    parser_sw.add_argument('--logconf', 
     1227                           help='path to logging config') 
    12011228    parser_sw.add_argument('--foreground', action='store_true', default=False, 
    12021229                           help='run as foreground mode') 
     
    13261353            'code':    0 - 32603, 
    13271354            'message': 'Internal error', 
    1328             'data':    '%s: %s' % (e.__class__.__name__, str(e)), 
     1355            'data':    '%s: %s' % (type(e).__name__, str(e)), 
    13291356        }) 
    13301357 
Note: See TracChangeset for help on using the changeset viewer.