Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♿ 优化网络警告文本的日志呈现 #655

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/usage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ next: /usage/cookie
- `BISON_PROXY`: 使用的代理连接,形如`http://<ip>:<port>`(可选)
- `BISON_UA`: 使用的 User-Agent,默认为 Chrome
- `BISON_SHOW_NETWORK_WARNING`: 是否在日志中输出网络异常,默认为`True`
- `BISON_COLLAPSE_NETWORK_WARNING`: 在启用`BISON_SHOW_NETWORK_WARNING`后选择是否清理警告文本中的换行符并当文本字符数超过限制时折叠这段文本,默认为`False`
- `BISON_COLLAPSE_NETWORK_WARNING_LENGTH`: 在启用`BISON_COLLAPSE_NETWORK_WARNING`后限制警告文本字符数
- `BISON_USE_BROWSER`: 环境中是否存在浏览器,某些主题或者平台需要浏览器,默认为`False`
- `BISON_PLATFORM_THEME`: 为[平台](#平台)指定渲染用[主题](#主题),用于渲染推送消息,默认为`{}`
::: details BISON_PLATFORM_THEME 配置项示例
Expand Down
36 changes: 24 additions & 12 deletions nonebot_bison/platform/platform.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
import ssl
import json
import time
Expand Down Expand Up @@ -48,20 +49,31 @@ def __init__(cls, name, bases, namespace, **kwargs):
R = TypeVar("R")


async def catch_network_error(func: Callable[P, Awaitable[R]], *args: P.args, **kwargs: P.kwargs) -> R | None:
try:
return await func(*args, **kwargs)
except httpx.RequestError as err:
if plugin_config.bison_show_network_warning:
logger.warning(f"network connection error: {type(err)}, url: {err.request.url}")
def logger_custom_warning(_msg: str) -> None:
if plugin_config.bison_collapse_network_warning:
_msg = re.sub(r"\s*[\r\n]+\s*", "", _msg)
_max_length = plugin_config.bison_collapse_network_warning_length
logger.warning(_msg if len(_msg) < _max_length else f"{_msg[:_max_length]}...")
return None
except ssl.SSLError as err:
if plugin_config.bison_show_network_warning:
logger.warning(f"ssl error: {err}")
else:
logger.warning(_msg)
return None
except json.JSONDecodeError as err:
logger.warning(f"json error, parsing: {err.doc}")
raise err


async def catch_network_error(func: Callable[P, Awaitable[R]], *args: P.args, **kwargs: P.kwargs) -> R | None:
if plugin_config.bison_show_network_warning:
try:
return await func(*args, **kwargs)
except httpx.RequestError as err:
return logger_custom_warning(f"network connection error: {type(err)}, url: {err.request.url}")
except ssl.SSLError as err:
return logger_custom_warning(f"ssl error: {err}")
except json.JSONDecodeError as err:
return logger_custom_warning(f"json error, parsing: {err.doc}")
except Exception as err:
return logger_custom_warning(f"unmatched exception: {err}")
else:
return await func(*args, **kwargs)


class PlatformMeta(RegistryMeta):
Expand Down
2 changes: 2 additions & 0 deletions nonebot_bison/plugin_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class Config:
description="默认UA",
)
bison_show_network_warning: bool = True
bison_collapse_network_warning: bool = False # 清理警告文本中的换行符,当文本字符数超过限制时折叠
bison_collapse_network_warning_length: int = 100
bison_platform_theme: dict[PlatformName, ThemeName] = {}

@property
Expand Down
66 changes: 66 additions & 0 deletions tests/platforms/test_platform.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from time import time
from typing import Any
from collections.abc import Iterator

import pytest
from loguru import logger
from nonebug.app import App
from _pytest.logging import LogCaptureFixture

now = time()
passed = now - 3 * 60 * 60
Expand All @@ -16,6 +19,69 @@
]


@pytest.fixture
def caplog(caplog: LogCaptureFixture) -> Iterator[LogCaptureFixture]:
def filter_(record):
return record["level"].no >= caplog.handler.level

handler_id = logger.add(caplog.handler, level=0, format="{message}", filter=filter_)
yield caplog
logger.remove(handler_id)


def test_logger_custom_warning_enable(app: App, caplog):
from nonebot_bison.plugin_config import plugin_config
from nonebot_bison.platform.platform import logger_custom_warning

plugin_config.bison_collapse_network_warning = True
plugin_config.bison_collapse_network_warning_length = 100

test_message = """
<h1>502 Bad Gateway</h1>
<p>The proxy server received an invalid response from an upstream server. Sorry for the inconvenience.<br/>
Please report this message and include the following information to us.<br/>
Thank you very much!</p>
""" # 沟槽的微博
logger_custom_warning(test_message)
assert (
"<h1>502 Bad Gateway</h1><p>The proxy server received an invalid response from an upstream server. So..."
in caplog.text
)


def test_logger_custom_warning_disable(app: App, caplog):
from nonebot_bison.plugin_config import plugin_config
from nonebot_bison.platform.platform import logger_custom_warning

plugin_config.bison_collapse_network_warning = False
plugin_config.bison_collapse_network_warning_length = 100

test_message = """
<h1>502 Bad Gateway</h1>
<p>The proxy server received an invalid response from an upstream server. Sorry for the inconvenience.<br/>
Please report this message and include the following information to us.<br/>
Thank you very much!</p>
"""
logger_custom_warning(test_message)
assert test_message in caplog.text


@pytest.mark.asyncio
async def test_catch_network_error_unmatched_exception(app: App, caplog):
from nonebot_bison.plugin_config import plugin_config
from nonebot_bison.platform.platform import catch_network_error

plugin_config.bison_collapse_network_warning = True

async def mock_exception():
raise Exception("unmatched exception")

result = await catch_network_error(mock_exception)

assert result is None
assert "unmatched exception: unmatched exception" in caplog.text


@pytest.fixture
def dummy_user(app: App):
from nonebot_plugin_saa import TargetQQGroup
Expand Down
Loading