aiologging 0.1.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.
Files changed (33) hide show
  1. aiologging-0.1.0/LICENSE +21 -0
  2. aiologging-0.1.0/PKG-INFO +600 -0
  3. aiologging-0.1.0/README.md +530 -0
  4. aiologging-0.1.0/aiologging/__init__.py +326 -0
  5. aiologging-0.1.0/aiologging/config.py +529 -0
  6. aiologging-0.1.0/aiologging/exceptions.py +898 -0
  7. aiologging-0.1.0/aiologging/handlers/__init__.py +32 -0
  8. aiologging-0.1.0/aiologging/handlers/base.py +793 -0
  9. aiologging-0.1.0/aiologging/handlers/file.py +418 -0
  10. aiologging-0.1.0/aiologging/handlers/http.py +779 -0
  11. aiologging-0.1.0/aiologging/handlers/rotating.py +563 -0
  12. aiologging-0.1.0/aiologging/handlers/stream.py +296 -0
  13. aiologging-0.1.0/aiologging/logger.py +721 -0
  14. aiologging-0.1.0/aiologging/py.typed +0 -0
  15. aiologging-0.1.0/aiologging/types.py +624 -0
  16. aiologging-0.1.0/aiologging/utils.py +275 -0
  17. aiologging-0.1.0/aiologging.egg-info/PKG-INFO +600 -0
  18. aiologging-0.1.0/aiologging.egg-info/SOURCES.txt +31 -0
  19. aiologging-0.1.0/aiologging.egg-info/dependency_links.txt +1 -0
  20. aiologging-0.1.0/aiologging.egg-info/requires.txt +29 -0
  21. aiologging-0.1.0/aiologging.egg-info/top_level.txt +1 -0
  22. aiologging-0.1.0/pyproject.toml +112 -0
  23. aiologging-0.1.0/setup.cfg +4 -0
  24. aiologging-0.1.0/tests/test_config.py +697 -0
  25. aiologging-0.1.0/tests/test_exceptions.py +506 -0
  26. aiologging-0.1.0/tests/test_file_handlers.py +376 -0
  27. aiologging-0.1.0/tests/test_handlers.py +522 -0
  28. aiologging-0.1.0/tests/test_http_handlers.py +618 -0
  29. aiologging-0.1.0/tests/test_logger.py +408 -0
  30. aiologging-0.1.0/tests/test_regressions.py +163 -0
  31. aiologging-0.1.0/tests/test_rotating_handlers.py +947 -0
  32. aiologging-0.1.0/tests/test_types.py +480 -0
  33. aiologging-0.1.0/tests/test_utils.py +308 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Евгений Дементьев
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,600 @@
1
+ Metadata-Version: 2.4
2
+ Name: aiologging
3
+ Version: 0.1.0
4
+ Summary: Asynchronous logging library with full compatibility to standard logging module
5
+ Author: Evgenii Dementev (m6mok)
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Евгений Дементьев
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/m6mok/aiologging
29
+ Project-URL: Repository, https://github.com/m6mok/aiologging
30
+ Project-URL: Bug Tracker, https://github.com/m6mok/aiologging/issues
31
+ Keywords: logging,async,asyncio,aiologging
32
+ Classifier: Development Status :: 4 - Beta
33
+ Classifier: Intended Audience :: Developers
34
+ Classifier: License :: OSI Approved :: MIT License
35
+ Classifier: Operating System :: OS Independent
36
+ Classifier: Programming Language :: Python :: 3
37
+ Classifier: Programming Language :: Python :: 3.9
38
+ Classifier: Programming Language :: Python :: 3.10
39
+ Classifier: Programming Language :: Python :: 3.11
40
+ Classifier: Programming Language :: Python :: 3.12
41
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
42
+ Classifier: Topic :: System :: Logging
43
+ Classifier: Typing :: Typed
44
+ Requires-Python: >=3.9
45
+ Description-Content-Type: text/markdown
46
+ License-File: LICENSE
47
+ Requires-Dist: typing-extensions>=4.0.0; python_version < "3.10"
48
+ Provides-Extra: aiofiles
49
+ Requires-Dist: aiofiles>=23.0.0; extra == "aiofiles"
50
+ Provides-Extra: aiohttp
51
+ Requires-Dist: aiohttp>=3.8.0; extra == "aiohttp"
52
+ Provides-Extra: protobuf
53
+ Requires-Dist: protobuf>=4.0.0; extra == "protobuf"
54
+ Provides-Extra: all
55
+ Requires-Dist: aiofiles>=23.0.0; extra == "all"
56
+ Requires-Dist: aiohttp>=3.8.0; extra == "all"
57
+ Requires-Dist: protobuf>=4.0.0; extra == "all"
58
+ Provides-Extra: dev
59
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
60
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
61
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
62
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
63
+ Requires-Dist: flake8>=6.0.0; extra == "dev"
64
+ Requires-Dist: types-aiofiles; extra == "dev"
65
+ Requires-Dist: types-protobuf; extra == "dev"
66
+ Requires-Dist: aiofiles>=23.0.0; extra == "dev"
67
+ Requires-Dist: aiohttp>=3.8.0; extra == "dev"
68
+ Requires-Dist: protobuf>=4.0.0; extra == "dev"
69
+ Dynamic: license-file
70
+
71
+ # aiologging
72
+
73
+ [![CI](https://github.com/m6mok/aiologging/actions/workflows/ci.yml/badge.svg)](https://github.com/m6mok/aiologging/actions/workflows/ci.yml)
74
+
75
+ Asynchronous logging library for Python (3.9+) with full compatibility to the standard logging module but with async methods requiring await.
76
+
77
+ ## Features
78
+
79
+ - **Full API Compatibility**: Drop-in replacement for standard logging with async methods
80
+ - **Async Handlers**: Non-blocking I/O for streams, files, and HTTP endpoints
81
+ - **File Rotation**: Size and time-based log rotation with async support
82
+ - **HTTP Handlers**: Send logs to HTTP endpoints with extensible authentication
83
+ - **Buffered Handlers**: High-performance batch processing for high-volume logging
84
+ - **Performance Metrics**: Built-in metrics collection for monitoring logging performance
85
+ - **Error Handling**: Comprehensive error handling with custom exception types
86
+ - **Configuration Management**: Flexible configuration from files, dictionaries, or environment variables
87
+ - **Optional Dependencies**: Install only what you need
88
+ - **Strict Type Checking**: Full mypy support with type hints
89
+ - **Context Manager Support**: Safe resource management with `async with`
90
+
91
+ ## Installation
92
+
93
+ ### Basic Installation
94
+
95
+ ```bash
96
+ pip install aiologging
97
+ ```
98
+
99
+ ### With Optional Dependencies
100
+
101
+ ```bash
102
+ # For file handlers
103
+ pip install aiologging[aiofiles]
104
+
105
+ # For HTTP handlers
106
+ pip install aiologging[aiohttp]
107
+
108
+ # For Protobuf support
109
+ pip install aiologging[protobuf]
110
+
111
+ # All dependencies
112
+ pip install aiologging[all]
113
+
114
+ # Development dependencies
115
+ pip install aiologging[dev]
116
+ ```
117
+
118
+ ## Quick Start
119
+
120
+ ### Basic Usage
121
+
122
+ ```python
123
+ import asyncio
124
+ import aiologging
125
+
126
+ async def main():
127
+ async with aiologging.getLogger("app") as logger:
128
+ await logger.info("Application started")
129
+ await logger.warning("Something might be wrong")
130
+ await logger.error("An error occurred")
131
+
132
+ asyncio.run(main())
133
+ ```
134
+
135
+ ### Basic Configuration
136
+
137
+ ```python
138
+ import aiologging
139
+
140
+ # Configure basic logging (similar to logging.basicConfig)
141
+ aiologging.basicConfig(
142
+ level=aiologging.INFO,
143
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
144
+ )
145
+
146
+ async def main():
147
+ async with aiologging.getLogger("app") as logger:
148
+ await logger.info("This will be logged to stderr")
149
+ ```
150
+
151
+ ### Using Convenience Functions
152
+
153
+ ```python
154
+ import asyncio
155
+ import aiologging
156
+
157
+ async def main():
158
+ # Create handlers using convenience functions
159
+ stream_handler = aiologging.create_stream_handler(level=aiologging.INFO)
160
+ file_handler = aiologging.create_file_handler("app.log", level=aiologging.DEBUG)
161
+
162
+ # Get logger and add handlers
163
+ async with aiologging.getLogger("app") as logger:
164
+ logger.addHandler(stream_handler)
165
+ logger.addHandler(file_handler)
166
+
167
+ await logger.info("This goes to both stderr and app.log")
168
+
169
+ asyncio.run(main())
170
+ ```
171
+
172
+ ## Examples
173
+
174
+ Complete runnable examples live in the [examples/](examples/) directory:
175
+
176
+ - [examples/basic_usage.py](examples/basic_usage.py) — levels, `basicConfig`, `exc_info`, one-off logging
177
+ - [examples/file_logging.py](examples/file_logging.py) — file handler, size- and time-based rotation
178
+ - [examples/http_logging.py](examples/http_logging.py) — JSON batches over HTTP with a custom authenticator (includes a local test collector)
179
+ - [examples/config_usage.py](examples/config_usage.py) — configuring loggers from a dictionary
180
+
181
+ ## Handlers
182
+
183
+ ### Stream Handler
184
+
185
+ ```python
186
+ import aiologging
187
+ import sys
188
+
189
+ async def main():
190
+ async with aiologging.getLogger("app") as logger:
191
+ # Add stdout handler
192
+ stdout_handler = aiologging.AsyncStreamHandler(sys.stdout)
193
+ logger.addHandler(stdout_handler)
194
+
195
+ await logger.info("This goes to stdout")
196
+ ```
197
+
198
+ ### File Handler (requires aiofiles)
199
+
200
+ ```python
201
+ import aiologging
202
+
203
+ async def main():
204
+ async with aiologging.getLogger("app") as logger:
205
+ # Add file handler
206
+ file_handler = aiologging.AsyncFileHandler("app.log")
207
+ logger.addHandler(file_handler)
208
+
209
+ await logger.info("This goes to app.log")
210
+ ```
211
+
212
+ ### Rotating File Handler (requires aiofiles)
213
+
214
+ ```python
215
+ import aiologging
216
+
217
+ async def main():
218
+ async with aiologging.getLogger("app") as logger:
219
+ # Size-based rotation
220
+ rotating_handler = aiologging.AsyncRotatingFileHandler(
221
+ "app.log",
222
+ max_bytes=1024*1024, # 1MB
223
+ backup_count=5
224
+ )
225
+ logger.addHandler(rotating_handler)
226
+
227
+ # Time-based rotation
228
+ timed_handler = aiologging.AsyncTimedRotatingFileHandler(
229
+ "app.log",
230
+ when="midnight",
231
+ backup_count=7
232
+ )
233
+ logger.addHandler(timed_handler)
234
+
235
+ await logger.info("This will be rotated")
236
+ ```
237
+
238
+ ### HTTP Handler (requires aiohttp)
239
+
240
+ ```python
241
+ import aiologging
242
+
243
+ async def main():
244
+ async with aiologging.getLogger("app") as logger:
245
+ # Basic HTTP handler
246
+ http_handler = aiologging.AsyncHttpHandler(
247
+ "https://api.example.com/logs",
248
+ headers={"Authorization": "Bearer token"}
249
+ )
250
+ logger.addHandler(http_handler)
251
+
252
+ await logger.info("This will be sent via HTTP")
253
+ ```
254
+
255
+ ### Custom Authentication
256
+
257
+ ```python
258
+ import aiologging
259
+
260
+ async def oauth_authenticator(session, request_data):
261
+ """Custom OAuth authentication."""
262
+ # Refresh token logic here
263
+ token = await refresh_oauth_token()
264
+ return {"Authorization": f"Bearer {token}"}
265
+
266
+ async def main():
267
+ async with aiologging.getLogger("app") as logger:
268
+ http_handler = aiologging.AsyncHttpHandler(
269
+ "https://api.example.com/logs",
270
+ authenticator=oauth_authenticator
271
+ )
272
+ logger.addHandler(http_handler)
273
+
274
+ await logger.info("This uses custom authentication")
275
+ ```
276
+
277
+ ## HTTP Handler Formats
278
+
279
+ ### JSON Handler
280
+
281
+ ```python
282
+ json_handler = aiologging.AsyncHttpJsonHandler(
283
+ "https://api.example.com/logs"
284
+ )
285
+ ```
286
+
287
+ ### Text Handler
288
+
289
+ ```python
290
+ text_handler = aiologging.AsyncHttpTextHandler(
291
+ "https://api.example.com/logs"
292
+ )
293
+ ```
294
+
295
+ ### Protobuf Handler (requires protobuf)
296
+
297
+ ```python
298
+ proto_handler = aiologging.AsyncHttpProtoHandler(
299
+ "https://api.example.com/logs"
300
+ )
301
+ ```
302
+
303
+ ### Universal Handler (auto-detect format)
304
+
305
+ ```python
306
+ universal_handler = aiologging.AsyncHttpHandler(
307
+ "https://api.example.com/logs",
308
+ format_type="application/json" # Optional: auto-detected if not specified
309
+ )
310
+ ```
311
+
312
+ ## Advanced Usage
313
+
314
+ ### Custom Filters
315
+
316
+ ```python
317
+ import aiologging
318
+
319
+ class CustomFilter:
320
+ def filter(self, record):
321
+ return "important" in record.getMessage()
322
+
323
+ async def main():
324
+ async with aiologging.getLogger("app") as logger:
325
+ logger.addFilter(CustomFilter())
326
+
327
+ await logger.info("This is important") # Will be logged
328
+ await logger.info("This is not") # Will be filtered
329
+ ```
330
+
331
+ ### Custom Formatters
332
+
333
+ ```python
334
+ import logging
335
+ import aiologging
336
+
337
+ async def main():
338
+ async with aiologging.getLogger("app") as logger:
339
+ formatter = logging.Formatter(
340
+ "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
341
+ )
342
+
343
+ handler = aiologging.AsyncStreamHandler()
344
+ handler.setFormatter(formatter)
345
+ logger.addHandler(handler)
346
+
347
+ await logger.info("Formatted message")
348
+ ```
349
+
350
+ ### Error Handling
351
+
352
+ ```python
353
+ import aiologging
354
+
355
+ async def error_handler(record, exception):
356
+ """Custom error handler for failed log operations."""
357
+ print(f"Failed to log {record.getMessage()}: {exception}")
358
+
359
+ async def main():
360
+ async with aiologging.getLogger("app") as logger:
361
+ handler = aiologging.AsyncStreamHandler()
362
+ handler.error_handler = error_handler
363
+ logger.addHandler(handler)
364
+
365
+ await logger.info("This has custom error handling")
366
+ ```
367
+
368
+ ### Performance Metrics
369
+
370
+ ```python
371
+ import asyncio
372
+ import aiologging
373
+
374
+ async def main():
375
+ # Create logger with metrics enabled
376
+ async with aiologging.getLogger("app") as logger:
377
+ # Get metrics for the logger
378
+ metrics = logger.get_metrics()
379
+ print(f"Logger metrics: {metrics}")
380
+
381
+ # Get metrics for handlers
382
+ for handler in logger.handlers:
383
+ if hasattr(handler, 'get_metrics'):
384
+ handler_metrics = handler.get_metrics()
385
+ print(f"Handler metrics: {handler_metrics}")
386
+
387
+ asyncio.run(main())
388
+ ```
389
+
390
+ ### Batch Processing
391
+
392
+ ```python
393
+ import aiologging
394
+ from aiologging.types import BatchConfig
395
+
396
+ async def main():
397
+ async with aiologging.getLogger("app") as logger:
398
+ # Configure batch processing for HTTP handler
399
+ batch_config = BatchConfig(
400
+ batch_size=100,
401
+ flush_interval=5.0,
402
+ max_retries=3
403
+ )
404
+
405
+ http_handler = aiologging.AsyncHttpHandler(
406
+ "https://api.example.com/logs",
407
+ batch_config=batch_config
408
+ )
409
+ logger.addHandler(http_handler)
410
+
411
+ # Log many messages - they'll be sent in batches
412
+ for i in range(150):
413
+ await logger.info(f"Message {i}")
414
+ ```
415
+
416
+ ## Configuration Management
417
+
418
+ ### Configuration from Dictionary
419
+
420
+ ```python
421
+ import asyncio
422
+ import aiologging
423
+
424
+ config = {
425
+ "version": 1,
426
+ "loggers": {
427
+ "myapp": {
428
+ "level": "INFO",
429
+ "handlers": ["console", "file"]
430
+ }
431
+ },
432
+ "handlers": {
433
+ "console": {
434
+ "class": "stream",
435
+ "level": "INFO",
436
+ "stream": "stdout"
437
+ },
438
+ "file": {
439
+ "class": "file",
440
+ "level": "DEBUG",
441
+ "filename": "app.log",
442
+ "mode": "a"
443
+ }
444
+ }
445
+ }
446
+
447
+ # Configure from dictionary
448
+ aiologging.configure_from_dict(config)
449
+
450
+ async def main():
451
+ logger = aiologging.get_configured_logger("myapp")
452
+ await logger.info("This uses configured logger")
453
+
454
+ asyncio.run(main())
455
+ ```
456
+
457
+ ### Configuration from File
458
+
459
+ ```python
460
+ import asyncio
461
+ import aiologging
462
+
463
+ # Configure from JSON file
464
+ aiologging.configure_from_file("logging_config.json")
465
+
466
+ async def main():
467
+ logger = aiologging.get_configured_logger("myapp")
468
+ await logger.info("This uses logger configured from file")
469
+
470
+ asyncio.run(main())
471
+ ```
472
+
473
+ ## Migration from Standard Logging
474
+
475
+ ### Standard Logging
476
+
477
+ ```python
478
+ import logging
479
+
480
+ logger = logging.getLogger("app")
481
+ logger.info("Message")
482
+ ```
483
+
484
+ ### With aiologging
485
+
486
+ ```python
487
+ import aiologging
488
+
489
+ async def main():
490
+ async with aiologging.getLogger("app") as logger:
491
+ await logger.info("Message")
492
+ ```
493
+
494
+ ### Key Differences
495
+
496
+ 1. **Async Context**: Use `async with` for proper resource management
497
+ 2. **Await Methods**: All logging methods require `await`
498
+ 3. **Async Handlers**: All handlers are non-blocking
499
+ 4. **Type Safety**: Full type hints and mypy compliance
500
+ 5. **Error Handling**: Enhanced error handling with custom exception types
501
+ 6. **Performance Metrics**: Built-in metrics collection for monitoring
502
+
503
+ ## API Reference
504
+
505
+ ### Logger Methods
506
+
507
+ All standard logging methods are available as async:
508
+
509
+ - `await logger.log(level, msg, *args, **kwargs)`
510
+ - `await logger.debug(msg, *args, **kwargs)`
511
+ - `await logger.info(msg, *args, **kwargs)`
512
+ - `await logger.warning(msg, *args, **kwargs)`
513
+ - `await logger.error(msg, *args, **kwargs)`
514
+ - `await logger.critical(msg, *args, **kwargs)`
515
+ - `await logger.exception(msg, *args, **kwargs)`
516
+
517
+ ### Handler Classes
518
+
519
+ - `AsyncHandler` - Base async handler
520
+ - `AsyncStreamHandler` - Stream output handler
521
+ - `AsyncFileHandler` - File output handler (requires aiofiles)
522
+ - `AsyncRotatingFileHandler` - Size-based rotation (requires aiofiles)
523
+ - `AsyncTimedRotatingFileHandler` - Time-based rotation (requires aiofiles)
524
+ - `AsyncHttpHandler` - Universal HTTP handler (requires aiohttp)
525
+ - `AsyncHttpTextHandler` - Plain text HTTP handler (requires aiohttp)
526
+ - `AsyncHttpJsonHandler` - JSON HTTP handler (requires aiohttp)
527
+ - `AsyncHttpProtoHandler` - Protobuf HTTP handler (requires aiohttp, protobuf)
528
+
529
+ ### Configuration Classes
530
+
531
+ - `BatchConfig` - Batch processing configuration
532
+ - `FileConfig` - File handler configuration
533
+ - `HttpConfig` - HTTP handler configuration
534
+ - `LoggerConfig` - Logger configuration
535
+ - `RotationConfig` - Rotation configuration for file handlers
536
+
537
+ ### Exception Classes
538
+
539
+ - `AiologgingError` - Base exception for all aiologging errors
540
+ - `HandlerError` - Base exception for handler errors
541
+ - `ConfigurationError` - Configuration-related errors
542
+ - `DependencyError` - Missing optional dependencies
543
+ - `AuthenticationError` - Authentication failures
544
+ - `NetworkError` - Network-related errors
545
+ - `FileError` - File operation errors
546
+ - `RotationError` - File rotation errors
547
+ - `BatchError` - Batch processing errors
548
+ - `FormatterError` - Formatting errors
549
+ - `LoggerError` - Logger operation errors
550
+ - `ContextError` - Context manager errors
551
+
552
+ ## Performance Considerations
553
+
554
+ 1. **Buffering**: Use buffered handlers for high-volume logging
555
+ 2. **Batch Processing**: Configure appropriate batch sizes for HTTP handlers
556
+ 3. **Async I/O**: All I/O operations are non-blocking
557
+ 4. **Resource Management**: Always use context managers for proper cleanup
558
+ 5. **Metrics Collection**: Enable metrics to monitor performance
559
+ 6. **Rate Limiting**: Use rate limiters to prevent log flooding
560
+ 7. **Adaptive Buffering**: Enable adaptive buffering for optimal performance
561
+
562
+ ## Testing
563
+
564
+ ```bash
565
+ # Install development dependencies
566
+ pip install aiologging[dev]
567
+
568
+ # Run tests
569
+ pytest
570
+
571
+ # Run tests with coverage
572
+ pytest --cov=aiologging
573
+
574
+ # Run type checking
575
+ mypy aiologging
576
+ ```
577
+
578
+ ## Contributing
579
+
580
+ 1. Fork the repository
581
+ 2. Create a feature branch
582
+ 3. Add tests for new functionality
583
+ 4. Ensure all tests pass and type checking succeeds
584
+ 5. Submit a pull request
585
+
586
+ ## License
587
+
588
+ MIT License - see LICENSE file for details.
589
+
590
+ ## Changelog
591
+
592
+ ### 0.1.0
593
+
594
+ - Initial release
595
+ - Full async logging API
596
+ - Stream, file, and HTTP handlers
597
+ - File rotation support
598
+ - Extensible authentication
599
+ - Optional dependencies
600
+ - Strict type checking