elven-logs-interceptor-python 0.1.2__py3-none-any.whl
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.
- elven_logs_interceptor_python-0.1.2.dist-info/METADATA +262 -0
- elven_logs_interceptor_python-0.1.2.dist-info/RECORD +56 -0
- elven_logs_interceptor_python-0.1.2.dist-info/WHEEL +4 -0
- logs_interceptor/__init__.py +333 -0
- logs_interceptor/application/__init__.py +27 -0
- logs_interceptor/application/config_service.py +232 -0
- logs_interceptor/application/log_service.py +383 -0
- logs_interceptor/config.py +190 -0
- logs_interceptor/domain/__init__.py +25 -0
- logs_interceptor/domain/entities.py +41 -0
- logs_interceptor/domain/interfaces.py +149 -0
- logs_interceptor/domain/value_objects.py +40 -0
- logs_interceptor/infrastructure/__init__.py +48 -0
- logs_interceptor/infrastructure/buffer/__init__.py +3 -0
- logs_interceptor/infrastructure/buffer/memory_buffer.py +187 -0
- logs_interceptor/infrastructure/circuit_breaker/__init__.py +3 -0
- logs_interceptor/infrastructure/circuit_breaker/circuit_breaker.py +110 -0
- logs_interceptor/infrastructure/compression/__init__.py +14 -0
- logs_interceptor/infrastructure/compression/base.py +20 -0
- logs_interceptor/infrastructure/compression/brotli_compressor.py +27 -0
- logs_interceptor/infrastructure/compression/factory.py +18 -0
- logs_interceptor/infrastructure/compression/gzip_compressor.py +20 -0
- logs_interceptor/infrastructure/compression/noop_compressor.py +14 -0
- logs_interceptor/infrastructure/context/__init__.py +3 -0
- logs_interceptor/infrastructure/context/context_provider.py +44 -0
- logs_interceptor/infrastructure/dlq/__init__.py +4 -0
- logs_interceptor/infrastructure/dlq/file_dlq.py +170 -0
- logs_interceptor/infrastructure/dlq/memory_dlq.py +59 -0
- logs_interceptor/infrastructure/filter/__init__.py +3 -0
- logs_interceptor/infrastructure/filter/log_filter.py +55 -0
- logs_interceptor/infrastructure/interceptors/__init__.py +3 -0
- logs_interceptor/infrastructure/interceptors/runtime_interceptor.py +139 -0
- logs_interceptor/infrastructure/memory/__init__.py +3 -0
- logs_interceptor/infrastructure/memory/memory_tracker.py +95 -0
- logs_interceptor/infrastructure/metrics/__init__.py +3 -0
- logs_interceptor/infrastructure/metrics/metrics_collector.py +104 -0
- logs_interceptor/infrastructure/transport/__init__.py +12 -0
- logs_interceptor/infrastructure/transport/loki_json_transport.py +226 -0
- logs_interceptor/infrastructure/transport/loki_protobuf_transport.py +209 -0
- logs_interceptor/infrastructure/transport/resilient_transport.py +161 -0
- logs_interceptor/infrastructure/transport/transport_factory.py +39 -0
- logs_interceptor/infrastructure/workers/__init__.py +3 -0
- logs_interceptor/infrastructure/workers/worker_pool.py +57 -0
- logs_interceptor/integrations/__init__.py +17 -0
- logs_interceptor/integrations/celery.py +53 -0
- logs_interceptor/integrations/django.py +44 -0
- logs_interceptor/integrations/fastapi.py +53 -0
- logs_interceptor/integrations/flask.py +50 -0
- logs_interceptor/integrations/logging_handler.py +43 -0
- logs_interceptor/integrations/loguru.py +36 -0
- logs_interceptor/integrations/structlog.py +21 -0
- logs_interceptor/preload.py +61 -0
- logs_interceptor/presentation/__init__.py +3 -0
- logs_interceptor/presentation/factory.py +128 -0
- logs_interceptor/types.py +89 -0
- logs_interceptor/utils.py +508 -0
|
@@ -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,56 @@
|
|
|
1
|
+
logs_interceptor/__init__.py,sha256=ABMJGimpNjQMn9BtSCkmvTpjlAKEKiw0r_gqj4uO3qk,12143
|
|
2
|
+
logs_interceptor/config.py,sha256=AdRGtoZ_XG8CgC-yYC9O0a1h16bU5I0tL62NNoTgKcU,5057
|
|
3
|
+
logs_interceptor/preload.py,sha256=8BQEpLibDCQJpm0PwSdvikEEbfGxZSms0ov2v9eQbiY,1735
|
|
4
|
+
logs_interceptor/types.py,sha256=USRT-1t8K12nlyqFES38jOtvzi-ZU3wPgeAhIGssjcQ,1971
|
|
5
|
+
logs_interceptor/utils.py,sha256=Mnnigx3WfC55ILDxJ872KB59T9hymHlO-Fv-FkM59dk,18232
|
|
6
|
+
logs_interceptor/application/__init__.py,sha256=UeK-yoi200-4FryM-v2cCruTHe0Yjzbzyiiti4ZIwes,613
|
|
7
|
+
logs_interceptor/application/config_service.py,sha256=zDvNsx3L5bNNCLavgquVdELwudO5kPqxc_AZRmoHMNM,10265
|
|
8
|
+
logs_interceptor/application/log_service.py,sha256=Rorlfq_L1C0fs8661MP61toq7fTfVezR1NGUU8RXEXE,13699
|
|
9
|
+
logs_interceptor/domain/__init__.py,sha256=01vyK7FVaGTaMbgjoBYD8SyQJ0oWMRpCqMNwNu_4pIE,474
|
|
10
|
+
logs_interceptor/domain/entities.py,sha256=RleSeQmU5rK3Vv8onNYHFkDMXHdfjpE-6R0heLvdjTw,1158
|
|
11
|
+
logs_interceptor/domain/interfaces.py,sha256=trFLzgauQdGRxMCdeVgli-fzvg_X8RKHtSjHSSyfMPQ,3787
|
|
12
|
+
logs_interceptor/domain/value_objects.py,sha256=Z9yIMF6-kJLC9juO2rLCo5MRaUlqFG1deFtwvexrlmc,1130
|
|
13
|
+
logs_interceptor/infrastructure/__init__.py,sha256=HSB0RlVGL_14SrwFOvC-Fnfqg35MPJlDBoFW0H0MLMc,1177
|
|
14
|
+
logs_interceptor/infrastructure/buffer/__init__.py,sha256=paRwx_7lvJ8quGeOMdJdZeDEHRUBGEkg6923LH-DQmY,68
|
|
15
|
+
logs_interceptor/infrastructure/buffer/memory_buffer.py,sha256=ZVRRJwROImAc3xVBR1NsovYq6vX5H8pIdO89esPx6L8,6437
|
|
16
|
+
logs_interceptor/infrastructure/circuit_breaker/__init__.py,sha256=KKKX5AHbvkPoI6gO6o3e4xqS0ch9F0uk0PoZJGLEoWs,74
|
|
17
|
+
logs_interceptor/infrastructure/circuit_breaker/circuit_breaker.py,sha256=8BZHFY1AjzWRnoGL1l47yrP1BEE-WEKLRGK1xanB_oM,3858
|
|
18
|
+
logs_interceptor/infrastructure/compression/__init__.py,sha256=063D7o9SuB_42T6XxIaxXgfyvs3yu0svPBJ7Th-_K8I,372
|
|
19
|
+
logs_interceptor/infrastructure/compression/base.py,sha256=DNgUfyPaONj9FkKnEeE4JOP0OspMZZRlbkkQMIq5t64,425
|
|
20
|
+
logs_interceptor/infrastructure/compression/brotli_compressor.py,sha256=lYSReVzY2SsUvNJK8gHxfGbhTpgFgf3jH54pbIzDCVs,813
|
|
21
|
+
logs_interceptor/infrastructure/compression/factory.py,sha256=BoRA-3Am8jqrYZOqrLGMzKdieJGRYKoh00Syb3znZxM,645
|
|
22
|
+
logs_interceptor/infrastructure/compression/gzip_compressor.py,sha256=1cOO_GEQCaTQYjKmvpv-LfbJ9WN88ecjT_DkdIqGnmI,563
|
|
23
|
+
logs_interceptor/infrastructure/compression/noop_compressor.py,sha256=GCxjF3NFMQvQokoMjCZS7vkS97bH5NjKo-SmNgdWgZE,283
|
|
24
|
+
logs_interceptor/infrastructure/context/__init__.py,sha256=0jj06F58P3d0cK0xzW-TQUwQolmk-VM7-MmgPISo-zE,83
|
|
25
|
+
logs_interceptor/infrastructure/context/context_provider.py,sha256=ntTK5QygprGgJPmBfXodJ57OlfDG_2uov8-w3exjAhw,1367
|
|
26
|
+
logs_interceptor/infrastructure/dlq/__init__.py,sha256=BHmiKjxD2RfToQoYwwwpnQrZq7BjTEiOF3dYHsP6ouc,148
|
|
27
|
+
logs_interceptor/infrastructure/dlq/file_dlq.py,sha256=YgI7800Gf8z6SvMDHplSmmAo_2Ea_fRcaYLEA3GCLOY,6184
|
|
28
|
+
logs_interceptor/infrastructure/dlq/memory_dlq.py,sha256=2ekk4-IRLA5zt6nfE4LtwNenYqTU7KvIcy70z4dSVws,1714
|
|
29
|
+
logs_interceptor/infrastructure/filter/__init__.py,sha256=j5x8PzlxkLQRuzQBV2TvR9MOgKbSY7s687j2XJEzPRc,59
|
|
30
|
+
logs_interceptor/infrastructure/filter/log_filter.py,sha256=_xWK9OQS8avntzKk4COBtH8IWVlweaFX7-0RCZBwtPo,1839
|
|
31
|
+
logs_interceptor/infrastructure/interceptors/__init__.py,sha256=vJ6b8mM_7xHgw0aw8IBJjy5d3Bml-DZRIK7zWTDvThc,86
|
|
32
|
+
logs_interceptor/infrastructure/interceptors/runtime_interceptor.py,sha256=9LyqbnbACO0YSb8GRSa6fw6PDpLRJaQ0HpiyRdSUDCY,4482
|
|
33
|
+
logs_interceptor/infrastructure/memory/__init__.py,sha256=hzGBIBZ7uWdEW5wY8NYITonz5BMXjn5msbJ7pgbccVs,99
|
|
34
|
+
logs_interceptor/infrastructure/memory/memory_tracker.py,sha256=1LnkxeCPp8fpl2Bem6nT4O0hcbtiGTXak_kGj2bnsTc,2601
|
|
35
|
+
logs_interceptor/infrastructure/metrics/__init__.py,sha256=2eCe6cjBoqNTB4AmatfLogzxLiZH3rUsgA1TOPUJu5w,80
|
|
36
|
+
logs_interceptor/infrastructure/metrics/metrics_collector.py,sha256=aU8X7npzc0LTtExVpbCsT84dWjy5lk9IsHPNdB2JBI0,3862
|
|
37
|
+
logs_interceptor/infrastructure/transport/__init__.py,sha256=VOjWlaP7swEYL0Vp2RJMPXIbEU5dS5C76Haz9Ail6ig,387
|
|
38
|
+
logs_interceptor/infrastructure/transport/loki_json_transport.py,sha256=7_ZX7Tkg_FqXk545T1o8bHj8G69Uo4h9TbchCGce5Yw,8806
|
|
39
|
+
logs_interceptor/infrastructure/transport/loki_protobuf_transport.py,sha256=D10_IdUOdHsSoPr2zT0jLTFHimRwB28-Ykda5QO0FhE,8158
|
|
40
|
+
logs_interceptor/infrastructure/transport/resilient_transport.py,sha256=sFGvUCAGLhw2pbIRYVZxj2m2pHCcHEiGVQqZKAQ9avM,5728
|
|
41
|
+
logs_interceptor/infrastructure/transport/transport_factory.py,sha256=wgRnwhMOmM6zgQmZiL3HehkYX8cf0lAxdybQMpOx5W0,1530
|
|
42
|
+
logs_interceptor/infrastructure/workers/__init__.py,sha256=bsSn5S7sl5Mq0hh5QjD3y-ThEqWjZDcTGrVPX44Mxpk,94
|
|
43
|
+
logs_interceptor/infrastructure/workers/worker_pool.py,sha256=zVStQELQVmjUOnj41K-U1XZmziGkX-b9a2KAzFS4tas,1738
|
|
44
|
+
logs_interceptor/integrations/__init__.py,sha256=ahZMYjrtL954TR9Hg-bD8sQCafkoLVsyz66tmlRhweU,434
|
|
45
|
+
logs_interceptor/integrations/celery.py,sha256=RmvBgXQbaami459ixcVs0rxhPx3yc7-2NbSbGpN49K0,1853
|
|
46
|
+
logs_interceptor/integrations/django.py,sha256=lPj_rvxOXoz62udqjP2NlAqaCxUFQ_ZYWjP5eRrNNV8,1291
|
|
47
|
+
logs_interceptor/integrations/fastapi.py,sha256=UvzCt7o3OU7o6cqjsC4aj1p6ZN12tGzm8V9Hi78o51o,1806
|
|
48
|
+
logs_interceptor/integrations/flask.py,sha256=8XG_Wtnqc-XD8H27fZttxbONUvCFHn3ls7IqKQ_iBZs,1670
|
|
49
|
+
logs_interceptor/integrations/logging_handler.py,sha256=CxN0kRUuITC4c3aKPQfq7bL6r_VdX3CPhhegkaWz1QM,1340
|
|
50
|
+
logs_interceptor/integrations/loguru.py,sha256=Tz7ivaVdQr7H5f0jwaPewU9cPEodCTNMCxNQexqL5u4,1074
|
|
51
|
+
logs_interceptor/integrations/structlog.py,sha256=7TFT-4s7D8ER5_Tg9F1r8XhJGRCuKZcwMMIRc8RhSkU,700
|
|
52
|
+
logs_interceptor/presentation/__init__.py,sha256=_U16fFB-s0ub0Tl1rfAK4zvzANQRD3KO81ni0qynjRA,114
|
|
53
|
+
logs_interceptor/presentation/factory.py,sha256=rvPU1kaQcgQlCZ8iPrwZQG7U70FukNjwaIe9eHzE2WY,4473
|
|
54
|
+
elven_logs_interceptor_python-0.1.2.dist-info/METADATA,sha256=D5RLzXt3_hF7m9c_tswYkxCyzznGZMccYJS8CyO1alM,6498
|
|
55
|
+
elven_logs_interceptor_python-0.1.2.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
56
|
+
elven_logs_interceptor_python-0.1.2.dist-info/RECORD,,
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import os
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from .application import ConfigService
|
|
9
|
+
from .config import (
|
|
10
|
+
BufferConfig,
|
|
11
|
+
CircuitBreakerConfig,
|
|
12
|
+
DeadLetterQueueConfig,
|
|
13
|
+
FilterConfig,
|
|
14
|
+
IntegrationsConfig,
|
|
15
|
+
LogsInterceptorConfig,
|
|
16
|
+
PerformanceConfig,
|
|
17
|
+
TransportConfig,
|
|
18
|
+
)
|
|
19
|
+
from .domain.interfaces import ILogger
|
|
20
|
+
from .integrations import (
|
|
21
|
+
CelerySignals,
|
|
22
|
+
DjangoMiddleware,
|
|
23
|
+
FastAPIMiddleware,
|
|
24
|
+
FlaskExtension,
|
|
25
|
+
LoggingHandler,
|
|
26
|
+
LoguruSink,
|
|
27
|
+
StructlogProcessor,
|
|
28
|
+
)
|
|
29
|
+
from .presentation import LogsInterceptorFactory
|
|
30
|
+
from .types import HealthStatus, LoggerMetrics, LogLevel
|
|
31
|
+
from .utils import internal_debug, internal_error, load_config_from_env, merge_configs, parse_bool
|
|
32
|
+
|
|
33
|
+
__all__ = [
|
|
34
|
+
"init",
|
|
35
|
+
"get_logger",
|
|
36
|
+
"is_initialized",
|
|
37
|
+
"destroy",
|
|
38
|
+
"adestroy",
|
|
39
|
+
"logger",
|
|
40
|
+
"LogsInterceptorConfig",
|
|
41
|
+
"TransportConfig",
|
|
42
|
+
"BufferConfig",
|
|
43
|
+
"FilterConfig",
|
|
44
|
+
"CircuitBreakerConfig",
|
|
45
|
+
"DeadLetterQueueConfig",
|
|
46
|
+
"PerformanceConfig",
|
|
47
|
+
"IntegrationsConfig",
|
|
48
|
+
"LoggingHandler",
|
|
49
|
+
"FastAPIMiddleware",
|
|
50
|
+
"DjangoMiddleware",
|
|
51
|
+
"FlaskExtension",
|
|
52
|
+
"CelerySignals",
|
|
53
|
+
"StructlogProcessor",
|
|
54
|
+
"LoguruSink",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass(slots=True)
|
|
59
|
+
class _RuntimeState:
|
|
60
|
+
logger: ILogger
|
|
61
|
+
runtime_interceptor: Any | None = None
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
_global_runtime: _RuntimeState | None = None
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _pick(config: dict[str, Any], snake: str, camel: str, default: Any = None) -> Any:
|
|
68
|
+
if snake in config:
|
|
69
|
+
return config[snake]
|
|
70
|
+
if camel in config:
|
|
71
|
+
return config[camel]
|
|
72
|
+
return default
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _coerce_config(user_config: LogsInterceptorConfig | dict[str, Any] | None) -> LogsInterceptorConfig:
|
|
76
|
+
if user_config is None:
|
|
77
|
+
return LogsInterceptorConfig()
|
|
78
|
+
if isinstance(user_config, LogsInterceptorConfig):
|
|
79
|
+
return user_config
|
|
80
|
+
|
|
81
|
+
transport_raw = _pick(user_config, "transport", "transport", {}) or {}
|
|
82
|
+
buffer_raw = _pick(user_config, "buffer", "buffer")
|
|
83
|
+
filter_raw = _pick(user_config, "filter", "filter")
|
|
84
|
+
cb_raw = _pick(user_config, "circuit_breaker", "circuitBreaker")
|
|
85
|
+
perf_raw = _pick(user_config, "performance", "performance")
|
|
86
|
+
dlq_raw = _pick(user_config, "dead_letter_queue", "deadLetterQueue")
|
|
87
|
+
integrations_raw = _pick(user_config, "integrations", "integrations")
|
|
88
|
+
|
|
89
|
+
return LogsInterceptorConfig(
|
|
90
|
+
transport=TransportConfig(
|
|
91
|
+
url=_pick(transport_raw, "url", "url", ""),
|
|
92
|
+
tenant_id=_pick(transport_raw, "tenant_id", "tenantId", ""),
|
|
93
|
+
auth_token=_pick(transport_raw, "auth_token", "authToken"),
|
|
94
|
+
timeout=_pick(transport_raw, "timeout", "timeout"),
|
|
95
|
+
max_retries=_pick(transport_raw, "max_retries", "maxRetries"),
|
|
96
|
+
retry_delay=_pick(transport_raw, "retry_delay", "retryDelay"),
|
|
97
|
+
compression=_pick(transport_raw, "compression", "compression"),
|
|
98
|
+
compression_level=_pick(transport_raw, "compression_level", "compressionLevel"),
|
|
99
|
+
compression_threshold=_pick(transport_raw, "compression_threshold", "compressionThreshold"),
|
|
100
|
+
use_workers=_pick(transport_raw, "use_workers", "useWorkers"),
|
|
101
|
+
max_workers=_pick(transport_raw, "max_workers", "maxWorkers"),
|
|
102
|
+
worker_timeout=_pick(transport_raw, "worker_timeout", "workerTimeout"),
|
|
103
|
+
enable_connection_pooling=_pick(
|
|
104
|
+
transport_raw, "enable_connection_pooling", "enableConnectionPooling"
|
|
105
|
+
),
|
|
106
|
+
max_sockets=_pick(transport_raw, "max_sockets", "maxSockets"),
|
|
107
|
+
),
|
|
108
|
+
app_name=_pick(user_config, "app_name", "appName", ""),
|
|
109
|
+
version=_pick(user_config, "version", "version"),
|
|
110
|
+
environment=_pick(user_config, "environment", "environment"),
|
|
111
|
+
labels=_pick(user_config, "labels", "labels"),
|
|
112
|
+
dynamic_labels=_pick(user_config, "dynamic_labels", "dynamicLabels"),
|
|
113
|
+
buffer=(
|
|
114
|
+
BufferConfig(
|
|
115
|
+
max_size=_pick(buffer_raw, "max_size", "maxSize") if buffer_raw else None,
|
|
116
|
+
flush_interval=_pick(buffer_raw, "flush_interval", "flushInterval")
|
|
117
|
+
if buffer_raw
|
|
118
|
+
else None,
|
|
119
|
+
max_age=_pick(buffer_raw, "max_age", "maxAge") if buffer_raw else None,
|
|
120
|
+
auto_flush=_pick(buffer_raw, "auto_flush", "autoFlush") if buffer_raw else None,
|
|
121
|
+
max_memory_mb=_pick(buffer_raw, "max_memory_mb", "maxMemoryMB")
|
|
122
|
+
if buffer_raw
|
|
123
|
+
else None,
|
|
124
|
+
)
|
|
125
|
+
if buffer_raw
|
|
126
|
+
else None
|
|
127
|
+
),
|
|
128
|
+
filter=(
|
|
129
|
+
FilterConfig(
|
|
130
|
+
levels=_pick(filter_raw, "levels", "levels"),
|
|
131
|
+
patterns=_pick(filter_raw, "patterns", "patterns"),
|
|
132
|
+
sampling_rate=_pick(filter_raw, "sampling_rate", "samplingRate"),
|
|
133
|
+
max_message_length=_pick(filter_raw, "max_message_length", "maxMessageLength"),
|
|
134
|
+
sanitize=_pick(filter_raw, "sanitize", "sanitize"),
|
|
135
|
+
sensitive_patterns=_pick(filter_raw, "sensitive_patterns", "sensitivePatterns"),
|
|
136
|
+
)
|
|
137
|
+
if filter_raw
|
|
138
|
+
else None
|
|
139
|
+
),
|
|
140
|
+
circuit_breaker=(
|
|
141
|
+
CircuitBreakerConfig(
|
|
142
|
+
enabled=_pick(cb_raw, "enabled", "enabled"),
|
|
143
|
+
failure_threshold=_pick(cb_raw, "failure_threshold", "failureThreshold"),
|
|
144
|
+
reset_timeout=_pick(cb_raw, "reset_timeout", "resetTimeout"),
|
|
145
|
+
half_open_requests=_pick(cb_raw, "half_open_requests", "halfOpenRequests"),
|
|
146
|
+
)
|
|
147
|
+
if cb_raw
|
|
148
|
+
else None
|
|
149
|
+
),
|
|
150
|
+
integrations=(IntegrationsConfig() if integrations_raw is not None else None),
|
|
151
|
+
performance=(
|
|
152
|
+
PerformanceConfig(
|
|
153
|
+
use_workers=_pick(perf_raw, "use_workers", "useWorkers"),
|
|
154
|
+
max_concurrent_flushes=_pick(perf_raw, "max_concurrent_flushes", "maxConcurrentFlushes"),
|
|
155
|
+
compression_level=_pick(perf_raw, "compression_level", "compressionLevel"),
|
|
156
|
+
max_workers=_pick(perf_raw, "max_workers", "maxWorkers"),
|
|
157
|
+
worker_timeout=_pick(perf_raw, "worker_timeout", "workerTimeout"),
|
|
158
|
+
)
|
|
159
|
+
if perf_raw
|
|
160
|
+
else None
|
|
161
|
+
),
|
|
162
|
+
dead_letter_queue=(
|
|
163
|
+
DeadLetterQueueConfig(
|
|
164
|
+
enabled=_pick(dlq_raw, "enabled", "enabled"),
|
|
165
|
+
type=_pick(dlq_raw, "type", "type"),
|
|
166
|
+
max_size=_pick(dlq_raw, "max_size", "maxSize"),
|
|
167
|
+
max_file_size_mb=_pick(dlq_raw, "max_file_size_mb", "maxFileSizeMB"),
|
|
168
|
+
max_retries=_pick(dlq_raw, "max_retries", "maxRetries"),
|
|
169
|
+
base_path=_pick(dlq_raw, "base_path", "basePath"),
|
|
170
|
+
)
|
|
171
|
+
if dlq_raw
|
|
172
|
+
else None
|
|
173
|
+
),
|
|
174
|
+
enable_metrics=_pick(user_config, "enable_metrics", "enableMetrics"),
|
|
175
|
+
enable_health_check=_pick(user_config, "enable_health_check", "enableHealthCheck"),
|
|
176
|
+
intercept_console=_pick(user_config, "intercept_console", "interceptConsole"),
|
|
177
|
+
preserve_original_console=_pick(
|
|
178
|
+
user_config,
|
|
179
|
+
"preserve_original_console",
|
|
180
|
+
"preserveOriginalConsole",
|
|
181
|
+
),
|
|
182
|
+
debug=_pick(user_config, "debug", "debug"),
|
|
183
|
+
silent_errors=_pick(user_config, "silent_errors", "silentErrors"),
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def init(user_config: LogsInterceptorConfig | dict[str, Any] | None = None) -> ILogger:
|
|
188
|
+
global _global_runtime
|
|
189
|
+
|
|
190
|
+
env_config = load_config_from_env()
|
|
191
|
+
if user_config is None:
|
|
192
|
+
merged_config = env_config
|
|
193
|
+
else:
|
|
194
|
+
coerced_user = _coerce_config(user_config)
|
|
195
|
+
merged_config = merge_configs(coerced_user, env_config)
|
|
196
|
+
|
|
197
|
+
errors = ConfigService.validate(merged_config)
|
|
198
|
+
if errors:
|
|
199
|
+
raise ValueError("Configuration errors:\n" + "\n".join(errors))
|
|
200
|
+
|
|
201
|
+
resolved = ConfigService.resolve(merged_config)
|
|
202
|
+
|
|
203
|
+
previous = _global_runtime
|
|
204
|
+
if previous is not None:
|
|
205
|
+
if previous.runtime_interceptor is not None:
|
|
206
|
+
previous.runtime_interceptor.restore()
|
|
207
|
+
try:
|
|
208
|
+
previous.logger.destroy()
|
|
209
|
+
except Exception:
|
|
210
|
+
pass
|
|
211
|
+
|
|
212
|
+
runtime = LogsInterceptorFactory.create(resolved)
|
|
213
|
+
_global_runtime = _RuntimeState(
|
|
214
|
+
logger=runtime.logger,
|
|
215
|
+
runtime_interceptor=runtime.runtime_interceptor,
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
return runtime.logger
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def get_logger() -> ILogger:
|
|
222
|
+
if _global_runtime is None:
|
|
223
|
+
raise RuntimeError("LogsInterceptor not initialized. Call init() first.")
|
|
224
|
+
return _global_runtime.logger
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
def is_initialized() -> bool:
|
|
228
|
+
return _global_runtime is not None
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def destroy() -> None:
|
|
232
|
+
global _global_runtime
|
|
233
|
+
|
|
234
|
+
if _global_runtime is None:
|
|
235
|
+
return
|
|
236
|
+
|
|
237
|
+
runtime = _global_runtime
|
|
238
|
+
_global_runtime = None
|
|
239
|
+
|
|
240
|
+
if runtime.runtime_interceptor is not None:
|
|
241
|
+
runtime.runtime_interceptor.restore()
|
|
242
|
+
|
|
243
|
+
runtime.logger.destroy()
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
async def adestroy() -> None:
|
|
247
|
+
await asyncio.to_thread(destroy)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
class _GlobalLoggerProxy:
|
|
251
|
+
def debug(self, message: str, context: dict[str, Any] | None = None) -> None:
|
|
252
|
+
if _global_runtime is not None:
|
|
253
|
+
_global_runtime.logger.debug(message, context)
|
|
254
|
+
|
|
255
|
+
def info(self, message: str, context: dict[str, Any] | None = None) -> None:
|
|
256
|
+
if _global_runtime is not None:
|
|
257
|
+
_global_runtime.logger.info(message, context)
|
|
258
|
+
|
|
259
|
+
def warn(self, message: str, context: dict[str, Any] | None = None) -> None:
|
|
260
|
+
if _global_runtime is not None:
|
|
261
|
+
_global_runtime.logger.warn(message, context)
|
|
262
|
+
|
|
263
|
+
def error(self, message: str, context: dict[str, Any] | None = None) -> None:
|
|
264
|
+
if _global_runtime is not None:
|
|
265
|
+
_global_runtime.logger.error(message, context)
|
|
266
|
+
|
|
267
|
+
def fatal(self, message: str, context: dict[str, Any] | None = None) -> None:
|
|
268
|
+
if _global_runtime is not None:
|
|
269
|
+
_global_runtime.logger.fatal(message, context)
|
|
270
|
+
|
|
271
|
+
def log(self, level: LogLevel, message: str, context: dict[str, Any] | None = None) -> None:
|
|
272
|
+
if _global_runtime is not None:
|
|
273
|
+
_global_runtime.logger.log(level, message, context)
|
|
274
|
+
|
|
275
|
+
def track_event(self, event_name: str, properties: dict[str, Any] | None = None) -> None:
|
|
276
|
+
if _global_runtime is not None:
|
|
277
|
+
_global_runtime.logger.track_event(event_name, properties)
|
|
278
|
+
|
|
279
|
+
def with_context(self, context: dict[str, Any], fn: Any) -> Any:
|
|
280
|
+
if _global_runtime is None:
|
|
281
|
+
raise RuntimeError("LogsInterceptor not initialized")
|
|
282
|
+
return _global_runtime.logger.with_context(context, fn)
|
|
283
|
+
|
|
284
|
+
async def with_context_async(self, context: dict[str, Any], fn: Any) -> Any:
|
|
285
|
+
if _global_runtime is None:
|
|
286
|
+
raise RuntimeError("LogsInterceptor not initialized")
|
|
287
|
+
return await _global_runtime.logger.with_context_async(context, fn)
|
|
288
|
+
|
|
289
|
+
def flush(self) -> None:
|
|
290
|
+
if _global_runtime is not None:
|
|
291
|
+
_global_runtime.logger.flush()
|
|
292
|
+
|
|
293
|
+
async def aflush(self) -> None:
|
|
294
|
+
if _global_runtime is not None:
|
|
295
|
+
await _global_runtime.logger.aflush()
|
|
296
|
+
|
|
297
|
+
def get_metrics(self) -> LoggerMetrics:
|
|
298
|
+
if _global_runtime is None:
|
|
299
|
+
raise RuntimeError("LogsInterceptor not initialized")
|
|
300
|
+
return _global_runtime.logger.get_metrics()
|
|
301
|
+
|
|
302
|
+
def get_health(self) -> HealthStatus:
|
|
303
|
+
if _global_runtime is None:
|
|
304
|
+
raise RuntimeError("LogsInterceptor not initialized")
|
|
305
|
+
return _global_runtime.logger.get_health()
|
|
306
|
+
|
|
307
|
+
def destroy(self) -> None:
|
|
308
|
+
destroy()
|
|
309
|
+
|
|
310
|
+
async def adestroy(self) -> None:
|
|
311
|
+
await adestroy()
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
logger = _GlobalLoggerProxy()
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def _auto_init_if_enabled() -> None:
|
|
318
|
+
if not parse_bool(os.getenv("LOGS_AUTO_INIT"), False):
|
|
319
|
+
return
|
|
320
|
+
|
|
321
|
+
env_config = load_config_from_env()
|
|
322
|
+
if not env_config.transport.url or not env_config.transport.tenant_id or not env_config.app_name:
|
|
323
|
+
internal_debug("Auto-init skipped due to missing required LOGS_* variables")
|
|
324
|
+
return
|
|
325
|
+
|
|
326
|
+
try:
|
|
327
|
+
init(env_config)
|
|
328
|
+
internal_debug("Auto-initialized from LOGS_* environment variables")
|
|
329
|
+
except Exception as exc:
|
|
330
|
+
internal_error("Auto-initialization failed", exc)
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
_auto_init_if_enabled()
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from ..config import (
|
|
2
|
+
BufferConfig,
|
|
3
|
+
CircuitBreakerConfig,
|
|
4
|
+
DeadLetterQueueConfig,
|
|
5
|
+
FilterConfig,
|
|
6
|
+
IntegrationsConfig,
|
|
7
|
+
LogsInterceptorConfig,
|
|
8
|
+
PerformanceConfig,
|
|
9
|
+
ResolvedLogsInterceptorConfig,
|
|
10
|
+
TransportConfig,
|
|
11
|
+
)
|
|
12
|
+
from .config_service import ConfigService
|
|
13
|
+
from .log_service import LogService
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"ConfigService",
|
|
17
|
+
"LogService",
|
|
18
|
+
"LogsInterceptorConfig",
|
|
19
|
+
"ResolvedLogsInterceptorConfig",
|
|
20
|
+
"TransportConfig",
|
|
21
|
+
"BufferConfig",
|
|
22
|
+
"FilterConfig",
|
|
23
|
+
"CircuitBreakerConfig",
|
|
24
|
+
"DeadLetterQueueConfig",
|
|
25
|
+
"PerformanceConfig",
|
|
26
|
+
"IntegrationsConfig",
|
|
27
|
+
]
|