feat: control API and Tor integration #1
@@ -110,6 +110,7 @@ Options:
|
|||||||
-v, --verbose Debug logging
|
-v, --verbose Debug logging
|
||||||
-q, --quiet Errors only
|
-q, --quiet Errors only
|
||||||
--cprofile [FILE] Enable cProfile, dump to FILE (default: s5p.prof)
|
--cprofile [FILE] Enable cProfile, dump to FILE (default: s5p.prof)
|
||||||
|
--tracemalloc [N] Enable tracemalloc, show top N allocators on exit (default: 10)
|
||||||
-V, --version Show version
|
-V, --version Show version
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ s5p -m 512 # max concurrent connections
|
|||||||
s5p --api 127.0.0.1:1081 # enable control API
|
s5p --api 127.0.0.1:1081 # enable control API
|
||||||
s5p --cprofile # profile to s5p.prof
|
s5p --cprofile # profile to s5p.prof
|
||||||
s5p --cprofile out.prof # profile to custom file
|
s5p --cprofile out.prof # profile to custom file
|
||||||
|
s5p --tracemalloc # memory profile (top 10)
|
||||||
|
s5p --tracemalloc 20 # memory profile (top 20)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Container
|
## Container
|
||||||
|
|||||||
@@ -419,6 +419,15 @@ s5p --cprofile output.prof -c config/s5p.yaml
|
|||||||
|
|
||||||
# Analyze after stopping
|
# Analyze after stopping
|
||||||
python -m pstats s5p.prof
|
python -m pstats s5p.prof
|
||||||
|
|
||||||
|
# Memory profiling with tracemalloc (top 10 allocators on exit)
|
||||||
|
s5p --tracemalloc -c config/s5p.yaml
|
||||||
|
|
||||||
|
# Show top 20 allocators
|
||||||
|
s5p --tracemalloc 20 -c config/s5p.yaml
|
||||||
|
|
||||||
|
# Both profilers simultaneously
|
||||||
|
s5p --cprofile --tracemalloc -c config/s5p.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
## Testing the Proxy
|
## Testing the Proxy
|
||||||
|
|||||||
@@ -62,6 +62,10 @@ def _parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|||||||
"--cprofile", metavar="FILE", nargs="?", const="s5p.prof",
|
"--cprofile", metavar="FILE", nargs="?", const="s5p.prof",
|
||||||
help="enable cProfile, dump stats to FILE (default: s5p.prof)",
|
help="enable cProfile, dump stats to FILE (default: s5p.prof)",
|
||||||
)
|
)
|
||||||
|
p.add_argument(
|
||||||
|
"--tracemalloc", metavar="N", nargs="?", const=10, type=int,
|
||||||
|
help="enable tracemalloc, show top N allocators on exit (default: 10)",
|
||||||
|
)
|
||||||
return p.parse_args(argv)
|
return p.parse_args(argv)
|
||||||
|
|
||||||
|
|
||||||
@@ -112,6 +116,11 @@ def main(argv: list[str] | None = None) -> int:
|
|||||||
config.log_level = "error"
|
config.log_level = "error"
|
||||||
|
|
||||||
_setup_logging(config.log_level)
|
_setup_logging(config.log_level)
|
||||||
|
logger = logging.getLogger("s5p")
|
||||||
|
|
||||||
|
if args.tracemalloc:
|
||||||
|
import tracemalloc
|
||||||
|
tracemalloc.start()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if args.cprofile:
|
if args.cprofile:
|
||||||
@@ -123,13 +132,21 @@ def main(argv: list[str] | None = None) -> int:
|
|||||||
finally:
|
finally:
|
||||||
prof.disable()
|
prof.disable()
|
||||||
prof.dump_stats(args.cprofile)
|
prof.dump_stats(args.cprofile)
|
||||||
logging.getLogger("s5p").info("profile saved to %s", args.cprofile)
|
logger.info("profile saved to %s", args.cprofile)
|
||||||
else:
|
else:
|
||||||
asyncio.run(serve(config))
|
asyncio.run(serve(config))
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
return 0
|
return 0
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.getLogger("s5p").error("%s", e)
|
logger.error("%s", e)
|
||||||
return 1
|
return 1
|
||||||
|
finally:
|
||||||
|
if args.tracemalloc:
|
||||||
|
import tracemalloc
|
||||||
|
snapshot = tracemalloc.take_snapshot()
|
||||||
|
stats = snapshot.statistics("lineno")
|
||||||
|
logger.info("tracemalloc: top %d allocations", args.tracemalloc)
|
||||||
|
for stat in stats[:args.tracemalloc]:
|
||||||
|
logger.info(" %s", stat)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
Reference in New Issue
Block a user