bufferlog 0.1.0__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.
- bufferlog/__init__.py +170 -0
- bufferlog/adapters/__init__.py +7 -0
- bufferlog/adapters/base.py +16 -0
- bufferlog/adapters/datadog.py +58 -0
- bufferlog/adapters/splunk.py +55 -0
- bufferlog/adapters/stdout.py +25 -0
- bufferlog/buffer_manager.py +85 -0
- bufferlog/config.py +47 -0
- bufferlog/context.py +47 -0
- bufferlog/control_plane/__init__.py +1 -0
- bufferlog/control_plane/policy_fetcher.py +112 -0
- bufferlog/control_plane/telemetry_reporter.py +118 -0
- bufferlog/flash_controller.py +78 -0
- bufferlog/integrations/__init__.py +82 -0
- bufferlog/log_event.py +50 -0
- bufferlog/middleware/__init__.py +1 -0
- bufferlog/middleware/django_mw.py +85 -0
- bufferlog/middleware/fastapi_mw.py +92 -0
- bufferlog/middleware/flask_mw.py +71 -0
- bufferlog/ring_buffer.py +94 -0
- bufferlog-0.1.0.dist-info/METADATA +219 -0
- bufferlog-0.1.0.dist-info/RECORD +24 -0
- bufferlog-0.1.0.dist-info/WHEEL +5 -0
- bufferlog-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bufferlog
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: BufferLog — Buffer logs in memory, flush only on errors. Save 90%+ on APM costs.
|
|
5
|
+
Author: BufferLog.io
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/lehan0328/bufferlog
|
|
8
|
+
Project-URL: Repository, https://github.com/lehan0328/bufferlog
|
|
9
|
+
Project-URL: Issues, https://github.com/lehan0328/bufferlog/issues
|
|
10
|
+
Keywords: logging,apm,buffer,datadog,splunk,observability,cost-reduction
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: System :: Logging
|
|
20
|
+
Requires-Python: >=3.9
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Provides-Extra: flask
|
|
23
|
+
Requires-Dist: flask>=2.0; extra == "flask"
|
|
24
|
+
Provides-Extra: fastapi
|
|
25
|
+
Requires-Dist: fastapi>=0.100; extra == "fastapi"
|
|
26
|
+
Requires-Dist: starlette>=0.27; extra == "fastapi"
|
|
27
|
+
Provides-Extra: django
|
|
28
|
+
Requires-Dist: django>=4.0; extra == "django"
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
|
|
32
|
+
Requires-Dist: flask>=2.0; extra == "dev"
|
|
33
|
+
Requires-Dist: fastapi>=0.100; extra == "dev"
|
|
34
|
+
Requires-Dist: starlette>=0.27; extra == "dev"
|
|
35
|
+
Requires-Dist: httpx>=0.24; extra == "dev"
|
|
36
|
+
Requires-Dist: uvicorn>=0.20; extra == "dev"
|
|
37
|
+
|
|
38
|
+
# bufferlog
|
|
39
|
+
|
|
40
|
+
Buffer logs in memory per-request. Flush only on errors. Save 90%+ on APM costs.
|
|
41
|
+
|
|
42
|
+
## Table of Contents
|
|
43
|
+
|
|
44
|
+
- [Install](#install)
|
|
45
|
+
- [Usage](#usage)
|
|
46
|
+
- [Flask](#flask)
|
|
47
|
+
- [FastAPI](#fastapi)
|
|
48
|
+
- [Django](#django)
|
|
49
|
+
- [Configuration](#configuration)
|
|
50
|
+
- [Control Plane](#control-plane)
|
|
51
|
+
- [Metrics](#metrics)
|
|
52
|
+
- [Shutdown](#shutdown)
|
|
53
|
+
- [License](#license)
|
|
54
|
+
|
|
55
|
+
## Install
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install bufferlog
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
With framework extras:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install bufferlog[flask]
|
|
65
|
+
pip install bufferlog[fastapi]
|
|
66
|
+
pip install bufferlog[django]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Usage
|
|
70
|
+
|
|
71
|
+
### Flask
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import logging
|
|
75
|
+
from flask import Flask
|
|
76
|
+
from bufferlog import BufferLog
|
|
77
|
+
from bufferlog.adapters import StdOutAdapter
|
|
78
|
+
|
|
79
|
+
app = Flask(__name__)
|
|
80
|
+
bl = BufferLog(adapters=[StdOutAdapter(pretty=True)])
|
|
81
|
+
bl.init_flask(app)
|
|
82
|
+
|
|
83
|
+
logger = logging.getLogger("myapp")
|
|
84
|
+
logger.addHandler(bl.logging_handler())
|
|
85
|
+
logger.setLevel(logging.DEBUG)
|
|
86
|
+
|
|
87
|
+
@app.route("/")
|
|
88
|
+
def index():
|
|
89
|
+
logger.info("Processing request") # Buffered (discarded on 200)
|
|
90
|
+
logger.debug("SQL: SELECT * ...") # Buffered (discarded on 200)
|
|
91
|
+
return "OK" # 200 → logs discarded ($0)
|
|
92
|
+
|
|
93
|
+
@app.route("/fail")
|
|
94
|
+
def fail():
|
|
95
|
+
logger.info("Starting transaction")
|
|
96
|
+
logger.error("Connection lost") # Triggers flush
|
|
97
|
+
return "Error", 500 # 500 → context sent to APM
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### FastAPI
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
import logging
|
|
104
|
+
from fastapi import FastAPI
|
|
105
|
+
from bufferlog import BufferLog
|
|
106
|
+
from bufferlog.adapters import StdOutAdapter
|
|
107
|
+
from bufferlog.middleware.fastapi_mw import BufferLogMiddleware
|
|
108
|
+
|
|
109
|
+
app = FastAPI()
|
|
110
|
+
bl = BufferLog(adapters=[StdOutAdapter()])
|
|
111
|
+
app.add_middleware(BufferLogMiddleware, **bl.asgi_kwargs())
|
|
112
|
+
|
|
113
|
+
logger = logging.getLogger("myapp")
|
|
114
|
+
logger.addHandler(bl.logging_handler())
|
|
115
|
+
logger.setLevel(logging.DEBUG)
|
|
116
|
+
|
|
117
|
+
@app.get("/")
|
|
118
|
+
async def index():
|
|
119
|
+
logger.info("Handling request")
|
|
120
|
+
return {"ok": True}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Django
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
# settings.py
|
|
127
|
+
MIDDLEWARE = [
|
|
128
|
+
"bufferlog.middleware.django_mw.BufferLogDjangoMiddleware",
|
|
129
|
+
# ... other middleware
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
# apps.py or wsgi.py
|
|
133
|
+
from bufferlog import BufferLog
|
|
134
|
+
from bufferlog.adapters import StdOutAdapter
|
|
135
|
+
|
|
136
|
+
bl = BufferLog(adapters=[StdOutAdapter()])
|
|
137
|
+
bl.init_django()
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Configuration
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from bufferlog import BufferLog, BufferLogConfig
|
|
144
|
+
from bufferlog.adapters import DatadogAdapter, SplunkAdapter, StdOutAdapter
|
|
145
|
+
|
|
146
|
+
bl = BufferLog(config=BufferLogConfig(
|
|
147
|
+
# Max logs per request buffer. Oldest overwritten when full.
|
|
148
|
+
buffer_capacity=100,
|
|
149
|
+
|
|
150
|
+
# Log levels that trigger immediate flush.
|
|
151
|
+
flush_on_levels=["error", "critical"],
|
|
152
|
+
|
|
153
|
+
# HTTP status codes that trigger flush.
|
|
154
|
+
flush_on_status_codes=[500, 501, 502, 503, 504],
|
|
155
|
+
|
|
156
|
+
# Downstream targets for flushed logs.
|
|
157
|
+
adapters=[
|
|
158
|
+
DatadogAdapter(api_key="your-key"),
|
|
159
|
+
SplunkAdapter(token="your-token", url="https://splunk.example.com"),
|
|
160
|
+
StdOutAdapter(),
|
|
161
|
+
],
|
|
162
|
+
|
|
163
|
+
# Enable/disable buffering.
|
|
164
|
+
enabled=True,
|
|
165
|
+
|
|
166
|
+
# If True, logs fall through to stderr on adapter failure.
|
|
167
|
+
fail_open=True,
|
|
168
|
+
|
|
169
|
+
# Scrub PII before logs enter the buffer.
|
|
170
|
+
scrubber=lambda msg, meta: (msg.replace("password", "***"), meta),
|
|
171
|
+
))
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Control Plane
|
|
175
|
+
|
|
176
|
+
Connect to the BufferLog Control Plane for remote policy management and usage tracking.
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
from bufferlog import BufferLog, ControlPlaneConfig
|
|
180
|
+
|
|
181
|
+
bl = BufferLog(
|
|
182
|
+
control_plane=ControlPlaneConfig(
|
|
183
|
+
url="https://control.bufferlog.io",
|
|
184
|
+
api_key="bl_sk_your_key",
|
|
185
|
+
poll_interval_s=60,
|
|
186
|
+
telemetry_interval_s=60,
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
When connected:
|
|
192
|
+
- **Poll for policy updates** — buffer capacity, sampling rate, flush triggers, and bypass rules can all be changed remotely.
|
|
193
|
+
- **Push usage metrics** — counters (never log data) are sent to power the ROI dashboard.
|
|
194
|
+
|
|
195
|
+
If the control plane is unreachable, the SDK continues with its last known configuration.
|
|
196
|
+
|
|
197
|
+
## Metrics
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
metrics = bl.get_metrics()
|
|
201
|
+
# {
|
|
202
|
+
# "buffers": {"created": 1000, "discarded": 995, "flushed": 5, "active": 0},
|
|
203
|
+
# "flash": {"flush_count": 5, "events_flushed": 45, "adapter_errors": 0}
|
|
204
|
+
# }
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Shutdown
|
|
208
|
+
|
|
209
|
+
Stop background threads and send a final telemetry report.
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
import atexit
|
|
213
|
+
|
|
214
|
+
atexit.register(bl.shutdown)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## License
|
|
218
|
+
|
|
219
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
bufferlog/__init__.py,sha256=vxExPhcvEmVVdql1FS5cuYsJMvp9GBu4dcxoE6_hspQ,5643
|
|
2
|
+
bufferlog/buffer_manager.py,sha256=IGo1jkJFqrf2zT3EspzGXZIMY6OsETUg0LZfUY2HviA,2738
|
|
3
|
+
bufferlog/config.py,sha256=V0ah8pDRA-KPEfUwgyC3ZhxTjBPo_6euqtLpXrvlus8,1288
|
|
4
|
+
bufferlog/context.py,sha256=kfXTsLG6xILIJpUcg31k0ulrAP4jQyIUe8lbRvjaCuk,1361
|
|
5
|
+
bufferlog/flash_controller.py,sha256=FerOwB-4qKlPNa1lXJtBB07yhVRoFjk47OppKITE0pw,2180
|
|
6
|
+
bufferlog/log_event.py,sha256=JG7l_DKxn7iepTrBUI2FBTypUkUL_TgLsbojai59tPI,1206
|
|
7
|
+
bufferlog/ring_buffer.py,sha256=hMfyLtlYmPfrioBbWjKaElQ3Lx2S9UwPEQFkL8TIsSM,2849
|
|
8
|
+
bufferlog/adapters/__init__.py,sha256=HEPhucFuimbNPZe3sDvZevuh-KmbmfoPGRZawK_DC_U,195
|
|
9
|
+
bufferlog/adapters/base.py,sha256=XOXI4k-O7PBjLyMVWzaRifv4OufKyEUsZdlQhBJqwjk,438
|
|
10
|
+
bufferlog/adapters/datadog.py,sha256=k7TlvbfTjFlGqRIJrGe26Ye7sawB8QZIV8MyKPQKFoo,1681
|
|
11
|
+
bufferlog/adapters/splunk.py,sha256=iujBjgF4nqv1iYuytJCFJUBVIQObWnRfzOsczrjqm1o,1587
|
|
12
|
+
bufferlog/adapters/stdout.py,sha256=jKwPIJx9CbPKiRfoA9ZQgSoRUxpqpusoptpW17VHdi8,714
|
|
13
|
+
bufferlog/control_plane/__init__.py,sha256=_ievQvidVIdygvZRSFwm_5pb2KAdKzbDTaH5pV1yAkU,39
|
|
14
|
+
bufferlog/control_plane/policy_fetcher.py,sha256=VapZQBkPCn0DsYyzHxEbxjvfBmKU8YPrrVDUy5E_63I,3185
|
|
15
|
+
bufferlog/control_plane/telemetry_reporter.py,sha256=Vcneilcficiqb0gEe8ef_QPfTRwDb9P70ZN3wPCR_EY,3256
|
|
16
|
+
bufferlog/integrations/__init__.py,sha256=oKywGBNAEoPiSVRGBxCoq76BEVRf1q1eHqQ2-ZPlTZo,2394
|
|
17
|
+
bufferlog/middleware/__init__.py,sha256=jKaAZI9aHMEFD-6CW0fMJOC70MFXeUCUfGp4J5Cp9cw,36
|
|
18
|
+
bufferlog/middleware/django_mw.py,sha256=q_eYEffK8iWb2rMSCqHw1SUXy0Y-Ymlu_0dnQ_JbwZM,2924
|
|
19
|
+
bufferlog/middleware/fastapi_mw.py,sha256=MRFdb0cWj9khAEESI-qmK3Tk1ejDZUhFFa6S-m0p2mg,3090
|
|
20
|
+
bufferlog/middleware/flask_mw.py,sha256=IYkBjM-2Y6j8f5MEaAUUN9gVXxC28GKGfqjRvKj7cA8,2253
|
|
21
|
+
bufferlog-0.1.0.dist-info/METADATA,sha256=tN5yJ0_WQWZH-FpyEA7axqgrzeScsS_9zA2Kigb7wtk,5751
|
|
22
|
+
bufferlog-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
23
|
+
bufferlog-0.1.0.dist-info/top_level.txt,sha256=gzYBsdusu9nk0_u7pIGk4EXW-akvM1BAi6BQKDH9m78,10
|
|
24
|
+
bufferlog-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
bufferlog
|