redline-core 0.2.0a1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. redline_core-0.2.0a1/.gitignore +21 -0
  2. redline_core-0.2.0a1/LICENSE +21 -0
  3. redline_core-0.2.0a1/PKG-INFO +121 -0
  4. redline_core-0.2.0a1/README.md +71 -0
  5. redline_core-0.2.0a1/pyproject.toml +106 -0
  6. redline_core-0.2.0a1/src/redline_core/__init__.py +66 -0
  7. redline_core-0.2.0a1/src/redline_core/access.py +1091 -0
  8. redline_core-0.2.0a1/src/redline_core/api.py +900 -0
  9. redline_core-0.2.0a1/src/redline_core/blocking.py +538 -0
  10. redline_core-0.2.0a1/src/redline_core/callsite.py +173 -0
  11. redline_core-0.2.0a1/src/redline_core/cli.py +826 -0
  12. redline_core-0.2.0a1/src/redline_core/conf.py +670 -0
  13. redline_core-0.2.0a1/src/redline_core/config.py +686 -0
  14. redline_core-0.2.0a1/src/redline_core/contrib/__init__.py +13 -0
  15. redline_core-0.2.0a1/src/redline_core/contrib/_resolver.py +143 -0
  16. redline_core-0.2.0a1/src/redline_core/contrib/asgi.py +31 -0
  17. redline_core-0.2.0a1/src/redline_core/contrib/asyncpg.py +80 -0
  18. redline_core-0.2.0a1/src/redline_core/contrib/graphene.py +22 -0
  19. redline_core-0.2.0a1/src/redline_core/contrib/httpx.py +85 -0
  20. redline_core-0.2.0a1/src/redline_core/contrib/marshmallow.py +74 -0
  21. redline_core-0.2.0a1/src/redline_core/contrib/psycopg.py +103 -0
  22. redline_core-0.2.0a1/src/redline_core/contrib/redis.py +144 -0
  23. redline_core-0.2.0a1/src/redline_core/contrib/requests.py +65 -0
  24. redline_core-0.2.0a1/src/redline_core/contrib/sqlalchemy/__init__.py +350 -0
  25. redline_core-0.2.0a1/src/redline_core/contrib/sqlalchemy/suggest.py +566 -0
  26. redline_core-0.2.0a1/src/redline_core/contrib/strawberry.py +29 -0
  27. redline_core-0.2.0a1/src/redline_core/detect.py +438 -0
  28. redline_core-0.2.0a1/src/redline_core/detectors/__init__.py +29 -0
  29. redline_core-0.2.0a1/src/redline_core/detectors/_common.py +22 -0
  30. redline_core-0.2.0a1/src/redline_core/detectors/blocking.py +119 -0
  31. redline_core-0.2.0a1/src/redline_core/detectors/external.py +195 -0
  32. redline_core-0.2.0a1/src/redline_core/detectors/results.py +341 -0
  33. redline_core-0.2.0a1/src/redline_core/detectors/serializers.py +60 -0
  34. redline_core-0.2.0a1/src/redline_core/detectors/transactions.py +123 -0
  35. redline_core-0.2.0a1/src/redline_core/explain.py +161 -0
  36. redline_core-0.2.0a1/src/redline_core/histogram.py +231 -0
  37. redline_core-0.2.0a1/src/redline_core/index_advisor.py +840 -0
  38. redline_core-0.2.0a1/src/redline_core/linefix.py +42 -0
  39. redline_core-0.2.0a1/src/redline_core/load/__init__.py +59 -0
  40. redline_core-0.2.0a1/src/redline_core/load/analysis.py +187 -0
  41. redline_core-0.2.0a1/src/redline_core/load/control.py +295 -0
  42. redline_core-0.2.0a1/src/redline_core/load/engine.py +544 -0
  43. redline_core-0.2.0a1/src/redline_core/load/generate.py +445 -0
  44. redline_core-0.2.0a1/src/redline_core/load/profile.py +478 -0
  45. redline_core-0.2.0a1/src/redline_core/load/scenario.py +413 -0
  46. redline_core-0.2.0a1/src/redline_core/load/sinks.py +273 -0
  47. redline_core-0.2.0a1/src/redline_core/load/worker.py +319 -0
  48. redline_core-0.2.0a1/src/redline_core/model.py +515 -0
  49. redline_core-0.2.0a1/src/redline_core/plan_analysis.py +750 -0
  50. redline_core-0.2.0a1/src/redline_core/predicates.py +228 -0
  51. redline_core-0.2.0a1/src/redline_core/profiler.py +168 -0
  52. redline_core-0.2.0a1/src/redline_core/py.typed +0 -0
  53. redline_core-0.2.0a1/src/redline_core/recorder.py +1097 -0
  54. redline_core-0.2.0a1/src/redline_core/redact.py +574 -0
  55. redline_core-0.2.0a1/src/redline_core/runs.py +102 -0
  56. redline_core-0.2.0a1/src/redline_core/sampling.py +150 -0
  57. redline_core-0.2.0a1/src/redline_core/scan.py +520 -0
  58. redline_core-0.2.0a1/src/redline_core/sql.py +349 -0
  59. redline_core-0.2.0a1/src/redline_core/storage/__init__.py +53 -0
  60. redline_core-0.2.0a1/src/redline_core/storage/base.py +561 -0
  61. redline_core-0.2.0a1/src/redline_core/storage/derive.py +242 -0
  62. redline_core-0.2.0a1/src/redline_core/storage/private.py +80 -0
  63. redline_core-0.2.0a1/src/redline_core/storage/sqlite.py +1809 -0
  64. redline_core-0.2.0a1/src/redline_core/stream.py +200 -0
  65. redline_core-0.2.0a1/src/redline_core/transactions.py +101 -0
  66. redline_core-0.2.0a1/src/redline_core/ui/__init__.py +220 -0
  67. redline_core-0.2.0a1/src/redline_core/ui/static/assets/Flamegraph-pOyiCXpy.js +1 -0
  68. redline_core-0.2.0a1/src/redline_core/ui/static/assets/index-WiSpvf2f.css +1 -0
  69. redline_core-0.2.0a1/src/redline_core/ui/static/assets/index-rF9G2W0X.js +24 -0
  70. redline_core-0.2.0a1/src/redline_core/ui/static/badge.js +93 -0
  71. redline_core-0.2.0a1/src/redline_core/ui/static/index.html +25 -0
  72. redline_core-0.2.0a1/tests/__init__.py +0 -0
  73. redline_core-0.2.0a1/tests/conftest.py +94 -0
  74. redline_core-0.2.0a1/tests/contrib/__init__.py +0 -0
  75. redline_core-0.2.0a1/tests/contrib/conftest.py +30 -0
  76. redline_core-0.2.0a1/tests/contrib/test_drivers.py +129 -0
  77. redline_core-0.2.0a1/tests/contrib/test_http.py +104 -0
  78. redline_core-0.2.0a1/tests/contrib/test_marshmallow.py +62 -0
  79. redline_core-0.2.0a1/tests/contrib/test_redis.py +131 -0
  80. redline_core-0.2.0a1/tests/contrib/test_sqlalchemy.py +87 -0
  81. redline_core-0.2.0a1/tests/contrib/test_sqlalchemy_data.py +172 -0
  82. redline_core-0.2.0a1/tests/fixtures/mysql_full_scan.json +37 -0
  83. redline_core-0.2.0a1/tests/fixtures/pg_seq_scan.json +78 -0
  84. redline_core-0.2.0a1/tests/load/__init__.py +0 -0
  85. redline_core-0.2.0a1/tests/load/conftest.py +83 -0
  86. redline_core-0.2.0a1/tests/load/test_cli.py +475 -0
  87. redline_core-0.2.0a1/tests/load/test_engine.py +153 -0
  88. redline_core-0.2.0a1/tests/load/test_generate_routes.py +36 -0
  89. redline_core-0.2.0a1/tests/load/test_run_redaction.py +104 -0
  90. redline_core-0.2.0a1/tests/load/test_scenario.py +205 -0
  91. redline_core-0.2.0a1/tests/load/test_schedule_analysis.py +224 -0
  92. redline_core-0.2.0a1/tests/test_access.py +723 -0
  93. redline_core-0.2.0a1/tests/test_api.py +188 -0
  94. redline_core-0.2.0a1/tests/test_api_v2.py +405 -0
  95. redline_core-0.2.0a1/tests/test_badge_stream.py +221 -0
  96. redline_core-0.2.0a1/tests/test_blocking.py +432 -0
  97. redline_core-0.2.0a1/tests/test_cli_config.py +159 -0
  98. redline_core-0.2.0a1/tests/test_conf.py +58 -0
  99. redline_core-0.2.0a1/tests/test_config.py +390 -0
  100. redline_core-0.2.0a1/tests/test_contrib_graphql.py +263 -0
  101. redline_core-0.2.0a1/tests/test_detect.py +145 -0
  102. redline_core-0.2.0a1/tests/test_detectors_v02.py +281 -0
  103. redline_core-0.2.0a1/tests/test_explain.py +515 -0
  104. redline_core-0.2.0a1/tests/test_hardening.py +268 -0
  105. redline_core-0.2.0a1/tests/test_histogram.py +152 -0
  106. redline_core-0.2.0a1/tests/test_index_advisor.py +618 -0
  107. redline_core-0.2.0a1/tests/test_logs_locals.py +624 -0
  108. redline_core-0.2.0a1/tests/test_model.py +86 -0
  109. redline_core-0.2.0a1/tests/test_overhead.py +50 -0
  110. redline_core-0.2.0a1/tests/test_recorder.py +389 -0
  111. redline_core-0.2.0a1/tests/test_redact.py +151 -0
  112. redline_core-0.2.0a1/tests/test_review_fixes.py +262 -0
  113. redline_core-0.2.0a1/tests/test_sampling_callsite.py +108 -0
  114. redline_core-0.2.0a1/tests/test_scan.py +255 -0
  115. redline_core-0.2.0a1/tests/test_security_access.py +274 -0
  116. redline_core-0.2.0a1/tests/test_security_redaction.py +271 -0
  117. redline_core-0.2.0a1/tests/test_sql.py +156 -0
  118. redline_core-0.2.0a1/tests/test_storage.py +345 -0
  119. redline_core-0.2.0a1/tests/test_storage_v2.py +715 -0
  120. redline_core-0.2.0a1/tests/test_transactions.py +289 -0
  121. redline_core-0.2.0a1/tests/test_ui_profiler.py +120 -0
  122. redline_core-0.2.0a1/tests/test_v02_model_conf.py +297 -0
@@ -0,0 +1,21 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .venv/
4
+ venv/
5
+ dist/
6
+ build/
7
+ site/
8
+ .redline/
9
+ *.db
10
+ *.sqlite3
11
+ .pytest_cache/
12
+ .ruff_cache/
13
+ .coverage
14
+ htmlcov/
15
+ node_modules/
16
+ frontend/dist/
17
+ .DS_Store
18
+ frontend/screenshots/
19
+
20
+ # agent worktrees
21
+ .claude/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mahmoud Ahmed
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,121 @@
1
+ Metadata-Version: 2.5
2
+ Name: redline-core
3
+ Version: 0.2.0a1
4
+ Summary: Framework-agnostic request profiler engine: span tracing, SQL fingerprinting, N+1 detection, EXPLAIN analysis, storage and the Redline web UI.
5
+ Project-URL: Homepage, https://github.com/Pythondeveloper6/redline
6
+ Project-URL: Documentation, https://pythondeveloper6.github.io/redline/
7
+ Project-URL: Source, https://github.com/Pythondeveloper6/redline
8
+ Project-URL: Issues, https://github.com/Pythondeveloper6/redline/issues
9
+ Project-URL: Changelog, https://github.com/Pythondeveloper6/redline/blob/main/CHANGELOG.md
10
+ Author-email: Mahmoud Ahmed <pythondeveloper6@gmail.com>
11
+ Maintainer-email: Mahmoud Ahmed <pythondeveloper6@gmail.com>
12
+ License-Expression: MIT
13
+ License-File: LICENSE
14
+ Keywords: apm,explain,flamegraph,load-testing,n+1,performance,profiler,profiling,sql
15
+ Classifier: Development Status :: 3 - Alpha
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3 :: Only
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Programming Language :: Python :: 3.14
25
+ Classifier: Topic :: Software Development :: Debuggers
26
+ Classifier: Topic :: System :: Monitoring
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: >=3.10
29
+ Provides-Extra: asyncpg
30
+ Requires-Dist: asyncpg>=0.29; extra == 'asyncpg'
31
+ Provides-Extra: graphene
32
+ Requires-Dist: graphene>=3.3; extra == 'graphene'
33
+ Provides-Extra: httpx
34
+ Requires-Dist: httpx>=0.27; extra == 'httpx'
35
+ Provides-Extra: load
36
+ Requires-Dist: httpx>=0.27; extra == 'load'
37
+ Provides-Extra: profile
38
+ Requires-Dist: pyinstrument<6.0,>=5.0; extra == 'profile'
39
+ Provides-Extra: psycopg
40
+ Requires-Dist: psycopg>=3.1; extra == 'psycopg'
41
+ Provides-Extra: redis
42
+ Requires-Dist: redis>=5.0; extra == 'redis'
43
+ Provides-Extra: requests
44
+ Requires-Dist: requests>=2.31; extra == 'requests'
45
+ Provides-Extra: sqlalchemy
46
+ Requires-Dist: sqlalchemy<3.0,>=2.0; extra == 'sqlalchemy'
47
+ Provides-Extra: strawberry
48
+ Requires-Dist: strawberry-graphql>=0.240; extra == 'strawberry'
49
+ Description-Content-Type: text/markdown
50
+
51
+ <p align="center">
52
+ <a href="https://pythondeveloper6.github.io/redline/">
53
+ <picture>
54
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/Pythondeveloper6/redline/main/docs/assets/logo-dark.svg">
55
+ <img alt="Redline" src="https://raw.githubusercontent.com/Pythondeveloper6/redline/main/docs/assets/logo-light.svg" height="56">
56
+ </picture>
57
+ </a>
58
+ </p>
59
+
60
+ # redline-core
61
+
62
+ The framework-agnostic engine behind **Redline**, a self-hosted request profiler and
63
+ backend analyzer and load tester for Django, FastAPI, Flask and Litestar.
64
+
65
+ `redline-core` holds everything that does not depend on a web framework:
66
+
67
+ - the trace/span data model and a `contextvars` recorder that is correct across threads
68
+ and `asyncio` tasks and costs next to nothing when no request is being recorded;
69
+ - SQL fingerprinting, project-only callsite capture and secret redaction;
70
+ - detectors for N+1 queries, duplicate queries, slow queries and query budgets, plus
71
+ event-loop blocking, long transactions, huge and unbounded results, `len(qs)` vs `.exists()`,
72
+ slow serializers and slow, duplicated or retried external calls;
73
+ - an on-demand `EXPLAIN` runner with plan analysis for PostgreSQL, MySQL and SQLite;
74
+ - an optional `pyinstrument` flamegraph profiler (`redline-core[profile]`);
75
+ - a separate SQLite store with a background writer, retention, hourly rollups and release
76
+ history;
77
+ - a load tester (`redline load`, extra `load`) with an open-model scheduler, knee detection
78
+ and per-step bottlenecks;
79
+ - optional integrations in `redline_core.contrib` (SQLAlchemy, httpx, requests, redis,
80
+ asyncpg, psycopg, Marshmallow, Strawberry, Graphene);
81
+ - the access policy and layered configuration shared by every adapter;
82
+ - the framework-neutral JSON API and the prebuilt web UI.
83
+
84
+ It has **no runtime dependencies**.
85
+
86
+ ## You probably want an adapter
87
+
88
+ Install the package for your framework; it pulls in `redline-core` for you:
89
+
90
+ Redline is not on PyPI yet: install from GitHub, naming the adapter **and** `redline-core` in
91
+ one command (the adapter pins the core exactly). Adapters: `django-redline`,
92
+ `fastapi-redline`, `flask-redline`, `litestar-redline`.
93
+
94
+ ```console
95
+ pip install \
96
+ "django-redline @ git+https://github.com/Pythondeveloper6/redline#subdirectory=packages/django-redline" \
97
+ "redline-core @ git+https://github.com/Pythondeveloper6/redline#subdirectory=packages/redline-core"
98
+ ```
99
+
100
+ Extras on the core requirement: `profile` (flamegraphs), `load` (the load tester), and
101
+ `httpx`, `requests`, `redis`, `asyncpg`, `psycopg`, `strawberry`, `graphene`. Documentation:
102
+ <https://pythondeveloper6.github.io/redline/>.
103
+
104
+ ## Timing your own code
105
+
106
+ ```python
107
+ import redline_core
108
+
109
+ @redline_core.span("pricing.compute")
110
+ def compute_price(order): ...
111
+
112
+ async def handler():
113
+ async with redline_core.span("fetch-rates", kind="custom", provider="ecb"):
114
+ ...
115
+ ```
116
+
117
+ `span()` does nothing (and costs almost nothing) outside a recorded request.
118
+
119
+ ## License
120
+
121
+ MIT
@@ -0,0 +1,71 @@
1
+ <p align="center">
2
+ <a href="https://pythondeveloper6.github.io/redline/">
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/Pythondeveloper6/redline/main/docs/assets/logo-dark.svg">
5
+ <img alt="Redline" src="https://raw.githubusercontent.com/Pythondeveloper6/redline/main/docs/assets/logo-light.svg" height="56">
6
+ </picture>
7
+ </a>
8
+ </p>
9
+
10
+ # redline-core
11
+
12
+ The framework-agnostic engine behind **Redline**, a self-hosted request profiler and
13
+ backend analyzer and load tester for Django, FastAPI, Flask and Litestar.
14
+
15
+ `redline-core` holds everything that does not depend on a web framework:
16
+
17
+ - the trace/span data model and a `contextvars` recorder that is correct across threads
18
+ and `asyncio` tasks and costs next to nothing when no request is being recorded;
19
+ - SQL fingerprinting, project-only callsite capture and secret redaction;
20
+ - detectors for N+1 queries, duplicate queries, slow queries and query budgets, plus
21
+ event-loop blocking, long transactions, huge and unbounded results, `len(qs)` vs `.exists()`,
22
+ slow serializers and slow, duplicated or retried external calls;
23
+ - an on-demand `EXPLAIN` runner with plan analysis for PostgreSQL, MySQL and SQLite;
24
+ - an optional `pyinstrument` flamegraph profiler (`redline-core[profile]`);
25
+ - a separate SQLite store with a background writer, retention, hourly rollups and release
26
+ history;
27
+ - a load tester (`redline load`, extra `load`) with an open-model scheduler, knee detection
28
+ and per-step bottlenecks;
29
+ - optional integrations in `redline_core.contrib` (SQLAlchemy, httpx, requests, redis,
30
+ asyncpg, psycopg, Marshmallow, Strawberry, Graphene);
31
+ - the access policy and layered configuration shared by every adapter;
32
+ - the framework-neutral JSON API and the prebuilt web UI.
33
+
34
+ It has **no runtime dependencies**.
35
+
36
+ ## You probably want an adapter
37
+
38
+ Install the package for your framework; it pulls in `redline-core` for you:
39
+
40
+ Redline is not on PyPI yet: install from GitHub, naming the adapter **and** `redline-core` in
41
+ one command (the adapter pins the core exactly). Adapters: `django-redline`,
42
+ `fastapi-redline`, `flask-redline`, `litestar-redline`.
43
+
44
+ ```console
45
+ pip install \
46
+ "django-redline @ git+https://github.com/Pythondeveloper6/redline#subdirectory=packages/django-redline" \
47
+ "redline-core @ git+https://github.com/Pythondeveloper6/redline#subdirectory=packages/redline-core"
48
+ ```
49
+
50
+ Extras on the core requirement: `profile` (flamegraphs), `load` (the load tester), and
51
+ `httpx`, `requests`, `redis`, `asyncpg`, `psycopg`, `strawberry`, `graphene`. Documentation:
52
+ <https://pythondeveloper6.github.io/redline/>.
53
+
54
+ ## Timing your own code
55
+
56
+ ```python
57
+ import redline_core
58
+
59
+ @redline_core.span("pricing.compute")
60
+ def compute_price(order): ...
61
+
62
+ async def handler():
63
+ async with redline_core.span("fetch-rates", kind="custom", provider="ecb"):
64
+ ...
65
+ ```
66
+
67
+ `span()` does nothing (and costs almost nothing) outside a recorded request.
68
+
69
+ ## License
70
+
71
+ MIT
@@ -0,0 +1,106 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "redline-core"
7
+ version = "0.2.0a1"
8
+ description = "Framework-agnostic request profiler engine: span tracing, SQL fingerprinting, N+1 detection, EXPLAIN analysis, storage and the Redline web UI."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{ name = "Mahmoud Ahmed", email = "pythondeveloper6@gmail.com" }]
14
+ maintainers = [{ name = "Mahmoud Ahmed", email = "pythondeveloper6@gmail.com" }]
15
+ keywords = [
16
+ "profiler",
17
+ "profiling",
18
+ "performance",
19
+ "apm",
20
+ "n+1",
21
+ "sql",
22
+ "explain",
23
+ "flamegraph",
24
+ "load-testing",
25
+ ]
26
+ classifiers = [
27
+ "Development Status :: 3 - Alpha",
28
+ "Intended Audience :: Developers",
29
+ "Operating System :: OS Independent",
30
+ "Programming Language :: Python :: 3",
31
+ "Programming Language :: Python :: 3 :: Only",
32
+ "Programming Language :: Python :: 3.10",
33
+ "Programming Language :: Python :: 3.11",
34
+ "Programming Language :: Python :: 3.12",
35
+ "Programming Language :: Python :: 3.13",
36
+ "Programming Language :: Python :: 3.14",
37
+ "Topic :: Software Development :: Debuggers",
38
+ "Topic :: System :: Monitoring",
39
+ "Typing :: Typed",
40
+ ]
41
+ # Deliberately empty. The core is imported into the request path of an application and
42
+ # must never pull a framework (or anything else) into it uninvited. Storage is stdlib
43
+ # sqlite3; the flamegraph profiler is an opt-in extra.
44
+ dependencies = []
45
+
46
+ [project.optional-dependencies]
47
+ profile = ["pyinstrument>=5.0,<6.0"]
48
+ sqlalchemy = ["sqlalchemy>=2.0,<3.0"]
49
+ httpx = ["httpx>=0.27"]
50
+ requests = ["requests>=2.31"]
51
+ redis = ["redis>=5.0"]
52
+ asyncpg = ["asyncpg>=0.29"]
53
+ psycopg = ["psycopg>=3.1"]
54
+ strawberry = ["strawberry-graphql>=0.240"]
55
+ graphene = ["graphene>=3.3"]
56
+ load = ["httpx>=0.27"]
57
+
58
+ [project.scripts]
59
+ redline = "redline_core.cli:main"
60
+
61
+ [project.urls]
62
+ Homepage = "https://github.com/Pythondeveloper6/redline"
63
+ Documentation = "https://pythondeveloper6.github.io/redline/"
64
+ Source = "https://github.com/Pythondeveloper6/redline"
65
+ Issues = "https://github.com/Pythondeveloper6/redline/issues"
66
+ Changelog = "https://github.com/Pythondeveloper6/redline/blob/main/CHANGELOG.md"
67
+
68
+ [dependency-groups]
69
+ dev = [
70
+ "pytest>=8.3",
71
+ "pytest-asyncio>=0.24",
72
+ "ruff>=0.8",
73
+ "pyinstrument>=5.0",
74
+ "sqlalchemy[asyncio]>=2.0,<3.0",
75
+ "aiosqlite>=0.20",
76
+ "greenlet>=3.0",
77
+ "httpx>=0.27",
78
+ "requests>=2.31",
79
+ "marshmallow>=3.20",
80
+ "redis>=5.0",
81
+ "fakeredis>=2.20",
82
+ "asyncpg>=0.29",
83
+ "psycopg>=3.1",
84
+ "strawberry-graphql>=0.240",
85
+ "graphene>=3.3",
86
+ ]
87
+
88
+ [tool.hatch.build.targets.wheel]
89
+ packages = ["src/redline_core"]
90
+ exclude = ["**/__pycache__", "**/*.py[cod]", "**/.DS_Store"]
91
+
92
+ [tool.hatch.build.targets.sdist]
93
+ include = ["/src/redline_core", "/tests", "/README.md", "/LICENSE"]
94
+ exclude = ["**/__pycache__", "**/*.py[cod]", "**/.DS_Store"]
95
+
96
+ [tool.pytest.ini_options]
97
+ testpaths = ["tests"]
98
+ addopts = "--strict-markers -q"
99
+ asyncio_mode = "auto"
100
+ asyncio_default_fixture_loop_scope = "function"
101
+ markers = [
102
+ "slow: spawns load-test worker processes (a few seconds each)",
103
+ ]
104
+
105
+ [tool.ruff]
106
+ extend = "../../pyproject.toml"
@@ -0,0 +1,66 @@
1
+ """redline-core: the framework-agnostic engine of Redline.
2
+
3
+ Redline is a self-hosted request profiler and backend analyzer for Django and FastAPI.
4
+ This package holds everything that does not depend on a web framework – the data model,
5
+ the ``contextvars`` recorder, SQL fingerprinting, callsite capture, redaction, the N+1 /
6
+ duplicate / slow-query detectors, EXPLAIN plan analysis, the optional pyinstrument
7
+ profiler, the SQLite store and the JSON API. It has no runtime dependencies.
8
+
9
+ Applications install ``django-redline`` or ``fastapi-redline``; the only thing most user
10
+ code touches directly is :func:`span`::
11
+
12
+ import redline_core
13
+
14
+ @redline_core.span("pricing.compute")
15
+ def compute_price(order): ...
16
+
17
+ async with redline_core.span("fetch-rates", provider="ecb"):
18
+ ...
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ __version__ = "0.2.0a1"
24
+
25
+ from .conf import Settings, SettingsError
26
+ from .detect import Detector, FixSuggester, GenericSuggester
27
+ from .model import Callsite, Frame, Issue, Span, Suggestion, Trace
28
+ from .recorder import (
29
+ Recorder,
30
+ SpanContext,
31
+ TraceBuilder,
32
+ configure,
33
+ current,
34
+ finish_trace,
35
+ get_recorder,
36
+ record_query,
37
+ record_span,
38
+ span,
39
+ start_trace,
40
+ )
41
+
42
+ __all__ = [
43
+ "Callsite",
44
+ "Detector",
45
+ "FixSuggester",
46
+ "Frame",
47
+ "GenericSuggester",
48
+ "Issue",
49
+ "Recorder",
50
+ "Settings",
51
+ "SettingsError",
52
+ "Span",
53
+ "SpanContext",
54
+ "Suggestion",
55
+ "Trace",
56
+ "TraceBuilder",
57
+ "__version__",
58
+ "configure",
59
+ "current",
60
+ "finish_trace",
61
+ "get_recorder",
62
+ "record_query",
63
+ "record_span",
64
+ "span",
65
+ "start_trace",
66
+ ]