elven-logs-interceptor-python 0.1.2__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 (83) hide show
  1. elven_logs_interceptor_python-0.1.2/.github/workflows/ci.yml +30 -0
  2. elven_logs_interceptor_python-0.1.2/.github/workflows/publish.yml +65 -0
  3. elven_logs_interceptor_python-0.1.2/.gitignore +15 -0
  4. elven_logs_interceptor_python-0.1.2/ARCHITECTURE.md +36 -0
  5. elven_logs_interceptor_python-0.1.2/Makefile +34 -0
  6. elven_logs_interceptor_python-0.1.2/PKG-INFO +262 -0
  7. elven_logs_interceptor_python-0.1.2/README.md +201 -0
  8. elven_logs_interceptor_python-0.1.2/examples/basic_app.py +18 -0
  9. elven_logs_interceptor_python-0.1.2/examples/fastapi_integration.py +26 -0
  10. elven_logs_interceptor_python-0.1.2/examples/full_config_reference.py +67 -0
  11. elven_logs_interceptor_python-0.1.2/examples/high_volume.py +30 -0
  12. elven_logs_interceptor_python-0.1.2/examples/tracking_usage.py +14 -0
  13. elven_logs_interceptor_python-0.1.2/pyproject.toml +141 -0
  14. elven_logs_interceptor_python-0.1.2/scripts/publish.sh +180 -0
  15. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/__init__.py +333 -0
  16. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/application/__init__.py +27 -0
  17. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/application/config_service.py +232 -0
  18. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/application/log_service.py +383 -0
  19. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/config.py +190 -0
  20. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/domain/__init__.py +25 -0
  21. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/domain/entities.py +41 -0
  22. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/domain/interfaces.py +149 -0
  23. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/domain/value_objects.py +40 -0
  24. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/__init__.py +48 -0
  25. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/buffer/__init__.py +3 -0
  26. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/buffer/memory_buffer.py +187 -0
  27. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/circuit_breaker/__init__.py +3 -0
  28. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/circuit_breaker/circuit_breaker.py +110 -0
  29. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/compression/__init__.py +14 -0
  30. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/compression/base.py +20 -0
  31. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/compression/brotli_compressor.py +27 -0
  32. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/compression/factory.py +18 -0
  33. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/compression/gzip_compressor.py +20 -0
  34. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/compression/noop_compressor.py +14 -0
  35. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/context/__init__.py +3 -0
  36. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/context/context_provider.py +44 -0
  37. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/dlq/__init__.py +4 -0
  38. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/dlq/file_dlq.py +170 -0
  39. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/dlq/memory_dlq.py +59 -0
  40. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/filter/__init__.py +3 -0
  41. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/filter/log_filter.py +55 -0
  42. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/interceptors/__init__.py +3 -0
  43. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/interceptors/runtime_interceptor.py +139 -0
  44. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/memory/__init__.py +3 -0
  45. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/memory/memory_tracker.py +95 -0
  46. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/metrics/__init__.py +3 -0
  47. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/metrics/metrics_collector.py +104 -0
  48. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/transport/__init__.py +12 -0
  49. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/transport/loki_json_transport.py +226 -0
  50. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/transport/loki_protobuf_transport.py +209 -0
  51. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/transport/resilient_transport.py +161 -0
  52. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/transport/transport_factory.py +39 -0
  53. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/workers/__init__.py +3 -0
  54. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/infrastructure/workers/worker_pool.py +57 -0
  55. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/integrations/__init__.py +17 -0
  56. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/integrations/celery.py +53 -0
  57. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/integrations/django.py +44 -0
  58. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/integrations/fastapi.py +53 -0
  59. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/integrations/flask.py +50 -0
  60. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/integrations/logging_handler.py +43 -0
  61. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/integrations/loguru.py +36 -0
  62. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/integrations/structlog.py +21 -0
  63. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/preload.py +61 -0
  64. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/presentation/__init__.py +3 -0
  65. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/presentation/factory.py +128 -0
  66. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/types.py +89 -0
  67. elven_logs_interceptor_python-0.1.2/src/logs_interceptor/utils.py +508 -0
  68. elven_logs_interceptor_python-0.1.2/test-apps/elven-observability-smoke/.env.example +167 -0
  69. elven_logs_interceptor_python-0.1.2/test-apps/elven-observability-smoke/README.md +27 -0
  70. elven_logs_interceptor_python-0.1.2/test-apps/elven-observability-smoke/app.py +90 -0
  71. elven_logs_interceptor_python-0.1.2/test-apps/elven-observability-smoke/run.sh +21 -0
  72. elven_logs_interceptor_python-0.1.2/tests/integration/test_api.py +102 -0
  73. elven_logs_interceptor_python-0.1.2/tests/unit/test_circuit_breaker_extra.py +48 -0
  74. elven_logs_interceptor_python-0.1.2/tests/unit/test_config_service.py +114 -0
  75. elven_logs_interceptor_python-0.1.2/tests/unit/test_core_components.py +77 -0
  76. elven_logs_interceptor_python-0.1.2/tests/unit/test_env_config.py +47 -0
  77. elven_logs_interceptor_python-0.1.2/tests/unit/test_log_filter_extra.py +68 -0
  78. elven_logs_interceptor_python-0.1.2/tests/unit/test_log_service_unit.py +377 -0
  79. elven_logs_interceptor_python-0.1.2/tests/unit/test_loki_json_transport.py +82 -0
  80. elven_logs_interceptor_python-0.1.2/tests/unit/test_memory_buffer_extra.py +118 -0
  81. elven_logs_interceptor_python-0.1.2/tests/unit/test_protobuf_transport_safety.py +93 -0
  82. elven_logs_interceptor_python-0.1.2/tests/unit/test_resilient_transport.py +211 -0
  83. elven_logs_interceptor_python-0.1.2/tests/unit/test_utils_extra.py +274 -0
@@ -0,0 +1,30 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches: ["main", "master"]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ python-version: ["3.10", "3.11", "3.12"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: ${{ matrix.python-version }}
21
+ - name: Install
22
+ run: |
23
+ python -m pip install --upgrade pip
24
+ pip install -e ".[dev]"
25
+ - name: Lint
26
+ run: ruff check .
27
+ - name: Typecheck
28
+ run: mypy src
29
+ - name: Tests
30
+ run: pytest
@@ -0,0 +1,65 @@
1
+ name: publish
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ repository:
7
+ description: Target repository
8
+ required: true
9
+ default: testpypi
10
+ type: choice
11
+ options:
12
+ - testpypi
13
+ - pypi
14
+
15
+ jobs:
16
+ publish:
17
+ runs-on: ubuntu-latest
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - uses: actions/setup-python@v5
23
+ with:
24
+ python-version: "3.12"
25
+
26
+ - name: Install dependencies
27
+ run: |
28
+ python -m pip install --upgrade pip
29
+ pip install -e ".[dev]"
30
+
31
+ - name: Quality gates
32
+ run: |
33
+ python -m ruff check .
34
+ python -m mypy src
35
+ python -m pytest -q
36
+
37
+ - name: Build package
38
+ run: |
39
+ rm -rf build dist
40
+ python -m build
41
+ python -m twine check dist/*
42
+
43
+ - name: Publish to TestPyPI
44
+ if: ${{ inputs.repository == 'testpypi' }}
45
+ env:
46
+ TWINE_USERNAME: __token__
47
+ TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
48
+ run: |
49
+ if [ -z "${TWINE_PASSWORD}" ]; then
50
+ echo "Missing secret TEST_PYPI_API_TOKEN"
51
+ exit 1
52
+ fi
53
+ python -m twine upload --repository-url https://test.pypi.org/legacy/ --skip-existing dist/*
54
+
55
+ - name: Publish to PyPI
56
+ if: ${{ inputs.repository == 'pypi' }}
57
+ env:
58
+ TWINE_USERNAME: __token__
59
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
60
+ run: |
61
+ if [ -z "${TWINE_PASSWORD}" ]; then
62
+ echo "Missing secret PYPI_API_TOKEN"
63
+ exit 1
64
+ fi
65
+ python -m twine upload --repository-url https://upload.pypi.org/legacy/ --skip-existing dist/*
@@ -0,0 +1,15 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .pytest_cache/
5
+ .mypy_cache/
6
+ .ruff_cache/
7
+ .coverage
8
+ htmlcov/
9
+ .venv/
10
+ .env
11
+ .DS_Store
12
+ .logs-interceptor-dlq/
13
+ build/
14
+ dist/
15
+ test-apps/**/.env
@@ -0,0 +1,36 @@
1
+ # Clean Architecture - elven-logs-interceptor-python
2
+
3
+ This project follows Clean Architecture and SOLID principles.
4
+
5
+ ## Layers
6
+
7
+ - `domain/`: entities, value objects, interfaces/protocols.
8
+ - `application/`: orchestration use-cases (`ConfigService`, `LogService`).
9
+ - `infrastructure/`: concrete implementations (transport, buffer, filter, circuit breaker, DLQ, interceptors).
10
+ - `presentation/`: object graph factory and runtime wiring.
11
+
12
+ ## Core Flow
13
+
14
+ 1. User logs through API (`logger.info`, etc).
15
+ 2. `LogService` builds `LogEntryEntity` with context and dynamic labels.
16
+ 3. `LogFilter` applies level checks, sampling, sanitization.
17
+ 4. `MemoryBuffer` stores entries with bounded-memory policies.
18
+ 5. Flush pipeline pushes batches to `ResilientTransport`.
19
+ 6. `ResilientTransport` applies retry + circuit breaker + DLQ fallback.
20
+ 7. Loki receives logs through JSON or Snappy path.
21
+
22
+ ## Resilience
23
+
24
+ - Retry with exponential backoff + jitter.
25
+ - Circuit breaker with closed/open/half-open states.
26
+ - DLQ with bounded memory/file storage and drop-oldest policy.
27
+
28
+ ## Runtime Model
29
+
30
+ - Sync-first API for app safety.
31
+ - Async wrappers (`aflush`, `adestroy`) via thread offload.
32
+ - Background flush workers capped by `max_concurrent_flushes`.
33
+
34
+ ## Extensibility
35
+
36
+ Add a new transport by implementing `ILogTransport` contract and wiring it in `TransportFactory`.
@@ -0,0 +1,34 @@
1
+ PYTHON ?= python3
2
+
3
+ .PHONY: install-dev lint typecheck test qa build clean publish-dry-run publish-testpypi publish-pypi
4
+
5
+ install-dev:
6
+ $(PYTHON) -m pip install -e ".[dev]"
7
+
8
+ lint:
9
+ $(PYTHON) -m ruff check .
10
+
11
+ typecheck:
12
+ $(PYTHON) -m mypy src
13
+
14
+ test:
15
+ $(PYTHON) -m pytest -q
16
+
17
+ qa: lint typecheck test
18
+
19
+ clean:
20
+ rm -rf build dist
21
+ find . -maxdepth 1 -type d -name "*.egg-info" -exec rm -rf {} +
22
+
23
+ build: clean
24
+ $(PYTHON) -m build
25
+ $(PYTHON) -m twine check dist/*
26
+
27
+ publish-dry-run:
28
+ ./scripts/publish.sh --dry-run
29
+
30
+ publish-testpypi:
31
+ ./scripts/publish.sh --repository testpypi
32
+
33
+ publish-pypi:
34
+ ./scripts/publish.sh --repository pypi
@@ -0,0 +1,262 @@
1
+ Metadata-Version: 2.4
2
+ Name: elven-logs-interceptor-python
3
+ Version: 0.1.2
4
+ Summary: Production-grade logs interceptor for Python with Loki transport, resilience, batching, and framework integrations.
5
+ Author: Elven Observability
6
+ License: MIT
7
+ Keywords: clean-architecture,interceptor,logging,logs,loki,observability,resilience
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Topic :: System :: Logging
16
+ Requires-Python: >=3.10
17
+ Requires-Dist: httpx>=0.27.0
18
+ Requires-Dist: typing-extensions>=4.12.0
19
+ Provides-Extra: all
20
+ Requires-Dist: brotli>=1.1.0; extra == 'all'
21
+ Requires-Dist: celery>=5.4.0; extra == 'all'
22
+ Requires-Dist: django>=4.2; extra == 'all'
23
+ Requires-Dist: fastapi>=0.111.0; extra == 'all'
24
+ Requires-Dist: flask>=3.0.0; extra == 'all'
25
+ Requires-Dist: loguru>=0.7.2; extra == 'all'
26
+ Requires-Dist: opentelemetry-api>=1.24.0; extra == 'all'
27
+ Requires-Dist: orjson>=3.10.0; extra == 'all'
28
+ Requires-Dist: protobuf>=5.0.0; extra == 'all'
29
+ Requires-Dist: python-snappy>=0.7.1; extra == 'all'
30
+ Requires-Dist: starlette>=0.37.0; extra == 'all'
31
+ Requires-Dist: structlog>=24.0.0; extra == 'all'
32
+ Provides-Extra: celery
33
+ Requires-Dist: celery>=5.4.0; extra == 'celery'
34
+ Provides-Extra: dev
35
+ Requires-Dist: build>=1.2.2; extra == 'dev'
36
+ Requires-Dist: mypy>=1.11.0; extra == 'dev'
37
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
38
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
39
+ Requires-Dist: pytest>=8.3.0; extra == 'dev'
40
+ Requires-Dist: ruff>=0.6.0; extra == 'dev'
41
+ Requires-Dist: twine>=5.1.1; extra == 'dev'
42
+ Provides-Extra: django
43
+ Requires-Dist: django>=4.2; extra == 'django'
44
+ Provides-Extra: fastapi
45
+ Requires-Dist: fastapi>=0.111.0; extra == 'fastapi'
46
+ Requires-Dist: starlette>=0.37.0; extra == 'fastapi'
47
+ Provides-Extra: flask
48
+ Requires-Dist: flask>=3.0.0; extra == 'flask'
49
+ Provides-Extra: loguru
50
+ Requires-Dist: loguru>=0.7.2; extra == 'loguru'
51
+ Provides-Extra: otel
52
+ Requires-Dist: opentelemetry-api>=1.24.0; extra == 'otel'
53
+ Provides-Extra: perf
54
+ Requires-Dist: brotli>=1.1.0; extra == 'perf'
55
+ Requires-Dist: orjson>=3.10.0; extra == 'perf'
56
+ Requires-Dist: protobuf>=5.0.0; extra == 'perf'
57
+ Requires-Dist: python-snappy>=0.7.1; extra == 'perf'
58
+ Provides-Extra: structlog
59
+ Requires-Dist: structlog>=24.0.0; extra == 'structlog'
60
+ Description-Content-Type: text/markdown
61
+
62
+ # elven-logs-interceptor-python
63
+
64
+ High-performance, production-ready log interceptor for Python with Loki transport, batching, compression, circuit breaker, DLQ, and framework integrations.
65
+
66
+ ## Installation
67
+
68
+ ```bash
69
+ pip install elven-logs-interceptor-python
70
+ ```
71
+
72
+ With all extras:
73
+
74
+ ```bash
75
+ pip install "elven-logs-interceptor-python[all]"
76
+ ```
77
+
78
+ ## Quick Start
79
+
80
+ ```python
81
+ from logs_interceptor import init, logger
82
+
83
+ init(
84
+ {
85
+ "appName": "billing-service",
86
+ "interceptConsole": True,
87
+ "transport": {
88
+ "url": "https://loki.example.com/loki/api/v1/push",
89
+ "tenantId": "tenant-a",
90
+ "authToken": "token",
91
+ "compression": "gzip",
92
+ },
93
+ }
94
+ )
95
+
96
+ logger.info("service started", {"port": 3000})
97
+ ```
98
+
99
+ ## Environment Variables
100
+
101
+ The package supports all `LOGS_*` variables from the JS v3 design.
102
+
103
+ Required:
104
+
105
+ - `LOGS_URL`
106
+ - `LOGS_TENANT`
107
+ - `LOGS_APP_NAME`
108
+
109
+ Core:
110
+
111
+ - `LOGS_TOKEN`
112
+ - `LOGS_APP_VERSION`
113
+ - `LOGS_ENVIRONMENT`
114
+
115
+ Transport:
116
+
117
+ - `LOGS_COMPRESSION` (`none|gzip|brotli|snappy`)
118
+ - `LOGS_COMPRESSION_LEVEL`
119
+ - `LOGS_COMPRESSION_THRESHOLD`
120
+ - `LOGS_USE_WORKERS`
121
+ - `LOGS_MAX_WORKERS`
122
+ - `LOGS_WORKER_TIMEOUT`
123
+ - `LOGS_CONNECTION_POOLING`
124
+ - `LOGS_MAX_SOCKETS`
125
+ - `LOGS_TIMEOUT`
126
+ - `LOGS_MAX_RETRIES`
127
+ - `LOGS_RETRY_DELAY`
128
+
129
+ Buffer:
130
+
131
+ - `LOGS_BUFFER_MAX_SIZE`
132
+ - `LOGS_BUFFER_FLUSH_INTERVAL`
133
+ - `LOGS_BUFFER_MAX_MEMORY_MB`
134
+ - `LOGS_BUFFER_MAX_AGE`
135
+ - `LOGS_BUFFER_AUTO_FLUSH`
136
+
137
+ Filter:
138
+
139
+ - `LOGS_FILTER_LEVELS`
140
+ - `LOGS_FILTER_SAMPLING_RATE`
141
+ - `LOGS_FILTER_SANITIZE`
142
+ - `LOGS_FILTER_MAX_MESSAGE_LENGTH`
143
+
144
+ Circuit Breaker:
145
+
146
+ - `LOGS_CIRCUIT_BREAKER_ENABLED`
147
+ - `LOGS_CIRCUIT_BREAKER_FAILURE_THRESHOLD`
148
+ - `LOGS_CIRCUIT_BREAKER_RESET_TIMEOUT`
149
+ - `LOGS_CIRCUIT_BREAKER_HALF_OPEN_REQUESTS`
150
+
151
+ DLQ:
152
+
153
+ - `LOGS_DLQ_ENABLED`
154
+ - `LOGS_DLQ_TYPE` (`memory|file`)
155
+ - `LOGS_DLQ_MAX_SIZE`
156
+ - `LOGS_DLQ_MAX_RETRIES`
157
+ - `LOGS_DLQ_BASE_PATH`
158
+
159
+ Runtime:
160
+
161
+ - `LOGS_MAX_CONCURRENT_FLUSHES`
162
+ - `LOGS_INTERCEPT_CONSOLE`
163
+ - `LOGS_PRESERVE_ORIGINAL_CONSOLE`
164
+ - `LOGS_ENABLE_METRICS`
165
+ - `LOGS_ENABLE_HEALTH_CHECK`
166
+ - `LOGS_DEBUG`
167
+ - `LOGS_SILENT_ERRORS`
168
+ - `LOGS_ENABLED`
169
+ - `LOGS_AUTO_INIT`
170
+ - `LOGS_ENABLE_EXPERIMENTAL_PROTOBUF` (optional, enables experimental snappy/protobuf transport path)
171
+
172
+ Labels:
173
+
174
+ - Prefix `LOGS_LABEL_*` (example: `LOGS_LABEL_SERVICE=billing`)
175
+
176
+ ## Public API
177
+
178
+ - `init(config)`
179
+ - `get_logger()`
180
+ - `is_initialized()`
181
+ - `destroy()`
182
+ - `adestroy()`
183
+ - `logger` proxy with `debug/info/warn/error/fatal/log/track_event/flush/aflush/get_metrics/get_health/destroy/adestroy/with_context/with_context_async`
184
+
185
+ Python import remains:
186
+
187
+ ```python
188
+ import logs_interceptor
189
+ ```
190
+
191
+ ## Integrations
192
+
193
+ - Python `logging` (`LoggingHandler`)
194
+ - FastAPI / Starlette (`FastAPIMiddleware`)
195
+ - Django (`DjangoMiddleware`)
196
+ - Flask (`FlaskExtension`)
197
+ - Celery (`CelerySignals`)
198
+ - structlog (`StructlogProcessor`)
199
+ - loguru (`LoguruSink`)
200
+
201
+ ## Auto Init
202
+
203
+ Set `LOGS_AUTO_INIT=true` and import the package.
204
+
205
+ Preload mode:
206
+
207
+ ```bash
208
+ python -m logs_interceptor.preload
209
+ ```
210
+
211
+ ## Development
212
+
213
+ ```bash
214
+ pip install -e ".[dev]"
215
+ ruff check .
216
+ mypy src
217
+ pytest
218
+ ```
219
+
220
+ ## Deploy / Publish
221
+
222
+ Local publish script:
223
+
224
+ ```bash
225
+ ./scripts/publish.sh --repository testpypi --dry-run
226
+ ./scripts/publish.sh --repository testpypi
227
+ ./scripts/publish.sh --repository pypi
228
+ ```
229
+
230
+ Token environment variables used by default:
231
+
232
+ - `TEST_PYPI_API_TOKEN` for `--repository testpypi`
233
+ - `PYPI_API_TOKEN` for `--repository pypi`
234
+
235
+ Optional script flags:
236
+
237
+ - `--skip-checks` (skip lint/type/test)
238
+ - `--skip-build` (skip build/twine check)
239
+ - `--token-env CUSTOM_VAR` (custom token env var name)
240
+ - `--no-skip-existing` (upload fails if version already exists)
241
+
242
+ Makefile shortcuts:
243
+
244
+ ```bash
245
+ make qa
246
+ make publish-dry-run
247
+ make publish-testpypi
248
+ make publish-pypi
249
+ ```
250
+
251
+ GitHub Actions publish workflow:
252
+
253
+ - File: `.github/workflows/publish.yml`
254
+ - Trigger: manual (`workflow_dispatch`)
255
+ - Inputs: `repository = testpypi | pypi`
256
+ - Required secrets:
257
+ - `TEST_PYPI_API_TOKEN`
258
+ - `PYPI_API_TOKEN`
259
+
260
+ ## License
261
+
262
+ MIT
@@ -0,0 +1,201 @@
1
+ # elven-logs-interceptor-python
2
+
3
+ High-performance, production-ready log interceptor for Python with Loki transport, batching, compression, circuit breaker, DLQ, and framework integrations.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install elven-logs-interceptor-python
9
+ ```
10
+
11
+ With all extras:
12
+
13
+ ```bash
14
+ pip install "elven-logs-interceptor-python[all]"
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```python
20
+ from logs_interceptor import init, logger
21
+
22
+ init(
23
+ {
24
+ "appName": "billing-service",
25
+ "interceptConsole": True,
26
+ "transport": {
27
+ "url": "https://loki.example.com/loki/api/v1/push",
28
+ "tenantId": "tenant-a",
29
+ "authToken": "token",
30
+ "compression": "gzip",
31
+ },
32
+ }
33
+ )
34
+
35
+ logger.info("service started", {"port": 3000})
36
+ ```
37
+
38
+ ## Environment Variables
39
+
40
+ The package supports all `LOGS_*` variables from the JS v3 design.
41
+
42
+ Required:
43
+
44
+ - `LOGS_URL`
45
+ - `LOGS_TENANT`
46
+ - `LOGS_APP_NAME`
47
+
48
+ Core:
49
+
50
+ - `LOGS_TOKEN`
51
+ - `LOGS_APP_VERSION`
52
+ - `LOGS_ENVIRONMENT`
53
+
54
+ Transport:
55
+
56
+ - `LOGS_COMPRESSION` (`none|gzip|brotli|snappy`)
57
+ - `LOGS_COMPRESSION_LEVEL`
58
+ - `LOGS_COMPRESSION_THRESHOLD`
59
+ - `LOGS_USE_WORKERS`
60
+ - `LOGS_MAX_WORKERS`
61
+ - `LOGS_WORKER_TIMEOUT`
62
+ - `LOGS_CONNECTION_POOLING`
63
+ - `LOGS_MAX_SOCKETS`
64
+ - `LOGS_TIMEOUT`
65
+ - `LOGS_MAX_RETRIES`
66
+ - `LOGS_RETRY_DELAY`
67
+
68
+ Buffer:
69
+
70
+ - `LOGS_BUFFER_MAX_SIZE`
71
+ - `LOGS_BUFFER_FLUSH_INTERVAL`
72
+ - `LOGS_BUFFER_MAX_MEMORY_MB`
73
+ - `LOGS_BUFFER_MAX_AGE`
74
+ - `LOGS_BUFFER_AUTO_FLUSH`
75
+
76
+ Filter:
77
+
78
+ - `LOGS_FILTER_LEVELS`
79
+ - `LOGS_FILTER_SAMPLING_RATE`
80
+ - `LOGS_FILTER_SANITIZE`
81
+ - `LOGS_FILTER_MAX_MESSAGE_LENGTH`
82
+
83
+ Circuit Breaker:
84
+
85
+ - `LOGS_CIRCUIT_BREAKER_ENABLED`
86
+ - `LOGS_CIRCUIT_BREAKER_FAILURE_THRESHOLD`
87
+ - `LOGS_CIRCUIT_BREAKER_RESET_TIMEOUT`
88
+ - `LOGS_CIRCUIT_BREAKER_HALF_OPEN_REQUESTS`
89
+
90
+ DLQ:
91
+
92
+ - `LOGS_DLQ_ENABLED`
93
+ - `LOGS_DLQ_TYPE` (`memory|file`)
94
+ - `LOGS_DLQ_MAX_SIZE`
95
+ - `LOGS_DLQ_MAX_RETRIES`
96
+ - `LOGS_DLQ_BASE_PATH`
97
+
98
+ Runtime:
99
+
100
+ - `LOGS_MAX_CONCURRENT_FLUSHES`
101
+ - `LOGS_INTERCEPT_CONSOLE`
102
+ - `LOGS_PRESERVE_ORIGINAL_CONSOLE`
103
+ - `LOGS_ENABLE_METRICS`
104
+ - `LOGS_ENABLE_HEALTH_CHECK`
105
+ - `LOGS_DEBUG`
106
+ - `LOGS_SILENT_ERRORS`
107
+ - `LOGS_ENABLED`
108
+ - `LOGS_AUTO_INIT`
109
+ - `LOGS_ENABLE_EXPERIMENTAL_PROTOBUF` (optional, enables experimental snappy/protobuf transport path)
110
+
111
+ Labels:
112
+
113
+ - Prefix `LOGS_LABEL_*` (example: `LOGS_LABEL_SERVICE=billing`)
114
+
115
+ ## Public API
116
+
117
+ - `init(config)`
118
+ - `get_logger()`
119
+ - `is_initialized()`
120
+ - `destroy()`
121
+ - `adestroy()`
122
+ - `logger` proxy with `debug/info/warn/error/fatal/log/track_event/flush/aflush/get_metrics/get_health/destroy/adestroy/with_context/with_context_async`
123
+
124
+ Python import remains:
125
+
126
+ ```python
127
+ import logs_interceptor
128
+ ```
129
+
130
+ ## Integrations
131
+
132
+ - Python `logging` (`LoggingHandler`)
133
+ - FastAPI / Starlette (`FastAPIMiddleware`)
134
+ - Django (`DjangoMiddleware`)
135
+ - Flask (`FlaskExtension`)
136
+ - Celery (`CelerySignals`)
137
+ - structlog (`StructlogProcessor`)
138
+ - loguru (`LoguruSink`)
139
+
140
+ ## Auto Init
141
+
142
+ Set `LOGS_AUTO_INIT=true` and import the package.
143
+
144
+ Preload mode:
145
+
146
+ ```bash
147
+ python -m logs_interceptor.preload
148
+ ```
149
+
150
+ ## Development
151
+
152
+ ```bash
153
+ pip install -e ".[dev]"
154
+ ruff check .
155
+ mypy src
156
+ pytest
157
+ ```
158
+
159
+ ## Deploy / Publish
160
+
161
+ Local publish script:
162
+
163
+ ```bash
164
+ ./scripts/publish.sh --repository testpypi --dry-run
165
+ ./scripts/publish.sh --repository testpypi
166
+ ./scripts/publish.sh --repository pypi
167
+ ```
168
+
169
+ Token environment variables used by default:
170
+
171
+ - `TEST_PYPI_API_TOKEN` for `--repository testpypi`
172
+ - `PYPI_API_TOKEN` for `--repository pypi`
173
+
174
+ Optional script flags:
175
+
176
+ - `--skip-checks` (skip lint/type/test)
177
+ - `--skip-build` (skip build/twine check)
178
+ - `--token-env CUSTOM_VAR` (custom token env var name)
179
+ - `--no-skip-existing` (upload fails if version already exists)
180
+
181
+ Makefile shortcuts:
182
+
183
+ ```bash
184
+ make qa
185
+ make publish-dry-run
186
+ make publish-testpypi
187
+ make publish-pypi
188
+ ```
189
+
190
+ GitHub Actions publish workflow:
191
+
192
+ - File: `.github/workflows/publish.yml`
193
+ - Trigger: manual (`workflow_dispatch`)
194
+ - Inputs: `repository = testpypi | pypi`
195
+ - Required secrets:
196
+ - `TEST_PYPI_API_TOKEN`
197
+ - `PYPI_API_TOKEN`
198
+
199
+ ## License
200
+
201
+ MIT
@@ -0,0 +1,18 @@
1
+ from logs_interceptor import init
2
+
3
+ init(
4
+ {
5
+ "appName": "my-service",
6
+ "interceptConsole": True,
7
+ "transport": {
8
+ "url": "http://localhost:3100/loki/api/v1/push",
9
+ "tenantId": "my-tenant",
10
+ "compression": "gzip",
11
+ "enableConnectionPooling": True,
12
+ },
13
+ "deadLetterQueue": {"enabled": True, "type": "file"},
14
+ "circuitBreaker": {"enabled": True},
15
+ }
16
+ )
17
+
18
+ print("service started")
@@ -0,0 +1,26 @@
1
+ from fastapi import FastAPI
2
+
3
+ from logs_interceptor import init, logger
4
+ from logs_interceptor.integrations import FastAPIMiddleware
5
+
6
+ init(
7
+ {
8
+ "transport": {
9
+ "url": "http://localhost:3100/loki/api/v1/push",
10
+ "tenantId": "my-tenant",
11
+ "compression": "brotli",
12
+ },
13
+ "appName": "my-api",
14
+ "interceptConsole": True,
15
+ "deadLetterQueue": {"enabled": True, "type": "file"},
16
+ }
17
+ )
18
+
19
+ app = FastAPI()
20
+ app.add_middleware(FastAPIMiddleware, logger=logger)
21
+
22
+
23
+ @app.get("/ping")
24
+ def ping() -> dict[str, str]:
25
+ logger.info("ping called")
26
+ return {"message": "pong"}