From 3e4f75e11d8ec42d01695895f5727e41399868a9 Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 8 May 2025 11:26:54 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D1=83=D1=80=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BB=D0=BE=D0=B3=D0=B8=D1=80=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - обавлена ротация логов по размеру - обавлены отдельные логгеры для разных компонентов - лучшен формат сообщений - аменены все использования app.logger на logger --- app.py | 193 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 118 insertions(+), 75 deletions(-) diff --git a/app.py b/app.py index 17a920a..9a5f497 100644 --- a/app.py +++ b/app.py @@ -22,6 +22,7 @@ from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.lib.units import inch, mm from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT import sys +import logging @@ -78,34 +79,76 @@ def save_request(request): req_data['remote_addr'] = request.remote_addr return req_data -dictConfig( - { - "version": 1, - "formatters": { - "default": { - "format": "[%(asctime)s] [%(levelname)s | %(module)s] %(message)s", - "datefmt": " %d/%m/%Y %H:%M:%S" - }, - }, - "handlers": { - "console": { - "class": "logging.StreamHandler", - "formatter": "default", - }, - "file": { - "class": "logging.handlers.TimedRotatingFileHandler", - "filename": app_path + "/logs/app.log", - "when": "D", - "interval": 10, - "backupCount": 5, - "formatter": "default", - }, - - }, - "root": {"level": "DEBUG", "handlers": ["console", "file"]}, - } -) +# Создаем директорию для логов если её нет +log_dir = os.path.join(app_path, 'logs') +if not os.path.exists(log_dir): + os.makedirs(log_dir) +# Определяем уровень логирования в зависимости от окружения +log_level = 'DEBUG' if app_debug else 'INFO' + +dictConfig({ + "version": 1, + "disable_existing_loggers": False, + "formatters": { + "default": { + "format": "[%(asctime)s] [%(levelname)s] [%(name)s:%(lineno)d] %(message)s", + "datefmt": "%Y-%m-%d %H:%M:%S" + }, + "error": { + "format": "[%(asctime)s] [%(levelname)s] [%(name)s:%(lineno)d] [%(pathname)s] %(message)s", + "datefmt": "%Y-%m-%d %H:%M:%S" + } + }, + "handlers": { + "console": { + "class": "logging.StreamHandler", + "formatter": "default", + "stream": "ext://sys.stdout" + }, + "file": { + "class": "logging.handlers.RotatingFileHandler", + "formatter": "default", + "filename": os.path.join(log_dir, "app.log"), + "maxBytes": 10485760, # 10MB + "backupCount": 10, + "encoding": "utf8" + }, + "error_file": { + "class": "logging.handlers.RotatingFileHandler", + "formatter": "error", + "filename": os.path.join(log_dir, "error.log"), + "maxBytes": 10485760, # 10MB + "backupCount": 10, + "encoding": "utf8", + "level": "ERROR" + } + }, + "loggers": { + "werkzeug": { + "handlers": ["console", "file"], + "level": log_level, + "propagate": False + }, + "flask": { + "handlers": ["console", "file"], + "level": log_level, + "propagate": False + }, + "app": { + "handlers": ["console", "file", "error_file"], + "level": log_level, + "propagate": False + } + }, + "root": { + "level": log_level, + "handlers": ["console", "file", "error_file"] + } +}) + +# Создаем логгер для приложения +logger = logging.getLogger("app") @app.after_request def after_request(response): @@ -161,7 +204,7 @@ def sitemaps_xml(sitemap_id): sitemap_pages = cur.fetchall() return render_template('sitemaps.xml', site=site, sitemap_pages=sitemap_pages) except: - app.logger.error(traceback.format_exc()) + logger.error(traceback.format_exc()) return 'bad request!', 500 @app.route("/") @@ -179,7 +222,7 @@ def index_html(): app.cache['maxnum'] = cnt return render_template('index.html', site=site, cnt=cnt ,capcha_site=capcha_site) except: - app.logger.error(traceback.format_exc()) + logger.error(traceback.format_exc()) return 'bad request!', 500 @app.route("/privacy.html") @@ -188,7 +231,7 @@ def privacy_html(): return render_template('privacy.html', site=site) except: - app.logger.error(traceback.format_exc()) + logger.error(traceback.format_exc()) return 'bad request!', 500 @app.route("/robots.txt") @@ -196,7 +239,7 @@ def robot_txt(): try: return render_template('robots.txt', site=site) except: - app.logger.error(traceback.format_exc()) + logger.error(traceback.format_exc()) return 'bad request!', 500 @app.route("/decode", methods = ['POST']) @@ -206,12 +249,12 @@ def decode(): g_respone = request.form['g-recaptcha-response'] capcha_check = requests.post(url=f'{capcha_site_url}?secret={capcha_site_sec}&response={g_respone}').json() if capcha_check['success'] == False or capcha_check['score'] .html") @@ -234,7 +277,7 @@ def database_page_prc(page_num): returnVal = cur.callfunc("checkip", int, [user_ip, request.headers.get("CF-IPCountry", 'None'), get_addr(user_ip), 1, 0, 0]) except: print(request) - app.logger.error(traceback.format_exc()) + logger.error(traceback.format_exc()) cur.execute('select max(pg) from mv_pages') max_page = int(cur.fetchall()[0][0]) @@ -248,7 +291,7 @@ def database_page_prc(page_num): pgf = cur.fetchall() return render_template('database.html', site=site, cur_page=pg, max_page=max_page, pg=pgf) except: - app.logger.error(traceback.format_exc()) + logger.error(traceback.format_exc()) return 'bad request!', 500 @app.route("/detail/.html") @@ -261,7 +304,7 @@ def detail_vin(vin): returnVal = cur.callfunc("checkip", int, [user_ip, request.headers.get("CF-IPCountry", 'None'), get_addr(user_ip), 0, 0, 1]) except: print(request) - app.logger.error(traceback.format_exc()) + logger.error(traceback.format_exc()) cur.execute("""select 'None', COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='26'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Make'),'UNKNOWN') make, COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='28'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Model'),'UNKNOWN') model, @@ -274,7 +317,7 @@ def detail_vin(vin): res = cur.fetchall() return render_template('details.html', site=site, vin=vin, det=res, capcha_site=capcha_site) except: - app.logger.error(traceback.format_exc()) + logger.error(traceback.format_exc()) return 'bad request!', 500 @@ -284,17 +327,17 @@ def search(): user_ip = get_ip(request) ## определение ip клиента vin = request.form.get('q') ua = request.headers.get('User-Agent') - app.logger.info(f'AgeNt: {ua}') + logger.info(f'AgeNt: {ua}') g_respone = request.form.get('g-recaptcha-response') capcha_check = requests.post(url=f'{capcha_site_url}?secret={capcha_site_sec}&response={g_respone}').json() if capcha_check['success'] == False or capcha_check['score'] 16 or access_code is None: ret = {'status': 'incorrect access_code'} @@ -348,7 +391,7 @@ def api_search(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response conn = pool.acquire() @@ -373,7 +416,7 @@ def api_search(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response ## ищем в истории cur.execute('select t.odo,t.odos,t.title,t.dem1,t.dem2,t.year,t.month from salvagedb t where vin =:p1 and svin = :p2', @@ -404,7 +447,7 @@ def api_search(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) cur.execute("insert into billing(access_code, vin, ip, status, dt, cost) values (:p1, :p2, :p3, :p4, CAST(SYSTIMESTAMP AT TIME ZONE 'UTC' AS DATE), :p5)", {'p1': str(access_code), 'p2': str(vin), 'p3': str(user_ip), 'p4': 'FOUND', 'p5': found_price}) conn.commit() @@ -414,7 +457,7 @@ def api_search(): # nor found ret = {'status': 'NOT FOUND', 'cost': notfound_price} if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) response = app.response_class( response=json.dumps(ret), status=200, @@ -426,7 +469,7 @@ def api_search(): return response except: - app.logger.error(traceback.format_exc()) + logger.error(traceback.format_exc()) return 'bad request!', 500 @@ -441,7 +484,7 @@ def api_restfact(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response conn = pool.acquire() @@ -460,7 +503,7 @@ def api_restfact(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response else: ret = { @@ -473,7 +516,7 @@ def api_restfact(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response @app.route("/api/restfact_detail") @@ -487,7 +530,7 @@ def restfact_detail(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response conn = pool.acquire() @@ -503,7 +546,7 @@ def restfact_detail(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response cur.execute("select vin, ip, status, dt, cost from billing where access_code = :p1 and dt > CAST(SYSTIMESTAMP AT TIME ZONE 'UTC' AS DATE) - 45 and made = 1 order by id", {'p1': str(access_code)}) res = cur.fetchall() @@ -515,7 +558,7 @@ def restfact_detail(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response else: dat = [] @@ -539,7 +582,7 @@ def restfact_detail(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response ## API V2 @@ -561,7 +604,7 @@ def api_search_v2(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response if len(access_code) > 16 or access_code is None: ret = {'status': 'incorrect access_code'} @@ -571,7 +614,7 @@ def api_search_v2(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response conn = pool.acquire() @@ -596,7 +639,7 @@ def api_search_v2(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response ## ищем в истории cur.execute('''select s.odo,s.odos,s.title,s.dem1,s.dem2,s.year,s.month, json_value(i.jdata, '$.Runs_Drive') RD_Status, json_value(i.jdata, '$.Locate') Sale_Location, json_value(i.jdata, '$.RepCost') as Repear_cost, @@ -632,7 +675,7 @@ def api_search_v2(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) cur.execute("insert into billing(access_code, vin, ip, status, dt, cost) values (:p1, :p2, :p3, :p4, CAST(SYSTIMESTAMP AT TIME ZONE 'UTC' AS DATE), :p5)", {'p1': str(access_code), 'p2': str(vin), 'p3': str(user_ip), 'p4': 'FOUND', 'p5': found_price}) conn.commit() @@ -642,7 +685,7 @@ def api_search_v2(): # nor found ret = {'status': 'NOT FOUND', 'cost': notfound_price} if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) response = app.response_class( response=json.dumps(ret), status=200, @@ -654,7 +697,7 @@ def api_search_v2(): return response except: - app.logger.error(traceback.format_exc()) + logger.error(traceback.format_exc()) return 'bad request!', 500 @app.route("/api/v2/reqphoto") @@ -674,7 +717,7 @@ def api_reqimage(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response if len(access_code) > 16 or access_code is None: ret = {'status': 'incorrect access_code'} @@ -684,7 +727,7 @@ def api_reqimage(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response conn = pool.acquire() @@ -708,7 +751,7 @@ def api_reqimage(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response cur.execute('select count(*) from salvagedb.salvage_images where vin = :p1 and fn = 1' , {'p1':vin.upper()}) @@ -722,7 +765,7 @@ def api_reqimage(): mimetype='application/json' ) if app.debug: - app.logger.debug(json.dumps(ret)) + logger.debug(json.dumps(ret)) return response else: cur.execute("""select GenImages('{}','{}') as ui from dual""".format(access_code, vin.upper())) @@ -753,7 +796,7 @@ def api_reqimage(): except: - app.logger.error(traceback.format_exc()) + logger.error(traceback.format_exc()) return 'bad request!', 500 @@ -762,7 +805,7 @@ def ads_txt(): try: return render_template('ads.txt') except: - app.logger.error(traceback.format_exc()) + logger.error(traceback.format_exc()) return 'bad request!', 500 @app.route('/favicon.ico') @@ -774,7 +817,7 @@ def rate_limit(): try: return render_template('rate_limit.html', site=site) except: - app.logger.error(traceback.format_exc()) + logger.error(traceback.format_exc()) return 'bad request!', 500 @app.route('/donate') @@ -809,13 +852,13 @@ def serve_static(filename): file_ext = os.path.splitext(filename)[1].lower() if file_ext not in allowed_extensions: - app.logger.warning(f'Попытка доступа к запрещенному типу файла: {filename}') + logger.warning(f'Попытка доступа к запрещенному типу файла: {filename}') return 'Access denied', 403 # Проверка пути на directory traversal safe_path = os.path.normpath(os.path.join('static', filename)) if not safe_path.startswith('static'): - app.logger.warning(f'Попытка доступа к файлу вне директории static: {filename}') + logger.warning(f'Попытка доступа к файлу вне директории static: {filename}') return 'Access denied', 403 # Определение MIME-типа @@ -834,7 +877,7 @@ def serve_static(filename): mime_type = mime_types.get(file_ext, 'application/octet-stream') # Логирование доступа - app.logger.info(f'Доступ к статическому файлу: {filename}') + logger.info(f'Доступ к статическому файлу: {filename}') response = make_response(send_from_directory('static', filename)) response.headers['Content-Type'] = mime_type @@ -848,7 +891,7 @@ def serve_static(filename): return response except Exception as e: - app.logger.error(f'Ошибка доступа к файлу {filename}: {str(e)}') + logger.error(f'Ошибка доступа к файлу {filename}: {str(e)}') return 'File not found', 404 @app.route("/salvagereport/") @@ -861,7 +904,7 @@ def generate_pdf_report(vin): try: returnVal = cur.callfunc("checkip", int, [user_ip, request.headers.get("CF-IPCountry", 'None'), get_addr(user_ip), 1, 0, 0]) except: - app.logger.error(traceback.format_exc()) + logger.error(traceback.format_exc()) # Get vehicle details cur.execute("""select 'None', COALESCE((select value from m_JSONS_FROM_NHTSA v3 where v3.svin =s.svin and v3.variableid ='26'),(select val from vind2 where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2) and varb = 'Make'),'UNKNOWN') make,