17

By default I can enable logging in settings.py in the LOGGING configuration by creating a logger "" which will catch all logs. But what if I only want to see logging from my project's apps as opposed to Django internals?

I can imagine explicitly getting a logger in each of my Django app modules and naming it by some convention, e.g. logging.getLogger("myproject." + __file__). Then I can create a logger called 'myproject' (in SETTINGS) which picks up all of these to output. I'd prefer not to hardcode my project name, so I'd do some os.path logic on ___file___ to extract the full namespace up to the file at any arbitrary depth.

At this point, I stop and wonder is there an easier way?

Nitin Nain
  • 5,113
  • 1
  • 37
  • 51
John Lehmann
  • 7,975
  • 4
  • 58
  • 71
  • 1
    Have you read through the logging docs (https://docs.djangoproject.com/en/dev/topics/logging/#configuring-logging) ? There is a "myproject.custom" logger that appears similar to what you are looking for. – Scott Woodall Jun 01 '13 at 19:37
  • 1
    Yes I did. I didn't see anything that would simplify what I described, but if it does that would be a great answer. – John Lehmann Jun 01 '13 at 20:07
  • 1
    I re-read your question after I posted my comment and realized it probably wouldn't offer any additional insight. To that, apologies. – Scott Woodall Jun 01 '13 at 20:13
  • Did you ever find a nice solution to this? – seans Mar 24 '16 at 12:18
  • Honestly can't remember/tell at this point. I have upvoted these answers as they look pretty good. – John Lehmann Mar 25 '16 at 14:47

3 Answers3

22

You could use a scheme like the following to create identical loggers for all of your local apps without having to manually add them all to the logging configuration.

First, split out your local apps:

LOCAL_APPS = [
    'myapp1',
    'myapp2',
    ...
]

THIRD_PARTY_APPS = [
    'django. ...',
    ...
]

INSTALLED_APPS = LOCAL_APPS + THIRD_PARTY_APPS

Next create the logger configuration for your local apps:

local_logger_conf = {
    'handlers': ['my_handler',],
    'level': 'DEBUG',
}

Finally, define your loggers as follows:

'loggers': { app: copy.deepcopy(local_logger_conf) for app in LOCAL_APPS }
alanwj
  • 539
  • 5
  • 5
  • this is a really good answer. It allows several applications to be created without having them all reside in a unique namespace that is specific to the project. However, it also allows you to grab DEBUG logging on all of them. Otherwise you end up with a cluttered log of all libraries OR you have to write a huge settings tree for each application, disrespecting DRY. – pascalwhoop Nov 14 '18 at 13:10
  • yes. This is fairly easy. +1 for your answer and +1 for django using python as configuration file – Lukr Feb 08 '20 at 14:05
13

Not sure if I fully understood your question, because the answer seems too simple.

Assuming you have defined in LOGGING a handler for your project's apps, for example like this:

'handlers': {
    'handler_for_my_apps': {
        'level': 'DEBUG',
        'class': 'logging.FileHandler',
        'filename': 'debug.log',
    },

and given your apps app1, app2, and so, you could have all the logs from those apps without any Django's internal logs by defining the loggers:

'loggers': {
    'app1': {
        'handlers': ['handler_for_my_apps'],
        'level': 'DEBUG',
    },
    'app2': {
        'handlers': ['handler_for_my_apps'],
        'level': 'DEBUG',
    },

There will be no Django logs in the same file, unless of course you defined a logger named django with a handler handler_for_my_apps.

In your apps you can get the logger using logging.getLogger(__name__) as recommended by the docs.

Unless I misunderstood your question...

janos
  • 120,954
  • 29
  • 226
  • 236
2

Thank you for sharing, reading this post helped solve logging for my project. I'll share the solution I opted for, hoping it can help other people. Define a list of Dictionaries:

LOCAL_APPS = [
   {'app_name': 'app1', 'level': 'INFO'},
   {'app_name': 'app2', 'level': 'DEBUG'},
   ]

Now create a function to modify settings' LOGGING:

def create_app_logger(app_name, level):
    app_handler = app_name + '_handler'
    LOGGING['handlers'][app_handler] = {
        'level': 'INFO',
        'class': 'logging.FileHandler',
        'filename': f'../logs/{app_name}_logs.log',
        'formatter': 'custom',
    }
    LOGGING['loggers'][app_name] = {
        'handlers': ['console', app_handler],
        'level': level,
        'propagate': False,
    }

Finally loop through the list:

for dictionary in LOCAL_APPS:
    create_app_logger(dictionary['app_name'], dictionary['level'])

Since an app can be a world on it's own, this way you'll have a log file for each app, plus you have control over the logging level you want. It could be further personalized of course.

Cheers