mirror of
https://github.com/PaiGramTeam/PaiGram.git
synced 2024-11-25 01:29:42 +00:00
🎨 Improve error push
This commit is contained in:
parent
60b8e46924
commit
bda5f4fdd0
@ -47,7 +47,7 @@ LOGGER_LOCALS_MAX_DEPTH=0
|
|||||||
LOGGER_LOCALS_MAX_LENGTH=10
|
LOGGER_LOCALS_MAX_LENGTH=10
|
||||||
LOGGER_LOCALS_MAX_STRING=80
|
LOGGER_LOCALS_MAX_STRING=80
|
||||||
# 可被 logger 打印的 record 的名称(默认包含了 LOGGER_NAME )
|
# 可被 logger 打印的 record 的名称(默认包含了 LOGGER_NAME )
|
||||||
LOGGER_FILTERED_NAMES=["uvicorn"]
|
LOGGER_FILTERED_NAMES=["uvicorn","ErrorPush"]
|
||||||
|
|
||||||
|
|
||||||
# 超时配置 可选配置项
|
# 超时配置 可选配置项
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
import sentry_sdk
|
|
||||||
from git.repo import Repo
|
|
||||||
from git.repo.fun import rev_parse
|
|
||||||
from sentry_sdk.integrations.excepthook import ExcepthookIntegration
|
|
||||||
from sentry_sdk.integrations.httpx import HttpxIntegration
|
|
||||||
from sentry_sdk.integrations.logging import LoggingIntegration
|
|
||||||
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
|
|
||||||
from telegram import Update
|
|
||||||
|
|
||||||
from core.config import config
|
|
||||||
from utils.log import logger
|
|
||||||
|
|
||||||
repo = Repo(os.getcwd())
|
|
||||||
sentry_sdk_git_hash = rev_parse(repo, "HEAD").hexsha
|
|
||||||
sentry_sdk.init(
|
|
||||||
config.error.sentry_dsn,
|
|
||||||
traces_sample_rate=1.0,
|
|
||||||
release=sentry_sdk_git_hash,
|
|
||||||
environment="production",
|
|
||||||
integrations=[
|
|
||||||
HttpxIntegration(),
|
|
||||||
ExcepthookIntegration(always_run=False),
|
|
||||||
LoggingIntegration(event_level=50),
|
|
||||||
SqlalchemyIntegration(),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Sentry:
|
|
||||||
@staticmethod
|
|
||||||
def report_error(update: object, exc_info):
|
|
||||||
if not config.error.sentry_dsn:
|
|
||||||
return
|
|
||||||
logger.info("正在上传日记到 sentry")
|
|
||||||
message: str = ""
|
|
||||||
chat_id: int = 0
|
|
||||||
user_id: int = 0
|
|
||||||
if isinstance(update, Update):
|
|
||||||
if update.effective_user:
|
|
||||||
chat_id = update.effective_user.id
|
|
||||||
if update.effective_chat:
|
|
||||||
user_id = update.effective_chat.id
|
|
||||||
if update.effective_message:
|
|
||||||
if update.effective_message.text:
|
|
||||||
message = update.effective_message.text
|
|
||||||
sentry_sdk.set_context("Target", {"ChatID": str(chat_id), "UserID": str(user_id), "Msg": message})
|
|
||||||
sentry_sdk.capture_exception(exc_info)
|
|
||||||
logger.success("上传日记到 sentry 成功")
|
|
5
modules/errorpush/__init__.py
Normal file
5
modules/errorpush/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from .pb import PbClient, PbClientException
|
||||||
|
from .sentry import SentryClient, SentryClientException
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ["PbClient", "PbClientException", "SentryClient", "SentryClientException"]
|
3
modules/errorpush/logger.py
Normal file
3
modules/errorpush/logger.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger("ErrorPush")
|
@ -2,23 +2,42 @@ from typing import Optional
|
|||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from core.config import config
|
|
||||||
from utils.log import logger
|
from utils.log import logger
|
||||||
|
|
||||||
|
__all__ = ["PbClient", "PbClientException"]
|
||||||
|
|
||||||
|
|
||||||
|
class PbClientException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class PbClient:
|
class PbClient:
|
||||||
def __init__(self):
|
def __init__(self, pb_url: Optional[str] = None, pb_sunset: Optional[int] = None, pb_max_lines: int = 1000):
|
||||||
|
"""PbClient
|
||||||
|
:param pb_url:
|
||||||
|
:param pb_sunset: 自动销毁时间 单位为秒
|
||||||
|
:param pb_max_lines:
|
||||||
|
"""
|
||||||
self.client = httpx.AsyncClient()
|
self.client = httpx.AsyncClient()
|
||||||
self.PB_API = config.error.pb_url
|
self.PB_API = pb_url
|
||||||
self.sunset: int = config.error.pb_sunset # 自动销毁时间 单位为秒
|
self.sunset: int = pb_sunset
|
||||||
self.private: bool = True
|
self.private: bool = True
|
||||||
self.max_lines: int = config.error.pb_max_lines
|
self.max_lines: int = pb_max_lines
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enabled(self) -> bool:
|
||||||
|
return bool(self.PB_API)
|
||||||
|
|
||||||
async def create_pb(self, content: str) -> Optional[str]:
|
async def create_pb(self, content: str) -> Optional[str]:
|
||||||
|
try:
|
||||||
|
return await self._create_pb(content)
|
||||||
|
except Exception as exc:
|
||||||
|
raise PbClientException from exc
|
||||||
|
|
||||||
|
async def _create_pb(self, content: str) -> Optional[str]:
|
||||||
if not self.PB_API:
|
if not self.PB_API:
|
||||||
return None
|
return None
|
||||||
logger.info("正在上传日记到 pb")
|
content = "\n".join(content.splitlines()[-self.max_lines :]) + "\n"
|
||||||
content = "\n".join(content.splitlines()[-self.max_lines:]) + "\n"
|
|
||||||
data = {
|
data = {
|
||||||
"c": content,
|
"c": content,
|
||||||
}
|
}
|
||||||
@ -30,5 +49,4 @@ class PbClient:
|
|||||||
if result.is_error:
|
if result.is_error:
|
||||||
logger.warning("上传日记到 pb 失败 status_code[%s]", result.status_code)
|
logger.warning("上传日记到 pb 失败 status_code[%s]", result.status_code)
|
||||||
return None
|
return None
|
||||||
logger.success("上传日记到 pb 成功")
|
|
||||||
return result.headers.get("location")
|
return result.headers.get("location")
|
63
modules/errorpush/sentry.py
Normal file
63
modules/errorpush/sentry.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import os
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import sentry_sdk
|
||||||
|
from git.repo import Repo
|
||||||
|
from git.repo.fun import rev_parse
|
||||||
|
from sentry_sdk.integrations.excepthook import ExcepthookIntegration
|
||||||
|
from sentry_sdk.integrations.httpx import HttpxIntegration
|
||||||
|
from sentry_sdk.integrations.logging import LoggingIntegration
|
||||||
|
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
|
||||||
|
from telegram import Update
|
||||||
|
|
||||||
|
__all__ = ["SentryClient", "SentryClientException"]
|
||||||
|
|
||||||
|
|
||||||
|
class SentryClientException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SentryClient:
|
||||||
|
def __init__(self, sentry_dsn: Optional[str] = None):
|
||||||
|
self.sentry_dsn = sentry_dsn
|
||||||
|
if sentry_dsn:
|
||||||
|
repo = Repo(os.getcwd())
|
||||||
|
sentry_sdk_git_hash = rev_parse(repo, "HEAD").hexsha
|
||||||
|
sentry_sdk.init(
|
||||||
|
sentry_dsn,
|
||||||
|
traces_sample_rate=1.0,
|
||||||
|
release=sentry_sdk_git_hash,
|
||||||
|
environment="production",
|
||||||
|
integrations=[
|
||||||
|
HttpxIntegration(),
|
||||||
|
ExcepthookIntegration(always_run=False),
|
||||||
|
LoggingIntegration(event_level=50),
|
||||||
|
SqlalchemyIntegration(),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def enabled(self) -> bool:
|
||||||
|
return bool(self.sentry_dsn)
|
||||||
|
|
||||||
|
def report_error(self, update: object, exc_info):
|
||||||
|
try:
|
||||||
|
return self._report_error(update, exc_info)
|
||||||
|
except Exception as exc:
|
||||||
|
raise SentryClientException from exc
|
||||||
|
|
||||||
|
def _report_error(self, update: object, exc_info):
|
||||||
|
if not self.sentry_dsn:
|
||||||
|
return
|
||||||
|
message: str = ""
|
||||||
|
chat_id: int = 0
|
||||||
|
user_id: int = 0
|
||||||
|
if isinstance(update, Update):
|
||||||
|
if update.effective_user:
|
||||||
|
chat_id = update.effective_user.id
|
||||||
|
if update.effective_chat:
|
||||||
|
user_id = update.effective_chat.id
|
||||||
|
if update.effective_message and update.effective_message.text:
|
||||||
|
message = update.effective_message.text
|
||||||
|
sentry_sdk.set_context("Target", {"ChatID": str(chat_id), "UserID": str(user_id), "Msg": message})
|
||||||
|
sentry_sdk.capture_exception(exc_info)
|
@ -10,9 +10,9 @@ from telegram.error import BadRequest, Forbidden
|
|||||||
from telegram.ext import CallbackContext
|
from telegram.ext import CallbackContext
|
||||||
|
|
||||||
from core.bot import bot
|
from core.bot import bot
|
||||||
|
from core.config import config
|
||||||
from core.plugin import Plugin, error_handler
|
from core.plugin import Plugin, error_handler
|
||||||
from modules.error.pb import PbClient
|
from modules.errorpush import PbClient, SentryClient, PbClientException, SentryClientException
|
||||||
from modules.error.sentry import Sentry
|
|
||||||
from utils.log import logger
|
from utils.log import logger
|
||||||
|
|
||||||
notice_chat_id = bot.config.error.notification_chat_id
|
notice_chat_id = bot.config.error.notification_chat_id
|
||||||
@ -23,8 +23,8 @@ if not os.path.exists(logs_dir):
|
|||||||
report_dir = os.path.join(current_dir, "report")
|
report_dir = os.path.join(current_dir, "report")
|
||||||
if not os.path.exists(report_dir):
|
if not os.path.exists(report_dir):
|
||||||
os.mkdir(report_dir)
|
os.mkdir(report_dir)
|
||||||
pb_client = PbClient()
|
pb_client = PbClient(config.error.pb_url, config.error.pb_sunset, config.error.pb_max_lines)
|
||||||
sentry = Sentry()
|
sentry = SentryClient(config.error.sentry_dsn)
|
||||||
|
|
||||||
|
|
||||||
class ErrorHandler(Plugin):
|
class ErrorHandler(Plugin):
|
||||||
@ -91,19 +91,29 @@ class ErrorHandler(Plugin):
|
|||||||
except (BadRequest, Forbidden) as exc:
|
except (BadRequest, Forbidden) as exc:
|
||||||
logger.error(f"发送 update_id[{update.update_id}] 错误信息失败 错误信息为")
|
logger.error(f"发送 update_id[{update.update_id}] 错误信息失败 错误信息为")
|
||||||
logger.exception(exc)
|
logger.exception(exc)
|
||||||
try:
|
if pb_client.enabled:
|
||||||
pb_url = await pb_client.create_pb(error_text)
|
logger.info("正在上传日记到 pb")
|
||||||
if pb_url:
|
try:
|
||||||
await context.bot.send_message(
|
pb_url = await pb_client.create_pb(error_text)
|
||||||
chat_id=notice_chat_id,
|
if pb_url:
|
||||||
text=f"错误信息已上传至 <a href='{pb_url}'>fars</a> 请查看",
|
logger.success("上传日记到 pb 成功")
|
||||||
parse_mode=ParseMode.HTML,
|
await context.bot.send_message(
|
||||||
)
|
chat_id=notice_chat_id,
|
||||||
except Exception as exc: # pylint: disable=W0703
|
text=f"错误信息已上传至 <a href='{pb_url}'>fars</a> 请查看",
|
||||||
logger.error("上传错误信息至 fars 失败")
|
parse_mode=ParseMode.HTML,
|
||||||
logger.exception(exc)
|
)
|
||||||
try:
|
except PbClientException as exc:
|
||||||
sentry.report_error(update, (type(context.error), context.error, context.error.__traceback__))
|
logger.warning("上传错误信息至 fars 失败", exc_info=exc)
|
||||||
except Exception as exc: # pylint: disable=W0703
|
except Exception as exc:
|
||||||
logger.error("上传错误信息至 sentry 失败")
|
logger.error("上传错误信息至 fars 失败")
|
||||||
logger.exception(exc)
|
logger.exception(exc)
|
||||||
|
if sentry.enabled:
|
||||||
|
logger.info("正在上传日记到 sentry")
|
||||||
|
try:
|
||||||
|
sentry.report_error(update, (type(context.error), context.error, context.error.__traceback__))
|
||||||
|
logger.success("上传日记到 sentry 成功")
|
||||||
|
except SentryClientException as exc:
|
||||||
|
logger.warning("上传错误信息至 sentry 失败", exc_info=exc)
|
||||||
|
except Exception as exc:
|
||||||
|
logger.error("上传错误信息至 sentry 失败")
|
||||||
|
logger.exception(exc)
|
||||||
|
Loading…
Reference in New Issue
Block a user