How to enable logging to console when using Cherrypy as backend WSGI server?

3,058 views
Skip to first unread message

Daniel

unread,
Aug 31, 2012, 3:48:36 PM8/31/12
to bott...@googlegroups.com
Hello Bottle people,
I switched from using the reference WSGI server to Cherrypy server.  I then noticed that I no longer can see the access or error log output sent to console.  How do I enable this?  Is it something in Bottle's configuration that I must change or is it Cherrpy's?  That is where I am confused at. 
 
I went to here: http://docs.cherrypy.org/dev/refman/_cplogging.html , but I am still not sure where and how to create this configuration file that it mentions to set log.screen=True.
 
Thanks in advance!
 
- Daniel

Daniel

unread,
Sep 5, 2012, 2:45:35 PM9/5/12
to bott...@googlegroups.com
OK, I know this is probably not the best way, but this is what I am doing now until someone can provide a better solution (some day...seems like this group is not very active or people are not willing to help...sigh, maybe I should join Flask, just kidding!)

import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')

Then for each @route function, I add these 2 lines:
requestIP = request.get('REMOTE_ADDR')
logging.debug("Request IP: " + requestIP + " - " + request.path + " - " + str(response.status_code))

But I don't like this solution because I would have to add those lines for each route function.  There has to be a way to enable logging across all application URL requests without having to explicitly tell which URL requests need to be logged.

Maybe I need to do something in Cherrypy, but their documentation is terrible in my opinion or not easily understood by me (a beginner).  But this solution that I discovered will suffice for now.

bender

unread,
Sep 5, 2012, 3:00:35 PM9/5/12
to bott...@googlegroups.com
I think you could download bottle file (in case if you intall bottle via pip) and edit it so routing method will contain you logging code.

Sent from my iPad
--
You are member of the "bottlepy" group at google groups.
See http://groups.google.de/group/bottlepy for mailing list options.
See http://bottlepy.org/ for news and documentation.

Iuri

unread,
Sep 5, 2012, 3:03:30 PM9/5/12
to bott...@googlegroups.com
Take a look at wsgilog (http://pypi.python.org/pypi/wsgilog/), it is awesome to log WSGI requests.

You can integrate it with a bottle plugin to log every route without code duplication.

cheers,
iuri

Daniel

unread,
Sep 5, 2012, 3:39:04 PM9/5/12
to bott...@googlegroups.com
Assuming it is the route method listed under the Bottle class declaration starting with line # 647 (version 0.10.9) in the "Application Object" section, but how do I make a reference to the request object so that I can get the "REMOTE_ADDR" value?

Here is the route function declaration:
def route(self, path=None, method='GET', callback=None, name=None,
              apply=None, skip=None, **config):
        """ A decorator to bind a function to a request URL. Example::

                @app.route('/hello/:name')
                def hello(name):
                    return 'Hello %s' % name

            The ``:name`` part is a wildcard. See :class:`Router` for syntax
            details.

            :param path: Request path or a list of paths to listen to. If no
              path is specified, it is automatically generated from the
              signature of the function.
            :param method: HTTP method (`GET`, `POST`, `PUT`, ...) or a list of
              methods to listen to. (default: `GET`)
            :param callback: An optional shortcut to avoid the decorator
              syntax. ``route(..., callback=func)`` equals ``route(...)(func)``
            :param name: The name for this route. (default: None)
            :param apply: A decorator or plugin or a list of plugins. These are
              applied to the route callback in addition to installed plugins.
            :param skip: A list of plugins, plugin classes or names. Matching
              plugins are not installed to this route. ``True`` skips all.

            Any additional keyword arguments are stored as route-specific
            configuration and passed to plugins (see :meth:`Plugin.apply`).
        """
        if callable(path): path, callback = None, path
        plugins = makelist(apply)
        skiplist = makelist(skip)
        def decorator(callback):
            # TODO: Documentation and tests
            if isinstance(callback, basestring): callback = load(callback)
            for rule in makelist(path) or yieldroutes(callback):
                for verb in makelist(method):
                    verb = verb.upper()
                    route = Route(self, rule, verb, callback, name=name,
                                  plugins=plugins, skiplist=skiplist, **config)
                    self.routes.append(route)
                    self.router.add(rule, verb, route, name=name)
                    if DEBUG: route.prepare()
            return callback
        return decorator(callback) if callback else decorator

I would like to try modifying bottle.py before implementing wsgilog module.

Thanks.

Iuri

unread,
Sep 5, 2012, 8:34:10 PM9/5/12
to bott...@googlegroups.com
Take a look at the hooks plugin, it is what you need.


cheers,
iurisilvio

Daniel

unread,
Sep 5, 2012, 9:50:29 PM9/5/12
to bott...@googlegroups.com
Wow am I suppose to know what "Cross-Origin Resource Sharing" means?? 
Could someone elaborate or provide a better explanation of what this "hook" does?  Sorry the documentation does not explain itself very well.  Does it allow you to run some code for every URL request?

From the documentation:

For example, if you want to allow Cross-Origin Resource Sharing for the content returned by all of your URL, you can use the hook decorator and setup a callback function:

from bottle import hook, response, route

@hook('after_request')
def enable_cors():
    response.headers['Access-Control-Allow-Origin'] = '*'

@route('/foo')
def say_foo():
    return 'foo!'

@route('/bar')
def say_bar():
    return {'type': 'friendly', 'content': 'Hi!'}

You can also use the before_callback to take an action before every function gets called.

Daniel

unread,
Sep 5, 2012, 10:08:19 PM9/5/12
to bott...@googlegroups.com
Ahhh I think I found a thread that explains what hooks does much better:

Iuri

unread,
Sep 6, 2012, 6:54:56 AM9/6/12
to bott...@googlegroups.com
Here an example of bottle hooks working with wsgilog: https://gist.github.com/3654741

The "Cross-Origin Resource Sharing" thing is just an example, probably this docs can be improved.

Daniel

unread,
Sep 6, 2012, 9:36:38 AM9/6/12
to bott...@googlegroups.com
Thank you Iuri de Silvio, you have been very helpful!

Daniel

unread,
Sep 17, 2012, 3:54:14 PM9/17/12
to bott...@googlegroups.com
OK I have one more question I think is simple.  What module or code is bottlepy using to echo logging to the console?  I looked at bottle.py source file, but I don't see anything obvious.  I looked at a few modules it is importing, but I must be looking/guessing at the wrong ones.  There are so many more I need to look.

Thanks,
Daniel

ma...@gsites.de

unread,
Sep 17, 2012, 4:18:47 PM9/17/12
to bott...@googlegroups.com
> OK I have one more question I think is simple. What module or code is
> bottlepy using to echo logging to the console? I looked at bottle.py
> source file, but I don't see anything obvious. I looked at a few modules
> it is importing, but I must be looking/guessing at the wrong ones. There
> are so many more I need to look.

bottle.py (line 68-74)
# Workaround for the "print is a keyword/function" Python 2/3 dilemma
# and a fallback for mod_wsgi (resticts stdout/err attribute access)
try:
_stdout, _stderr = sys.stdout.write, sys.stderr.write
except IOError:
_stdout = lambda x: sys.stdout.write(x)
_stderr = lambda x: sys.stderr.write(x)

ma...@gsites.de

unread,
Sep 17, 2012, 4:22:50 PM9/17/12
to bott...@googlegroups.com
I forgot: Most of the output is not generated by bottle, but the WSGI
server implementation used. To disable/change the access-log prints, look
at the server documentation or source.

Reply all
Reply to author
Forward
0 new messages