Sanic: Custom log not working with sanic

Created on 29 May 2017  路  19Comments  路  Source: sanic-org/sanic

Hi, I am using custom logger with Sanic. However, the log is neither written to file nor printing in the console. My code for logging is list below:

def create_logger(logger_name, level, filename):
    logger = logging.getLogger(logger_name)
    logger.setLevel(level)
    fh = logging.FileHandler("./logs/"+filename)
    fh.setLevel(level)
    ch = logging.StreamHandler()
    ch.setLevel(level)
    logger.addHandler(fh)
    logger.addHandler(ch)
    return logger

May I know how to properly use log with Sanic, especially log to different files?

help wanted

Most helpful comment

For me the logging seems a bit too complex. There are good ideas in it. However, it should not be necessary to learn logging for Sanic, people should just be able to use plain stdlib logging. So IMHO instead of making little fixes here and there it would be best to refactor logging to be really simple. Instead of providing a big default config which needs to be altered (and therefore known) we could maybe provide a small default config and some opt-in building blocks. -- Just some thoughts without having dug into the implementation too much...

All 19 comments

Did you take a look at examples/override_logging.py yet?

Also, specifying log files is mentioned in #721 as removed currently.

For something quick I just grab the sanic logger and use it directly e.g.:

from sanic.log import log

log.info("Hello sanic log")

Hope you get something working to your needs!

Found this problem too since v0.5.2, my custom logger was working on v0.5.1.

@kbfu I also found this problem after I upgrade to 0.5.4

Thanks for reporting this @MrXu, and everyone. Can someone please post a complete example, to make this easier to fix?

Here is my code :

logger = logging.getLogger('urp')
logger.setLevel(logging.DEBUG)

fh = logging.FileHandler("logging.log")
fh.setLevel(logging.DEBUG)

ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)

logger.addHandler(fh)
logger.addHandler(ch)

It would not show in both cosole and file if I use it in my controllers which extends HTTPMethodView like logger.error(err)

seems like you have to do sth. like

from sanic import Sanic
from sanic.response import json
import sys
import logging
from sanic.config import LOGGING

# my_logger
LOGGER = logging.getLogger('my_logger')

# my_handler
HANDLER = 'logging.StreamHandler'

# my Formatter
FORMATTER = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'


# Register your formatter
LOGGING["formatters"]['my_formatter'] = {
    'format' : FORMATTER,
    'datefmt': '%Y-%m-%d %H:%M:%S',
}
# Register your Handler
LOGGING['handlers']['my_handler'] = {
    'class': HANDLER,
    'formatter': 'my_formatter',
    'stream': sys.stderr
}
# Register your LOGGER
LOGGING["loggers"]['my_logger'] = {
    'level': 'INFO',
    'handlers': ['my_handler'],
}


app = Sanic(__name__)


@app.route("/")
async def test(request):
    LOGGER.info("Hello, World!")
    return json({"hello":"world"})


def main():
    app.run(log_config=LOGGING)


if __name__ == '__main__':
    main()

I can add it to examples if needed.

Because it just overrides the whole logging dictConfig inside sanic app, https://github.com/channelcat/sanic/blob/master/sanic/app.py#L33.

Maybe it's not a good pattern.

@r0fls @seemethere What do you guys think ? is there any good reason for this design ?

I agree this needs to be reworked/enhanced, from a UX perspective. It should be easier to use and more intuitive. @zenixls2 @messense would either of you be interested in giving a stab at improving the usability of this?

How about a boolean value access_log=True for enabling ?
Two default loggersaccess_log and error_log are provided, but they can be disabled or enabled.
User can also add their custom loggers.

https://github.com/channelcat/sanic/blob/master/sanic/config.py
notice that this is only a configuration in dict.
you could extend this configuration like:

from sanic.config import LOGGING
myHandler = {
    'class': 'logging.handlers.TimedRotatingFileHandler',
    'filters': ['access_filter'],
    'formatter': 'simple',
     'when': 'D',
    'interval': 1,
    'backupCount': 7,
    'filename': 'access.log'
}
LOGGING['handlers']['myHandler'] = myHandler
LOGGING['loggers']['sanic']['handlers'].append('myHandler')

@yunstanford 's implementation also works.
You could also provide your own dict configuration to log_config parameter of Sanic.__init__.
set log_config to False or None and set with your own logging config could also work.
ex:

app = Sanic(__name__, log_config=None)

That's what i did in above example, it works fine. But I agree with @r0fls, from UX standpoint, it's not very good.

@yunstanford what about this:

from sanic.config import LOGGING
LOGGING["disable_existing_loggers"] = False
# do whatever you want on logging package. setting this to false would not let LOGGING
# overwrite any of your config

maybe set disable_existing_loggers to False by default in LOGGING would be a better design?

@MrXu is this still an issue? There have been some changes to logging. It's unfortunately still a mess though...

Still an issue yes

@ekarlso are you using the master branch? I was able to set a custom logger using the master branch and the override_logging.py example.

For me the logging seems a bit too complex. There are good ideas in it. However, it should not be necessary to learn logging for Sanic, people should just be able to use plain stdlib logging. So IMHO instead of making little fixes here and there it would be best to refactor logging to be really simple. Instead of providing a big default config which needs to be altered (and therefore known) we could maybe provide a small default config and some opt-in building blocks. -- Just some thoughts without having dug into the implementation too much...

Still an issue until now.....

@tonyplayboy I am closing this for now. If you are still experiencing an issue with logging, please open a new issue or conversation on the community forums/

Was this page helpful?
0 / 5 - 0 ratings