simplibs-logger 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.
- simplibs_logger-0.1.0/LICENSE +21 -0
- simplibs_logger-0.1.0/PKG-INFO +508 -0
- simplibs_logger-0.1.0/README.md +474 -0
- simplibs_logger-0.1.0/pyproject.toml +78 -0
- simplibs_logger-0.1.0/setup.cfg +4 -0
- simplibs_logger-0.1.0/src/simplibs/logger/SimpleLogger.py +347 -0
- simplibs_logger-0.1.0/src/simplibs/logger/__init__.py +87 -0
- simplibs_logger-0.1.0/src/simplibs/logger/annotations/BackupCount.py +24 -0
- simplibs_logger-0.1.0/src/simplibs/logger/annotations/LogStream.py +29 -0
- simplibs_logger-0.1.0/src/simplibs/logger/annotations/MaxBytes.py +24 -0
- simplibs_logger-0.1.0/src/simplibs/logger/annotations/__init__.py +20 -0
- simplibs_logger-0.1.0/src/simplibs/logger/annotations/_helpers/__init__.py +19 -0
- simplibs_logger-0.1.0/src/simplibs/logger/annotations/_helpers/is_backup_count.py +25 -0
- simplibs_logger-0.1.0/src/simplibs/logger/annotations/_helpers/is_max_bytes.py +26 -0
- simplibs_logger-0.1.0/src/simplibs/logger/annotations/_helpers/is_writable_stream.py +30 -0
- simplibs_logger-0.1.0/src/simplibs/logger/definitions/DateFormat.py +51 -0
- simplibs_logger-0.1.0/src/simplibs/logger/definitions/LoggerLevel.py +73 -0
- simplibs_logger-0.1.0/src/simplibs/logger/definitions/LoggerName.py +58 -0
- simplibs_logger-0.1.0/src/simplibs/logger/definitions/MessageFormat.py +59 -0
- simplibs_logger-0.1.0/src/simplibs/logger/definitions/OutputFormat.py +38 -0
- simplibs_logger-0.1.0/src/simplibs/logger/definitions/__init__.py +31 -0
- simplibs_logger-0.1.0/src/simplibs/logger/definitions/constants/LEVEL_NAMES.py +36 -0
- simplibs_logger-0.1.0/src/simplibs/logger/definitions/constants/OUTPUT_FORMATS.py +25 -0
- simplibs_logger-0.1.0/src/simplibs/logger/definitions/constants/SUCCESS_LEVEL.py +23 -0
- simplibs_logger-0.1.0/src/simplibs/logger/definitions/constants/__init__.py +19 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/ColoredFormatter.py +97 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/JsonFormatter.py +159 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/__init__.py +21 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/_helpers/__init__.py +24 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/_helpers/collect_extra_fields.py +43 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/_helpers/constants/JSON_KEYS.py +22 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/_helpers/constants/LEVEL_STYLES.py +38 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/_helpers/constants/RECORD_ATTRIBUTES.py +24 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/_helpers/constants/__init__.py +16 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/_helpers/encode_unknown_value.py +69 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/_helpers/format_json_time.py +40 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/_helpers/parse_levelname_field.py +56 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/_helpers/pick_level_style.py +34 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/_helpers/replace_non_finite.py +48 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/_helpers/style_levelname.py +47 -0
- simplibs_logger-0.1.0/src/simplibs/logger/formatting/build_formatter.py +89 -0
- simplibs_logger-0.1.0/src/simplibs/logger/handlers/__init__.py +18 -0
- simplibs_logger-0.1.0/src/simplibs/logger/handlers/_validations/__init__.py +12 -0
- simplibs_logger-0.1.0/src/simplibs/logger/handlers/_validations/raise_log_file_open_error.py +47 -0
- simplibs_logger-0.1.0/src/simplibs/logger/handlers/build_console_handler.py +83 -0
- simplibs_logger-0.1.0/src/simplibs/logger/handlers/build_file_handler.py +119 -0
- simplibs_logger-0.1.0/src/simplibs/logger/levels/__init__.py +18 -0
- simplibs_logger-0.1.0/src/simplibs/logger/levels/register_success_level.py +33 -0
- simplibs_logger-0.1.0/src/simplibs/logger/levels/resolve_level.py +43 -0
- simplibs_logger-0.1.0/src/simplibs/logger/lifecycle/__init__.py +19 -0
- simplibs_logger-0.1.0/src/simplibs/logger/lifecycle/close_logger.py +45 -0
- simplibs_logger-0.1.0/src/simplibs/logger/lifecycle/create_logger.py +172 -0
- simplibs_logger-0.1.0/src/simplibs/logger/py.typed +1 -0
- simplibs_logger-0.1.0/src/simplibs_logger.egg-info/PKG-INFO +508 -0
- simplibs_logger-0.1.0/src/simplibs_logger.egg-info/SOURCES.txt +58 -0
- simplibs_logger-0.1.0/src/simplibs_logger.egg-info/dependency_links.txt +1 -0
- simplibs_logger-0.1.0/src/simplibs_logger.egg-info/requires.txt +10 -0
- simplibs_logger-0.1.0/src/simplibs_logger.egg-info/top_level.txt +1 -0
- simplibs_logger-0.1.0/tests/test_SimpleLogger.py +454 -0
- simplibs_logger-0.1.0/tests/test_root_init.py +28 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dalibor Sova (Sudip2708)
|
|
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
|
|
13
|
+
all 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
|
|
21
|
+
THE SOFTWARE.
|
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: simplibs-logger
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A ready-to-use logger on top of the standard logging module: a console, an optional rotating file, colored level names, optional JSON output and a short calling interface.
|
|
5
|
+
Author-email: "Dalibor Sova (Sudip2708)" <daliborsova@seznam.cz>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/simplibs/simplibs-logger
|
|
8
|
+
Project-URL: Repository, https://github.com/simplibs/simplibs-logger
|
|
9
|
+
Project-URL: Issues, https://github.com/simplibs/simplibs-logger/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/simplibs/simplibs-logger/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: logger,logging,log,console,json,jsonl,rotating-file,colors,simplibs,simplibs-logger,developer-tools
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Classifier: Topic :: System :: Logging
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: simplibs-exception>=1.1.4
|
|
25
|
+
Requires-Dist: simplibs-object>=0.1.0
|
|
26
|
+
Requires-Dist: simplibs-validate>=0.3.2
|
|
27
|
+
Requires-Dist: simplibs-path>=0.1.1
|
|
28
|
+
Requires-Dist: simplibs-style>=0.1.0
|
|
29
|
+
Requires-Dist: simplibs-file>=0.1.0
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=9.0; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# 📜 `simplibs-logger`
|
|
36
|
+
|
|
37
|
+
[](https://pypi.org/project/simplibs-logger/)
|
|
38
|
+
[](https://www.python.org/downloads/)
|
|
39
|
+
[](https://github.com/simplibs/simplibs-logger/blob/main/LICENSE)
|
|
40
|
+
[](https://github.com/simplibs/simplibs-logger/actions)
|
|
41
|
+
|
|
42
|
+
**A logger that works the moment you create it.**
|
|
43
|
+
|
|
44
|
+
A ready-to-use logger built **on** the standard `logging` module, not instead of it: one constructor gives
|
|
45
|
+
you a colored console, an optional rotating file, optional JSON output and a short way to write —
|
|
46
|
+
`logger.log_info("text %s", value)`. A wrong level, format or stream fails when you give it, not when the
|
|
47
|
+
first record is written, and a record always points at the line of *your* code.
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from simplibs.logger import SimpleLogger
|
|
51
|
+
|
|
52
|
+
logger = SimpleLogger(name="my_app", file_path="logs/app.log")
|
|
53
|
+
|
|
54
|
+
logger.log_info("Application started")
|
|
55
|
+
logger.log_success("Import finished: %d rows", 120) # SUCCESS, level 25 — between INFO and WARNING
|
|
56
|
+
logger("Disk almost full", level="warning") # the logger is callable
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
> Works with [`simplibs-cli`](https://pypi.org/project/simplibs-cli/): `resolve_verbosity(quiet=…, verbose=…)`
|
|
60
|
+
> returns a level that `SimpleLogger(level=…)` accepts as it is.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 🧭 The Core Philosophy
|
|
65
|
+
|
|
66
|
+
The standard `logging` module is powerful and starts empty: a logger with no handler, a default level that
|
|
67
|
+
swallows `info`, a format that fails with a bare `ValueError` on the first record, a file that grows
|
|
68
|
+
until the disk is full. Every program configures the same things by hand — and every copy forgets one.
|
|
69
|
+
`simplibs-logger` is that configuration, written once and checked.
|
|
70
|
+
|
|
71
|
+
* **It works at once.** The default level is INFO, the console is colored, and nothing needs configuring
|
|
72
|
+
before `log_info` writes a line.
|
|
73
|
+
* **On top of `logging`, never beside it.** A `SimpleLogger` wraps a real `logging.Logger` (`logger.logger`),
|
|
74
|
+
and the handlers and formatters are standard classes you can attach to any logger yourself.
|
|
75
|
+
* **A wrong value fails early.** Levels, names, formats, output kinds and streams are validated when they
|
|
76
|
+
are given — with the very function the standard library will call later.
|
|
77
|
+
* **Build first, swap after.** Every handler is built, and the file opened, before the existing logger is
|
|
78
|
+
touched. A bad path leaves the previous setup in place, and handlers are closed, never leaked.
|
|
79
|
+
* **The right place in the traceback.** File, line and function are those of the code that called the
|
|
80
|
+
logger, for `log_info`, for `logger("text")` and for everything between.
|
|
81
|
+
* **Text for people, JSON for machines.** A readable console and a JSON Lines file are one call.
|
|
82
|
+
* **Layers that only look left.** `definitions` and `annotations` ← `levels` ← `formatting` ← `handlers` ←
|
|
83
|
+
`lifecycle` ← `SimpleLogger` — every layer imports only from those before it.
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
SimpleLogger(level="loud") # -> raises: unknown level name
|
|
87
|
+
SimpleLogger(message_format="%(asctime)s %") # -> raises: not a valid message format
|
|
88
|
+
SimpleLogger(max_bytes=0) # -> raises: zero would mean "never rotate"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 📦 Installation
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
pip install simplibs-logger
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Requires Python 3.11+. The runtime dependencies (installed automatically) are other simplibs libraries:
|
|
100
|
+
[`simplibs-exception`](https://pypi.org/project/simplibs-exception/) for the error card of a log file that
|
|
101
|
+
cannot be opened, [`simplibs-object`](https://pypi.org/project/simplibs-object/) for the validated atoms,
|
|
102
|
+
[`simplibs-validate`](https://pypi.org/project/simplibs-validate/) for `@validate_call` and the validated
|
|
103
|
+
types, [`simplibs-path`](https://pypi.org/project/simplibs-path/) for the log file's path,
|
|
104
|
+
[`simplibs-style`](https://pypi.org/project/simplibs-style/) for the colors, and
|
|
105
|
+
[`simplibs-file`](https://pypi.org/project/simplibs-file/) for the type of the encoding.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 🚀 Quick Start in 60 Seconds
|
|
110
|
+
|
|
111
|
+
### Level 1: A logger with no setup
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
from simplibs.logger import SimpleLogger
|
|
115
|
+
|
|
116
|
+
logger = SimpleLogger()
|
|
117
|
+
|
|
118
|
+
logger.log_debug("Not shown — the default level is INFO")
|
|
119
|
+
logger.log_info("Application started")
|
|
120
|
+
logger.log_success("Import finished: %d rows", 120)
|
|
121
|
+
logger.log_warning("Disk almost full")
|
|
122
|
+
logger.log_error("Request failed")
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```text
|
|
126
|
+
2026-10-24 12:00:00 | INFO | simplibs | Application started
|
|
127
|
+
2026-10-24 12:00:00 | SUCCESS | simplibs | Import finished: 120 rows
|
|
128
|
+
2026-10-24 12:00:00 | WARNING | simplibs | Disk almost full
|
|
129
|
+
2026-10-24 12:00:00 | ERROR | simplibs | Request failed
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The records go to standard error, and the level names are colored in a terminal. The columns stay
|
|
133
|
+
straight, because the padding counts the visible name, not the color codes.
|
|
134
|
+
|
|
135
|
+
### Level 2: A file that rotates, closed properly
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from simplibs.logger import SimpleLogger
|
|
139
|
+
|
|
140
|
+
with SimpleLogger(name="my_app", level="debug", file_path="logs/app.log",
|
|
141
|
+
max_bytes=1_000_000, backup_count=5) as logger:
|
|
142
|
+
logger.log_debug("Connecting to %s", "db.local")
|
|
143
|
+
logger.log_info("Ready")
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`logs/` and the file are created when missing. The file is plain text, never colored, and at 1 MB it
|
|
147
|
+
becomes `app.log.1` while five older files are kept. Leaving the `with` block closes the file.
|
|
148
|
+
|
|
149
|
+
### Level 3: JSON for the machines
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from simplibs.logger import SimpleLogger
|
|
153
|
+
|
|
154
|
+
logger = SimpleLogger(name="api", file_path="logs/api.jsonl", file_output="json", utc=True)
|
|
155
|
+
|
|
156
|
+
logger.log_info("request done", extra={"request_id": "r-7", "status": 200})
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The console stays readable text; the file gets one JSON object per line:
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{"time":"2026-10-24T12:34:56.789Z","level":"INFO","logger":"api","message":"request done","function":"<module>","file":"app.py","line":5,"request_id":"r-7","status":200}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Level 4: Exceptions, the switch and your own wiring
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
import logging
|
|
169
|
+
from simplibs.logger import SimpleLogger, build_console_handler
|
|
170
|
+
|
|
171
|
+
logger = SimpleLogger(name="importer", level="debug")
|
|
172
|
+
|
|
173
|
+
def import_rows():
|
|
174
|
+
raise ValueError("row 3 is broken")
|
|
175
|
+
|
|
176
|
+
try:
|
|
177
|
+
import_rows()
|
|
178
|
+
except ValueError:
|
|
179
|
+
logger.log_exception("Import failed") # ERROR + the traceback
|
|
180
|
+
|
|
181
|
+
if logger.is_enabled_for("debug"): # worth asking before an expensive message
|
|
182
|
+
logger.log_debug("state: %s", {"rows": 3})
|
|
183
|
+
|
|
184
|
+
logger.enabled = False # silence it, whatever the level
|
|
185
|
+
logger.log_error("not written")
|
|
186
|
+
|
|
187
|
+
# the pieces work on any standard logger
|
|
188
|
+
third_party = logging.getLogger("third_party")
|
|
189
|
+
third_party.addHandler(build_console_handler(level="warning"))
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 🛠️ Architecture & Package Structure
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
src/simplibs/logger/
|
|
198
|
+
├── annotations/ ◄── Validated types for signatures (BackupCount, MaxBytes, LogStream)
|
|
199
|
+
├── definitions/ ◄── Validated atoms and fixed values (LoggerLevel, LoggerName, ... SUCCESS_LEVEL)
|
|
200
|
+
├── levels/ ◄── A name to a number, and the name SUCCESS (resolve_level, register_success_level)
|
|
201
|
+
├── formatting/ ◄── How a record looks (build_formatter, ColoredFormatter, JsonFormatter)
|
|
202
|
+
├── handlers/ ◄── Where records go (build_console_handler, build_file_handler)
|
|
203
|
+
├── lifecycle/ ◄── Create and release (create_logger, close_logger)
|
|
204
|
+
└── SimpleLogger.py ◄── The ready-to-use logger class
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The root of the package exports everything — the logger, the building blocks, the atoms, the constants and
|
|
208
|
+
the annotations — so one import line is all a program needs. The folders are plain packages for the code's
|
|
209
|
+
own organization; nothing has to be imported from them. The internal `_helpers` and `_validations` of each
|
|
210
|
+
folder are not exported.
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
from simplibs.logger import SimpleLogger, create_logger, close_logger
|
|
214
|
+
from simplibs.logger import build_console_handler, build_file_handler, build_formatter, JsonFormatter
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 📒 SimpleLogger — The Ready-to-Use Logger
|
|
220
|
+
|
|
221
|
+
The class most programs need: a configured `logging.Logger` behind a small calling interface. The
|
|
222
|
+
constructor builds the console, the file, the colors and the JSON output; `log_info`, `log_success`,
|
|
223
|
+
`log_warning`, … write the records, `logger("text")` writes at the default level, and `log_exception`
|
|
224
|
+
adds the traceback. It has an `enabled` switch, `is_enabled_for(level)`, `set_level`, `close()` and works as
|
|
225
|
+
a context manager.
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
logger = SimpleLogger(file_path="logs/app.log")
|
|
229
|
+
logger.log_info("user %s logged in", name)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
➡️ [README_LOGGER_SIMPLELOGGER](https://github.com/simplibs/simplibs-logger/blob/main/docs/README_LOGGER_SIMPLELOGGER.md)
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## 🔄 Lifecycle — Create and Release
|
|
237
|
+
|
|
238
|
+
Two functions underneath `SimpleLogger`, for a program that wants a plain `logging.Logger`:
|
|
239
|
+
`create_logger` builds one, validated, with no duplicate handlers however often it is called, and
|
|
240
|
+
`close_logger` detaches **and closes** every handler so the log file is released.
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
logger = create_logger(name="my_app", level="debug", file_path="logs/app.log", propagate=True)
|
|
244
|
+
close_logger(logger)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
➡️ [README_LOGGER_LIFECYCLE](https://github.com/simplibs/simplibs-logger/blob/main/docs/README_LOGGER_LIFECYCLE.md)
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## 📮 Handlers — Where Records Go
|
|
252
|
+
|
|
253
|
+
Two builders of standard handlers: `build_console_handler` (standard error by default, any object with
|
|
254
|
+
`write` as a stream) and `build_file_handler` (creates its folder and file, rotates with `max_bytes`, and
|
|
255
|
+
turns a failed open into a structured card). A handler has no level of its own unless one is asked for, so
|
|
256
|
+
the logger decides.
|
|
257
|
+
|
|
258
|
+
```python
|
|
259
|
+
console = build_console_handler(level="warning", output="json")
|
|
260
|
+
file = build_file_handler("logs/app.log", max_bytes=1_000_000)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
➡️ [README_LOGGER_HANDLERS](https://github.com/simplibs/simplibs-logger/blob/main/docs/README_LOGGER_HANDLERS.md)
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## 🎨 Formatting — How a Record Looks
|
|
268
|
+
|
|
269
|
+
`build_formatter` is the one place a formatter is made and validated. `ColoredFormatter` colors the level
|
|
270
|
+
name and keeps the columns straight; `JsonFormatter` writes each record as one line of valid JSON, with the
|
|
271
|
+
fields of `extra=` as flat keys.
|
|
272
|
+
|
|
273
|
+
| Output | Formatter | For |
|
|
274
|
+
|----------|---------------------|------------------------------------------------|
|
|
275
|
+
| `text` | `logging.Formatter` | A file read by a person. |
|
|
276
|
+
| `text`, colored | `ColoredFormatter` | The console. |
|
|
277
|
+
| `json` | `JsonFormatter` | A log collector, `jq`, a container's stderr. |
|
|
278
|
+
|
|
279
|
+
➡️ [README_LOGGER_FORMATTING](https://github.com/simplibs/simplibs-logger/blob/main/docs/README_LOGGER_FORMATTING.md)
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## 📶 Levels — Numbers and Names
|
|
284
|
+
|
|
285
|
+
`resolve_level` turns a level written as a number or a name (`"debug"`, `"SUCCESS"`, `35`) into the number,
|
|
286
|
+
and `register_success_level` gives the number 25 the name `SUCCESS` in `logging`, once, without overwriting
|
|
287
|
+
a name another library chose.
|
|
288
|
+
|
|
289
|
+
```python
|
|
290
|
+
resolve_level("debug") # -> 10
|
|
291
|
+
resolve_level(None) # -> 20
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
➡️ [README_LOGGER_LEVELS](https://github.com/simplibs/simplibs-logger/blob/main/docs/README_LOGGER_LEVELS.md)
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## 🧬 Definitions — Validated Atoms and Fixed Values
|
|
299
|
+
|
|
300
|
+
The vocabulary of the library. Five validated atoms say what a value may be and what it is when nobody
|
|
301
|
+
chose; three constants hold the fixed values behind them.
|
|
302
|
+
|
|
303
|
+
| Name | What it is |
|
|
304
|
+
|-------------------|----------------------------------------------------------------------------|
|
|
305
|
+
| `LoggerLevel` | A positive number or a level name; default INFO. |
|
|
306
|
+
| `LoggerName` | A name that cannot reach the root logger; default `"simplibs"`. |
|
|
307
|
+
| `DateFormat` | A `time.strftime` format; default `"%Y-%m-%d %H:%M:%S"`. |
|
|
308
|
+
| `MessageFormat` | A `%`-style line format, syntax checked, field names free. |
|
|
309
|
+
| `OutputFormat` | `"text"` (default) or `"json"`. |
|
|
310
|
+
| `SUCCESS_LEVEL`, `LEVEL_NAMES`, `OUTPUT_FORMATS` | The level 25, the six level names, the two output formats. |
|
|
311
|
+
|
|
312
|
+
➡️ [README_LOGGER_DEFINITIONS](https://github.com/simplibs/simplibs-logger/blob/main/docs/README_LOGGER_DEFINITIONS.md)
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## 🔖 Annotations — Types for Your Signatures
|
|
317
|
+
|
|
318
|
+
Three validated types that this library's signatures use and a caller can use in theirs, with
|
|
319
|
+
`@validate_call`:
|
|
320
|
+
|
|
321
|
+
| Type | Accepts |
|
|
322
|
+
|---------------|----------------------------------------------------------|
|
|
323
|
+
| `BackupCount` | An `int` of at least one. |
|
|
324
|
+
| `MaxBytes` | An `int` greater than zero, or `None` — never rotate. |
|
|
325
|
+
| `LogStream` | Any object with `write`, or `None` — standard error. |
|
|
326
|
+
|
|
327
|
+
➡️ [README_LOGGER_ANNOTATIONS](https://github.com/simplibs/simplibs-logger/blob/main/docs/README_LOGGER_ANNOTATIONS.md)
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## 📖 Quick Reference
|
|
332
|
+
|
|
333
|
+
### 📒 `SimpleLogger` — The Ready-to-Use Logger
|
|
334
|
+
|
|
335
|
+
| Member | Description / Parameters |
|
|
336
|
+
|------------------------------|--------------------------------------------------------------------------------------------|
|
|
337
|
+
| `SimpleLogger(...)` | Builds the logger (`enabled`, `name`, `level`, `default_level`, `file_path`, `encoding`, `console`, `colored`, `console_level`, `file_level`, `stream`, `message_format`, `date_format`, `utc`, `max_bytes`, `backup_count`, `console_output`, `file_output`, `json_default`). |
|
|
338
|
+
| `log`, `logger(...)` | Writes at `level` or at `default_level` (`message`, `*args`, `level=None`, `**kwargs`). |
|
|
339
|
+
| `log_debug` … `log_critical` | One method per level, incl. `log_success` (`message`, `*args`, `**kwargs`). |
|
|
340
|
+
| `log_exception` | ERROR with the traceback (`message`, `*args`, `**kwargs`). |
|
|
341
|
+
| `is_enabled_for` | Would a record of this level be written now (`level=None`). |
|
|
342
|
+
| `set_level` | Changes the level of the logger (`level`). |
|
|
343
|
+
| `enabled` | The switch; assignable. |
|
|
344
|
+
| `logger`, `name`, `level` | The underlying logger, its name and level. Read-only. |
|
|
345
|
+
| `close`, `with` | Closes every handler and stops writing. |
|
|
346
|
+
|
|
347
|
+
➡️ [README_LOGGER_SIMPLELOGGER](https://github.com/simplibs/simplibs-logger/blob/main/docs/README_LOGGER_SIMPLELOGGER.md)
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
### 🔄 `lifecycle/` — Create and Release
|
|
352
|
+
|
|
353
|
+
| Function | Description / Parameters |
|
|
354
|
+
|-----------------|------------------------------------------------------------------------------------------|
|
|
355
|
+
| `create_logger` | Builds a validated `logging.Logger` (the arguments of `SimpleLogger` without `enabled` and `default_level`, plus `propagate=False`). |
|
|
356
|
+
| `close_logger` | Detaches and closes every handler of a logger (`logger`). |
|
|
357
|
+
|
|
358
|
+
➡️ [README_LOGGER_LIFECYCLE](https://github.com/simplibs/simplibs-logger/blob/main/docs/README_LOGGER_LIFECYCLE.md)
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
### 📮 `handlers/` — Where Records Go
|
|
363
|
+
|
|
364
|
+
| Function | Description / Parameters |
|
|
365
|
+
|-------------------------|-----------------------------------------------------------------------------------|
|
|
366
|
+
| `build_console_handler` | A stream handler (`level`, `stream`, `message_format`, `date_format`, `colored=True`, `utc`, `output`, `json_default`). |
|
|
367
|
+
| `build_file_handler` | A file handler, optionally rotating (`file_path`, `level`, `encoding`, `message_format`, `date_format`, `utc`, `max_bytes`, `backup_count=3`, `output`, `json_default`). |
|
|
368
|
+
|
|
369
|
+
➡️ [README_LOGGER_HANDLERS](https://github.com/simplibs/simplibs-logger/blob/main/docs/README_LOGGER_HANDLERS.md)
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
### 🎨 `formatting/` — How a Record Looks
|
|
374
|
+
|
|
375
|
+
| Name | Description / Parameters |
|
|
376
|
+
|--------------------|---------------------------------------------------------------------------------------|
|
|
377
|
+
| `build_formatter` | A validated formatter (`message_format`, `date_format`, `colored=False`, `utc`, `output`, `json_default`). |
|
|
378
|
+
| `ColoredFormatter` | Colors the level name, padding included (`fmt`, `datefmt`). |
|
|
379
|
+
| `JsonFormatter` | One JSON object per line (`utc=False`, `default=None`). |
|
|
380
|
+
|
|
381
|
+
➡️ [README_LOGGER_FORMATTING](https://github.com/simplibs/simplibs-logger/blob/main/docs/README_LOGGER_FORMATTING.md)
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
### 📶 `levels/` — Numbers and Names
|
|
386
|
+
|
|
387
|
+
| Function | Description / Parameters |
|
|
388
|
+
|--------------------------|------------------------------------------------------------------|
|
|
389
|
+
| `resolve_level` | A level as a number (`level=None`). |
|
|
390
|
+
| `register_success_level` | Names the number 25 `SUCCESS`, once. |
|
|
391
|
+
|
|
392
|
+
➡️ [README_LOGGER_LEVELS](https://github.com/simplibs/simplibs-logger/blob/main/docs/README_LOGGER_LEVELS.md)
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
### 🧬 `definitions/` — Validated Atoms and Fixed Values
|
|
397
|
+
|
|
398
|
+
| Name | Description |
|
|
399
|
+
|----------------------------------------|---------------------------------------------------------------|
|
|
400
|
+
| `LoggerLevel`, `LoggerName` | A level (default INFO); a logger name (default `"simplibs"`). |
|
|
401
|
+
| `DateFormat`, `MessageFormat` | A `strftime` format; a `%`-style line format. |
|
|
402
|
+
| `OutputFormat` | `"text"` or `"json"`. |
|
|
403
|
+
| `SUCCESS_LEVEL`, `LEVEL_NAMES`, `OUTPUT_FORMATS` | `25`; the six level names; `("text", "json")`. |
|
|
404
|
+
|
|
405
|
+
➡️ [README_LOGGER_DEFINITIONS](https://github.com/simplibs/simplibs-logger/blob/main/docs/README_LOGGER_DEFINITIONS.md)
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
### 🔖 `annotations/` — Types for Your Signatures
|
|
410
|
+
|
|
411
|
+
| Type | Description |
|
|
412
|
+
|---------------|----------------------------------------------------------|
|
|
413
|
+
| `BackupCount` | How many rotated files to keep; at least one. |
|
|
414
|
+
| `MaxBytes` | A size limit in bytes, or `None` for no rotation. |
|
|
415
|
+
| `LogStream` | A stream with `write`, or `None` for standard error. |
|
|
416
|
+
|
|
417
|
+
➡️ [README_LOGGER_ANNOTATIONS](https://github.com/simplibs/simplibs-logger/blob/main/docs/README_LOGGER_ANNOTATIONS.md)
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## 🔌 Streams, Colors and Files
|
|
422
|
+
|
|
423
|
+
How the logger behaves where the output goes somewhere other than a terminal:
|
|
424
|
+
|
|
425
|
+
* **The console is standard error.** Diagnostics belong there. A program that prints its log next to its own
|
|
426
|
+
output passes `stream=sys.stdout`; any object with `write` works.
|
|
427
|
+
* **The color follows the style switch, not the stream.** `simplibs-style` decides — from `NO_COLOR`,
|
|
428
|
+
`FORCE_COLOR`, `TERM=dumb` and from whether *standard output* is a terminal. A program that redirects
|
|
429
|
+
only one of the two passes `colored=False`, or calls `set_styles_enabled(False)`.
|
|
430
|
+
* **Files and JSON are never colored.** ANSI codes do not belong in a file.
|
|
431
|
+
* **The default level is INFO** (the standard library starts at WARNING), and `SUCCESS` is the number 25.
|
|
432
|
+
* **One name, one logger.** `SimpleLogger(name="x")` twice gives the same underlying logger and the second
|
|
433
|
+
reconfigures the first. The default name `"simplibs"` is the parent of every `simplibs.*` logger, so the default logger also
|
|
434
|
+
receives what other simplibs libraries log through plain `logging`. A `SimpleLogger` or `create_logger`
|
|
435
|
+
logger does not pass its records up unless `propagate=True`.
|
|
436
|
+
* **Close what you open.** `close()` and `with` release the log file — on Windows an open handler blocks
|
|
437
|
+
deleting or rotating it. On Windows, rotation also needs the file to be open in one process only.
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## ⚠️ Exceptions
|
|
442
|
+
|
|
443
|
+
The library defines one error of its own: a structured
|
|
444
|
+
[`AccessError`](https://pypi.org/project/simplibs-exception/) card, with a name that starts with `LOGGER_`.
|
|
445
|
+
Everything else is refused by the libraries it is built on, each with its own structured card: an invalid
|
|
446
|
+
level, name or format by the atoms (`simplibs-object`), a wrong argument type by `@validate_call`
|
|
447
|
+
(`simplibs-validate`), and a path that cannot be prepared by `ensure_file` (`simplibs-path`).
|
|
448
|
+
|
|
449
|
+
| Error name | Card | Wraps | Raised when |
|
|
450
|
+
|---------------------------|---------------|-------------------------------------|--------------------------------------------|
|
|
451
|
+
| `LOGGER_FILE_OPEN_FAILED` | `AccessError` | the caught `OSError` (its own type) | The OS refuses to open the log file. |
|
|
452
|
+
|
|
453
|
+
Because the card keeps the original exception type, `except PermissionError` still works.
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
## 🔗 Related libraries
|
|
458
|
+
|
|
459
|
+
* **[`simplibs-exception`](https://pypi.org/project/simplibs-exception/)** — the structured card of a log file that cannot be opened.
|
|
460
|
+
* **[`simplibs-object`](https://pypi.org/project/simplibs-object/)** — `SimpleConstant`, the base of the validated atoms.
|
|
461
|
+
* **[`simplibs-validate`](https://pypi.org/project/simplibs-validate/)** — `@validate_call` and the validated types behind the annotations.
|
|
462
|
+
* **[`simplibs-path`](https://pypi.org/project/simplibs-path/)** — `ensure_file` and `PathLike` for the log file.
|
|
463
|
+
* **[`simplibs-style`](https://pypi.org/project/simplibs-style/)** — the colors of the level names and the switch that turns them off.
|
|
464
|
+
* **[`simplibs-file`](https://pypi.org/project/simplibs-file/)** — `EncodingName`, the type of the file's encoding.
|
|
465
|
+
* **[`simplibs-cli`](https://pypi.org/project/simplibs-cli/)** — `resolve_verbosity` turns `--quiet` and `-v` into a level for this logger.
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## ☯️ About simplibs
|
|
470
|
+
|
|
471
|
+
All libraries in the **simplibs** (Simple Libraries) ecosystem share a common
|
|
472
|
+
engineering philosophy:
|
|
473
|
+
|
|
474
|
+
* **Dyslexia-friendly:**
|
|
475
|
+
We actively minimize cognitive load. Code is atomized into small, self-contained units,
|
|
476
|
+
files are named directly after the logical task they perform, and explanations describe
|
|
477
|
+
*why* something is designed, not just *what* it is.
|
|
478
|
+
* **Programmer's Zen:**
|
|
479
|
+
Nothing should be missing, and nothing should be superfluous. We value clean execution
|
|
480
|
+
paths and robust, understandable code architectures over rushed, messy feature sets.
|
|
481
|
+
* **Defensive Style:**
|
|
482
|
+
We actively anticipate edge cases and failure modes so that only safe operational paths
|
|
483
|
+
remain. Our code is built to degrade gracefully rather than crash unexpectedly.
|
|
484
|
+
* **Minimalism:**
|
|
485
|
+
Find the most direct path to the goal in as few operational steps as possible without
|
|
486
|
+
taking shortcuts on safety, readability, or completeness.
|
|
487
|
+
* **Code as Craft:**
|
|
488
|
+
Code should be pleasant to look at, readable at a glance, and evoke structural harmony.
|
|
489
|
+
We treat software engineering as a precision trade.
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
### 🤝 Contributing & Community
|
|
494
|
+
|
|
495
|
+
This is an **open-source project** built with love and care. We strongly believe in
|
|
496
|
+
community collaboration and welcome any feedback, bug reports, or feature ideas!
|
|
497
|
+
|
|
498
|
+
* **Want to contribute?** Feel free to open an Issue or submit a Pull Request.
|
|
499
|
+
* **Want to get in touch?** If you'd like to discuss the project further, collaborate,
|
|
500
|
+
or just say hello, feel free to open a GitHub Issue or start a Discussion.
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
### 📝 License
|
|
505
|
+
|
|
506
|
+
This library is released under the **MIT License**. Build great things!
|
|
507
|
+
|
|
508
|
+
---
|