LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': FORMATTERS, 'handlers': HANDLERS, 'loggers': { 'django': { 'handlers': ['django', 'mail_admin', 'exception'], 'level': 'INFO', 'propagate': False }, 'django.db.backends': { 'handlers': ['default'], 'level': 'DEBUG', 'propagate': False }, 'access': { 'handlers': ['access'], 'level': 'INFO', 'propagate': False }, 'celery.tasks': { 'handlers': ['mail_admin'], 'level': 'INFO', 'propagate': False }, 'parso': { 'handlers': ['parso'], 'level': 'INFO' } }, 'root': { 'handlers': ['default', 'mail_admin', 'exception'], 'level': 'DEBUG' }, }
If thedisable_existing_loggers
key in theLOGGING
dictConfig is set toTrue
(which is thedictConfig
default if the key is missing) then
all loggers from the default configuration will be disabled.
FORMATTERS
FORMATTERS = { 'access': { 'format': '%(client_ip)s %(x_forwarded_ip)s %(asctime)s %(process)d/%(thread)d %(http_user_agent)s ' '%(server_name)s %(protocol)s %(path)s %(status)s %(content_length)s %(duration)s ' '%(levelname)s %(user)s %(last_login_role)s %(data_b)s %(message)s', 'datefmt': "%Y/%m/%d %H:%M:%S" }, 'django': { 'format': '[%(asctime)s] %(process)d/%(thread)d %(levelname)s %(message)s', 'datefmt': "%Y/%m/%d %H:%M:%S" }, 'exception': { 'format': '[%(asctime)s] %(process)d/%(thread)d %(name)s %(funcName)s %(lineno)s %(levelname)s %(message)s', 'datefmt': "%Y/%m/%d %H:%M:%S" }, 'default': { 'format': '%(asctime)s %(process)d/%(thread)d %(name)s:%(lineno)s %(levelname)s - %(message)s', 'datefmt': "%Y/%m/%d %H:%M:%S" } }
if datefmt (a string) is specified, it is used with time.strftime() to format the creation time of the record.
fields:
Attribute name | Format | Description |
---|---|---|
args | You shouldn’t need to format this yourself. | The tuple of arguments merged into |
asctime |
| Human-readable time when the |
created |
| Time when the |
exc_info | You shouldn’t need to format this yourself. | Exception tuple (à la |
filename |
| Filename portion of |
funcName |
| Name of function containing the logging call. |
levelname |
| Text logging level for the message ( |
levelno |
| Numeric logging level for the message ( |
lineno |
| Source line number where the logging call was issued (if available). |
message |
| The logged message, computed as |
module |
| Module (name portion of |
msecs |
| Millisecond portion of the time when the |
msg | You shouldn’t need to format this yourself. | The format string passed in the original logging call. Merged with |
name |
| Name of the logger used to log the call. |
pathname |
| Full pathname of the source file where the logging call was issued (if available). |
process |
| Process ID (if available). |
processName |
| Process name (if available). |
relativeCreated |
| Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded. |
stack_info | You shouldn’t need to format this yourself. | Stack frame information (where available) from the bottom of the stack in the current thread, up to and including the stack frame of the logging call which resulted in the creation of this record. |
thread |
| Thread ID (if available). |
threadName |
| Thread name (if available). |
你也可以自定义
建议在自定义中间件中设置
class LoggingMiddleware(object): def __init__(self, get_response): self.get_response = get_response self.logger = logging.getLogger('django') self.logger_access = logging.getLogger('access') def process_response(self, request, response): logging_dict = { 'duration': time() - request.timer, 'client_ip': request.META.get('REMOTE_ADDR'), 'x_forwarded_ip': 'path': request.full_path, 'status': response.status_code, 'user': user_login_id, 'last_login_role': last_login_role, 'http_user_agent': request.META.get('HTTP_USER_AGENT'), 'server_name': request.META.get('SERVER_NAME'), 'content_length': request.META.get('CONTENT_LENGTH'), 'protocol': request.META.get('SERVER_PROTOCOL'), 'data_b': data_b } self.logger_access.info(data_c, extra=logging_dict) # 通过关键字参数extra
HANDLERS
HANDLERS = {
'mail_admin': {
'level': 'ERROR',
'class': 'gacommon.helpers.SendEmailHandler'
},
'django': {
'level': 'INFO',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': '/logs/server.log',
'when': 'midnight', # 时间后缀
'interval': 1,
'formatter': 'django'
},
'exception': {
'level': 'WARNING',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': '/logs/exception.log',
'when': 'midnight',
'interval': 1,
'formatter': 'exception'
},
'access': {
'level': 'INFO',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': '/logs/access.log',
'when': 'midnight',
'interval': 1,
'formatter': 'access'
},
'parso': {
'level': 'INFO',
'class': 'logging.StreamHandler',
'formatter': 'default'
},
'default': {
'level': 'INFO',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': '/logs/default.log',
'when': 'midnight',
'interval': 1,
'formatter': 'default'
}
}
通过自定email,在异常发生时发送邮件
class SendEmailHandler(Handler): """An exception log handler that emails log entries to settings.EXCEPTION_MAIL_LIST. """ actitve_count = 0 @postpone def send_admin_mail(self, subject, message, mail_from, mail_to, fail_silently): if SendEmailHandler.actitve_count < 5: SendEmailHandler.actitve_count += 1 send_mail(subject, message, mail_from, mail_to, fail_silently=fail_silently) SendEmailHandler.actitve_count -= 1 else: pass def emit(self, record): if os.getenv('DONT_SEND_EXCEPTION_MAIL'): # 应用于本地开发 return
subject = '%s: %s %s' % ( ENV.upper(), record.levelname, record.getMessage() ) def format_subject(subject): """ Escape CR and LF characters. """ return subject.replace('\n', ' ').replace('\r', ' ') subject = format_subject(subject) # 邮件标题 message = record.getMessage() + '\n' + traceback.format_exc() self.send_admin_mail(subject, message, EXCEPTION_MAIL_FROM, EXCEPTION_MAIL_LIST, False)
settings中邮件配置
EXCEPTION_MAIL_FROM = '' EMAIL_HOST = 'smtp.xx.com' EMAIL_PORT = '' EMAIL_HOST_USER = '' EMAIL_HOST_PASSWORD = '' EMAIL_USE_TLS = True EXCEPTION_MAIL_LIST = []