优化错误日志及重试机制
This commit is contained in:
@@ -1,3 +1,10 @@
|
|||||||
|
# 尝试次数
|
||||||
|
TRY_TIMES = 3
|
||||||
|
# 最小等待时间(秒)
|
||||||
|
MIN_WAIT_TIME = 1
|
||||||
|
# 最大等待时间(秒)
|
||||||
|
MAX_WAIT_TIME = 3
|
||||||
|
|
||||||
# 程序异常短信配置
|
# 程序异常短信配置
|
||||||
ERROR_EMAIL_CONFIG = {
|
ERROR_EMAIL_CONFIG = {
|
||||||
# SMTP服务器地址
|
# SMTP服务器地址
|
||||||
|
|||||||
@@ -3,7 +3,24 @@ import logging
|
|||||||
import smtplib
|
import smtplib
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
|
|
||||||
from auto_email import ERROR_EMAIL_CONFIG
|
from tenacity import retry, stop_after_attempt, wait_random
|
||||||
|
|
||||||
|
from auto_email import ERROR_EMAIL_CONFIG, TRY_TIMES, MIN_WAIT_TIME, MAX_WAIT_TIME
|
||||||
|
|
||||||
|
|
||||||
|
@retry(stop=stop_after_attempt(TRY_TIMES), wait=wait_random(MIN_WAIT_TIME, MAX_WAIT_TIME), reraise=True,
|
||||||
|
retry_error_callback=lambda x: logging.warning("邮件发送失败!"))
|
||||||
|
def send_email(email_config, massage):
|
||||||
|
smtp_server = email_config["smtp_server"]
|
||||||
|
port = email_config["port"]
|
||||||
|
sender = email_config["sender"]
|
||||||
|
authorization_code = email_config["authorization_code"]
|
||||||
|
receivers = email_config["receivers"]
|
||||||
|
mail = smtplib.SMTP_SSL(smtp_server, port) # 连接SMTP服务
|
||||||
|
mail.login(sender, authorization_code) # 登录到SMTP服务
|
||||||
|
mail.sendmail(sender, receivers, massage.as_string()) # 发送邮件
|
||||||
|
mail.quit()
|
||||||
|
logging.info(f"成功发送了一封邮件到[{','.join(receivers)}]")
|
||||||
|
|
||||||
|
|
||||||
def send_error_email(program_name, error_name, error_detail):
|
def send_error_email(program_name, error_name, error_detail):
|
||||||
@@ -16,12 +33,8 @@ def send_error_email(program_name, error_name, error_detail):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# SMTP 服务器配置
|
# SMTP 服务器配置
|
||||||
smtp_server = ERROR_EMAIL_CONFIG["smtp_server"]
|
|
||||||
port = ERROR_EMAIL_CONFIG["port"]
|
|
||||||
sender = ERROR_EMAIL_CONFIG["sender"]
|
sender = ERROR_EMAIL_CONFIG["sender"]
|
||||||
authorization_code = ERROR_EMAIL_CONFIG["authorization_code"]
|
|
||||||
receivers = ERROR_EMAIL_CONFIG["receivers"]
|
receivers = ERROR_EMAIL_CONFIG["receivers"]
|
||||||
retry_times = ERROR_EMAIL_CONFIG["retry_times"]
|
|
||||||
|
|
||||||
# 获取程序出错的时间
|
# 获取程序出错的时间
|
||||||
error_time = datetime.datetime.strftime(datetime.datetime.today(), "%Y-%m-%d %H:%M:%S:%f")
|
error_time = datetime.datetime.strftime(datetime.datetime.today(), "%Y-%m-%d %H:%M:%S:%f")
|
||||||
@@ -60,14 +73,4 @@ def send_error_email(program_name, error_name, error_detail):
|
|||||||
receivers_str = ','.join(receivers)
|
receivers_str = ','.join(receivers)
|
||||||
massage['To'] = receivers_str # 收件人
|
massage['To'] = receivers_str # 收件人
|
||||||
|
|
||||||
for i in range(retry_times):
|
send_email(ERROR_EMAIL_CONFIG, massage)
|
||||||
try:
|
|
||||||
mail = smtplib.SMTP_SSL(smtp_server, port) # 连接SMTP服务
|
|
||||||
mail.login(sender, authorization_code) # 登录到SMTP服务
|
|
||||||
mail.sendmail(sender, receivers, massage.as_string()) # 发送邮件
|
|
||||||
mail.quit()
|
|
||||||
logging.info("成功发送了一封邮件到" + receivers_str)
|
|
||||||
break
|
|
||||||
except smtplib.SMTPException:
|
|
||||||
if i == retry_times - 1:
|
|
||||||
logging.warning("邮件发送失败!")
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ HOSTNAME = socket.gethostname()
|
|||||||
# 检测日志文件的路径是否存在,不存在则创建
|
# 检测日志文件的路径是否存在,不存在则创建
|
||||||
LOG_PATHS = [
|
LOG_PATHS = [
|
||||||
f"log/{HOSTNAME}/ucloud",
|
f"log/{HOSTNAME}/ucloud",
|
||||||
|
f"log/{HOSTNAME}/error",
|
||||||
]
|
]
|
||||||
for path in LOG_PATHS:
|
for path in LOG_PATHS:
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
@@ -43,14 +44,24 @@ LOGGING_CONFIG = {
|
|||||||
'encoding': 'utf-8', # 显式指定文件编码为UTF-8以支持中文
|
'encoding': 'utf-8', # 显式指定文件编码为UTF-8以支持中文
|
||||||
},
|
},
|
||||||
'ucloud': {
|
'ucloud': {
|
||||||
'class': 'logging.handlers.TimedRotatingFileHandler', # 文件处理器,支持日志滚动
|
'class': 'logging.handlers.TimedRotatingFileHandler',
|
||||||
'level': 'INFO',
|
'level': 'INFO',
|
||||||
'formatter': 'standard',
|
'formatter': 'standard',
|
||||||
'filename': f'log/{HOSTNAME}/ucloud/fcb_photo_review_ucloud.log', # 日志文件路径
|
'filename': f'log/{HOSTNAME}/ucloud/fcb_photo_review_ucloud.log',
|
||||||
'when': 'midnight',
|
'when': 'midnight',
|
||||||
'interval': 1,
|
'interval': 1,
|
||||||
'backupCount': 14, # 保留的备份文件数量
|
'backupCount': 14,
|
||||||
'encoding': 'utf-8', # 显式指定文件编码为UTF-8以支持中文
|
'encoding': 'utf-8',
|
||||||
|
},
|
||||||
|
'error': {
|
||||||
|
'class': 'logging.handlers.TimedRotatingFileHandler',
|
||||||
|
'level': 'INFO',
|
||||||
|
'formatter': 'standard',
|
||||||
|
'filename': f'log/{HOSTNAME}/error/fcb_photo_review_error.log',
|
||||||
|
'when': 'midnight',
|
||||||
|
'interval': 1,
|
||||||
|
'backupCount': 14,
|
||||||
|
'encoding': 'utf-8',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -65,6 +76,11 @@ LOGGING_CONFIG = {
|
|||||||
'handlers': ['console', 'ucloud'],
|
'handlers': ['console', 'ucloud'],
|
||||||
'level': 'DEBUG',
|
'level': 'DEBUG',
|
||||||
'propagate': False,
|
'propagate': False,
|
||||||
|
},
|
||||||
|
'error': {
|
||||||
|
'handlers': ['console', 'file', 'error'],
|
||||||
|
'level': 'DEBUG',
|
||||||
|
'propagate': False,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ if __name__ == '__main__':
|
|||||||
logging.info(f"【{program_name}】开始运行")
|
logging.info(f"【{program_name}】开始运行")
|
||||||
photo_mask.main()
|
photo_mask.main()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(traceback.format_exc())
|
error_logger = logging.getLogger("error")
|
||||||
|
error_logger.error(traceback.format_exc())
|
||||||
if SEND_ERROR_EMAIL:
|
if SEND_ERROR_EMAIL:
|
||||||
send_error_email(program_name=program_name, error_name=repr(e), error_detail=traceback.format_exc())
|
send_error_email(program_name=program_name, error_name=repr(e), error_detail=traceback.format_exc())
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ PHHD_BATCH_SIZE = 20
|
|||||||
SLEEP_MINUTES = 5
|
SLEEP_MINUTES = 5
|
||||||
# 是否发送异常提醒邮件
|
# 是否发送异常提醒邮件
|
||||||
SEND_ERROR_EMAIL = True
|
SEND_ERROR_EMAIL = True
|
||||||
# 备份原图的尝试次数
|
|
||||||
COPY_TRY_TIMES = 3
|
|
||||||
# 上传新图的尝试次数
|
|
||||||
UPLOAD_TRY_TIMES = 3
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
关键词配置
|
关键词配置
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ from sqlalchemy import update, and_
|
|||||||
|
|
||||||
from db import MysqlSession
|
from db import MysqlSession
|
||||||
from db.mysql import ZxPhrec, ZxPhhd
|
from db.mysql import ZxPhrec, ZxPhhd
|
||||||
from photo_mask import OCR, PHHD_BATCH_SIZE, SLEEP_MINUTES, COPY_TRY_TIMES, UPLOAD_TRY_TIMES, NAME_KEYS, \
|
from photo_mask import OCR, PHHD_BATCH_SIZE, SLEEP_MINUTES, NAME_KEYS, ID_CARD_NUM_KEYS
|
||||||
ID_CARD_NUM_KEYS
|
|
||||||
from ucloud import BUCKET, ufile
|
from ucloud import BUCKET, ufile
|
||||||
from util import image_util, util
|
from util import image_util, util
|
||||||
|
|
||||||
@@ -177,18 +176,12 @@ def photo_mask(pk_phhd, name, id_card_num):
|
|||||||
|
|
||||||
# 如果涂抹了要备份以及更新
|
# 如果涂抹了要备份以及更新
|
||||||
if is_masked:
|
if is_masked:
|
||||||
for i in range(COPY_TRY_TIMES):
|
ufile.copy_file(BUCKET, phrec.cfjaddress, "drg2015", phrec.cfjaddress)
|
||||||
is_copy_success = ufile.copy_file(BUCKET, phrec.cfjaddress, "drg2015", phrec.cfjaddress)
|
|
||||||
if is_copy_success:
|
|
||||||
break
|
|
||||||
|
|
||||||
with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_file:
|
with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as temp_file:
|
||||||
cv2.imwrite(temp_file.name, image)
|
cv2.imwrite(temp_file.name, image)
|
||||||
try:
|
try:
|
||||||
for i in range(UPLOAD_TRY_TIMES):
|
ufile.upload_file(phrec.cfjaddress, temp_file.name)
|
||||||
is_upload_success = ufile.upload_file(phrec.cfjaddress, temp_file.name)
|
|
||||||
if is_upload_success:
|
|
||||||
break
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("上传图片出错", exc_info=e)
|
logging.error("上传图片出错", exc_info=e)
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ if __name__ == '__main__':
|
|||||||
logging.info(f"【{program_name}】开始运行")
|
logging.info(f"【{program_name}】开始运行")
|
||||||
photo_review.main()
|
photo_review.main()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(traceback.format_exc())
|
error_logger = logging.getLogger('error')
|
||||||
|
error_logger.error(traceback.format_exc())
|
||||||
if SEND_ERROR_EMAIL:
|
if SEND_ERROR_EMAIL:
|
||||||
send_error_email(program_name, repr(e), traceback.format_exc())
|
send_error_email(program_name, repr(e), traceback.format_exc())
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# https://github.com/ucloud/ufile-sdk-python
|
# https://github.com/ucloud/ufile-sdk-python
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from tenacity import retry, stop_after_attempt, wait_random, retry_if_exception_type
|
from tenacity import retry, stop_after_attempt, wait_random, retry_if_exception_type, retry_if_result
|
||||||
from ufile import filemanager
|
from ufile import filemanager
|
||||||
|
|
||||||
from ucloud import PUBLIC_KEY, PRIVATE_KEY, UPLOAD_SUFFIX, DOWNLOAD_SUFFIX, BUCKET, PRIVATE_EXPIRES, TRY_TIMES, \
|
from ucloud import PUBLIC_KEY, PRIVATE_KEY, UPLOAD_SUFFIX, DOWNLOAD_SUFFIX, BUCKET, PRIVATE_EXPIRES, TRY_TIMES, \
|
||||||
@@ -32,13 +32,13 @@ def get_private_url(key, bucket=BUCKET):
|
|||||||
|
|
||||||
|
|
||||||
@retry(stop=stop_after_attempt(TRY_TIMES), wait=wait_random(MIN_WAIT_TIME, MAX_WAIT_TIME),
|
@retry(stop=stop_after_attempt(TRY_TIMES), wait=wait_random(MIN_WAIT_TIME, MAX_WAIT_TIME),
|
||||||
retry=retry_if_exception_type(ConnectionError), reraise=True)
|
retry=retry_if_result(lambda x: x is False))
|
||||||
def copy_file(source_bucket, source_key, target_bucket, target_key):
|
def copy_file(source_bucket, source_key, target_bucket, target_key):
|
||||||
# 复制文件
|
# 复制文件
|
||||||
_, resp = UFILE_HANDLER.copy(target_bucket, target_key, source_bucket, source_key)
|
_, resp = UFILE_HANDLER.copy(target_bucket, target_key, source_bucket, source_key)
|
||||||
if resp.status_code == -1:
|
if resp.status_code == -1:
|
||||||
UCLOUD_LOGGER.warning(f"复制{source_key}时uCloud连接失败!")
|
UCLOUD_LOGGER.warning(f"复制{source_key}时uCloud连接失败!")
|
||||||
raise ConnectionError("uCloud连接失败")
|
return False
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
UCLOUD_LOGGER.warning(
|
UCLOUD_LOGGER.warning(
|
||||||
f"将({source_key})从({source_bucket})拷贝到({target_bucket})失败! status: {resp.status_code} error: {resp.error}"
|
f"将({source_key})从({source_bucket})拷贝到({target_bucket})失败! status: {resp.status_code} error: {resp.error}"
|
||||||
@@ -48,13 +48,13 @@ def copy_file(source_bucket, source_key, target_bucket, target_key):
|
|||||||
|
|
||||||
|
|
||||||
@retry(stop=stop_after_attempt(TRY_TIMES), wait=wait_random(MIN_WAIT_TIME, MAX_WAIT_TIME),
|
@retry(stop=stop_after_attempt(TRY_TIMES), wait=wait_random(MIN_WAIT_TIME, MAX_WAIT_TIME),
|
||||||
retry=retry_if_exception_type(ConnectionError), reraise=True)
|
retry=retry_if_result(lambda x: x is False))
|
||||||
def upload_file(key, file_path, bucket=BUCKET):
|
def upload_file(key, file_path, bucket=BUCKET):
|
||||||
# 普通上传文件至云空间
|
# 普通上传文件至云空间
|
||||||
_, resp = UFILE_HANDLER.putfile(bucket, key, file_path, header=None)
|
_, resp = UFILE_HANDLER.putfile(bucket, key, file_path, header=None)
|
||||||
if resp.status_code == -1:
|
if resp.status_code == -1:
|
||||||
UCLOUD_LOGGER.warning(f"上传{key}时uCloud连接失败!即将重试...")
|
UCLOUD_LOGGER.warning(f"上传{key}时uCloud连接失败!即将重试...")
|
||||||
raise ConnectionError("uCloud连接失败")
|
return False
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
UCLOUD_LOGGER.warning(f"上传({key})失败! status: {resp.status_code} error: {resp.error}")
|
UCLOUD_LOGGER.warning(f"上传({key})失败! status: {resp.status_code} error: {resp.error}")
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
import urllib.request
|
import urllib.request
|
||||||
from time import sleep
|
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import numpy
|
import numpy
|
||||||
from paddleclas import PaddleClas
|
from paddleclas import PaddleClas
|
||||||
|
from tenacity import retry, stop_after_attempt, wait_random
|
||||||
|
|
||||||
|
|
||||||
|
@retry(stop=stop_after_attempt(3), wait=wait_random(1, 3), reraise=True,
|
||||||
|
retry_error_callback=lambda e: logging.warning("获取图片失败", exc_info=e))
|
||||||
def read(image_path):
|
def read(image_path):
|
||||||
"""
|
"""
|
||||||
从网络或本地读取图片
|
从网络或本地读取图片
|
||||||
@@ -15,15 +17,8 @@ def read(image_path):
|
|||||||
:return: NumPy数组形式的图片
|
:return: NumPy数组形式的图片
|
||||||
"""
|
"""
|
||||||
if image_path.startswith("http"):
|
if image_path.startswith("http"):
|
||||||
resp = None
|
|
||||||
for i in range(3):
|
|
||||||
# 发送HTTP请求并获取图像数据
|
# 发送HTTP请求并获取图像数据
|
||||||
try:
|
|
||||||
resp = urllib.request.urlopen(image_path, timeout=60)
|
resp = urllib.request.urlopen(image_path, timeout=60)
|
||||||
break
|
|
||||||
except Exception as e:
|
|
||||||
logging.warning("获取图片失败", exc_info=e)
|
|
||||||
sleep(3)
|
|
||||||
# 将数据读取为字节流
|
# 将数据读取为字节流
|
||||||
image_data = resp.read()
|
image_data = resp.read()
|
||||||
# 将字节流转换为NumPy数组
|
# 将字节流转换为NumPy数组
|
||||||
|
|||||||
Reference in New Issue
Block a user