mirror of
https://github.com/dmunozv04/iSponsorBlockTV.git
synced 2025-12-06 20:06:44 +03:00
Add http tracing
This commit is contained in:
25
src/iSponsorBlockTV/debug_helpers.py
Normal file
25
src/iSponsorBlockTV/debug_helpers.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
|
||||||
|
class AiohttpTracer:
|
||||||
|
def __init__(self, logger):
|
||||||
|
self.logger = logger
|
||||||
|
|
||||||
|
async def on_request_start(self, session, context, params):
|
||||||
|
self.logger.debug(f"Request started ({id(context):#x}): {params.method} {params.url}")
|
||||||
|
|
||||||
|
async def on_request_end(self, session, context, params):
|
||||||
|
self.logger.debug(f"Request ended ({id(context):#x}): {params.response.status}")
|
||||||
|
|
||||||
|
async def on_request_exception(self, session, context, params):
|
||||||
|
self.logger.debug(f"Request exception ({id(context):#x}): {params.exception}")
|
||||||
|
|
||||||
|
async def on_response_chunk_received(self, session, context, params):
|
||||||
|
chunk_size = len(params.chunk)
|
||||||
|
try:
|
||||||
|
# Try to decode as text
|
||||||
|
text = params.chunk.decode('utf-8')
|
||||||
|
self.logger.debug(f"Response chunk ({id(context):#x}) {chunk_size} bytes: {text}")
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
# If not valid UTF-8, show as hex
|
||||||
|
hex_data = params.chunk.hex()
|
||||||
|
self.logger.debug(f"Response chunk ({id(context):#x}) ({chunk_size} bytes) [HEX]: {hex_data}")
|
||||||
@@ -131,6 +131,7 @@ class Config:
|
|||||||
help="data directory",
|
help="data directory",
|
||||||
)
|
)
|
||||||
@click.option("--debug", is_flag=True, help="debug mode")
|
@click.option("--debug", is_flag=True, help="debug mode")
|
||||||
|
@click.option("--http-tracing", is_flag=True, help="Enable HTTP request/response tracing")
|
||||||
# legacy commands as arguments
|
# legacy commands as arguments
|
||||||
@click.option("--setup", is_flag=True, help="Setup the program graphically", hidden=True)
|
@click.option("--setup", is_flag=True, help="Setup the program graphically", hidden=True)
|
||||||
@click.option(
|
@click.option(
|
||||||
@@ -140,11 +141,12 @@ class Config:
|
|||||||
hidden=True,
|
hidden=True,
|
||||||
)
|
)
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def cli(ctx, data, debug, setup, setup_cli):
|
def cli(ctx, data, debug, http_tracing, setup, setup_cli):
|
||||||
"""iSponsorblockTV"""
|
"""iSponsorblockTV"""
|
||||||
ctx.ensure_object(dict)
|
ctx.ensure_object(dict)
|
||||||
ctx.obj["data_dir"] = data
|
ctx.obj["data_dir"] = data
|
||||||
ctx.obj["debug"] = debug
|
ctx.obj["debug"] = debug
|
||||||
|
ctx.obj["http_tracing"] = http_tracing
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
ctx.obj["logger"] = logger
|
ctx.obj["logger"] = logger
|
||||||
@@ -189,7 +191,7 @@ def start(ctx):
|
|||||||
"""Start the main program"""
|
"""Start the main program"""
|
||||||
config = Config(ctx.obj["data_dir"])
|
config = Config(ctx.obj["data_dir"])
|
||||||
config.validate()
|
config.validate()
|
||||||
main.main(config, ctx.obj["debug"])
|
main.main(config, ctx.obj["debug"], ctx.obj["http_tracing"])
|
||||||
|
|
||||||
|
|
||||||
# Create fake "self" group to show pyapp options in help menu
|
# Create fake "self" group to show pyapp options in help menu
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from typing import Optional
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
|
|
||||||
from . import api_helpers, ytlounge
|
from . import api_helpers, ytlounge
|
||||||
|
from .debug_helpers import AiohttpTracer
|
||||||
|
|
||||||
|
|
||||||
class DeviceListener:
|
class DeviceListener:
|
||||||
@@ -153,14 +154,28 @@ def handle_signal(signum, frame):
|
|||||||
raise KeyboardInterrupt()
|
raise KeyboardInterrupt()
|
||||||
|
|
||||||
|
|
||||||
async def main_async(config, debug):
|
async def main_async(config, debug, http_tracing):
|
||||||
loop = asyncio.get_event_loop_policy().get_event_loop()
|
loop = asyncio.get_event_loop_policy().get_event_loop()
|
||||||
tasks = [] # Save the tasks so the interpreter doesn't garbage collect them
|
tasks = [] # Save the tasks so the interpreter doesn't garbage collect them
|
||||||
devices = [] # Save the devices to close them later
|
devices = [] # Save the devices to close them later
|
||||||
if debug:
|
if debug:
|
||||||
loop.set_debug(True)
|
loop.set_debug(True)
|
||||||
|
|
||||||
tcp_connector = aiohttp.TCPConnector(ttl_dns_cache=300)
|
tcp_connector = aiohttp.TCPConnector(ttl_dns_cache=300)
|
||||||
web_session = aiohttp.ClientSession(connector=tcp_connector)
|
|
||||||
|
# Configure session with tracing if enabled
|
||||||
|
if http_tracing:
|
||||||
|
root_logger = logging.getLogger("aiohttp_trace")
|
||||||
|
tracer = AiohttpTracer(root_logger)
|
||||||
|
trace_config = aiohttp.TraceConfig()
|
||||||
|
trace_config.on_request_start.append(tracer.on_request_start)
|
||||||
|
trace_config.on_response_chunk_received.append(tracer.on_response_chunk_received)
|
||||||
|
trace_config.on_request_end.append(tracer.on_request_end)
|
||||||
|
trace_config.on_request_exception.append(tracer.on_request_exception)
|
||||||
|
web_session = aiohttp.ClientSession(connector=tcp_connector, trace_configs=[trace_config])
|
||||||
|
else:
|
||||||
|
web_session = aiohttp.ClientSession(connector=tcp_connector)
|
||||||
|
|
||||||
api_helper = api_helpers.ApiHelper(config, web_session)
|
api_helper = api_helpers.ApiHelper(config, web_session)
|
||||||
for i in config.devices:
|
for i in config.devices:
|
||||||
device = DeviceListener(api_helper, config, i, debug, web_session)
|
device = DeviceListener(api_helper, config, i, debug, web_session)
|
||||||
@@ -184,5 +199,5 @@ async def main_async(config, debug):
|
|||||||
print("Exited")
|
print("Exited")
|
||||||
|
|
||||||
|
|
||||||
def main(config, debug):
|
def main(config, debug, http_tracing):
|
||||||
asyncio.run(main_async(config, debug))
|
asyncio.run(main_async(config, debug, http_tracing))
|
||||||
|
|||||||
Reference in New Issue
Block a user