Skip to content

Commit 93a3db4

Browse files
committed
release 1.3.4
1 parent e19fb3b commit 93a3db4

File tree

4 files changed

+70
-32
lines changed

4 files changed

+70
-32
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44
1. fix `morebuiltins.utils.gen_id` wrong length issue.
55
2. fix `morebuiltins.funcs.LineProfiler` to handle nested function calls correctly.
66
3. update `morebuiltins.cmd.log_server` to support close idle file handlers after 300 seconds.
7-
4. add `get_logger` to `morebuiltins.cmd.log_server` to get a logger with `SocketHandler` to send logs to `LogServer`.
7+
4. add `get_logger` to `morebuiltins.cmd.log_server` to get a **singleton** logger with `SocketHandler` to send logs to `LogServer`.
8+
5. [**Compatibility Warnings**] Refactor of `morebuiltins.cmd.log_server`:
9+
1. use `LogSetting` struct instead of untyped dict, client send dict with `LogSetting` structure.
10+
2. add `level_specs` filter to specify log levels of files, like `[logging.ERROR, logging.CRITICAL]`.
11+
3. add cache file for log settings, readable by both server and human.
12+
4. THIS IS A BREAKING CHANGE, old clients may not work with new server.
813

914
### 1.3.3 (2025-09-01)
1015
1. add `morebuiltins.logs.LogHelper.handle_crash` to log uncaught exceptions.

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ This project enhances Python’s built-ins with extra functionality, prioritizin
1717
ibution.
1818

1919
## Compatibility Break Warnings
20-
1. **1.3.2 (2025-08-02)**
20+
21+
1. **1.3.4 (2025-09-17)**
22+
1. Refactor of `morebuiltins.cmd.log_server`
23+
2. **1.3.2 (2025-08-02)**
2124
1. move `async_logger`, `AsyncQueueListener`, `LogHelper`, `RotatingFileWriter`, and `SizedTimedRotatingFileHandler` from `morebuiltins.funcs` to `morebuiltins.logs`.
22-
2. **1.3.0 (2025-03-08)**
25+
3. **1.3.0 (2025-03-08)**
2326
1. rename `morebuiltins.functools` to `morebuiltins.funcs` to avoid conflict with `functools` in python standard library.
2427

2528
## Install
@@ -221,7 +224,7 @@ print(morebuiltins.__file__)
221224

222225
## 9. morebuiltins.cmd.log_server
223226

224-
9.1 `LogServer` - Log Server for SocketHandler, create a socket server with asyncio.start_server. Update settings of rotation/formatter with extra: {"max_size": 1024**2, "formatter": logging.Formatter(fmt="%(asctime)s - %(filename)s - %(message)s")}
227+
9.1 `LogServer` - Log server for SocketHandler, create a socket server with asyncio.start_server. Custom formatter or rotation strategy with extra in log record.
225228

226229

227230
## 10. morebuiltins.cmd.proxy_checker

doc.md

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2260,23 +2260,29 @@ Demo::
22602260

22612261

22622262

2263-
9.1 `LogServer` - Log Server for SocketHandler, create a socket server with asyncio.start_server. Update settings of rotation/formatter with extra: {"max_size": 1024**2, "formatter": logging.Formatter(fmt="%(asctime)s - %(filename)s - %(message)s")}
2263+
9.1 `LogServer` - Log server for SocketHandler, create a socket server with asyncio.start_server. Custom formatter or rotation strategy with extra in log record.
22642264

22652265

22662266
```python
22672267

2268+
[WARNING]: Ensure your log msg is "" if you only want to update settings, or the msg will be skipped.
2269+
2270+
logger.info("", extra={"log_setting": {"formatter": formatter, "max_size": 1024**2, "level_specs": [logging.ERROR]}})
2271+
2272+
22682273
### Server demo1:
22692274
start log server in terminal, only collect logs and print to console
22702275
> python -m morebuiltins.cmd.log_server
22712276

22722277
### Server demo2:
2273-
custom options to log to "logs" directory, default rotates at 10MB with 5 backups
2274-
> python -m morebuiltins.cmd.log_server --log-dir=./logs --host 127.0.0.1 --port 8901
2278+
custom options to log to "logs" directory, default rotates at 10MB with 5 backups, no log_stream, enable compress
2279+
> python -m morebuiltins.cmd.log_server --log-dir=./logs --host 127.0.0.1 --port 8901 --log-stream=None --compress
22752280

22762281
### Server demo3:
22772282
python code
22782283

22792284
```python
2285+
# Server side
22802286
import asyncio
22812287

22822288
from morebuiltins.cmd.log_server import LogServer
@@ -2293,6 +2299,7 @@ asyncio.run(main())
22932299
### Client demo1:
22942300

22952301
```python
2302+
# Client side(no dependency on morebuiltins)
22962303
import logging
22972304
import logging.handlers
22982305

@@ -2301,16 +2308,21 @@ logger.setLevel(logging.DEBUG)
23012308
h = logging.handlers.SocketHandler("127.0.0.1", 8901)
23022309
h.setLevel(logging.DEBUG)
23032310
logger.addHandler(h)
2304-
for _ in range(5):
2305-
logger.info(
2306-
"hello world!",
2307-
extra={
2311+
logger.info(
2312+
"",
2313+
extra={
2314+
"log_setting": {
23082315
"max_size": 1024**2,
23092316
"formatter": logging.Formatter(
23102317
fmt="%(asctime)s - %(filename)s - %(message)s"
23112318
),
2312-
},
2313-
)
2319+
"level_specs": [logging.ERROR],
2320+
}
2321+
},
2322+
)
2323+
for _ in range(5):
2324+
logger.info("hello world!")
2325+
23142326
# [client] 2024-08-10 19:30:07,113 - temp3.py - hello world!
23152327
# [client] 2024-08-10 19:30:07,113 - temp3.py - hello world!
23162328
# [client] 2024-08-10 19:30:07,113 - temp3.py - hello world!

morebuiltins/cmd/log_server.py

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -153,20 +153,26 @@ def __str__(self):
153153

154154

155155
class LogServer(SocketServer):
156-
"""Log Server for SocketHandler, create a socket server with asyncio.start_server. Update settings of rotation/formatter with extra: {"max_size": 1024**2, "formatter": logging.Formatter(fmt="%(asctime)s - %(filename)s - %(message)s")}
156+
"""Log server for SocketHandler, create a socket server with asyncio.start_server. Custom formatter or rotation strategy with extra in log record.
157+
158+
[WARNING]: Ensure your log msg is "" if you only want to update settings, or the msg will be skipped.
159+
160+
logger.info("", extra={"log_setting": {"formatter": formatter, "max_size": 1024**2, "level_specs": [logging.ERROR]}})
161+
157162
158163
### Server demo1:
159164
start log server in terminal, only collect logs and print to console
160165
> python -m morebuiltins.cmd.log_server
161166
162167
### Server demo2:
163-
custom options to log to "logs" directory, default rotates at 10MB with 5 backups
164-
> python -m morebuiltins.cmd.log_server --log-dir=./logs --host 127.0.0.1 --port 8901
168+
custom options to log to "logs" directory, default rotates at 10MB with 5 backups, no log_stream, enable compress
169+
> python -m morebuiltins.cmd.log_server --log-dir=./logs --host 127.0.0.1 --port 8901 --log-stream=None --compress
165170
166171
### Server demo3:
167172
python code
168173
169174
```python
175+
# Server side
170176
import asyncio
171177
172178
from morebuiltins.cmd.log_server import LogServer
@@ -183,6 +189,7 @@ async def main():
183189
### Client demo1:
184190
185191
```python
192+
# Client side(no dependency on morebuiltins)
186193
import logging
187194
import logging.handlers
188195
@@ -191,16 +198,21 @@ async def main():
191198
h = logging.handlers.SocketHandler("127.0.0.1", 8901)
192199
h.setLevel(logging.DEBUG)
193200
logger.addHandler(h)
194-
for _ in range(5):
195-
logger.info(
196-
"hello world!",
197-
extra={
201+
logger.info(
202+
"",
203+
extra={
204+
"log_setting": {
198205
"max_size": 1024**2,
199206
"formatter": logging.Formatter(
200207
fmt="%(asctime)s - %(filename)s - %(message)s"
201208
),
202-
},
203-
)
209+
"level_specs": [logging.ERROR],
210+
}
211+
},
212+
)
213+
for _ in range(5):
214+
logger.info("hello world!")
215+
204216
# [client] 2024-08-10 19:30:07,113 - temp3.py - hello world!
205217
# [client] 2024-08-10 19:30:07,113 - temp3.py - hello world!
206218
# [client] 2024-08-10 19:30:07,113 - temp3.py - hello world!
@@ -308,10 +320,13 @@ def _init_settings(
308320
for sig in self.handle_signals:
309321
signal.signal(sig, self.handle_signal)
310322
self._log_settings = self.load_settings()
323+
if self.name in self._log_settings:
324+
self._log_settings[self.name] = self._server_log_setting
325+
self.send_log("", init_setting=True)
311326

312327
def load_settings(self):
313328
result = typing.cast(typing.Dict[str, LogSetting], {})
314-
if not self.setting_path:
329+
if not (self.setting_path and self.setting_path.is_file()):
315330
return result
316331
try:
317332
with self.setting_path.open("r", encoding="utf-8") as f:
@@ -358,7 +373,6 @@ async def end_callback(self):
358373
def start_callback(self):
359374
self.send_log(
360375
f"started log server on {self.host}:{self.port}, handle_signals={self.handle_signals}, max_queue_size={self.max_queue_size}, max_queue_buffer={self.max_queue_buffer}, log_stream={getattr(self.log_stream, 'name', None)}, compress={self.compress}, log_dir={self.log_dir}, setting={self._server_log_setting}",
361-
init_setting=True,
362376
)
363377

364378
def send_log(
@@ -660,7 +674,7 @@ def close_opened_files(self):
660674
_, fw = self._opened_files.popitem()
661675
try:
662676
fw.close()
663-
except Exception as e:
677+
except Exception:
664678
pass
665679

666680
async def run_wrapper(self):
@@ -723,10 +737,9 @@ def get_logger(
723737
log_level: int = logging.DEBUG,
724738
socket_handler_level: int = logging.DEBUG,
725739
shorten_level: bool = True,
726-
# sys.stderr, sys.stdout, None
727-
streaming: typing.Optional[typing.TextIO] = None,
740+
streaming: typing.Optional[typing.TextIO] = None, # sys.stderr, sys.stdout, None
728741
streaming_level: int = logging.DEBUG,
729-
# custom settings
742+
# custom settings for log files
730743
formatter: typing.Optional[logging.Formatter] = LogHelper.DEFAULT_FORMATTER,
731744
max_size: int = DefaultLogSetting.max_size,
732745
max_backups: int = DefaultLogSetting.max_backups,
@@ -736,20 +749,25 @@ def get_logger(
736749
For easy use, you can use original logging.handlers.SocketHandler, but you need to manage the handler yourself.
737750
738751
Demo::
739-
# python -m morebuiltins.cmd.log_server --host localhost --port 8901
752+
753+
# python -m morebuiltins.cmd.log_server --host localhost --port 8901 --log-dir logs
740754
import logging
741755
import logging.handlers
742756
logger = logging.getLogger("client")
743757
logger.setLevel(logging.DEBUG)
744758
h = logging.handlers.SocketHandler("localhost", 8901)
745759
h.setLevel(logging.DEBUG)
746760
logger.addHandler(h)
747-
# add custom settings
761+
# Add custom settings
762+
# Add error log to a specific log file; use a custom formatter and max_size; set msg to ""
748763
formatter = logging.Formatter(fmt="%(asctime)s - %(filename)s - %(message)s")
749-
# add error log to specific log file
750-
logger.info("", extra={"max_size": 1024**2, "formatter": formatter, "level_specs": [logging.ERROR]})
764+
logger.info("", extra={"log_setting": {"formatter": formatter, "max_size": 1024**2, "level_specs": [logging.ERROR]}})
751765
for _ in range(5):
752766
logger.info("hello world!")
767+
# Send some error logs
768+
logger.error("this is an error!")
769+
# The remote log server will create a "client_error.log" file in log_dir if settings are applied
770+
753771
"""
754772
if shorten_level:
755773
LogHelper.shorten_level()

0 commit comments

Comments
 (0)