Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to use click_log.basic_config() to configure format? #13

Open
flokli opened this issue Jan 29, 2018 · 6 comments
Open

how to use click_log.basic_config() to configure format? #13

flokli opened this issue Jan 29, 2018 · 6 comments
Labels

Comments

@flokli
Copy link

flokli commented Jan 29, 2018

The docs are not really verbose about how to use click_log.basic_config().

Most intuitive way would be for it to have the same usage as here.

I wanted it to show the __name__ I pass into logging.getLogger(__name__), and preserve color output.

@untitaker
Copy link
Collaborator

click_log.basic_config works the same. You call it with the root logger or the logger you want to use at import time. The only thing that it does not do is to set the level, since that might be dependent on a CLI option. You can use simple_verbosity_option for that.

What are you missing from the docs? They contain an example where it's used after all.

@flokli
Copy link
Author

flokli commented Feb 21, 2018

This was more related to the format parameter that logging.basic_config(format=…) exposes, but click_log.basic_config() currently doesn't.

In my usecase I'd like to keep the coloring depending on log level as prefix, but change the rest of the printed text to include the loggers name, date etc, without having to duplicate most of the color handling in ColorFormatter.

What's your opinion on changing click_log.basic_configs signature to basic_config(logger=None, format='%(message)s'), and adding needed wiring to ColorFormatter? If somebody doesn't want the color formatting, he could simply use another Formatter, but configuring the rest of the format string inside ColorFormatter should be made possible.

@flokli flokli changed the title how to use click_log.basic_config()? how to use click_log.basic_config() to configure format? Feb 21, 2018
@untitaker
Copy link
Collaborator

untitaker commented Feb 22, 2018 via email

@flokli
Copy link
Author

flokli commented Apr 16, 2018

@untitaker I had a look into it.

We already subclass logging.Formatter, to which we could pass a custom format parameter, and simply use super().format(record) and click.style inside of our format(self, record) implementation - with getting support for all LogRecord parameters for free as a bonus :-)

However, honoring a passed format string would also mean and not treating messages differently depending on a log level, which is currently intended behaviour.

In addition, we'd only be able to color the message as a whole (by calling click.style on the string returned from super().format()). Working around that by passing a copy of the original record with color escape strings on the loglevel attribute to super().format() looks really hacky for me.

So what's your opinion on it? I'd really like to see support for the format parameter and friends in click-log, rather than having users subclassing on their own…

@untitaker
Copy link
Collaborator

untitaker commented Apr 16, 2018

You're suggesting this:

basic_config(format='...')

I would suggest:

basic_config(formatter=MyFormatter(format='...'))

Feel free to include a formatter you'd like (separate from ColorFormatter) in the PR too, but also with a default format string so I can understand what you're doing with it.

My usecase for the current logger is: simple command line applications where the output is usually not written to a file.

@jamestwebber
Copy link

👋 hello all, happened across this issue because I wanted my nicely-formatted logs to have fancy colors.

This is a bit of a hack but it does work:

class ColorFormatter(logging.Formatter):
    colors = {
        'ERROR': dict(fg='red'),
        'EXCEPTION': dict(fg='red'),
        'CRITICAL': dict(fg='red'),
        'DEBUG': dict(fg='blue'),
        'WARNING': dict(fg='yellow'),
        'INFO': dict(fg='green'),
    }

    def format(self, record):
        formatted_msg = super().format(record)

        if self._fmt.find("levelname") > -1:
            formatted_msg = formatted_msg.replace(
                record.levelname,
                click.style(record.levelname, **self.colors[record.levelname])
            )

        return formatted_msg 

A couple notes:

  • the main hackiness is using replace to find levelname. If your message happens to contain the same string, that will get the color formatting too. This was a heck of a lot easier than supporting all three of the logging formats, including potential formatting like %(levelname)5s, but it feels a bit gross
  • click_log usually outputs levelname in lowercase, the above code does not. This could easily be accomplished with a little tweaking. Ideally it'd be an option when setting up a formatter.
  • there was no color for INFO and rather than special-case it I just made it green (might as well hit Color on info level #19 :) )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants