set time zone
This commit is contained in:
parent
821304f1c8
commit
e1f3d72ab7
6 changed files with 193 additions and 1 deletions
0
utils/__init__.py
Normal file
0
utils/__init__.py
Normal file
51
utils/exceptions.py
Normal file
51
utils/exceptions.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import logging
|
||||
|
||||
from rest_framework.exceptions import APIException
|
||||
from rest_framework.views import exception_handler as drf_exception_handler
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
def exception_handler(exc, context):
|
||||
logger.exception(exc)
|
||||
# پاسخ پیشفرض DRF را دریافت میکنیم
|
||||
response = drf_exception_handler(exc, context)
|
||||
|
||||
if response is not None:
|
||||
# ساختار دلخواه خود را تعریف میکنیم
|
||||
response_data = {
|
||||
'success': False,
|
||||
'status_code': response.status_code,
|
||||
'message': 'An error occurred',
|
||||
'details': {}
|
||||
}
|
||||
|
||||
if isinstance(exc, APIException):
|
||||
response_data['message'] = exc.detail if isinstance(exc.detail, str) else "Validation error"
|
||||
response_data['details'] = exc.detail if isinstance(exc.detail, dict) else {}
|
||||
|
||||
response.data = response_data
|
||||
|
||||
return response
|
||||
|
||||
|
||||
# در فایل middleware.py
|
||||
from django.http import JsonResponse
|
||||
|
||||
class ErrorMiddleware:
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
|
||||
def __call__(self, request):
|
||||
response = self.get_response(request)
|
||||
return response
|
||||
|
||||
def process_exception(self, request, exception):
|
||||
logger.exception(exception)
|
||||
return JsonResponse(
|
||||
{
|
||||
"success": False,
|
||||
"status_code": 500,
|
||||
"message": "Internal server error",
|
||||
"details": str(exception) # فقط در حالت توسعه! در تولید بهتر است لاگ شود.
|
||||
},
|
||||
status=500
|
||||
)
|
||||
4
utils/logs/__init__.py
Normal file
4
utils/logs/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
from .formatters import LokiFormatter
|
||||
from .handlers import LokiHandler
|
||||
|
||||
__all__ = ['LokiHandler', 'LokiFormatter']
|
||||
77
utils/logs/formatters.py
Normal file
77
utils/logs/formatters.py
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import logging
|
||||
import socket
|
||||
from datetime import datetime
|
||||
from logging import BASIC_FORMAT
|
||||
|
||||
|
||||
class LokiFormatter(logging.Formatter):
|
||||
asctime_search = "%(asctime)"
|
||||
tz = "UTC"
|
||||
source = "Loki"
|
||||
src_host = "localhost"
|
||||
tags = {}
|
||||
|
||||
def __init__(self, fmt, dfmt, style, fqdn=False):
|
||||
super(LokiFormatter, self).__init__()
|
||||
|
||||
self.fmt = fmt or BASIC_FORMAT
|
||||
self.dfmt = dfmt or "%Y-%m-%d %H:%M:%S"
|
||||
self.style = style
|
||||
|
||||
if fqdn:
|
||||
self.host = socket.getfqdn()
|
||||
else:
|
||||
self.host = socket.gethostname()
|
||||
|
||||
def format_timestamp(self, time):
|
||||
return str(int(time * 10**9))
|
||||
|
||||
def usesTime(self):
|
||||
return self.fmt.find(self.asctime_search) >= 0
|
||||
|
||||
def formatMessage(self, record):
|
||||
try:
|
||||
return self.fmt % record.__dict__
|
||||
except KeyError as e:
|
||||
raise ValueError("Formatting field not found in record: %s" % e)
|
||||
|
||||
def format(self, record):
|
||||
record.message = record.getMessage()
|
||||
|
||||
if self.usesTime():
|
||||
record.asctime = self.formatTime(record, self.dfmt)
|
||||
|
||||
message = self.formatMessage(record)
|
||||
|
||||
if record.exc_info:
|
||||
if not record.exc_text:
|
||||
record.exc_text = self.formatException(record.exc_info)
|
||||
|
||||
if record.exc_text:
|
||||
if message[-1:] != "\n":
|
||||
message = message + "\n"
|
||||
message = message + record.exc_text
|
||||
|
||||
if record.stack_info:
|
||||
if message[-1:] != "\n":
|
||||
message = message + "\n"
|
||||
|
||||
message = message + self.formatStack(record.stack_info)
|
||||
|
||||
message = {
|
||||
"streams": [
|
||||
{
|
||||
"stream": {
|
||||
**self.tags,
|
||||
},
|
||||
"values": [
|
||||
[
|
||||
self.format_timestamp(record.created),
|
||||
message,
|
||||
]
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return message
|
||||
58
utils/logs/handlers.py
Normal file
58
utils/logs/handlers.py
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import logging
|
||||
import sys
|
||||
from threading import Thread
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
class LokiHandler(logging.Handler):
|
||||
def __init__(
|
||||
self,
|
||||
timeout=0.5,
|
||||
url="http://localhost:3100/loki/api/v1/push",
|
||||
auth=None,
|
||||
tags={},
|
||||
mode="sync",
|
||||
):
|
||||
super(LokiHandler, self).__init__()
|
||||
|
||||
self._url = url
|
||||
self._timeout = timeout
|
||||
self._auth = auth
|
||||
self._tags = tags
|
||||
|
||||
self._mode = mode
|
||||
|
||||
def emit(self, record):
|
||||
try:
|
||||
payload = self.formatter.format(record)
|
||||
|
||||
_push_message(
|
||||
self._url, json=payload, timeout=self._timeout, auth=self._auth
|
||||
)
|
||||
except requests.exceptions.ReadTimeout:
|
||||
sys.stderr.write("Loki connection timed out\n")
|
||||
except Exception as e:
|
||||
sys.stderr.write(f"Loki connection failed with: {e}\n")
|
||||
|
||||
def setFormatter(self, fmt):
|
||||
fmt.tags = self._tags
|
||||
|
||||
self.formatter = fmt
|
||||
|
||||
def _push_message(self, *args, **kwargs):
|
||||
print('hehe')
|
||||
if self._mode == "sync":
|
||||
return _push_message(*args, **kwargs)
|
||||
|
||||
if self._mode == "thread":
|
||||
return Thread(target=_push_message, args=args, kwargs=kwargs).start()
|
||||
|
||||
|
||||
def _push_message(*args, **kwargs):
|
||||
response = requests.post(*args, **kwargs)
|
||||
|
||||
if response.status_code != 204:
|
||||
sys.stderr.write(
|
||||
f"Got status {response.status_code} from loki with message: {response.text}\n"
|
||||
)
|
||||
|
|
@ -67,6 +67,7 @@ MIDDLEWARE = [
|
|||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
'utils.exceptions.ErrorMiddleware',
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -111,6 +112,7 @@ REST_FRAMEWORK = {
|
|||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
|
||||
'PAGE_SIZE': 50,
|
||||
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
|
||||
'EXCEPTION_HANDLER': 'utils.exceptions.exception_handler',
|
||||
}
|
||||
|
||||
SPECTACULAR_SETTINGS = {
|
||||
|
|
@ -195,7 +197,7 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||
|
||||
LANGUAGE_CODE = 'en'
|
||||
|
||||
TIME_ZONE = 'UTC'
|
||||
TIME_ZONE = 'Asia/Tehran'
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue