From ada0391922d74c2be6ee8ec334795e68cc228139 Mon Sep 17 00:00:00 2001 From: Sayyid Hamid Mahdavi Date: Sat, 11 Apr 2026 14:50:03 +0330 Subject: [PATCH] logger --- .gitignore | 1 + main/other_settings/__init__.py | 0 main/other_settings/logging.py | 141 ++++++++++++++++++++++++++++++++ main/settings.py | 40 +-------- run.sh | 2 +- 5 files changed, 146 insertions(+), 38 deletions(-) create mode 100644 main/other_settings/__init__.py create mode 100644 main/other_settings/logging.py diff --git a/.gitignore b/.gitignore index 0d9702f..d96bde8 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ delme*.py .env /venv/ oidc.key +/logs/*.log diff --git a/main/other_settings/__init__.py b/main/other_settings/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/main/other_settings/logging.py b/main/other_settings/logging.py new file mode 100644 index 0000000..1a857f0 --- /dev/null +++ b/main/other_settings/logging.py @@ -0,0 +1,141 @@ +import os + +def get_settings(key): + from django.conf import settings + return getattr(settings, 'BASE_DIR') + +BASE_DIR = get_settings('BASE_DIR') + +LOG_DIR = BASE_DIR / 'logs' +if not os.path.exists(LOG_DIR): + os.makedirs(LOG_DIR) + + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'formatters': { + 'verbose': { + 'format': '{asctime} [{levelname}] {name} {module} {process:d} {thread:d} {message}', + 'style': '{', + }, + 'standard': { + 'format': '{asctime} [{levelname}] {name}: {message}', + 'style': '{', + }, + 'simple': { + 'format': '{levelname} {message}', + 'style': '{', + }, + }, + 'filters': { + 'require_debug_true': { + '()': 'django.utils.log.RequireDebugTrue', + }, + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse', + }, + }, + 'handlers': { + # هندلر برای نوشتن در فایل + 'file': { + 'level': 'INFO', + 'class': 'logging.handlers.TimedRotatingFileHandler', + 'filename': os.path.join(LOG_DIR, 'accounts.log'), + # 'maxBytes': 1024 * 1024 * 10, # 10 MB + 'when': 'midnight', + 'interval': 5, + 'backupCount': 30, + 'formatter': 'verbose', + 'encoding': 'utf-8', + }, + # هندلر برای خطاها در فایل جداگانه + 'error_file': { + 'level': 'ERROR', + 'class': 'logging.handlers.TimedRotatingFileHandler', + 'filename': os.path.join(LOG_DIR, 'errors.log'), + # 'maxBytes': 1024 * 1024 * 10, + 'when': 'midnight', + 'interval': 5, + 'backupCount': 30, + 'formatter': 'verbose', + 'encoding': 'utf-8', + }, + # هندلر برای کنسول (فقط در حالت DEBUG) + 'console': { + 'level': 'DEBUG', + 'filters': ['require_debug_true'], + 'class': 'logging.StreamHandler', + 'formatter': 'simple', + }, + # هندلر برای کنسول همیشه فعال (حتی در production) + 'console_always': { + 'level': 'INFO', + 'class': 'logging.StreamHandler', + 'formatter': 'standard', + }, + }, + 'loggers': { + # لاگر ریشه + '': { # empty string = root logger + 'handlers': ['console', 'file', 'error_file'], + 'level': 'INFO', + 'propagate': True, + }, + # لاگر اختصاصی برای Django + 'django': { + 'handlers': ['console', 'file'], + 'level': 'INFO', + 'propagate': False, + }, + # لاگر اختصاصی برای درخواست‌ها + 'django.request': { + 'handlers': ['file', 'error_file', 'console'], + 'level': 'ERROR', + 'propagate': False, + }, + # # لاگر اختصاصی برای برنامه خودتان + # 'root': { + # 'handlers': ['console', 'file', 'error_file'], + # 'level': 'DEBUG', + # 'propagate': False, + # }, + }, +} + +# LOKI_BASE_PUBLIC_URL = config('LOKI_BASE_PUBLIC_URL', default=None, cast=str) +# { +# 'version': 1, +# 'disable_existing_loggers': False, +# 'formatters': { +# 'loki': { +# 'class': 'utils.logs.LokiFormatter', # required +# }, +# }, +# +# 'handlers': { +# 'loki': { +# 'level': 'DEBUG', # Log level. Required +# 'class': 'utils.logs.LokiHandler', # Required +# 'formatter': 'loki', # Loki formatter. Required +# 'timeout': 2, # Post request timeout, default is 0.5. Optional +# 'url': f'{LOKI_BASE_PUBLIC_URL}/loki/api/v1/push', # Loki url. Defaults to localhost. Optional. +# # 'auth': ("user", "password"), # Basic auth to authenticate with loki. Default is None (i.e. no auth). Optional +# 'tags': {"app": "accounts"}, # Tags / Labels to attach to the log. Optional, but strongly encoraged to use. +# 'mode': 'thread', +# # Push mode. Can be 'sync' or 'thread'. Sync is blocking, thread is non-blocking. Defaults to sync. Optional. +# }, +# 'console': { +# 'level': 'DEBUG', +# 'class': 'logging.StreamHandler', +# # 'formatter': 'verbose', +# }, +# }, +# 'loggers': { +# '': { +# 'handlers': ['console', 'loki'], +# 'level': 'INFO', +# 'propagate': True, +# }, +# }, +# } \ No newline at end of file diff --git a/main/settings.py b/main/settings.py index 3648b18..3dd9f8f 100644 --- a/main/settings.py +++ b/main/settings.py @@ -140,7 +140,7 @@ SPECTACULAR_SETTINGS = { "PARSER_WHITELIST": ["rest_framework.parsers.JSONParser"], } -ROOT_URLCONF = 'accounts.urls' +ROOT_URLCONF = 'main.urls' TEMPLATES = [ { @@ -164,7 +164,7 @@ AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', ) -WSGI_APPLICATION = 'accounts.wsgi.application' +WSGI_APPLICATION = 'main.wsgi.application' # Database # https://docs.djangoproject.com/en/5.0/ref/settings/#databases @@ -293,43 +293,9 @@ CACHES = { } } -LOKI_BASE_PUBLIC_URL = config('LOKI_BASE_PUBLIC_URL', default=None, cast=str) -LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'formatters': { - 'loki': { - 'class': 'utils.logs.LokiFormatter', # required - }, - }, - 'handlers': { - 'loki': { - 'level': 'DEBUG', # Log level. Required - 'class': 'utils.logs.LokiHandler', # Required - 'formatter': 'loki', # Loki formatter. Required - 'timeout': 2, # Post request timeout, default is 0.5. Optional - 'url': f'{LOKI_BASE_PUBLIC_URL}/loki/api/v1/push', # Loki url. Defaults to localhost. Optional. - # 'auth': ("user", "password"), # Basic auth to authenticate with loki. Default is None (i.e. no auth). Optional - 'tags': {"app": "accounts"}, # Tags / Labels to attach to the log. Optional, but strongly encoraged to use. - 'mode': 'thread', - # Push mode. Can be 'sync' or 'thread'. Sync is blocking, thread is non-blocking. Defaults to sync. Optional. - }, - 'console': { - 'level': 'DEBUG', - 'class': 'logging.StreamHandler', - # 'formatter': 'verbose', - }, - }, - 'loggers': { - '': { - 'handlers': ['console', 'loki'], - 'level': 'INFO', - 'propagate': True, - }, - }, -} +from main.other_settings.logging import LOGGING from datetime import timedelta from typing import List, Tuple diff --git a/run.sh b/run.sh index e4dfb50..051a5d0 100755 --- a/run.sh +++ b/run.sh @@ -5,5 +5,5 @@ #done #python3 manage.py collectstatic --noinput #python3 manage.py migrate -gunicorn accounts.wsgi:application --bind 0.0.0.0:8000 -w 4 +gunicorn main.wsgi:application --bind 0.0.0.0:8000 -w 4 #daphne -b 0.0.0.0 -p 8000 accounts.asgi:application \ No newline at end of file