lightlogger 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.
@@ -0,0 +1,36 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Set up Python ${{ matrix.python-version }}
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: ${{ matrix.python-version }}
22
+
23
+ - name: Install package with dev extras
24
+ run: pip install -e ".[dev]"
25
+
26
+ - name: Lint with ruff
27
+ run: ruff check src tests
28
+
29
+ - name: Check formatting with ruff
30
+ run: ruff format --check src tests
31
+
32
+ - name: Type check with mypy
33
+ run: mypy src/lightlogger
34
+
35
+ - name: Run tests with coverage
36
+ run: pytest -v --cov=lightlogger --cov-report=term-missing
@@ -0,0 +1,44 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ build:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+
13
+ - name: Set up Python
14
+ uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.12"
17
+
18
+ - name: Install build tool
19
+ run: pip install build
20
+
21
+ - name: Build sdist and wheel
22
+ run: python -m build
23
+
24
+ - name: Upload build artifacts
25
+ uses: actions/upload-artifact@v4
26
+ with:
27
+ name: dist
28
+ path: dist/
29
+
30
+ publish:
31
+ needs: build
32
+ runs-on: ubuntu-latest
33
+ environment: pypi
34
+ permissions:
35
+ id-token: write
36
+ steps:
37
+ - name: Download build artifacts
38
+ uses: actions/download-artifact@v4
39
+ with:
40
+ name: dist
41
+ path: dist/
42
+
43
+ - name: Publish to PyPI
44
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,27 @@
1
+ # Byte-compiled / cache
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.pyo
5
+
6
+ # Distribution / packaging
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ .eggs/
11
+
12
+ # Virtual environments
13
+ .venv/
14
+ venv/
15
+ env/
16
+
17
+ # Testing / type-checking / linting caches
18
+ .pytest_cache/
19
+ .mypy_cache/
20
+ .ruff_cache/
21
+ .coverage
22
+ htmlcov/
23
+
24
+ # Editors / OS
25
+ .vscode/
26
+ .idea/
27
+ .DS_Store
@@ -0,0 +1,7 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.6.9
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
@@ -0,0 +1,32 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Ideas (post-v1, not in scope for now)
11
+
12
+ - Multiple UI layouts / themes beyond dark mode
13
+ - AI-assisted log summarization
14
+ - Auth/login for the dashboard
15
+ - Flask/Django/FastAPI middleware integrations
16
+ - Node.js port
17
+
18
+ ## [0.1.0] - 2026-09-09
19
+
20
+ Initial release.
21
+
22
+ ### Added
23
+
24
+ - `lightlogger.start()` / `stop()` — a `ThreadingHTTPServer` on a daemon thread, binding `127.0.0.1:4356` by default with automatic port fallback on conflict; `host="0.0.0.0"` is an explicit, loudly-warned opt-in.
25
+ - `debug()` / `info()` / `warn()` / `error()` / `var()` / `request()` — write into a bounded in-memory ring buffer (`max_logs`, default 5000), with caller file/line captured via `sys._getframe` (never `inspect.stack()`).
26
+ - `lightlogger.group(name)` — a context manager for nested log grouping, backed by `contextvars` for thread/async safety.
27
+ - Zero-code `logging` capture: `start(capture_logging=True)` (the default) attaches a handler to the root logger, so existing and third-party `logging` calls appear automatically.
28
+ - Live dashboard UI (`GET /`, single self-contained HTML file, no CDN): dark theme, level-colored rows, search box, level filter, pause/resume with no dropped records, click-to-expand detail panels, download-as-JSON, a collapsible group tree with per-group counts and a worst-level badge.
29
+ - `GET /api/logs` (JSON backlog), `GET /api/stream` (Server-Sent Events, replacing polling), `POST /api/clear`.
30
+ - `open_browser=True` opens the dashboard automatically on `start()`.
31
+ - `lightlogger.help()` prints a full API cheatsheet to the terminal; `GET /help` serves the same reference as an offline HTML page, linked from the dashboard header.
32
+ - 100% test coverage, `mypy --strict` clean, CI across Python 3.9–3.13, PyPI publishing via Trusted Publishing (OIDC) — no long-lived API token ever stored.
@@ -0,0 +1,219 @@
1
+ # CLAUDE.md — Developer Brief for "lightlogger"
2
+
3
+ You (Claude Code) are the developer of this project. The owner is a solo student developer building this part-time. Follow this brief exactly. When in doubt, choose the simpler option.
4
+
5
+ > **Naming note:** the product was originally conceived as "lightlog" but that name is taken on PyPI. The distribution/import name is **`lightlogger`** everywhere below (PyPI verified free on 2026-09-09).
6
+
7
+ > **Scope amendment (post-Phase 6, 2026-09-09):** log grouping (`lightlogger.group(name)`) was added to the frozen v1 API as **Phase 6.5**, before Phase 7. This is a deliberate exception to golden rule "exactly this, nothing more" — the owner evaluated it as a real differentiator (no competing zero-dep local dashboard has nested log grouping) rather than scope creep, and chose to formalize it here rather than build it as an undocumented add-on. See the new API entry in section 5, the amended record structure in section 3, section 6.5, and Phase 6.5 in section 7.
8
+
9
+ ---
10
+
11
+ ## 1. WHAT WE ARE BUILDING
12
+
13
+ **lightlogger** — a zero-dependency Python library that gives developers a live web dashboard for their application logs.
14
+
15
+ Developer experience (this is sacred, never break it):
16
+
17
+ ```python
18
+ pip install lightlogger
19
+ ```
20
+
21
+ ```python
22
+ import lightlogger
23
+ lightlogger.start() # UI now live at http://127.0.0.1:4356
24
+ lightlogger.info("user logged in")
25
+ lightlogger.error("payment failed", data={"order_id": 123})
26
+ lightlogger.var("cart", cart_dict) # expandable JSON in UI
27
+ ```
28
+
29
+ Two lines to a live, beautiful, dark-theme log dashboard in the browser. Zero config. Zero third-party dependencies. That is the entire product.
30
+
31
+ **Why this wins (from competitive research):** No existing package does "import → background thread → live localhost web UI, zero config, zero deps." Logdy is a Go binary, Chronologer needs a separate server, cutelog needs PyQt, Logfire is closed-source cloud, lnav/klp are terminal-only, Django/Flask debug toolbars are framework-locked. Our moat = developer experience + zero dependencies + in-process capture.
32
+
33
+ ---
34
+
35
+ ## 2. GOLDEN RULES (NEVER VIOLATE)
36
+
37
+ 1. **ZERO third-party dependencies.** Python standard library ONLY. `dependencies = []` in pyproject.toml stays empty forever. If you ever feel you need a package — you don't; find the stdlib way.
38
+ 2. **Bind to `127.0.0.1` ONLY.** Never `0.0.0.0`. LAN exposure must be an explicit opt-in parameter (`host="0.0.0.0"`) that prints a loud warning when used. Logs are sensitive data.
39
+ 3. **Bounded memory.** All logs live in `collections.deque(maxlen=5000)` (configurable). The tool must NEVER be the reason a user's app runs out of RAM.
40
+ 4. **Never block the user's app.** Server runs in a daemon thread. Logging calls must return in microseconds. No disk I/O in the logging hot path.
41
+ 5. **Off unless started.** Nothing runs until the user calls `lightlogger.start()`. Document clearly: do not run in production.
42
+ 6. **Simple > clever.** Vanilla HTML/JS/CSS in ONE file for the UI. No React, no build step, no npm anywhere in v1.
43
+
44
+ ---
45
+
46
+ ## 3. HARD TECHNICAL REQUIREMENTS (from research)
47
+
48
+ ### Server
49
+ - Use `http.server.ThreadingHTTPServer` (NOT plain `HTTPServer` — SSE holds connections open and would block a single-threaded server).
50
+ - Subclass with `daemon_threads = True` and `allow_reuse_address = True`.
51
+ - Run `serve_forever()` inside `threading.Thread(daemon=True)`.
52
+ - Provide `lightlogger.stop()` → calls `httpd.shutdown()` + `server_close()` (needed for tests/notebooks).
53
+ - Port: default 4356. On `OSError` (port busy), auto-increment to next free port. Always print the final URL to stdout: `lightlogger UI → http://127.0.0.1:4356`.
54
+
55
+ ### Live streaming (SSE, not websockets)
56
+ - Endpoint `/api/stream` responds with headers: `Content-Type: text/event-stream`, `Cache-Control: no-cache`, `Connection: keep-alive`.
57
+ - Each event: `data: <json>\n\n` (double newline is mandatory).
58
+ - Send `retry: 3000` at connection start and a heartbeat comment line (`: ping\n\n`) every ~15s.
59
+ - Fan-out pattern: each connected client gets its own `queue.Queue`. New log records get pushed to every client queue. Guard the client-queue set with `threading.Lock`.
60
+ - Browser side is simply `new EventSource('/api/stream')`.
61
+
62
+ ### Ring buffer
63
+ - `collections.deque(maxlen=N)`. `append()` is atomic in CPython, but take a lock when ITERATING (serving backlog to a new client).
64
+
65
+ ### Caller file/line capture — PERFORMANCE CRITICAL
66
+ - **NEVER use `inspect.stack()`** — it reads source files from disk on every call. Forbidden in the hot path.
67
+ - Use the stdlib logging approach: `sys._getframe()` / walk `frame.f_back`, read `frame.f_code.co_filename` and `frame.f_lineno`. Cheap attribute reads, no I/O.
68
+
69
+ ### stdlib logging integration (killer feature — must have in v1)
70
+ - Ship `LightloggerHandler(logging.Handler)` whose `emit(record)` pushes into the buffer + SSE queues.
71
+ - `lightlogger.start(capture_logging=True)` attaches it to the root logger → user's EXISTING `logging` calls and even third-party library logs appear in the UI with zero code changes.
72
+ - Record structure (amended in Phase 6.5): `{time, level, message, data, file, line, logger_name, group_id, parent_group_id}`. `group_id`/`parent_group_id` are always-present keys (never omitted), typed `str | None` — every field defaults to `None` for code untouched by `group()`, so this is a value-level amendment, not a structural one. No `typing.NotRequired`/`typing_extensions` — that would violate zero-dependency on Python 3.9/3.10, where `NotRequired` doesn't exist in stdlib `typing`.
73
+
74
+ ### Log grouping (`lightlogger.group(name)`) — Phase 6.5
75
+ - A context manager: `with lightlogger.group("process_order #123"): ...`. On enter, emits one group-marker record immediately (so even an empty group is visible); on exit, restores the previous group context. Nesting supported (a `group()` inside a `group()`).
76
+ - A group-marker record is just a normal `LogRecord` with `group_id` set to a fresh id (e.g. `uuid.uuid4().hex`) and `message` set to the group's display name. Every OTHER record (marker or plain log) gets `parent_group_id` set to whatever group directly contains it (`None` if top-level) — this is how nesting and containment are reconstructed client-side, by walking `parent_group_id` chains.
77
+ - Thread/async safety via `contextvars.ContextVar` (stdlib) holding "the current group id" — NOT a plain module global, which would leak across threads. Each thread that doesn't explicitly share context gets its own independent value; each asyncio `Task` gets its own copy at creation. This is what makes concurrent, non-interleaving grouping possible without extra locking.
78
+ - Group-marker records stream over `/api/stream` and appear in `/api/logs` exactly like any other record — no special-casing needed in `buffer.py`/`server.py`, since `LogBuffer.add()` already treats every record uniformly.
79
+
80
+ ### Packaging the UI
81
+ - One file: `src/lightlogger/static/index.html` (HTML + CSS + JS inline).
82
+ - Read it at runtime with `importlib.resources.files("lightlogger") / "static" / "index.html"` — NEVER build paths from `__file__`.
83
+
84
+ ---
85
+
86
+ ## 4. FOLDER STRUCTURE (create exactly this — src layout)
87
+
88
+ ```
89
+ lightlog/ # workspace/repo root (kept as-is on disk)
90
+ ├── src/
91
+ │ └── lightlogger/ # actual PyPI distribution + import name
92
+ │ ├── __init__.py # public API: start, stop, info, warn, error, debug, var, request
93
+ │ ├── server.py # ThreadingHTTPServer + daemon thread + routes
94
+ │ ├── handler.py # LightloggerHandler (logging.Handler subclass)
95
+ │ ├── buffer.py # ring buffer + SSE client fan-out
96
+ │ ├── sse.py # SSE framing helpers
97
+ │ ├── py.typed # empty PEP 561 marker
98
+ │ └── static/
99
+ │ └── index.html # entire UI, single file
100
+ ├── tests/
101
+ │ ├── test_buffer.py
102
+ │ ├── test_handler.py
103
+ │ └── test_server.py
104
+ ├── .github/workflows/
105
+ │ ├── ci.yml # ruff + pytest, matrix Python 3.9–3.13
106
+ │ └── publish.yml # PyPI Trusted Publishing on GitHub Release
107
+ ├── assets/
108
+ │ └── demo.gif # README demo (added later)
109
+ ├── pyproject.toml # PEP 621
110
+ ├── README.md
111
+ ├── CHANGELOG.md # Keep a Changelog format
112
+ ├── CONTRIBUTING.md
113
+ ├── LICENSE # MIT
114
+ ├── .pre-commit-config.yaml # ruff lint + format
115
+ └── .gitignore
116
+ ```
117
+
118
+ ### pyproject.toml requirements
119
+ - Build backend: **Hatchling** (auto-detects src layout, includes package data).
120
+ - `[project]`: name `lightlogger`, version `0.1.0`, `requires-python = ">=3.9"`, description, readme, MIT license, classifiers, urls.
121
+ - `dependencies = []` — EMPTY, forever.
122
+ - `[project.optional-dependencies] dev = ["pytest", "ruff", "mypy"]`.
123
+ - Tool configs in same file: `[tool.pytest.ini_options]`, `[tool.ruff]`, `[tool.mypy]` (strict).
124
+ - Semantic Versioning. Full type hints everywhere + `py.typed`.
125
+
126
+ ### Publishing
127
+ - PyPI **Trusted Publishing (OIDC)** via `pypa/gh-action-pypi-publish` with `permissions: id-token: write`. **NEVER store a long-lived PyPI API token as a GitHub secret** (this exact mistake caused the LiteLLM supply-chain attack, March 2026).
128
+ - Name "lightlogger" confirmed free on PyPI (checked 2026-09-09).
129
+
130
+ ---
131
+
132
+ ## 5. PUBLIC API (v1 — exactly this, nothing more)
133
+
134
+ ```python
135
+ lightlogger.start(port=4356, host="127.0.0.1", max_logs=5000, capture_logging=True, open_browser=False)
136
+ lightlogger.stop()
137
+ lightlogger.debug(msg, data=None)
138
+ lightlogger.info(msg, data=None)
139
+ lightlogger.warn(msg, data=None)
140
+ lightlogger.error(msg, data=None)
141
+ lightlogger.var(name, value) # logs any variable as expandable JSON
142
+ lightlogger.request(method, url, status, duration_ms) # API/request logging
143
+ lightlogger.group(name) # context manager; nested groups supported (Phase 6.5)
144
+ ```
145
+
146
+ HTTP routes: `/` (UI), `/api/logs` (JSON backlog), `/api/stream` (SSE), `/api/clear` (POST, clears buffer).
147
+
148
+ `data`/`value` serialization: `json.dumps(..., default=str)` so any object works without crashing.
149
+
150
+ ---
151
+
152
+ ## 6. UI REQUIREMENTS (single index.html)
153
+
154
+ Must have in v1: dark theme (default), color-coded levels (debug grey, info blue, warn yellow, error red), live auto-scroll with **pause** button, **clear logs** button (calls /api/clear), search box (client-side filter), level filter dropdown, click row → expand full details (file:line, logger, pretty JSON data), download logs as .json button, connection status dot (connected/reconnecting), log counter.
155
+
156
+ Style: clean, modern, monospace font for messages, subtle borders, feels like a premium dev tool. No external fonts/CDNs (zero network deps — must work offline).
157
+
158
+ ## 6.5. UI REQUIREMENTS — log grouping (Phase 6.5)
159
+
160
+ - A group-marker record renders as a collapsible header row, not a normal log line: chevron/dropdown icon (inline SVG, no icon fonts, no CDN — same offline constraint as everything else), group name, child count, and a "worst-level" hint (e.g. a red tint/badge if any descendant is `error`-level) — computed client-side by walking descendants, no new server logic needed.
161
+ - Nested groups indent their children (mirrors the browser DevTools `console.group`/`console.groupEnd` UX — a familiar reference point, not an arbitrary accordion pattern). Chevron rotates on toggle — this is user-triggered motion answering a click, not ambient decoration, so it's fine alongside the existing single ambient motion moment (the reconnecting-dot pulse from Phase 6).
162
+ - Collapsed by default. Toolbar gains expand-all / collapse-all buttons.
163
+ - Search/filter must work across grouped records: a match on a nested record auto-expands its ancestor chain so the match is visible; a group the user manually expanded/collapsed keeps that state once the search is cleared (search-driven expansion doesn't overwrite a person's own manual choice).
164
+ - Visual theme gets richer/more colorful for this phase specifically — level colors (debug/info/warn/error) stay meaningful and unchanged, but group-related chrome (headers, chevrons, badges) can use more vivid accents than Phase 6's restrained palette, as a deliberate one-time exception to "keep it restrained."
165
+ - Still one file, no CDN, fully offline, zero third-party dependencies.
166
+
167
+ ---
168
+
169
+ ## 7. BUILD PHASES (do IN ORDER, one phase per session, test before moving on)
170
+
171
+ - **Phase 0:** Scaffold repo (structure above), pyproject.toml, LICENSE, ruff, pre-commit, empty CI. Verify `pip install -e .` works.
172
+ - **Phase 1:** buffer.py + logger functions writing to deque. Unit tests. No server yet.
173
+ - **Phase 2:** server.py — daemon thread, `/api/logs` returns JSON. Milestone: see JSON in browser.
174
+ - **Phase 3:** Basic index.html — polls `/api/logs` every 2s, renders list. Ugly is fine.
175
+ - **Phase 4:** SSE — `/api/stream`, EventSource, live updates, heartbeat, reconnect. Remove polling.
176
+ - **Phase 5:** LightloggerHandler + `capture_logging` + file/line capture via `sys._getframe`.
177
+ - **Phase 6:** Full UI polish — search, filters, pause, clear, expand, download, status dot.
178
+ - **Phase 6.5:** Log grouping — `lightlogger.group(name)` context manager (contextvars-based, thread/async-safe, nested), amended record structure, UI collapsible group rows with expand/collapse-all and search-aware auto-expand. Scope amendment, see note at top of this file.
179
+ - **Phase 7:** Tests to ~80% coverage, CI green on 3.9–3.13, mypy strict passes, README + demo GIF, publish 0.1.0 via Trusted Publishing.
180
+
181
+ ---
182
+
183
+ ## 8. DO NOT (explicit bans for v1)
184
+
185
+ - ❌ NO third-party packages (not even in tests beyond pytest/ruff/mypy as dev deps)
186
+ - ❌ NO websockets (SSE only), NO React/Vue/build tools/npm, NO CDN links in the UI
187
+ - ❌ NO database, NO writing logs to disk
188
+ - ❌ NO `inspect.stack()` in the logging path
189
+ - ❌ NO `0.0.0.0` default binding
190
+ - ❌ NO multiple layouts, NO AI features, NO auth/login, NO Flask/Django/FastAPI middleware, NO Node.js port — these are ALL post-v1. If tempted, add a note to CHANGELOG "Unreleased/Ideas" instead of building.
191
+ - ❌ NO flat layout — src layout only
192
+ - ❌ NO committing secrets/tokens ever
193
+
194
+ ---
195
+
196
+ ## 9. README (write at Phase 7 — it's our landing page)
197
+
198
+ Order: name + one-liner → badges (PyPI, CI, license, Python versions) → **demo GIF** (before any scrolling — the single biggest factor for stars) → install + 2-line quickstart within first 200 words → features table → "Why lightlogger" (problem story) → contributing invite → MIT.
199
+
200
+ One-liner: "Live web dashboard for your Python logs — pip install, add one line, open localhost:4356. Zero dependencies."
201
+
202
+ Length 500–1500 words. GIF: <15s, ~640px, <8MB, stored in /assets. Add a security note: localhost-only by default, not for production.
203
+
204
+ ---
205
+
206
+ ## 10. DEFINITION OF DONE (v1)
207
+
208
+ - [ ] `pip install lightlogger` + 2 lines → working live UI
209
+ - [ ] Zero runtime dependencies (verify: fresh venv, install, run)
210
+ - [ ] Existing `logging` calls appear in UI automatically
211
+ - [ ] RAM bounded (deque maxlen honored under log flood)
212
+ - [ ] Binds 127.0.0.1 only by default; warning on override
213
+ - [ ] Search/filter/pause/clear/expand/download all work
214
+ - [ ] `lightlogger.group()` nests correctly and stays isolated across concurrent threads
215
+ - [ ] Survives: port conflict, browser refresh, SSE reconnect, `stop()` + `start()` again
216
+ - [ ] Tests pass 3.9–3.13, mypy strict clean, ruff clean
217
+ - [ ] README with GIF, CHANGELOG, published on PyPI via Trusted Publishing
218
+
219
+ Owner's context: this project is also his portfolio piece for LinkedIn/recruiters — so code quality, comments, commit messages, and docs must look professional throughout. Write commit messages in conventional style (`feat:`, `fix:`, `docs:`).
@@ -0,0 +1,34 @@
1
+ # Contributing to lightlogger
2
+
3
+ Thanks for considering a contribution! This project intentionally stays small and dependency-free — please read the ground rules before opening a PR.
4
+
5
+ ## Ground rules
6
+
7
+ - **Zero third-party runtime dependencies.** Standard library only. Dev-only tools (`pytest`, `ruff`, `mypy`) are the sole exception.
8
+ - **Binds to `127.0.0.1` by default.** Any change touching networking must preserve this.
9
+ - **No `inspect.stack()`** in the logging hot path — use `sys._getframe()`.
10
+ - **Vanilla HTML/CSS/JS** for the dashboard UI — no frameworks, no build step, no CDN links.
11
+
12
+ ## Setup
13
+
14
+ ```bash
15
+ git clone https://github.com/Rahuwale123/lightlogger.git
16
+ cd lightlogger
17
+ python -m venv .venv
18
+ source .venv/bin/activate
19
+ pip install -e ".[dev]"
20
+ pre-commit install
21
+ ```
22
+
23
+ ## Before opening a PR
24
+
25
+ ```bash
26
+ ruff check .
27
+ ruff format --check .
28
+ mypy src/lightlogger
29
+ pytest
30
+ ```
31
+
32
+ ## Commit style
33
+
34
+ This repo uses [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, `docs:`, `test:`, `chore:`, ...).
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 rahul wale
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,122 @@
1
+ Metadata-Version: 2.5
2
+ Name: lightlogger
3
+ Version: 0.1.0
4
+ Summary: Live web dashboard for your Python logs — one line of code, zero dependencies
5
+ Project-URL: Homepage, https://github.com/Rahuwale123/lightlogger
6
+ Project-URL: Repository, https://github.com/Rahuwale123/lightlogger
7
+ Project-URL: Changelog, https://github.com/Rahuwale123/lightlogger/blob/main/CHANGELOG.md
8
+ Author-email: rahul wale <fthedrive@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: dashboard,debugging,developer-tools,logging,logs,sse
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Software Development :: Debuggers
23
+ Classifier: Topic :: System :: Logging
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.9
26
+ Provides-Extra: dev
27
+ Requires-Dist: mypy; extra == 'dev'
28
+ Requires-Dist: pytest; extra == 'dev'
29
+ Requires-Dist: pytest-cov; extra == 'dev'
30
+ Requires-Dist: ruff; extra == 'dev'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # lightlogger
34
+
35
+ Live web dashboard for your Python logs — pip install, add one line, open localhost:4356. Zero dependencies.
36
+
37
+ [![PyPI](https://img.shields.io/pypi/v/lightlogger.svg)](https://pypi.org/project/lightlogger/)
38
+ [![CI](https://github.com/Rahuwale123/lightlogger/actions/workflows/ci.yml/badge.svg)](https://github.com/Rahuwale123/lightlogger/actions/workflows/ci.yml)
39
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
40
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue.svg)](pyproject.toml)
41
+
42
+ ![lightlogger dashboard: a nested process_order group with a warning badge, a live error, and streaming request logs](https://raw.githubusercontent.com/Rahuwale123/lightlogger/main/assets/demo.gif)
43
+
44
+ ## Install
45
+
46
+ ```bash
47
+ pip install lightlogger
48
+ ```
49
+
50
+ ```python
51
+ import lightlogger
52
+ lightlogger.start()
53
+ lightlogger.info("user logged in")
54
+ ```
55
+
56
+ That's it — open `http://127.0.0.1:4356` and watch it stream in live, in a dark, searchable dashboard. No config file, no separate server process to run, no npm install.
57
+
58
+ Your existing `logging` calls show up too, with zero code changes:
59
+
60
+ ```python
61
+ lightlogger.start(capture_logging=True) # the default
62
+ import logging
63
+ logging.getLogger("some.third.party.lib").warning("disk almost full") # appears in the UI automatically
64
+ ```
65
+
66
+ And when one log message is really four related operations, group them:
67
+
68
+ ```python
69
+ with lightlogger.group("process_order #4821"):
70
+ lightlogger.info("validating cart")
71
+ lightlogger.info("charging payment", data={"amount": 49.99})
72
+ with lightlogger.group("send_notifications"):
73
+ lightlogger.info("email sent")
74
+ lightlogger.info("sms sent")
75
+ ```
76
+
77
+ They render as a collapsible tree — click to expand, nested groups indent, a red badge appears if anything inside failed.
78
+
79
+ ## Features
80
+
81
+ | | |
82
+ |---|---|
83
+ | **Live streaming** | Server-Sent Events, not polling — logs appear the instant they're written |
84
+ | **Zero-code `logging` capture** | Attaches to the root logger; your own and third-party libraries' logs show up automatically |
85
+ | **Nested log grouping** | `with lightlogger.group(name):` — collapsible, nested, thread- and async-safe |
86
+ | **Search & level filter** | Client-side, instant, works across grouped and ungrouped logs alike |
87
+ | **Pause / Resume** | Freeze the view to read something — nothing is dropped, a counter shows what's waiting |
88
+ | **Click to expand** | File, line, logger name, and pretty-printed JSON data for any entry |
89
+ | **Download as JSON** | One click, the full current backlog |
90
+ | **Bounded memory** | A fixed-size ring buffer — lightlogger can never be the reason your app runs out of RAM |
91
+ | **Zero dependencies** | Python standard library only, from the HTTP server to the JSON encoding |
92
+
93
+ ## Built-in help
94
+
95
+ Forgot the API? It's in the package, not just this README:
96
+
97
+ ```python
98
+ >>> import lightlogger
99
+ >>> lightlogger.help()
100
+ ```
101
+
102
+ Prints a full cheatsheet to your terminal — every function, one-line descriptions, tiny examples, the `capture_logging` gotcha, no need to leave your shell. And once the dashboard is running, open `http://127.0.0.1:4356/help` for the same reference as a page, with copyable code blocks.
103
+
104
+ ## Why lightlogger
105
+
106
+ Debugging a running Python process usually means one of three things: `print()` statements you'll forget to remove, a terminal window full of scrolling text you can't search, or reaching for a heavyweight observability platform to answer a question that takes ten seconds to answer once you can actually *see* your logs.
107
+
108
+ We looked at what else exists. [Logdy](https://logdy.dev/) is a Go binary you install separately from your app. [Chronologer](https://github.com/nkconnor/chronologer) needs its own server process. [cutelog](https://github.com/busimus/cutelog) needs PyQt. Logfire is closed-source and cloud-hosted. `lnav` and `klp` are terminal-only. Django and Flask debug toolbars only work inside those specific frameworks, in that specific request/response cycle.
109
+
110
+ None of them do the one thing that actually matches how a Python developer debugs: `import`, call one function, and get a live web page — from *inside* the process you're already running, with no extra install, no extra service, no dependencies to audit. That's the gap lightlogger fills. And once your logs have a real UI instead of a scrolling terminal, grouping related operations into a collapsible tree stops being a nice-to-have — it's the difference between reading a wall of text and reading a story.
111
+
112
+ ## Security
113
+
114
+ lightlogger binds to `127.0.0.1` only, by default — nothing is reachable outside your machine unless you explicitly pass `host="0.0.0.0"` (which prints a loud warning when you do). It's a local development tool, not a production observability system: don't run it against a public-facing process, and don't leave it running longer than your debugging session needs.
115
+
116
+ ## Contributing
117
+
118
+ Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for the ground rules (short version: zero dependencies, stay on stdlib, keep it simple). Bug reports and PRs both go through [GitHub Issues](https://github.com/Rahuwale123/lightlogger/issues).
119
+
120
+ ## License
121
+
122
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,90 @@
1
+ # lightlogger
2
+
3
+ Live web dashboard for your Python logs — pip install, add one line, open localhost:4356. Zero dependencies.
4
+
5
+ [![PyPI](https://img.shields.io/pypi/v/lightlogger.svg)](https://pypi.org/project/lightlogger/)
6
+ [![CI](https://github.com/Rahuwale123/lightlogger/actions/workflows/ci.yml/badge.svg)](https://github.com/Rahuwale123/lightlogger/actions/workflows/ci.yml)
7
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
8
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue.svg)](pyproject.toml)
9
+
10
+ ![lightlogger dashboard: a nested process_order group with a warning badge, a live error, and streaming request logs](https://raw.githubusercontent.com/Rahuwale123/lightlogger/main/assets/demo.gif)
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ pip install lightlogger
16
+ ```
17
+
18
+ ```python
19
+ import lightlogger
20
+ lightlogger.start()
21
+ lightlogger.info("user logged in")
22
+ ```
23
+
24
+ That's it — open `http://127.0.0.1:4356` and watch it stream in live, in a dark, searchable dashboard. No config file, no separate server process to run, no npm install.
25
+
26
+ Your existing `logging` calls show up too, with zero code changes:
27
+
28
+ ```python
29
+ lightlogger.start(capture_logging=True) # the default
30
+ import logging
31
+ logging.getLogger("some.third.party.lib").warning("disk almost full") # appears in the UI automatically
32
+ ```
33
+
34
+ And when one log message is really four related operations, group them:
35
+
36
+ ```python
37
+ with lightlogger.group("process_order #4821"):
38
+ lightlogger.info("validating cart")
39
+ lightlogger.info("charging payment", data={"amount": 49.99})
40
+ with lightlogger.group("send_notifications"):
41
+ lightlogger.info("email sent")
42
+ lightlogger.info("sms sent")
43
+ ```
44
+
45
+ They render as a collapsible tree — click to expand, nested groups indent, a red badge appears if anything inside failed.
46
+
47
+ ## Features
48
+
49
+ | | |
50
+ |---|---|
51
+ | **Live streaming** | Server-Sent Events, not polling — logs appear the instant they're written |
52
+ | **Zero-code `logging` capture** | Attaches to the root logger; your own and third-party libraries' logs show up automatically |
53
+ | **Nested log grouping** | `with lightlogger.group(name):` — collapsible, nested, thread- and async-safe |
54
+ | **Search & level filter** | Client-side, instant, works across grouped and ungrouped logs alike |
55
+ | **Pause / Resume** | Freeze the view to read something — nothing is dropped, a counter shows what's waiting |
56
+ | **Click to expand** | File, line, logger name, and pretty-printed JSON data for any entry |
57
+ | **Download as JSON** | One click, the full current backlog |
58
+ | **Bounded memory** | A fixed-size ring buffer — lightlogger can never be the reason your app runs out of RAM |
59
+ | **Zero dependencies** | Python standard library only, from the HTTP server to the JSON encoding |
60
+
61
+ ## Built-in help
62
+
63
+ Forgot the API? It's in the package, not just this README:
64
+
65
+ ```python
66
+ >>> import lightlogger
67
+ >>> lightlogger.help()
68
+ ```
69
+
70
+ Prints a full cheatsheet to your terminal — every function, one-line descriptions, tiny examples, the `capture_logging` gotcha, no need to leave your shell. And once the dashboard is running, open `http://127.0.0.1:4356/help` for the same reference as a page, with copyable code blocks.
71
+
72
+ ## Why lightlogger
73
+
74
+ Debugging a running Python process usually means one of three things: `print()` statements you'll forget to remove, a terminal window full of scrolling text you can't search, or reaching for a heavyweight observability platform to answer a question that takes ten seconds to answer once you can actually *see* your logs.
75
+
76
+ We looked at what else exists. [Logdy](https://logdy.dev/) is a Go binary you install separately from your app. [Chronologer](https://github.com/nkconnor/chronologer) needs its own server process. [cutelog](https://github.com/busimus/cutelog) needs PyQt. Logfire is closed-source and cloud-hosted. `lnav` and `klp` are terminal-only. Django and Flask debug toolbars only work inside those specific frameworks, in that specific request/response cycle.
77
+
78
+ None of them do the one thing that actually matches how a Python developer debugs: `import`, call one function, and get a live web page — from *inside* the process you're already running, with no extra install, no extra service, no dependencies to audit. That's the gap lightlogger fills. And once your logs have a real UI instead of a scrolling terminal, grouping related operations into a collapsible tree stops being a nice-to-have — it's the difference between reading a wall of text and reading a story.
79
+
80
+ ## Security
81
+
82
+ lightlogger binds to `127.0.0.1` only, by default — nothing is reachable outside your machine unless you explicitly pass `host="0.0.0.0"` (which prints a loud warning when you do). It's a local development tool, not a production observability system: don't run it against a public-facing process, and don't leave it running longer than your debugging session needs.
83
+
84
+ ## Contributing
85
+
86
+ Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for the ground rules (short version: zero dependencies, stay on stdlib, keep it simple). Bug reports and PRs both go through [GitHub Issues](https://github.com/Rahuwale123/lightlogger/issues).
87
+
88
+ ## License
89
+
90
+ MIT — see [LICENSE](LICENSE).