logging config & common app
Showing
19 changed files
with
520 additions
and
1 deletions
| 1 | certifi==2016.2.28 | 1 | certifi==2016.2.28 |
| 2 | Django==2.1 | 2 | Django==2.1 |
| 3 | djangorestframework==3.9.0 | ||
| 4 | djangorestframework-jwt==1.11.0 | ||
| 5 | PyJWT==1.7.1 | ||
| 6 | PyMuPDF==1.17.0 | ||
| 3 | pytz==2020.1 | 7 | pytz==2020.1 |
| 4 | # simple-config @ http://gitlab.situdata.com/zhouweiqi/simple_config/repository/archive.tar.gz?ref=master | 8 | # simple-config @ http://gitlab.situdata.com/zhouweiqi/simple_config/repository/archive.tar.gz?ref=master |
| 9 | # situlogger @ http://gitlab.situdata.com/zhouweiqi/situlogger/repository/archive.tar.gz?ref=master | ||
| 10 | six==1.14.0 | ... | ... |
| 1 | http://gitlab.situdata.com/zhouweiqi/simple_config/repository/archive.tar.gz?ref=master | 1 | http://gitlab.situdata.com/zhouweiqi/simple_config/repository/archive.tar.gz?ref=master |
| 2 | http://gitlab.situdata.com/zhouweiqi/situlogger/repository/archive.tar.gz?ref=master | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
src/apps/account/__init__.py
0 → 100644
File mode changed
src/apps/account/admin.py
0 → 100644
src/apps/account/apps.py
0 → 100644
src/apps/account/models.py
0 → 100644
src/apps/account/permissions.py
0 → 100644
| 1 | from rest_framework.permissions import DjangoModelPermissions | ||
| 2 | |||
| 3 | |||
| 4 | class Permissions(DjangoModelPermissions): | ||
| 5 | """ | ||
| 6 | copy from rest_framework/permissions.py | ||
| 7 | """ | ||
| 8 | |||
| 9 | def has_permission(self, request, view): | ||
| 10 | # Workaround to ensure DjangoModelPermissions are not applied | ||
| 11 | # to the root view when using DefaultRouter. | ||
| 12 | if getattr(view, '_ignore_model_permissions', False): | ||
| 13 | return True | ||
| 14 | |||
| 15 | if not request.user: | ||
| 16 | return False | ||
| 17 | |||
| 18 | if self.authenticated_users_only and not request.user.is_authenticated: | ||
| 19 | return False | ||
| 20 | |||
| 21 | # if not request.user.is_staff: | ||
| 22 | # return False | ||
| 23 | |||
| 24 | perms = getattr(view, 'method_perms', {}).get(request.method, []) | ||
| 25 | |||
| 26 | return request.user.has_perms(perms) |
src/apps/account/tests.py
0 → 100644
src/apps/account/urls.py
0 → 100644
src/apps/account/views.py
0 → 100644
| ... | @@ -14,8 +14,9 @@ Including another URLconf | ... | @@ -14,8 +14,9 @@ Including another URLconf |
| 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) | 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) |
| 15 | """ | 15 | """ |
| 16 | from django.contrib import admin | 16 | from django.contrib import admin |
| 17 | from django.urls import path | 17 | from django.urls import path, include |
| 18 | 18 | ||
| 19 | urlpatterns = [ | 19 | urlpatterns = [ |
| 20 | path('admin/', admin.site.urls), | 20 | path('admin/', admin.site.urls), |
| 21 | path(r'apis/v1/users/', include('apps.account.urls')), | ||
| 21 | ] | 22 | ] | ... | ... |
src/common/__init__.py
0 → 100644
File mode changed
src/common/apps.py
0 → 100644
src/common/exceptions.py
0 → 100644
| 1 | import logging | ||
| 2 | import six | ||
| 3 | from django.core.exceptions import PermissionDenied | ||
| 4 | from django.utils.translation import ugettext_lazy as _ | ||
| 5 | from django.http import Http404 | ||
| 6 | from rest_framework import exceptions, status | ||
| 7 | from rest_framework.response import Response | ||
| 8 | |||
| 9 | from .response import MetaStatus, res_content, APIResponse | ||
| 10 | |||
| 11 | error_logger = logging.getLogger('exception') | ||
| 12 | |||
| 13 | |||
| 14 | def exception_handler(exc, context): | ||
| 15 | """ | ||
| 16 | Returns the response that should be used for any given exception. | ||
| 17 | |||
| 18 | By default we handle the REST framework `APIException`, and also | ||
| 19 | Django's built-in `Http404` and `PermissionDenied` | ||
| 20 | |||
| 21 | Any unhandled exceptions may return `None`, which will cause a 500 error | ||
| 22 | to be raised. | ||
| 23 | """ | ||
| 24 | if isinstance(exc, exceptions.APIException): | ||
| 25 | headers = {} | ||
| 26 | if getattr(exc, 'auth_header', None): | ||
| 27 | headers['WWW-Authenticate'] = exc.auth_header | ||
| 28 | if getattr(exc, 'wait', None): | ||
| 29 | headers['Retry-After'] = '%d' % exc.wait | ||
| 30 | |||
| 31 | if exc.status_code == 403: | ||
| 32 | data = res_content(MetaStatus.NEED_LOGIN.value, MetaStatus.NEED_LOGIN.verbose_name) | ||
| 33 | else: | ||
| 34 | data = res_content(MetaStatus.INTERNAL_ERROR.value, exc.detail) | ||
| 35 | |||
| 36 | return Response(data, status=200, headers=headers) | ||
| 37 | |||
| 38 | elif isinstance(exc, Http404): | ||
| 39 | msg = _('Not found.') | ||
| 40 | data = {'detail': six.text_type(msg)} | ||
| 41 | |||
| 42 | return Response(data, status=status.HTTP_404_NOT_FOUND) | ||
| 43 | |||
| 44 | elif isinstance(exc, PermissionDenied): | ||
| 45 | msg = _('Permission denied.') | ||
| 46 | data = {'detail': six.text_type(msg)} | ||
| 47 | |||
| 48 | return Response(data, status=status.HTTP_403_FORBIDDEN) | ||
| 49 | |||
| 50 | elif isinstance(exc, Exception) and hasattr(exc, 'API_META_STATUS'): | ||
| 51 | msg = exc.API_META_STATUS.verbose_name | ||
| 52 | return APIResponse(exc.API_META_STATUS.value, msg=msg) | ||
| 53 | |||
| 54 | error_logger.exception('[system error]') | ||
| 55 | return APIResponse(MetaStatus.INTERNAL_ERROR.value, | ||
| 56 | msg=MetaStatus.INTERNAL_ERROR.verbose_name) | ||
| 57 | |||
| 58 | |||
| 59 | class NeedLoginException(Exception): | ||
| 60 | API_META_STATUS = MetaStatus.NEED_LOGIN | ||
| 61 | |||
| 62 | |||
| 63 | class InvalidParamsException(Exception): | ||
| 64 | API_META_STATUS = MetaStatus.INVALID_PARAMS | ||
| 65 | |||
| 66 | |||
| 67 | class InternalErrorException(Exception): | ||
| 68 | API_META_STATUS = MetaStatus.INTERNAL_ERROR | ||
| 69 | |||
| 70 | |||
| 71 | class ObjectNotExitException(Exception): | ||
| 72 | API_META_STATUS = MetaStatus.NOT_EXIST | ||
| 73 | |||
| 74 | |||
| 75 | class AsyncWaitException(Exception): | ||
| 76 | API_META_STATUS = MetaStatus.ASYNC_WAIT | ||
| 77 | |||
| 78 | |||
| 79 | class NoPermissionException(Exception): | ||
| 80 | API_META_STATUS = MetaStatus.NO_PERMISSION | ||
| 81 | |||
| 82 | |||
| 83 | class IllegalOperationException(Exception): | ||
| 84 | API_META_STATUS = MetaStatus.ILLEGAL_OPERATION |
src/common/mixins.py
0 → 100644
| 1 | import logging | ||
| 2 | from django.contrib.auth.models import AnonymousUser | ||
| 3 | from rest_framework.generics import GenericAPIView | ||
| 4 | from common.exceptions import ( | ||
| 5 | NeedLoginException, | ||
| 6 | InvalidParamsException, | ||
| 7 | InternalErrorException, | ||
| 8 | ObjectNotExitException, | ||
| 9 | AsyncWaitException, | ||
| 10 | NoPermissionException, | ||
| 11 | IllegalOperationException) | ||
| 12 | |||
| 13 | |||
| 14 | class GenericExceptionMixin: | ||
| 15 | |||
| 16 | def need_login(self, msg='need login'): | ||
| 17 | raise NeedLoginException(msg) | ||
| 18 | |||
| 19 | def invalid_params(self, msg='invalid params'): | ||
| 20 | raise InvalidParamsException(msg) | ||
| 21 | |||
| 22 | def internal_error(self, msg='internal error'): | ||
| 23 | raise InternalErrorException(msg) | ||
| 24 | |||
| 25 | def object_not_exit(self, msg='object not exit'): | ||
| 26 | raise ObjectNotExitException(msg) | ||
| 27 | |||
| 28 | def async_wait(self, msg='async wait'): | ||
| 29 | raise AsyncWaitException(msg) | ||
| 30 | |||
| 31 | def no_permission(self, msg='no permission'): | ||
| 32 | raise NoPermissionException(msg) | ||
| 33 | |||
| 34 | def illegal_operation(self, msg='illegal operation'): | ||
| 35 | raise IllegalOperationException(msg) | ||
| 36 | |||
| 37 | |||
| 38 | class LoggerMixin: | ||
| 39 | running_log = logging.getLogger('running') | ||
| 40 | exception_log = logging.getLogger('exception') | ||
| 41 | cronjob_log = logging.getLogger('cronjob') | ||
| 42 | |||
| 43 | |||
| 44 | class GenericView(LoggerMixin, GenericExceptionMixin, GenericAPIView): | ||
| 45 | need_print_logger = True | ||
| 46 | |||
| 47 | def print_logger(self, request): | ||
| 48 | parameters = getattr(request, request.method, {}) | ||
| 49 | if not parameters: | ||
| 50 | parameters = getattr(request, 'data', {}) | ||
| 51 | if not parameters: | ||
| 52 | parameters = {} | ||
| 53 | parameters_string = '' | ||
| 54 | for key, value in parameters.items(): | ||
| 55 | parameters_string += '[%s=%s] ' % (key, value) | ||
| 56 | for key, value in self.kwargs.items(): | ||
| 57 | parameters_string += '[%s=%s] ' % (key, value) | ||
| 58 | if request.user and not isinstance(request.user, AnonymousUser): | ||
| 59 | user_id = request.user.id | ||
| 60 | else: | ||
| 61 | user_id = 0 | ||
| 62 | self.running_log.info('[%s_%s_request] with parameters [user_id=%s] %s' | ||
| 63 | % (self.__class__.__name__, request.method, | ||
| 64 | user_id, parameters_string)) | ||
| 65 | |||
| 66 | def dispatch(self, request, *args, **kwargs): | ||
| 67 | """ | ||
| 68 | `.dispatch()` is pretty much the same as Django's regular dispatch, | ||
| 69 | but with extra hooks for startup, finalize, and exception handling. | ||
| 70 | """ | ||
| 71 | self.args = args | ||
| 72 | self.kwargs = kwargs | ||
| 73 | request = self.initialize_request(request, *args, **kwargs) | ||
| 74 | self.request = request | ||
| 75 | self.headers = self.default_response_headers # deprecate? | ||
| 76 | try: | ||
| 77 | self.initial(request, *args, **kwargs) | ||
| 78 | |||
| 79 | # Get the appropriate handler method | ||
| 80 | if request.method.lower() in self.http_method_names: | ||
| 81 | handler = getattr(self, request.method.lower(), | ||
| 82 | self.http_method_not_allowed) | ||
| 83 | else: | ||
| 84 | handler = self.http_method_not_allowed | ||
| 85 | |||
| 86 | if self.need_print_logger: | ||
| 87 | self.print_logger(request) | ||
| 88 | |||
| 89 | response = handler(request, *args, **kwargs) | ||
| 90 | except Exception as exc: | ||
| 91 | response = self.handle_exception(exc) | ||
| 92 | |||
| 93 | self.response = self.finalize_response( | ||
| 94 | request, response, *args, **kwargs) | ||
| 95 | return self.response | ||
| 96 | |||
| 97 | def get_object(self): | ||
| 98 | return None |
src/common/named_enum.py
0 → 100644
| 1 | import enum | ||
| 2 | from functools import lru_cache | ||
| 3 | |||
| 4 | |||
| 5 | class NamedEnum(enum.Enum): | ||
| 6 | """ | ||
| 7 | >>> @enum.unique | ||
| 8 | ... class Status(NamedEnum): | ||
| 9 | ... CREATED = (3, '初始化') | ||
| 10 | ... CANCELED = (2, '损坏') | ||
| 11 | ... FINISHED = (1, '完成') | ||
| 12 | ... REJECTED = (4, '拒绝') | ||
| 13 | ... TEST = (6, '拒绝') | ||
| 14 | >>> assert Status.CREATED != 3 | ||
| 15 | >>> assert Status.CREATED.value == 3 | ||
| 16 | >>> assert Status.CREATED.name == 'CREATED' | ||
| 17 | >>> assert Status.CREATED.verbose_name == '初始化' | ||
| 18 | >>> assert Status(3) == Status.CREATED | ||
| 19 | >>> assert Status['CREATED'] == Status.CREATED | ||
| 20 | >>> assert Status.get_verbose_name_or_raise(3) == '初始化' | ||
| 21 | >>> assert Status.get_mappings() == { | ||
| 22 | ... 3: '初始化', 2: '损坏', 1: '完成', 4: '拒绝', 6: '拒绝'} | ||
| 23 | >>> assert Status.get_mapping_lst() == [ | ||
| 24 | ... {'id': 3, 'name': '初始化'}, | ||
| 25 | ... {'id': 2, 'name': '损坏'}, | ||
| 26 | ... {'id': 1, 'name': '完成'}, | ||
| 27 | ... {'id': 4, 'name': '拒绝'}, | ||
| 28 | ... {'id': 6, 'name': '拒绝'} | ||
| 29 | ... ] | ||
| 30 | >>> assert Status.get_verbose_name(5, '默认') == '默认' | ||
| 31 | >>> assert Status.get_value_or_raise('完成') == 1 | ||
| 32 | >>> assert Status.get_value('完成完成', 100) == 100 | ||
| 33 | >>> assert Status.get_value_or_raise('拒绝') == 4 | ||
| 34 | >>> # 测试扩展功能 | ||
| 35 | >>> extend_values = { | ||
| 36 | ... 'EXTENDED': (6, '扩展') | ||
| 37 | ... } | ||
| 38 | >>> ExtendedStatus = extend(Status, 'ExtendedStatus', extend_values) | ||
| 39 | >>> assert ExtendedStatus.get_verbose_name(5, '默认') == '默认' | ||
| 40 | >>> assert ExtendedStatus.get_value_or_raise('完成') == 1 | ||
| 41 | >>> assert ExtendedStatus.get_value('完成完成', 100) == 100 | ||
| 42 | >>> assert ExtendedStatus.get_value_or_raise('拒绝') == 4 | ||
| 43 | >>> assert ExtendedStatus.EXTENDED.value == 6 | ||
| 44 | >>> ExtendedStatus = extend( | ||
| 45 | ... Status, 'ExtendedStatus', [('EXTENDED', (6, '扩展'))]) | ||
| 46 | >>> assert ExtendedStatus.EXTENDED.value == 6 | ||
| 47 | >>> try: | ||
| 48 | ... ExtendedStatus = extend( | ||
| 49 | ... Status, 'ExtendedStatus', extend_values, unique=True) | ||
| 50 | ... except ValueError as err: | ||
| 51 | ... assert 'duplicate' in str(err) | ||
| 52 | ... else: | ||
| 53 | ... raise Exception('except ValueError') | ||
| 54 | """ | ||
| 55 | |||
| 56 | def __new__(cls, *args): | ||
| 57 | value, verbose_name = args | ||
| 58 | res = object.__new__(cls) | ||
| 59 | res._value_ = value | ||
| 60 | return res | ||
| 61 | |||
| 62 | def __init__(self, *args, **kwargs): | ||
| 63 | self._value_ = args[0] | ||
| 64 | self.verbose_name = args[1] | ||
| 65 | |||
| 66 | @classmethod | ||
| 67 | def get_verbose_name_or_raise(cls, value): | ||
| 68 | return cls.get_verbose_name(value, raise_on_missing=True) | ||
| 69 | |||
| 70 | @classmethod | ||
| 71 | def get_verbose_name(cls, value, default=None, raise_on_missing=False): | ||
| 72 | """尝试根据value获取verbose_name,如果失败,返回默认值 | ||
| 73 | """ | ||
| 74 | try: | ||
| 75 | return cls(value).verbose_name | ||
| 76 | except ValueError as err: | ||
| 77 | if raise_on_missing: | ||
| 78 | raise err | ||
| 79 | else: | ||
| 80 | return default | ||
| 81 | |||
| 82 | @classmethod | ||
| 83 | def get_value_or_raise(cls, verbose_name): | ||
| 84 | return cls.get_value(verbose_name, raise_on_missing=True) | ||
| 85 | |||
| 86 | @classmethod | ||
| 87 | def get_value(cls, verbose_name, default=None, raise_on_missing=False): | ||
| 88 | try: | ||
| 89 | return cls.from_verbose_name(verbose_name).value | ||
| 90 | except ValueError as err: | ||
| 91 | if raise_on_missing: | ||
| 92 | raise err | ||
| 93 | else: | ||
| 94 | return default | ||
| 95 | |||
| 96 | @classmethod | ||
| 97 | def from_verbose_name(cls, verbose_name): | ||
| 98 | """根据verbose_name获取NamedEnum, | ||
| 99 | 如果verbose_name重复出现,会返回第一个定义的记录 | ||
| 100 | """ | ||
| 101 | for member in cls._value2member_map_.values(): | ||
| 102 | if member.verbose_name == verbose_name: | ||
| 103 | return member | ||
| 104 | raise ValueError('%s is not a valid "%s"' % ( | ||
| 105 | verbose_name, cls.__name__)) | ||
| 106 | |||
| 107 | @classmethod | ||
| 108 | @lru_cache() | ||
| 109 | def get_mappings(cls): | ||
| 110 | return { | ||
| 111 | item.value: item.verbose_name | ||
| 112 | for _, item in cls._member_map_.items() | ||
| 113 | } | ||
| 114 | |||
| 115 | @classmethod | ||
| 116 | @lru_cache() | ||
| 117 | def get_mapping_lst(cls): | ||
| 118 | return list([ | ||
| 119 | {'id': item.value, 'name': item.verbose_name} | ||
| 120 | for item in cls | ||
| 121 | ]) | ||
| 122 | |||
| 123 | @classmethod | ||
| 124 | @lru_cache() | ||
| 125 | def get_value_lst(cls): | ||
| 126 | return list([ | ||
| 127 | item.value | ||
| 128 | for item in cls | ||
| 129 | ]) | ||
| 130 | |||
| 131 | @property | ||
| 132 | def raw_value(self): | ||
| 133 | return (self.value, self.verbose_name) | ||
| 134 | |||
| 135 | |||
| 136 | def extend(cls, sub_cls_name, names, unique=False): | ||
| 137 | assert issubclass(cls, NamedEnum) | ||
| 138 | target_names = { | ||
| 139 | item.name: item.raw_value for item in cls | ||
| 140 | } | ||
| 141 | if not isinstance(names, dict): | ||
| 142 | names = {item[0]: item[1] for item in names} | ||
| 143 | target_names.update(names) | ||
| 144 | sub_cls = NamedEnum(sub_cls_name, names=target_names) | ||
| 145 | if unique: | ||
| 146 | sub_cls = enum.unique(sub_cls) | ||
| 147 | return sub_cls |
src/common/response.py
0 → 100644
| 1 | import enum | ||
| 2 | from django.http import JsonResponse | ||
| 3 | from .named_enum import NamedEnum | ||
| 4 | |||
| 5 | |||
| 6 | def res_content(meta_status, msg, data=None): | ||
| 7 | if data is None: | ||
| 8 | data = {} | ||
| 9 | return {'code': meta_status, 'message': msg, 'data': data} | ||
| 10 | |||
| 11 | |||
| 12 | @enum.unique | ||
| 13 | class MetaStatus(NamedEnum): | ||
| 14 | SUCCESS = (0, 'success') | ||
| 15 | NEED_LOGIN = (1, 'need login') | ||
| 16 | INVALID_PARAMS = (2, 'invalid params') | ||
| 17 | INTERNAL_ERROR = (3, 'internal error') | ||
| 18 | NOT_EXIST = (4, 'object not exist') | ||
| 19 | ASYNC_WAIT = (5, 'async wait') | ||
| 20 | NO_PERMISSION = (6, 'no permission') | ||
| 21 | ILLEGAL_OPERATION = (7, 'illegal operation') | ||
| 22 | |||
| 23 | |||
| 24 | class APIResponse(JsonResponse): | ||
| 25 | def __init__(self, meta_status, data=None, msg='', json_dumps_params=None, **kwargs): | ||
| 26 | data = res_content(meta_status, msg, data) | ||
| 27 | json_dumps_params = json_dumps_params or {'ensure_ascii': False} | ||
| 28 | kwargs['json_dumps_params'] = json_dumps_params | ||
| 29 | super().__init__(data, **kwargs) | ||
| 30 | |||
| 31 | |||
| 32 | def ok(**kwargs): | ||
| 33 | return APIResponse(MetaStatus.SUCCESS.value, msg=MetaStatus.SUCCESS.verbose_name, **kwargs) |
| ... | @@ -12,6 +12,7 @@ https://docs.djangoproject.com/en/2.1/ref/settings/ | ... | @@ -12,6 +12,7 @@ https://docs.djangoproject.com/en/2.1/ref/settings/ |
| 12 | 12 | ||
| 13 | import os | 13 | import os |
| 14 | from . import conf | 14 | from . import conf |
| 15 | from logging import config | ||
| 15 | 16 | ||
| 16 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) | 17 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) |
| 17 | BASE_DIR = conf.BASE_DIR | 18 | BASE_DIR = conf.BASE_DIR |
| ... | @@ -38,6 +39,8 @@ INSTALLED_APPS = [ | ... | @@ -38,6 +39,8 @@ INSTALLED_APPS = [ |
| 38 | 'django.contrib.sessions', | 39 | 'django.contrib.sessions', |
| 39 | 'django.contrib.messages', | 40 | 'django.contrib.messages', |
| 40 | 'django.contrib.staticfiles', | 41 | 'django.contrib.staticfiles', |
| 42 | 'rest_framework', | ||
| 43 | 'common', | ||
| 41 | ] | 44 | ] |
| 42 | 45 | ||
| 43 | MIDDLEWARE = [ | 46 | MIDDLEWARE = [ |
| ... | @@ -119,3 +122,20 @@ USE_TZ = False | ... | @@ -119,3 +122,20 @@ USE_TZ = False |
| 119 | # https://docs.djangoproject.com/en/2.1/howto/static-files/ | 122 | # https://docs.djangoproject.com/en/2.1/howto/static-files/ |
| 120 | 123 | ||
| 121 | STATIC_URL = '/static/' | 124 | STATIC_URL = '/static/' |
| 125 | |||
| 126 | # RestFramework Settings | ||
| 127 | REST_FRAMEWORK = { | ||
| 128 | 'DEFAULT_PERMISSION_CLASSES': ( | ||
| 129 | 'rest_framework.permissions.IsAuthenticated', | ||
| 130 | 'apps.account.permissions.Permissions' | ||
| 131 | ), | ||
| 132 | 'DEFAULT_AUTHENTICATION_CLASSES': ( | ||
| 133 | 'rest_framework.authentication.BasicAuthentication', | ||
| 134 | 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', | ||
| 135 | ), | ||
| 136 | 'EXCEPTION_HANDLER': 'common.exceptions.exception_handler' | ||
| 137 | } | ||
| 138 | |||
| 139 | # 日志配置 | ||
| 140 | LOGGING_CONFIG = None | ||
| 141 | config.fileConfig(conf.LOGGING_CONFIG_FILE, disable_existing_loggers=False) | ... | ... |
| 1 | [loggers] | ||
| 2 | keys=root, running, exception, cronjob, django.db.backends | ||
| 3 | |||
| 4 | [handlers] | ||
| 5 | keys=consoleHandler, django_rotateFileHandler, exceptionFileHandler, cronjobFileHandler, djangodbFileHandler | ||
| 6 | |||
| 7 | [formatters] | ||
| 8 | keys=SituFormatter, dataLogFormatter | ||
| 9 | |||
| 10 | [formatter_SituFormatter] | ||
| 11 | format=[%(asctime)s] [%(process)d] [%(thread)d] [%(threadName)s] [%(filename)s:%(lineno)d] %(levelname)s %(message)s | ||
| 12 | datefmt= | ||
| 13 | |||
| 14 | [formatter_dataLogFormatter] | ||
| 15 | class=situlogger.JsonFormatter | ||
| 16 | format=%(asctime)s %(levelname)s %(funcName)s | ||
| 17 | |||
| 18 | [handler_consoleHandler] | ||
| 19 | class=StreamHandler | ||
| 20 | level=ERROR | ||
| 21 | formatter=SituFormatter | ||
| 22 | args=(sys.stdout,) | ||
| 23 | |||
| 24 | [handler_django_rotateFileHandler] | ||
| 25 | class=situlogger.SituRotatingFileHandler | ||
| 26 | level=INFO | ||
| 27 | formatter=SituFormatter | ||
| 28 | args=('../logs/running.log',) | ||
| 29 | |||
| 30 | [handler_exceptionFileHandler] | ||
| 31 | class=situlogger.SituRotatingFileHandler | ||
| 32 | level=ERROR | ||
| 33 | formatter=SituFormatter | ||
| 34 | args=('../logs/exception.log',) | ||
| 35 | |||
| 36 | [handler_cronjobFileHandler] | ||
| 37 | class=situlogger.SituRotatingFileHandler | ||
| 38 | level=DEBUG | ||
| 39 | formatter=SituFormatter | ||
| 40 | args=('../logs/cronjob.log',) | ||
| 41 | |||
| 42 | [handler_djangodbFileHandler] | ||
| 43 | class=situlogger.SituRotatingFileHandler | ||
| 44 | level=DEBUG | ||
| 45 | formatter=SituFormatter | ||
| 46 | args=('../logs/sql.log',) | ||
| 47 | |||
| 48 | [logger_root] | ||
| 49 | level=DEBUG | ||
| 50 | handlers=consoleHandler | ||
| 51 | |||
| 52 | [logger_running] | ||
| 53 | level=INFO | ||
| 54 | handlers=django_rotateFileHandler | ||
| 55 | qualname=running | ||
| 56 | propagate=0 | ||
| 57 | |||
| 58 | [logger_exception] | ||
| 59 | level=ERROR | ||
| 60 | handlers=exceptionFileHandler | ||
| 61 | qualname=exception | ||
| 62 | propagate=0 | ||
| 63 | |||
| 64 | [logger_cronjob] | ||
| 65 | level=INFO | ||
| 66 | handlers=cronjobFileHandler | ||
| 67 | qualname=cronjob | ||
| 68 | propagate=0 | ||
| 69 | |||
| 70 | [logger_django.db.backends] | ||
| 71 | level=DEBUG | ||
| 72 | handlers=djangodbFileHandler | ||
| 73 | qualname=django.db.backends | ||
| 74 | propagate=0 | ... | ... |
-
Please register or sign in to post a comment