rapidlog 1.0.0__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.
rapidlog-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 fastlog contributors
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,404 @@
1
+ Metadata-Version: 2.4
2
+ Name: rapidlog
3
+ Version: 1.0.0
4
+ Summary: High-performance JSON logging for Python with zero dependencies
5
+ Author: fastlog contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yourusername/fastlog
8
+ Project-URL: Repository, https://github.com/yourusername/fastlog
9
+ Project-URL: Issues, https://github.com/yourusername/fastlog/issues
10
+ Keywords: logging,json,performance,structured-logging,async
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: System :: Logging
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=7.0; extra == "dev"
28
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
29
+ Provides-Extra: benchmark
30
+ Requires-Dist: structlog>=23.0; extra == "benchmark"
31
+ Requires-Dist: loguru>=0.7; extra == "benchmark"
32
+ Requires-Dist: python-json-logger>=2.0; extra == "benchmark"
33
+ Requires-Dist: fastlogging>=1.0; extra == "benchmark"
34
+ Dynamic: license-file
35
+
36
+ # rapidlog 🚀
37
+
38
+ **High-performance JSON logging for Python** — Pure Python, zero dependencies, designed for speed.
39
+
40
+ [![Tests](https://github.com/sid19991/fastlog/actions/workflows/test.yml/badge.svg)](https://github.com/sid19991/fastlog/actions/workflows/test.yml)
41
+ [![Benchmarks](https://github.com/sid19991/fastlog/actions/workflows/benchmark.yml/badge.svg)](https://github.com/sid19991/fastlog/actions/workflows/benchmark.yml)
42
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
43
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
44
+ [![PyPI](https://img.shields.io/pypi/v/rapidlog.svg)](https://pypi.org/project/rapidlog/)
45
+
46
+ ---
47
+
48
+ ## The Problem
49
+
50
+ Python's `logging` module has **lock contention under multi-threaded load**. When your application logs from multiple threads, they compete for a shared lock, killing throughput:
51
+
52
+ ```python
53
+ # stdlib logging: 6,487 logs/sec with 4 threads
54
+ import logging
55
+ logging.basicConfig(level=logging.INFO)
56
+ logger = logging.getLogger(__name__)
57
+
58
+ # Bottleneck: all threads compete for the lock
59
+ logger.info("msg", extra={"user_id": 123})
60
+ ```
61
+
62
+ **Result:** Logging becomes a bottleneck in multi-threaded applications.
63
+
64
+ ---
65
+
66
+ ## The Solution: rapidlog
67
+
68
+ **3.1x faster** structured JSON logging with a clean API and zero dependencies.
69
+
70
+ ```python
71
+ # rapidlog: 20,133 logs/sec with 4 threads (3.1x faster)
72
+ from rapidlog import get_logger
73
+
74
+ logger = get_logger()
75
+ logger.info("user login", user_id=123, ip="192.168.1.1")
76
+ ```
77
+
78
+ **That's 13.6K extra logs per second your application can handle.**
79
+
80
+ ---
81
+
82
+ ## Installation
83
+
84
+ ```bash
85
+ pip install rapidlog
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Quick Comparison: stdlib vs rapidlog
91
+
92
+ ### Before (stdlib logging)
93
+ ```python
94
+ import logging
95
+ from pythonjsonlogger import jsonlogger
96
+
97
+ handler = logging.StreamHandler()
98
+ formatter = jsonlogger.JsonFormatter()
99
+ handler.setFormatter(formatter)
100
+
101
+ logger = logging.getLogger()
102
+ logger.addHandler(handler)
103
+
104
+ # Extra kwargs are awkward
105
+ logger.info("user action", extra={"user_id": 123, "action": "login"})
106
+ ```
107
+
108
+ ### After (rapidlog)
109
+ ```python
110
+ from rapidlog import get_logger
111
+
112
+ logger = get_logger()
113
+ logger.info("user action", user_id=123, action="login")
114
+ ```
115
+
116
+ **That's it. Cleaner API, 3x faster, zero dependencies.**
117
+
118
+ ---
119
+
120
+ ## Key Features
121
+
122
+ ✨ **3.1x faster** than stdlib logging under multi-threaded load
123
+ ⚡ **Zero lock contention** on the hot path (per-thread buffers)
124
+ 🔧 **Configuration presets** for memory vs throughput trade-offs
125
+ 🧵 **Thread-safe** multi-producer, single-consumer design
126
+ 📦 **Zero dependencies** — pure Python stdlib only
127
+ 🛡️ **Battle-tested** — 37 comprehensive tests covering edge cases
128
+
129
+ ---
130
+
131
+ ## Quick Start
132
+
133
+ ### Basic Usage
134
+
135
+ ```python
136
+ from rapidlog import get_logger
137
+
138
+ # Create logger with default settings
139
+ logger = get_logger(level="INFO")
140
+
141
+ # Log with structured fields
142
+ logger.info("user action", user_id=123, action="login", ip="192.168.1.1")
143
+ logger.warning("cache miss", key="user:456", ttl=3600)
144
+ logger.error("database timeout", query="SELECT * FROM users", timeout_ms=5000)
145
+
146
+ # Always close when done
147
+ logger.close()
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Migrating from stdlib logging
153
+
154
+ ### Step 1: Replace imports
155
+ ```python
156
+ # Before
157
+ import logging
158
+ logger = logging.getLogger(__name__)
159
+
160
+ # After
161
+ from rapidlog import get_logger
162
+ logger = get_logger()
163
+ ```
164
+
165
+ ### Step 2: Update logging calls
166
+ ```python
167
+ # Before: Awkward extra= syntax
168
+ logger.info("user login", extra={"user_id": 123, "ip": "192.168.1.1"})
169
+
170
+ # After: Clean keyword arguments
171
+ logger.info("user login", user_id=123, ip="192.168.1.1")
172
+ ```
173
+
174
+ ### Step 3: Remove JSON formatter setup
175
+ ```python
176
+ # Before: Complex setup
177
+ import logging
178
+ from pythonjsonlogger import jsonlogger
179
+
180
+ handler = logging.StreamHandler()
181
+ formatter = jsonlogger.JsonFormatter()
182
+ handler.setFormatter(formatter)
183
+ logger = logging.getLogger()
184
+ logger.addHandler(handler)
185
+
186
+ # After: One line
187
+ from rapidlog import get_logger
188
+ logger = get_logger()
189
+ ```
190
+
191
+ ### That's it!
192
+ - Logs are now JSON by default
193
+ - You get 3x the throughput
194
+ - Zero dependencies
195
+ - Same thread-safe behavior
196
+
197
+ ---
198
+
199
+ ## Configuration Presets
200
+
201
+ Choose a preset based on your application's constraints:
202
+
203
+ ```python
204
+ # Low-memory mode (2-4 MiB peak, lower throughput)
205
+ logger = get_logger(preset="low-memory")
206
+
207
+ # Balanced mode (5-10 MiB peak, good throughput) - this is the default
208
+ logger = get_logger(preset="balanced")
209
+
210
+ # Throughput mode (10-20 MiB peak, maximum throughput)
211
+ logger = get_logger(preset="throughput")
212
+ ```
213
+
214
+ **Preset Comparison:**
215
+
216
+ | Preset | Queue Size | Batch Size | Peak Memory | Best For |
217
+ |--------|-----------|-----------|-------------|----------|
218
+ | `low-memory` | 2,048 | 64 | ~2-4 MiB | Memory-constrained environments |
219
+ | `balanced` | 32,768 | 256 | ~5-10 MiB | General-purpose applications (default) |
220
+ | `throughput` | 131,072 | 1,024 | ~10-20 MiB | High-volume logging |
221
+
222
+ ### Custom Configuration
223
+
224
+ ```python
225
+ logger = get_logger(
226
+ level="DEBUG",
227
+ queue_size=16384, # Size of cross-thread queue
228
+ batch_size=512, # Records per write batch
229
+ thread_buffer_size=64, # Records per thread buffer
230
+ flush_interval=0.02 # Seconds between auto-flushes
231
+ )
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Performance Benchmarks
237
+
238
+ Detailed benchmark results from comprehensive comparison (Python 3.13, Windows):
239
+
240
+ ### Single-Threaded Performance (1 thread, 100K logs)
241
+
242
+ | Library | Throughput | vs stdlib-json | Peak Memory |
243
+ |---------|-----------|----------------|-------------|
244
+ | **rapidlog** | **21,922 logs/s** | **2.35x faster** | 23.9 MiB |
245
+ | fastlogging | 26,527 logs/s | 2.85x faster | 0.02 MiB |
246
+ | structlog-json | 13,763 logs/s | 1.48x faster | 0.02 MiB |
247
+ | stdlib-batching | 11,955 logs/s | 1.28x faster | 0.04 MiB |
248
+ | **stdlib-json** | 9,317 logs/s | **baseline** | 0.01 MiB |
249
+ | python-json-logger | 8,344 logs/s | 0.90x | 0.01 MiB |
250
+ | loguru | 3,737 logs/s | 0.40x | 0.03 MiB |
251
+
252
+ ### Multi-Threaded Performance (4 threads, 100K logs each = 400K total)
253
+
254
+ | Library | Throughput | vs stdlib-json | Peak Memory |
255
+ |---------|-----------|----------------|-------------|
256
+ | fastlogging | 24,374 logs/s | 3.76x faster | 0.06 MiB |
257
+ | **rapidlog** | **20,133 logs/s** | **3.10x faster** | 23.9 MiB |
258
+ | structlog-json | 12,101 logs/s | 1.86x faster | 0.02 MiB |
259
+ | stdlib-batching | 6,453 logs/s | 0.99x | 0.05 MiB |
260
+ | python-json-logger | 6,527 logs/s | 1.01x | 0.02 MiB |
261
+ | **stdlib-json** | 6,487 logs/s | **baseline** | 0.02 MiB |
262
+ | loguru | 3,248 logs/s | 0.50x | 0.04 MiB |
263
+
264
+ ### High-Contention Performance (8 threads, 50K logs each = 400K total)
265
+
266
+ | Library | Throughput | vs stdlib-json | Peak Memory |
267
+ |---------|-----------|----------------|-------------|
268
+ | fastlogging | 25,674 logs/s | 3.99x faster | 0.10 MiB |
269
+ | **rapidlog** | **19,685 logs/s** | **3.06x faster** | 24.0 MiB |
270
+ | structlog-json | 10,152 logs/s | 1.58x faster | 0.04 MiB |
271
+ | stdlib-batching | 7,231 logs/s | 1.12x faster | 0.07 MiB |
272
+ | **stdlib-json** | 6,441 logs/s | **baseline** | 0.04 MiB |
273
+ | python-json-logger | 6,079 logs/s | 0.94x | 0.04 MiB |
274
+ | loguru | 3,030 logs/s | 0.47x | 0.09 MiB |
275
+
276
+ ### Key Takeaways
277
+
278
+ 1. **rapidlog excels in multi-threaded scenarios** — 3.1x faster than stdlib-json with 4+ threads
279
+ 2. **fastlogging is fastest** but lacks structured logging API (manual JSON encoding required)
280
+ 3. **Memory trade-off is intentional** — rapidlog uses ~24 MiB for pre-allocated buffers to eliminate lock contention
281
+ 4. **Throughput scales linearly** with threads due to per-thread buffer architecture
282
+
283
+ ### Benchmark Notes
284
+
285
+ **Output format considerations:**
286
+
287
+ - **rapidlog, stdlib-json, structlog, python-json-logger, loguru**: All output minimal structured JSON (~100 bytes per log)
288
+ ```json
289
+ {"ts_ns": 1739462130123456789, "level": "INFO", "msg": "hello", "user_id": 1, "i": 0, "thread": 12345}
290
+ ```
291
+
292
+ - **fastlogging**: Does NOT output structured JSON
293
+ - Outputs text format: `2026-02-13 10:15:30.123 INFO: {"msg": "hello", ...}`
294
+ - Requires manual JSON encoding in application code
295
+ - Not comparable as a structured logging solution
296
+
297
+ **All benchmarks use comparable output formats** except fastlogging, ensuring fair throughput comparisons.
298
+
299
+ ---
300
+
301
+ ## Design & Architecture
302
+
303
+ ### Design goals
304
+
305
+ - Faster than `structlog` and `logging + json-logger`
306
+ - Treat JSON as an **output format**, not the internal hot-path format
307
+ - Avoid dict creation on the hot path where possible
308
+ - Avoid per-log allocation where possible
309
+ - Defer JSON serialization
310
+ - Batch writes
311
+ - Stdout sink only (v1)
312
+
313
+ ### Constraints (v1)
314
+
315
+ - Python 3.10+
316
+ - No external runtime dependencies
317
+ - No async user-facing API
318
+ - Single writer thread allowed
319
+ - Thread-safe logging from multiple producer threads
320
+
321
+ ## Current architecture
322
+
323
+ The implementation in `rapidlog.py` currently follows this shape:
324
+
325
+ 1. **Hot path (`Logger._log`)**
326
+ - Level check first.
327
+ - Build a compact array/list record with fixed slots.
328
+ - Append to a per-thread buffer.
329
+ 2. **Cross-thread handoff**
330
+ - Per-thread buffers flush into a bounded `RingQueue`.
331
+ - Queue is multi-producer / single-consumer.
332
+ 3. **Writer thread**
333
+ - Background writer drains records in batches.
334
+ - JSON serialization happens only in writer thread.
335
+ - Batch is written to `sys.stdout.buffer`.
336
+
337
+ ## Repository layout
338
+
339
+ - `rapidlog.py` — core logger + queue + writer thread with presets
340
+ - `benchmark_logging.py` — original in-memory benchmark (legacy)
341
+ - `benchmark_persisted_logging.py` — production-style benchmark with logs persisted to files
342
+ - `benchmark_enhanced.py` — comprehensive comparison against stdlib, structlog, loguru, python-json-logger, and fastlogging
343
+ - `demo_presets.py` — demonstration of memory/throughput trade-offs across presets
344
+ - `test_fastlog.py` — comprehensive test suite (37 tests covering edge cases)
345
+ - `TEST_COVERAGE.md` — detailed documentation of all test scenarios
346
+
347
+ ## Running benchmarks
348
+
349
+ ### 1) Preset comparison
350
+
351
+ ```bash
352
+ python demo_presets.py
353
+ ```
354
+
355
+ Shows memory and throughput characteristics of each preset.
356
+
357
+ ### 2) Comprehensive comparison
358
+
359
+ ```bash
360
+ python benchmark_enhanced.py
361
+ ```
362
+
363
+ Compares rapidlog against:
364
+ - **stdlib logging** (basic, JSON formatter, batching)
365
+ - **python-json-logger** (optional)
366
+ - **structlog** (optional)
367
+ - **loguru** (optional)
368
+ - **fastlogging** (optional - similar-named library for comparison)
369
+
370
+ All benchmarks use actual file I/O to measure real-world performance.
371
+
372
+ ### 3) Legacy benchmarks
373
+
374
+ ```bash
375
+ # In-memory benchmark
376
+ python benchmark_logging.py
377
+
378
+ # Persisted benchmark
379
+ python benchmark_persisted_logging.py
380
+ ```
381
+
382
+ ## Running tests
383
+
384
+ ### 1) Full test suite
385
+
386
+ ```bash
387
+ pytest test_fastlog.py -v
388
+ ```
389
+
390
+ ### 2) Quick test
391
+
392
+ ```bash
393
+ pytest test_fastlog.py -q
394
+ ```
395
+
396
+ ### 3) Specific test class
397
+
398
+ ```bash
399
+ pytest test_fastlog.py::TestRingQueue -v
400
+ ```
401
+
402
+ ## Project status
403
+
404
+ This is intentionally minimal and focused on validating core architecture and performance trade-offs.
@@ -0,0 +1,369 @@
1
+ # rapidlog 🚀
2
+
3
+ **High-performance JSON logging for Python** — Pure Python, zero dependencies, designed for speed.
4
+
5
+ [![Tests](https://github.com/sid19991/fastlog/actions/workflows/test.yml/badge.svg)](https://github.com/sid19991/fastlog/actions/workflows/test.yml)
6
+ [![Benchmarks](https://github.com/sid19991/fastlog/actions/workflows/benchmark.yml/badge.svg)](https://github.com/sid19991/fastlog/actions/workflows/benchmark.yml)
7
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+ [![PyPI](https://img.shields.io/pypi/v/rapidlog.svg)](https://pypi.org/project/rapidlog/)
10
+
11
+ ---
12
+
13
+ ## The Problem
14
+
15
+ Python's `logging` module has **lock contention under multi-threaded load**. When your application logs from multiple threads, they compete for a shared lock, killing throughput:
16
+
17
+ ```python
18
+ # stdlib logging: 6,487 logs/sec with 4 threads
19
+ import logging
20
+ logging.basicConfig(level=logging.INFO)
21
+ logger = logging.getLogger(__name__)
22
+
23
+ # Bottleneck: all threads compete for the lock
24
+ logger.info("msg", extra={"user_id": 123})
25
+ ```
26
+
27
+ **Result:** Logging becomes a bottleneck in multi-threaded applications.
28
+
29
+ ---
30
+
31
+ ## The Solution: rapidlog
32
+
33
+ **3.1x faster** structured JSON logging with a clean API and zero dependencies.
34
+
35
+ ```python
36
+ # rapidlog: 20,133 logs/sec with 4 threads (3.1x faster)
37
+ from rapidlog import get_logger
38
+
39
+ logger = get_logger()
40
+ logger.info("user login", user_id=123, ip="192.168.1.1")
41
+ ```
42
+
43
+ **That's 13.6K extra logs per second your application can handle.**
44
+
45
+ ---
46
+
47
+ ## Installation
48
+
49
+ ```bash
50
+ pip install rapidlog
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Quick Comparison: stdlib vs rapidlog
56
+
57
+ ### Before (stdlib logging)
58
+ ```python
59
+ import logging
60
+ from pythonjsonlogger import jsonlogger
61
+
62
+ handler = logging.StreamHandler()
63
+ formatter = jsonlogger.JsonFormatter()
64
+ handler.setFormatter(formatter)
65
+
66
+ logger = logging.getLogger()
67
+ logger.addHandler(handler)
68
+
69
+ # Extra kwargs are awkward
70
+ logger.info("user action", extra={"user_id": 123, "action": "login"})
71
+ ```
72
+
73
+ ### After (rapidlog)
74
+ ```python
75
+ from rapidlog import get_logger
76
+
77
+ logger = get_logger()
78
+ logger.info("user action", user_id=123, action="login")
79
+ ```
80
+
81
+ **That's it. Cleaner API, 3x faster, zero dependencies.**
82
+
83
+ ---
84
+
85
+ ## Key Features
86
+
87
+ ✨ **3.1x faster** than stdlib logging under multi-threaded load
88
+ ⚡ **Zero lock contention** on the hot path (per-thread buffers)
89
+ 🔧 **Configuration presets** for memory vs throughput trade-offs
90
+ 🧵 **Thread-safe** multi-producer, single-consumer design
91
+ 📦 **Zero dependencies** — pure Python stdlib only
92
+ 🛡️ **Battle-tested** — 37 comprehensive tests covering edge cases
93
+
94
+ ---
95
+
96
+ ## Quick Start
97
+
98
+ ### Basic Usage
99
+
100
+ ```python
101
+ from rapidlog import get_logger
102
+
103
+ # Create logger with default settings
104
+ logger = get_logger(level="INFO")
105
+
106
+ # Log with structured fields
107
+ logger.info("user action", user_id=123, action="login", ip="192.168.1.1")
108
+ logger.warning("cache miss", key="user:456", ttl=3600)
109
+ logger.error("database timeout", query="SELECT * FROM users", timeout_ms=5000)
110
+
111
+ # Always close when done
112
+ logger.close()
113
+ ```
114
+
115
+ ---
116
+
117
+ ## Migrating from stdlib logging
118
+
119
+ ### Step 1: Replace imports
120
+ ```python
121
+ # Before
122
+ import logging
123
+ logger = logging.getLogger(__name__)
124
+
125
+ # After
126
+ from rapidlog import get_logger
127
+ logger = get_logger()
128
+ ```
129
+
130
+ ### Step 2: Update logging calls
131
+ ```python
132
+ # Before: Awkward extra= syntax
133
+ logger.info("user login", extra={"user_id": 123, "ip": "192.168.1.1"})
134
+
135
+ # After: Clean keyword arguments
136
+ logger.info("user login", user_id=123, ip="192.168.1.1")
137
+ ```
138
+
139
+ ### Step 3: Remove JSON formatter setup
140
+ ```python
141
+ # Before: Complex setup
142
+ import logging
143
+ from pythonjsonlogger import jsonlogger
144
+
145
+ handler = logging.StreamHandler()
146
+ formatter = jsonlogger.JsonFormatter()
147
+ handler.setFormatter(formatter)
148
+ logger = logging.getLogger()
149
+ logger.addHandler(handler)
150
+
151
+ # After: One line
152
+ from rapidlog import get_logger
153
+ logger = get_logger()
154
+ ```
155
+
156
+ ### That's it!
157
+ - Logs are now JSON by default
158
+ - You get 3x the throughput
159
+ - Zero dependencies
160
+ - Same thread-safe behavior
161
+
162
+ ---
163
+
164
+ ## Configuration Presets
165
+
166
+ Choose a preset based on your application's constraints:
167
+
168
+ ```python
169
+ # Low-memory mode (2-4 MiB peak, lower throughput)
170
+ logger = get_logger(preset="low-memory")
171
+
172
+ # Balanced mode (5-10 MiB peak, good throughput) - this is the default
173
+ logger = get_logger(preset="balanced")
174
+
175
+ # Throughput mode (10-20 MiB peak, maximum throughput)
176
+ logger = get_logger(preset="throughput")
177
+ ```
178
+
179
+ **Preset Comparison:**
180
+
181
+ | Preset | Queue Size | Batch Size | Peak Memory | Best For |
182
+ |--------|-----------|-----------|-------------|----------|
183
+ | `low-memory` | 2,048 | 64 | ~2-4 MiB | Memory-constrained environments |
184
+ | `balanced` | 32,768 | 256 | ~5-10 MiB | General-purpose applications (default) |
185
+ | `throughput` | 131,072 | 1,024 | ~10-20 MiB | High-volume logging |
186
+
187
+ ### Custom Configuration
188
+
189
+ ```python
190
+ logger = get_logger(
191
+ level="DEBUG",
192
+ queue_size=16384, # Size of cross-thread queue
193
+ batch_size=512, # Records per write batch
194
+ thread_buffer_size=64, # Records per thread buffer
195
+ flush_interval=0.02 # Seconds between auto-flushes
196
+ )
197
+ ```
198
+
199
+ ---
200
+
201
+ ## Performance Benchmarks
202
+
203
+ Detailed benchmark results from comprehensive comparison (Python 3.13, Windows):
204
+
205
+ ### Single-Threaded Performance (1 thread, 100K logs)
206
+
207
+ | Library | Throughput | vs stdlib-json | Peak Memory |
208
+ |---------|-----------|----------------|-------------|
209
+ | **rapidlog** | **21,922 logs/s** | **2.35x faster** | 23.9 MiB |
210
+ | fastlogging | 26,527 logs/s | 2.85x faster | 0.02 MiB |
211
+ | structlog-json | 13,763 logs/s | 1.48x faster | 0.02 MiB |
212
+ | stdlib-batching | 11,955 logs/s | 1.28x faster | 0.04 MiB |
213
+ | **stdlib-json** | 9,317 logs/s | **baseline** | 0.01 MiB |
214
+ | python-json-logger | 8,344 logs/s | 0.90x | 0.01 MiB |
215
+ | loguru | 3,737 logs/s | 0.40x | 0.03 MiB |
216
+
217
+ ### Multi-Threaded Performance (4 threads, 100K logs each = 400K total)
218
+
219
+ | Library | Throughput | vs stdlib-json | Peak Memory |
220
+ |---------|-----------|----------------|-------------|
221
+ | fastlogging | 24,374 logs/s | 3.76x faster | 0.06 MiB |
222
+ | **rapidlog** | **20,133 logs/s** | **3.10x faster** | 23.9 MiB |
223
+ | structlog-json | 12,101 logs/s | 1.86x faster | 0.02 MiB |
224
+ | stdlib-batching | 6,453 logs/s | 0.99x | 0.05 MiB |
225
+ | python-json-logger | 6,527 logs/s | 1.01x | 0.02 MiB |
226
+ | **stdlib-json** | 6,487 logs/s | **baseline** | 0.02 MiB |
227
+ | loguru | 3,248 logs/s | 0.50x | 0.04 MiB |
228
+
229
+ ### High-Contention Performance (8 threads, 50K logs each = 400K total)
230
+
231
+ | Library | Throughput | vs stdlib-json | Peak Memory |
232
+ |---------|-----------|----------------|-------------|
233
+ | fastlogging | 25,674 logs/s | 3.99x faster | 0.10 MiB |
234
+ | **rapidlog** | **19,685 logs/s** | **3.06x faster** | 24.0 MiB |
235
+ | structlog-json | 10,152 logs/s | 1.58x faster | 0.04 MiB |
236
+ | stdlib-batching | 7,231 logs/s | 1.12x faster | 0.07 MiB |
237
+ | **stdlib-json** | 6,441 logs/s | **baseline** | 0.04 MiB |
238
+ | python-json-logger | 6,079 logs/s | 0.94x | 0.04 MiB |
239
+ | loguru | 3,030 logs/s | 0.47x | 0.09 MiB |
240
+
241
+ ### Key Takeaways
242
+
243
+ 1. **rapidlog excels in multi-threaded scenarios** — 3.1x faster than stdlib-json with 4+ threads
244
+ 2. **fastlogging is fastest** but lacks structured logging API (manual JSON encoding required)
245
+ 3. **Memory trade-off is intentional** — rapidlog uses ~24 MiB for pre-allocated buffers to eliminate lock contention
246
+ 4. **Throughput scales linearly** with threads due to per-thread buffer architecture
247
+
248
+ ### Benchmark Notes
249
+
250
+ **Output format considerations:**
251
+
252
+ - **rapidlog, stdlib-json, structlog, python-json-logger, loguru**: All output minimal structured JSON (~100 bytes per log)
253
+ ```json
254
+ {"ts_ns": 1739462130123456789, "level": "INFO", "msg": "hello", "user_id": 1, "i": 0, "thread": 12345}
255
+ ```
256
+
257
+ - **fastlogging**: Does NOT output structured JSON
258
+ - Outputs text format: `2026-02-13 10:15:30.123 INFO: {"msg": "hello", ...}`
259
+ - Requires manual JSON encoding in application code
260
+ - Not comparable as a structured logging solution
261
+
262
+ **All benchmarks use comparable output formats** except fastlogging, ensuring fair throughput comparisons.
263
+
264
+ ---
265
+
266
+ ## Design & Architecture
267
+
268
+ ### Design goals
269
+
270
+ - Faster than `structlog` and `logging + json-logger`
271
+ - Treat JSON as an **output format**, not the internal hot-path format
272
+ - Avoid dict creation on the hot path where possible
273
+ - Avoid per-log allocation where possible
274
+ - Defer JSON serialization
275
+ - Batch writes
276
+ - Stdout sink only (v1)
277
+
278
+ ### Constraints (v1)
279
+
280
+ - Python 3.10+
281
+ - No external runtime dependencies
282
+ - No async user-facing API
283
+ - Single writer thread allowed
284
+ - Thread-safe logging from multiple producer threads
285
+
286
+ ## Current architecture
287
+
288
+ The implementation in `rapidlog.py` currently follows this shape:
289
+
290
+ 1. **Hot path (`Logger._log`)**
291
+ - Level check first.
292
+ - Build a compact array/list record with fixed slots.
293
+ - Append to a per-thread buffer.
294
+ 2. **Cross-thread handoff**
295
+ - Per-thread buffers flush into a bounded `RingQueue`.
296
+ - Queue is multi-producer / single-consumer.
297
+ 3. **Writer thread**
298
+ - Background writer drains records in batches.
299
+ - JSON serialization happens only in writer thread.
300
+ - Batch is written to `sys.stdout.buffer`.
301
+
302
+ ## Repository layout
303
+
304
+ - `rapidlog.py` — core logger + queue + writer thread with presets
305
+ - `benchmark_logging.py` — original in-memory benchmark (legacy)
306
+ - `benchmark_persisted_logging.py` — production-style benchmark with logs persisted to files
307
+ - `benchmark_enhanced.py` — comprehensive comparison against stdlib, structlog, loguru, python-json-logger, and fastlogging
308
+ - `demo_presets.py` — demonstration of memory/throughput trade-offs across presets
309
+ - `test_fastlog.py` — comprehensive test suite (37 tests covering edge cases)
310
+ - `TEST_COVERAGE.md` — detailed documentation of all test scenarios
311
+
312
+ ## Running benchmarks
313
+
314
+ ### 1) Preset comparison
315
+
316
+ ```bash
317
+ python demo_presets.py
318
+ ```
319
+
320
+ Shows memory and throughput characteristics of each preset.
321
+
322
+ ### 2) Comprehensive comparison
323
+
324
+ ```bash
325
+ python benchmark_enhanced.py
326
+ ```
327
+
328
+ Compares rapidlog against:
329
+ - **stdlib logging** (basic, JSON formatter, batching)
330
+ - **python-json-logger** (optional)
331
+ - **structlog** (optional)
332
+ - **loguru** (optional)
333
+ - **fastlogging** (optional - similar-named library for comparison)
334
+
335
+ All benchmarks use actual file I/O to measure real-world performance.
336
+
337
+ ### 3) Legacy benchmarks
338
+
339
+ ```bash
340
+ # In-memory benchmark
341
+ python benchmark_logging.py
342
+
343
+ # Persisted benchmark
344
+ python benchmark_persisted_logging.py
345
+ ```
346
+
347
+ ## Running tests
348
+
349
+ ### 1) Full test suite
350
+
351
+ ```bash
352
+ pytest test_fastlog.py -v
353
+ ```
354
+
355
+ ### 2) Quick test
356
+
357
+ ```bash
358
+ pytest test_fastlog.py -q
359
+ ```
360
+
361
+ ### 3) Specific test class
362
+
363
+ ```bash
364
+ pytest test_fastlog.py::TestRingQueue -v
365
+ ```
366
+
367
+ ## Project status
368
+
369
+ This is intentionally minimal and focused on validating core architecture and performance trade-offs.
@@ -0,0 +1,69 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "rapidlog"
7
+ version = "1.0.0"
8
+ description = "High-performance JSON logging for Python with zero dependencies"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ {name = "fastlog contributors"}
14
+ ]
15
+ keywords = ["logging", "json", "performance", "structured-logging", "async"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Topic :: Software Development :: Libraries :: Python Modules",
27
+ "Topic :: System :: Logging",
28
+ "Typing :: Typed",
29
+ ]
30
+
31
+ [project.urls]
32
+ Homepage = "https://github.com/yourusername/fastlog"
33
+ Repository = "https://github.com/yourusername/fastlog"
34
+ Issues = "https://github.com/yourusername/fastlog/issues"
35
+
36
+ [project.optional-dependencies]
37
+ dev = [
38
+ "pytest>=7.0",
39
+ "pytest-cov>=4.0",
40
+ ]
41
+ benchmark = [
42
+ "structlog>=23.0",
43
+ "loguru>=0.7",
44
+ "python-json-logger>=2.0",
45
+ "fastlogging>=1.0",
46
+ ]
47
+
48
+ [tool.setuptools]
49
+ py-modules = ["fastlog"]
50
+
51
+ [tool.pytest.ini_options]
52
+ testpaths = ["test_fastlog.py"]
53
+ python_files = ["test_*.py"]
54
+ python_classes = ["Test*"]
55
+ python_functions = ["test_*"]
56
+ addopts = "-v --tb=short"
57
+
58
+ [tool.coverage.run]
59
+ source = ["fastlog"]
60
+ omit = ["test_*", "benchmark_*", "demo_*", "compare_*", "verify_*"]
61
+
62
+ [tool.coverage.report]
63
+ exclude_lines = [
64
+ "pragma: no cover",
65
+ "def __repr__",
66
+ "raise AssertionError",
67
+ "raise NotImplementedError",
68
+ "if __name__ == .__main__.:",
69
+ ]
@@ -0,0 +1,404 @@
1
+ Metadata-Version: 2.4
2
+ Name: rapidlog
3
+ Version: 1.0.0
4
+ Summary: High-performance JSON logging for Python with zero dependencies
5
+ Author: fastlog contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yourusername/fastlog
8
+ Project-URL: Repository, https://github.com/yourusername/fastlog
9
+ Project-URL: Issues, https://github.com/yourusername/fastlog/issues
10
+ Keywords: logging,json,performance,structured-logging,async
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: System :: Logging
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=7.0; extra == "dev"
28
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
29
+ Provides-Extra: benchmark
30
+ Requires-Dist: structlog>=23.0; extra == "benchmark"
31
+ Requires-Dist: loguru>=0.7; extra == "benchmark"
32
+ Requires-Dist: python-json-logger>=2.0; extra == "benchmark"
33
+ Requires-Dist: fastlogging>=1.0; extra == "benchmark"
34
+ Dynamic: license-file
35
+
36
+ # rapidlog 🚀
37
+
38
+ **High-performance JSON logging for Python** — Pure Python, zero dependencies, designed for speed.
39
+
40
+ [![Tests](https://github.com/sid19991/fastlog/actions/workflows/test.yml/badge.svg)](https://github.com/sid19991/fastlog/actions/workflows/test.yml)
41
+ [![Benchmarks](https://github.com/sid19991/fastlog/actions/workflows/benchmark.yml/badge.svg)](https://github.com/sid19991/fastlog/actions/workflows/benchmark.yml)
42
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
43
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
44
+ [![PyPI](https://img.shields.io/pypi/v/rapidlog.svg)](https://pypi.org/project/rapidlog/)
45
+
46
+ ---
47
+
48
+ ## The Problem
49
+
50
+ Python's `logging` module has **lock contention under multi-threaded load**. When your application logs from multiple threads, they compete for a shared lock, killing throughput:
51
+
52
+ ```python
53
+ # stdlib logging: 6,487 logs/sec with 4 threads
54
+ import logging
55
+ logging.basicConfig(level=logging.INFO)
56
+ logger = logging.getLogger(__name__)
57
+
58
+ # Bottleneck: all threads compete for the lock
59
+ logger.info("msg", extra={"user_id": 123})
60
+ ```
61
+
62
+ **Result:** Logging becomes a bottleneck in multi-threaded applications.
63
+
64
+ ---
65
+
66
+ ## The Solution: rapidlog
67
+
68
+ **3.1x faster** structured JSON logging with a clean API and zero dependencies.
69
+
70
+ ```python
71
+ # rapidlog: 20,133 logs/sec with 4 threads (3.1x faster)
72
+ from rapidlog import get_logger
73
+
74
+ logger = get_logger()
75
+ logger.info("user login", user_id=123, ip="192.168.1.1")
76
+ ```
77
+
78
+ **That's 13.6K extra logs per second your application can handle.**
79
+
80
+ ---
81
+
82
+ ## Installation
83
+
84
+ ```bash
85
+ pip install rapidlog
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Quick Comparison: stdlib vs rapidlog
91
+
92
+ ### Before (stdlib logging)
93
+ ```python
94
+ import logging
95
+ from pythonjsonlogger import jsonlogger
96
+
97
+ handler = logging.StreamHandler()
98
+ formatter = jsonlogger.JsonFormatter()
99
+ handler.setFormatter(formatter)
100
+
101
+ logger = logging.getLogger()
102
+ logger.addHandler(handler)
103
+
104
+ # Extra kwargs are awkward
105
+ logger.info("user action", extra={"user_id": 123, "action": "login"})
106
+ ```
107
+
108
+ ### After (rapidlog)
109
+ ```python
110
+ from rapidlog import get_logger
111
+
112
+ logger = get_logger()
113
+ logger.info("user action", user_id=123, action="login")
114
+ ```
115
+
116
+ **That's it. Cleaner API, 3x faster, zero dependencies.**
117
+
118
+ ---
119
+
120
+ ## Key Features
121
+
122
+ ✨ **3.1x faster** than stdlib logging under multi-threaded load
123
+ ⚡ **Zero lock contention** on the hot path (per-thread buffers)
124
+ 🔧 **Configuration presets** for memory vs throughput trade-offs
125
+ 🧵 **Thread-safe** multi-producer, single-consumer design
126
+ 📦 **Zero dependencies** — pure Python stdlib only
127
+ 🛡️ **Battle-tested** — 37 comprehensive tests covering edge cases
128
+
129
+ ---
130
+
131
+ ## Quick Start
132
+
133
+ ### Basic Usage
134
+
135
+ ```python
136
+ from rapidlog import get_logger
137
+
138
+ # Create logger with default settings
139
+ logger = get_logger(level="INFO")
140
+
141
+ # Log with structured fields
142
+ logger.info("user action", user_id=123, action="login", ip="192.168.1.1")
143
+ logger.warning("cache miss", key="user:456", ttl=3600)
144
+ logger.error("database timeout", query="SELECT * FROM users", timeout_ms=5000)
145
+
146
+ # Always close when done
147
+ logger.close()
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Migrating from stdlib logging
153
+
154
+ ### Step 1: Replace imports
155
+ ```python
156
+ # Before
157
+ import logging
158
+ logger = logging.getLogger(__name__)
159
+
160
+ # After
161
+ from rapidlog import get_logger
162
+ logger = get_logger()
163
+ ```
164
+
165
+ ### Step 2: Update logging calls
166
+ ```python
167
+ # Before: Awkward extra= syntax
168
+ logger.info("user login", extra={"user_id": 123, "ip": "192.168.1.1"})
169
+
170
+ # After: Clean keyword arguments
171
+ logger.info("user login", user_id=123, ip="192.168.1.1")
172
+ ```
173
+
174
+ ### Step 3: Remove JSON formatter setup
175
+ ```python
176
+ # Before: Complex setup
177
+ import logging
178
+ from pythonjsonlogger import jsonlogger
179
+
180
+ handler = logging.StreamHandler()
181
+ formatter = jsonlogger.JsonFormatter()
182
+ handler.setFormatter(formatter)
183
+ logger = logging.getLogger()
184
+ logger.addHandler(handler)
185
+
186
+ # After: One line
187
+ from rapidlog import get_logger
188
+ logger = get_logger()
189
+ ```
190
+
191
+ ### That's it!
192
+ - Logs are now JSON by default
193
+ - You get 3x the throughput
194
+ - Zero dependencies
195
+ - Same thread-safe behavior
196
+
197
+ ---
198
+
199
+ ## Configuration Presets
200
+
201
+ Choose a preset based on your application's constraints:
202
+
203
+ ```python
204
+ # Low-memory mode (2-4 MiB peak, lower throughput)
205
+ logger = get_logger(preset="low-memory")
206
+
207
+ # Balanced mode (5-10 MiB peak, good throughput) - this is the default
208
+ logger = get_logger(preset="balanced")
209
+
210
+ # Throughput mode (10-20 MiB peak, maximum throughput)
211
+ logger = get_logger(preset="throughput")
212
+ ```
213
+
214
+ **Preset Comparison:**
215
+
216
+ | Preset | Queue Size | Batch Size | Peak Memory | Best For |
217
+ |--------|-----------|-----------|-------------|----------|
218
+ | `low-memory` | 2,048 | 64 | ~2-4 MiB | Memory-constrained environments |
219
+ | `balanced` | 32,768 | 256 | ~5-10 MiB | General-purpose applications (default) |
220
+ | `throughput` | 131,072 | 1,024 | ~10-20 MiB | High-volume logging |
221
+
222
+ ### Custom Configuration
223
+
224
+ ```python
225
+ logger = get_logger(
226
+ level="DEBUG",
227
+ queue_size=16384, # Size of cross-thread queue
228
+ batch_size=512, # Records per write batch
229
+ thread_buffer_size=64, # Records per thread buffer
230
+ flush_interval=0.02 # Seconds between auto-flushes
231
+ )
232
+ ```
233
+
234
+ ---
235
+
236
+ ## Performance Benchmarks
237
+
238
+ Detailed benchmark results from comprehensive comparison (Python 3.13, Windows):
239
+
240
+ ### Single-Threaded Performance (1 thread, 100K logs)
241
+
242
+ | Library | Throughput | vs stdlib-json | Peak Memory |
243
+ |---------|-----------|----------------|-------------|
244
+ | **rapidlog** | **21,922 logs/s** | **2.35x faster** | 23.9 MiB |
245
+ | fastlogging | 26,527 logs/s | 2.85x faster | 0.02 MiB |
246
+ | structlog-json | 13,763 logs/s | 1.48x faster | 0.02 MiB |
247
+ | stdlib-batching | 11,955 logs/s | 1.28x faster | 0.04 MiB |
248
+ | **stdlib-json** | 9,317 logs/s | **baseline** | 0.01 MiB |
249
+ | python-json-logger | 8,344 logs/s | 0.90x | 0.01 MiB |
250
+ | loguru | 3,737 logs/s | 0.40x | 0.03 MiB |
251
+
252
+ ### Multi-Threaded Performance (4 threads, 100K logs each = 400K total)
253
+
254
+ | Library | Throughput | vs stdlib-json | Peak Memory |
255
+ |---------|-----------|----------------|-------------|
256
+ | fastlogging | 24,374 logs/s | 3.76x faster | 0.06 MiB |
257
+ | **rapidlog** | **20,133 logs/s** | **3.10x faster** | 23.9 MiB |
258
+ | structlog-json | 12,101 logs/s | 1.86x faster | 0.02 MiB |
259
+ | stdlib-batching | 6,453 logs/s | 0.99x | 0.05 MiB |
260
+ | python-json-logger | 6,527 logs/s | 1.01x | 0.02 MiB |
261
+ | **stdlib-json** | 6,487 logs/s | **baseline** | 0.02 MiB |
262
+ | loguru | 3,248 logs/s | 0.50x | 0.04 MiB |
263
+
264
+ ### High-Contention Performance (8 threads, 50K logs each = 400K total)
265
+
266
+ | Library | Throughput | vs stdlib-json | Peak Memory |
267
+ |---------|-----------|----------------|-------------|
268
+ | fastlogging | 25,674 logs/s | 3.99x faster | 0.10 MiB |
269
+ | **rapidlog** | **19,685 logs/s** | **3.06x faster** | 24.0 MiB |
270
+ | structlog-json | 10,152 logs/s | 1.58x faster | 0.04 MiB |
271
+ | stdlib-batching | 7,231 logs/s | 1.12x faster | 0.07 MiB |
272
+ | **stdlib-json** | 6,441 logs/s | **baseline** | 0.04 MiB |
273
+ | python-json-logger | 6,079 logs/s | 0.94x | 0.04 MiB |
274
+ | loguru | 3,030 logs/s | 0.47x | 0.09 MiB |
275
+
276
+ ### Key Takeaways
277
+
278
+ 1. **rapidlog excels in multi-threaded scenarios** — 3.1x faster than stdlib-json with 4+ threads
279
+ 2. **fastlogging is fastest** but lacks structured logging API (manual JSON encoding required)
280
+ 3. **Memory trade-off is intentional** — rapidlog uses ~24 MiB for pre-allocated buffers to eliminate lock contention
281
+ 4. **Throughput scales linearly** with threads due to per-thread buffer architecture
282
+
283
+ ### Benchmark Notes
284
+
285
+ **Output format considerations:**
286
+
287
+ - **rapidlog, stdlib-json, structlog, python-json-logger, loguru**: All output minimal structured JSON (~100 bytes per log)
288
+ ```json
289
+ {"ts_ns": 1739462130123456789, "level": "INFO", "msg": "hello", "user_id": 1, "i": 0, "thread": 12345}
290
+ ```
291
+
292
+ - **fastlogging**: Does NOT output structured JSON
293
+ - Outputs text format: `2026-02-13 10:15:30.123 INFO: {"msg": "hello", ...}`
294
+ - Requires manual JSON encoding in application code
295
+ - Not comparable as a structured logging solution
296
+
297
+ **All benchmarks use comparable output formats** except fastlogging, ensuring fair throughput comparisons.
298
+
299
+ ---
300
+
301
+ ## Design & Architecture
302
+
303
+ ### Design goals
304
+
305
+ - Faster than `structlog` and `logging + json-logger`
306
+ - Treat JSON as an **output format**, not the internal hot-path format
307
+ - Avoid dict creation on the hot path where possible
308
+ - Avoid per-log allocation where possible
309
+ - Defer JSON serialization
310
+ - Batch writes
311
+ - Stdout sink only (v1)
312
+
313
+ ### Constraints (v1)
314
+
315
+ - Python 3.10+
316
+ - No external runtime dependencies
317
+ - No async user-facing API
318
+ - Single writer thread allowed
319
+ - Thread-safe logging from multiple producer threads
320
+
321
+ ## Current architecture
322
+
323
+ The implementation in `rapidlog.py` currently follows this shape:
324
+
325
+ 1. **Hot path (`Logger._log`)**
326
+ - Level check first.
327
+ - Build a compact array/list record with fixed slots.
328
+ - Append to a per-thread buffer.
329
+ 2. **Cross-thread handoff**
330
+ - Per-thread buffers flush into a bounded `RingQueue`.
331
+ - Queue is multi-producer / single-consumer.
332
+ 3. **Writer thread**
333
+ - Background writer drains records in batches.
334
+ - JSON serialization happens only in writer thread.
335
+ - Batch is written to `sys.stdout.buffer`.
336
+
337
+ ## Repository layout
338
+
339
+ - `rapidlog.py` — core logger + queue + writer thread with presets
340
+ - `benchmark_logging.py` — original in-memory benchmark (legacy)
341
+ - `benchmark_persisted_logging.py` — production-style benchmark with logs persisted to files
342
+ - `benchmark_enhanced.py` — comprehensive comparison against stdlib, structlog, loguru, python-json-logger, and fastlogging
343
+ - `demo_presets.py` — demonstration of memory/throughput trade-offs across presets
344
+ - `test_fastlog.py` — comprehensive test suite (37 tests covering edge cases)
345
+ - `TEST_COVERAGE.md` — detailed documentation of all test scenarios
346
+
347
+ ## Running benchmarks
348
+
349
+ ### 1) Preset comparison
350
+
351
+ ```bash
352
+ python demo_presets.py
353
+ ```
354
+
355
+ Shows memory and throughput characteristics of each preset.
356
+
357
+ ### 2) Comprehensive comparison
358
+
359
+ ```bash
360
+ python benchmark_enhanced.py
361
+ ```
362
+
363
+ Compares rapidlog against:
364
+ - **stdlib logging** (basic, JSON formatter, batching)
365
+ - **python-json-logger** (optional)
366
+ - **structlog** (optional)
367
+ - **loguru** (optional)
368
+ - **fastlogging** (optional - similar-named library for comparison)
369
+
370
+ All benchmarks use actual file I/O to measure real-world performance.
371
+
372
+ ### 3) Legacy benchmarks
373
+
374
+ ```bash
375
+ # In-memory benchmark
376
+ python benchmark_logging.py
377
+
378
+ # Persisted benchmark
379
+ python benchmark_persisted_logging.py
380
+ ```
381
+
382
+ ## Running tests
383
+
384
+ ### 1) Full test suite
385
+
386
+ ```bash
387
+ pytest test_fastlog.py -v
388
+ ```
389
+
390
+ ### 2) Quick test
391
+
392
+ ```bash
393
+ pytest test_fastlog.py -q
394
+ ```
395
+
396
+ ### 3) Specific test class
397
+
398
+ ```bash
399
+ pytest test_fastlog.py::TestRingQueue -v
400
+ ```
401
+
402
+ ## Project status
403
+
404
+ This is intentionally minimal and focused on validating core architecture and performance trade-offs.
@@ -0,0 +1,8 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ rapidlog.egg-info/PKG-INFO
5
+ rapidlog.egg-info/SOURCES.txt
6
+ rapidlog.egg-info/dependency_links.txt
7
+ rapidlog.egg-info/requires.txt
8
+ rapidlog.egg-info/top_level.txt
@@ -0,0 +1,10 @@
1
+
2
+ [benchmark]
3
+ structlog>=23.0
4
+ loguru>=0.7
5
+ python-json-logger>=2.0
6
+ fastlogging>=1.0
7
+
8
+ [dev]
9
+ pytest>=7.0
10
+ pytest-cov>=4.0
@@ -0,0 +1 @@
1
+ fastlog
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+