1 | # log.py - adapt python logging module to SQLAlchemy |
---|
2 | # Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com |
---|
3 | # |
---|
4 | # This module is part of SQLAlchemy and is released under |
---|
5 | # the MIT License: http://www.opensource.org/licenses/mit-license.php |
---|
6 | |
---|
7 | """Logging control and utilities. |
---|
8 | |
---|
9 | Control of logging for SA can be performed from the regular python logging |
---|
10 | module. The regular dotted module namespace is used, starting at |
---|
11 | 'sqlalchemy'. For class-level logging, the class name is appended. |
---|
12 | |
---|
13 | The "echo" keyword parameter which is available on SQLA ``Engine`` |
---|
14 | and ``Pool`` objects corresponds to a logger specific to that |
---|
15 | instance only. |
---|
16 | |
---|
17 | E.g.:: |
---|
18 | |
---|
19 | engine.echo = True |
---|
20 | |
---|
21 | is equivalent to:: |
---|
22 | |
---|
23 | import logging |
---|
24 | logger = logging.getLogger('sqlalchemy.engine.Engine.%s' % hex(id(engine))) |
---|
25 | logger.setLevel(logging.DEBUG) |
---|
26 | |
---|
27 | """ |
---|
28 | |
---|
29 | import logging |
---|
30 | import sys |
---|
31 | |
---|
32 | |
---|
33 | rootlogger = logging.getLogger('sqlalchemy') |
---|
34 | if rootlogger.level == logging.NOTSET: |
---|
35 | rootlogger.setLevel(logging.WARN) |
---|
36 | |
---|
37 | default_enabled = False |
---|
38 | def default_logging(name): |
---|
39 | global default_enabled |
---|
40 | if logging.getLogger(name).getEffectiveLevel() < logging.WARN: |
---|
41 | default_enabled = True |
---|
42 | if not default_enabled: |
---|
43 | default_enabled = True |
---|
44 | handler = logging.StreamHandler(sys.stdout) |
---|
45 | handler.setFormatter(logging.Formatter( |
---|
46 | '%(asctime)s %(levelname)s %(name)s %(message)s')) |
---|
47 | rootlogger.addHandler(handler) |
---|
48 | |
---|
49 | def class_logger(cls, enable=False): |
---|
50 | logger = logging.getLogger(cls.__module__ + "." + cls.__name__) |
---|
51 | if enable == 'debug': |
---|
52 | logger.setLevel(logging.DEBUG) |
---|
53 | elif enable == 'info': |
---|
54 | logger.setLevel(logging.INFO) |
---|
55 | cls._should_log_debug = logger.isEnabledFor(logging.DEBUG) |
---|
56 | cls._should_log_info = logger.isEnabledFor(logging.INFO) |
---|
57 | cls.logger = logger |
---|
58 | |
---|
59 | def instance_logger(instance, echoflag=None): |
---|
60 | """create a logger for an instance. |
---|
61 | |
---|
62 | Warning: this is an expensive call which also results in a permanent |
---|
63 | increase in memory overhead for each call. Use only for |
---|
64 | low-volume, long-time-spanning objects. |
---|
65 | |
---|
66 | """ |
---|
67 | |
---|
68 | # limit the number of loggers by chopping off the hex(id). |
---|
69 | # many novice users unfortunately create an unlimited number |
---|
70 | # of Engines in their applications which would otherwise |
---|
71 | # cause the app to run out of memory. |
---|
72 | name = "%s.%s.0x...%s" % (instance.__class__.__module__, |
---|
73 | instance.__class__.__name__, |
---|
74 | hex(id(instance))[-4:]) |
---|
75 | |
---|
76 | if echoflag is not None: |
---|
77 | l = logging.getLogger(name) |
---|
78 | if echoflag == 'debug': |
---|
79 | default_logging(name) |
---|
80 | l.setLevel(logging.DEBUG) |
---|
81 | elif echoflag is True: |
---|
82 | default_logging(name) |
---|
83 | l.setLevel(logging.INFO) |
---|
84 | elif echoflag is False: |
---|
85 | l.setLevel(logging.NOTSET) |
---|
86 | else: |
---|
87 | l = logging.getLogger(name) |
---|
88 | instance._should_log_debug = l.isEnabledFor(logging.DEBUG) |
---|
89 | instance._should_log_info = l.isEnabledFor(logging.INFO) |
---|
90 | return l |
---|
91 | |
---|
92 | class echo_property(object): |
---|
93 | __doc__ = """\ |
---|
94 | When ``True``, enable log output for this element. |
---|
95 | |
---|
96 | This has the effect of setting the Python logging level for the namespace |
---|
97 | of this element's class and object reference. A value of boolean ``True`` |
---|
98 | indicates that the loglevel ``logging.INFO`` will be set for the logger, |
---|
99 | whereas the string value ``debug`` will set the loglevel to |
---|
100 | ``logging.DEBUG``. |
---|
101 | """ |
---|
102 | |
---|
103 | def __get__(self, instance, owner): |
---|
104 | if instance is None: |
---|
105 | return self |
---|
106 | else: |
---|
107 | return instance._should_log_debug and 'debug' or (instance._should_log_info and True or False) |
---|
108 | |
---|
109 | def __set__(self, instance, value): |
---|
110 | instance_logger(instance, echoflag=value) |
---|