MapleX 3.1.3__tar.gz → 3.2.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.
- {maplex-3.1.3/src/MapleX.egg-info → maplex-3.2.0}/PKG-INFO +3 -3
- {maplex-3.1.3 → maplex-3.2.0}/pyproject.toml +4 -4
- {maplex-3.1.3 → maplex-3.2.0}/readmes/LoggingBestPractice.md +1 -1
- {maplex-3.1.3 → maplex-3.2.0}/readmes/README_Json.md +8 -0
- maplex-3.2.0/readmes/README_Logger.md +246 -0
- {maplex-3.1.3 → maplex-3.2.0/src/MapleX.egg-info}/PKG-INFO +3 -3
- {maplex-3.1.3 → maplex-3.2.0}/src/MapleX.egg-info/SOURCES.txt +4 -0
- maplex-3.2.0/src/MapleX.egg-info/requires.txt +2 -0
- {maplex-3.1.3 → maplex-3.2.0}/src/maplex/__init__.py +1 -1
- {maplex-3.1.3 → maplex-3.2.0}/src/maplex/library/logger/__init__.py +2 -1
- {maplex-3.1.3 → maplex-3.2.0}/src/maplex/library/logger/config.py +127 -18
- maplex-3.2.0/src/maplex/library/logger/consts/__init__.py +45 -0
- maplex-3.2.0/src/maplex/library/logger/consts/config_keys.py +21 -0
- maplex-3.2.0/src/maplex/library/logger/consts/defaults.py +7 -0
- maplex-3.2.0/src/maplex/library/logger/consts/dict_keys.py +11 -0
- {maplex-3.1.3 → maplex-3.2.0}/src/maplex/library/logger/formatter.py +9 -6
- {maplex-3.1.3 → maplex-3.2.0}/src/maplex/mapleLogger.py +25 -13
- maplex-3.1.3/readmes/README_Logger.md +0 -158
- maplex-3.1.3/src/MapleX.egg-info/requires.txt +0 -2
- {maplex-3.1.3 → maplex-3.2.0}/LICENSE +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/MANIFEST.in +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/README.md +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/logErrorOutputSample.png +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/logOutputSample.png +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/readmes/README_ConsoleColors.md +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/readmes/README_Exceptions.md +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/readmes/README_MapleTree.md +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/setup.cfg +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/src/MapleX.egg-info/dependency_links.txt +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/src/MapleX.egg-info/top_level.txt +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/src/maplex/jsonHandler.py +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/src/maplex/library/logger/consts.py +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/src/maplex/library/logger/file_handler.py +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/src/maplex/library/logger/log_levels.py +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/src/maplex/library/logger/utilities.py +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/src/maplex/mapleColors.py +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/src/maplex/mapleExceptions.py +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/src/maplex/mapleTreeEditor.py +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/src/maplex/utils.py +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/tests/test_logger_unittest.py +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/tests/test_maplejson_unittest.py +0 -0
- {maplex-3.1.3 → maplex-3.2.0}/tests/test_mapletree_unittest.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MapleX
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.2.0
|
|
4
4
|
Summary: A Python library for simple logging, json file operations, Maple file format operations, and console color utilities.
|
|
5
5
|
Author: Ryuji Hazama
|
|
6
6
|
Project-URL: PyPI, https://pypi.org/project/MapleX/
|
|
@@ -16,8 +16,8 @@ Classifier: Operating System :: OS Independent
|
|
|
16
16
|
Requires-Python: >=3.12
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
|
-
Requires-Dist: cryptography>=
|
|
20
|
-
Requires-Dist: pydantic>=2.
|
|
19
|
+
Requires-Dist: cryptography>=49.0.0
|
|
20
|
+
Requires-Dist: pydantic>=2.13.4
|
|
21
21
|
Dynamic: license-file
|
|
22
22
|
|
|
23
23
|
# MapleX
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "MapleX"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.2.0"
|
|
8
8
|
description = """A Python library for simple logging, json file operations, Maple file format operations, and console color utilities."""
|
|
9
9
|
keywords = ["logging", "logger", "json", "file operations", "maple file format", "console colors"]
|
|
10
10
|
readme = "README.md"
|
|
@@ -13,8 +13,8 @@ authors = [
|
|
|
13
13
|
{name = "Ryuji Hazama"}
|
|
14
14
|
]
|
|
15
15
|
dependencies = [
|
|
16
|
-
"cryptography>=
|
|
17
|
-
"pydantic>=2.
|
|
16
|
+
"cryptography>=49.0.0",
|
|
17
|
+
"pydantic>=2.13.4",
|
|
18
18
|
]
|
|
19
19
|
classifiers = [
|
|
20
20
|
"Programming Language :: Python :: 3.12",
|
|
@@ -41,4 +41,4 @@ Homepage = "https://github.com/Ryuji-Hazama"
|
|
|
41
41
|
Repository = "https://github.com/Ryuji-Hazama/MapleTree"
|
|
42
42
|
Issues = "https://github.com/Ryuji-Hazama/MapleTree/issues"
|
|
43
43
|
YouTube = "https://www.youtube.com/@ryujihazama"
|
|
44
|
-
Instagram = "https://www.instagram.com/ryujihazama/"
|
|
44
|
+
Instagram = "https://www.instagram.com/ryujihazama/"
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
|
|
102
102
|
### `NONE`
|
|
103
103
|
|
|
104
|
-
The `NONE` level is a special level in `MapleX` that not commonly exists in other logging libraries. It is used to bypass all the log level filters and always output the log, or suppress all other log levels if you set this in the logger configuration. This is useful for debugging in production environments, where you want to log a specific event, but don't want to log any other lower level events under the same logger configuration. For example, you can set the log level to `NONE` for a specific logger to always log suspicious events, while setting the log level to `
|
|
104
|
+
The `NONE` level is a special level in `MapleX` that not commonly exists in other logging libraries. It is used to bypass all the log level filters and always output the log, or suppress all other log levels if you set this in the logger configuration. This is useful for debugging in production environments, where you want to log a specific event, but don't want to log any other lower level events under the same logger configuration. For example, you can set the log level to `NONE` for a specific logger to always log suspicious events, while setting the log level to `WARN` for other loggers to only log warnings and errors.
|
|
105
105
|
|
|
106
106
|
## Conclusion
|
|
107
107
|
|
|
@@ -94,6 +94,10 @@ jsonInstance = MapleJson("jsonFile.json", fileEncoding="shift_jis")
|
|
|
94
94
|
|
|
95
95
|
**There is no *redo*** in encryption. **DO NOT FORGET** your encryption key, or *you will lose your data FOREVER.*
|
|
96
96
|
|
|
97
|
+
#### Disclaimers
|
|
98
|
+
|
|
99
|
+
This encryption is just a basic implementation using AES-128 (Fernet) and is intended for general use cases. It may not be suitable for highly sensitive data or scenarios requiring advanced security measures. If you need stronger security, consider using more robust encryption methods or libraries.
|
|
100
|
+
|
|
97
101
|
### Key
|
|
98
102
|
|
|
99
103
|
A 32-byte byte-string key for encryption.
|
|
@@ -339,3 +343,7 @@ jsonFile.write(jsonData)
|
|
|
339
343
|
Every class parameter has its own getter and setter functions, and you can set, change, or get those values after initializing the class.
|
|
340
344
|
|
|
341
345
|
- You need to set the encryption key when you set the encryption to `True`.
|
|
346
|
+
|
|
347
|
+
## Disclaimers for Encryption
|
|
348
|
+
|
|
349
|
+
The encryption provided by this library is just a basic implementation using AES-128 (Fernet) and is intended for general use cases. It may not be suitable for highly sensitive data or scenarios requiring advanced security measures. If you need stronger security, consider using more robust encryption methods or libraries.
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# Logger Class
|
|
2
|
+
|
|
3
|
+
Logger class is a logging object for Python applications. It outputs application logs to log files and to standard output.
|
|
4
|
+
|
|
5
|
+
## Logger Initialization
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
def __init__(
|
|
9
|
+
func: str = "",
|
|
10
|
+
workingDirectory: str | None = None,
|
|
11
|
+
cmdLogLevel: str | None = None,
|
|
12
|
+
fileLogLevel: str | None = None,
|
|
13
|
+
maxLogSize: float | None = None,
|
|
14
|
+
fileMode: Literal["append", "overwrite", "daily"] | None = None,
|
|
15
|
+
configFile: str = "config.json",
|
|
16
|
+
encoding: str | None = None,
|
|
17
|
+
) -> None:
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
|Property|Required|Value|Version|
|
|
21
|
+
|--------|--------|-----|-------|
|
|
22
|
+
|**`func`**||Primary function name||
|
|
23
|
+
|**`workingDirectory`**||Log file output directory||
|
|
24
|
+
|**`cmdLogLevel`**||Terminal output log level||
|
|
25
|
+
|**`fileLogLevel`**||Log file output log level||
|
|
26
|
+
|**`maxLogSize`**||Log file max size (MB)||
|
|
27
|
+
|**`fileMode`**||Logging file mode|`v3.0`|
|
|
28
|
+
|**`configFile`**||Logger configuration file path|`v3.0`|
|
|
29
|
+
|**`encoding`**||Log file encoding|`v3.0`|
|
|
30
|
+
|
|
31
|
+
The parameter overwrites the settings configured in `config.mpl`.
|
|
32
|
+
|
|
33
|
+
## Functions
|
|
34
|
+
|
|
35
|
+
### `getLogger()`
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
def getLogger(
|
|
39
|
+
name = "",
|
|
40
|
+
**kwargs
|
|
41
|
+
) -> maplex.Logger:
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
|Property|Required|Value|Version|
|
|
45
|
+
|--------|--------|-----|-------|
|
|
46
|
+
|**`name`**||Primary funcion name|`v3.0`|
|
|
47
|
+
|**`**kwargs`**||Other parameters|`v3.0`|
|
|
48
|
+
|
|
49
|
+
This get or creates a Logger instance.
|
|
50
|
+
|
|
51
|
+
If you already have a Logger class instance with the same name, the function returns the existing instance, and you can save your resources on the machine.
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from maplex
|
|
55
|
+
|
|
56
|
+
logger = maplex.getLogger(__name__)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Getters and Setters
|
|
60
|
+
|
|
61
|
+
Every class parameter has its own getter and setter functions, and you can set, change, or get those values after initializing the class.
|
|
62
|
+
|
|
63
|
+
## Logging Methods
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
def trace(object: any) -> None:
|
|
67
|
+
def debug(object: any) -> None:
|
|
68
|
+
def info(object: any) -> None:
|
|
69
|
+
def warn(object: any) -> None:
|
|
70
|
+
def error(object: any, exception: Exception | None = None) -> None:
|
|
71
|
+
def fatal(object: any, exception: Exception | None = None) -> None:
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- You can use `exception` parameter to log the exception details along with a custom message in `error` and `fatal` methods in `v3.2.0` or later.
|
|
75
|
+
|
|
76
|
+
Each function outputs the log in each log level.
|
|
77
|
+
|
|
78
|
+
## `ShowError` Function
|
|
79
|
+
|
|
80
|
+
This outputs the error logs and stuck trace.
|
|
81
|
+
|
|
82
|
+
Function:
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
def ShowError(
|
|
86
|
+
ex: Exception,
|
|
87
|
+
message: str | None = None,
|
|
88
|
+
fatal: bool = False
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
|Property|Required|Value|
|
|
93
|
+
|--------|--------|-----|
|
|
94
|
+
|**`ex`**|\*|Exception|
|
|
95
|
+
|**`message`**||Custom error message|
|
|
96
|
+
|**`fatal`**||Show error as `FATAL`|
|
|
97
|
+
|
|
98
|
+
- If `fatal=True`, it outputs log as a `FATAL` log level.
|
|
99
|
+
|
|
100
|
+
## Usage
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
from maplex
|
|
104
|
+
|
|
105
|
+
logger = maplex.getLogger("FunctionName")
|
|
106
|
+
logger.info("Hello there!")
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
This outputs:
|
|
110
|
+
|
|
111
|
+
```console
|
|
112
|
+
[INFO ][FunctionName] <module>(4) Hello there!
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
File output will be: `AppLog.log`
|
|
116
|
+
|
|
117
|
+
```log
|
|
118
|
+
(PsNo) yyyy-MM-dd HH:mm:ss.fff [INFO ][FunctionName] <module>(4) Hello there!
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Log Level
|
|
122
|
+
|
|
123
|
+
- `TRACE`
|
|
124
|
+
- `DEBUG`
|
|
125
|
+
- `INFO`
|
|
126
|
+
- `WARN`
|
|
127
|
+
- `ERROR`
|
|
128
|
+
- `FATAL`
|
|
129
|
+
|
|
130
|
+
## Settings
|
|
131
|
+
|
|
132
|
+
- You can configure log settings with a JSON formatted file (default: `config.json`).
|
|
133
|
+
- If the configuration file does not exist, the instance auto-generates the file.
|
|
134
|
+
- Instance uses the parameter values to auto-generate a configuration file, or uses the default value if it was not specified.
|
|
135
|
+
|
|
136
|
+
Auto-generated configuration file (parameters not specified):
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"MapleLogger": {
|
|
141
|
+
"ConsoleLogLevel": "INFO",
|
|
142
|
+
"FileLogLevel": "INFO",
|
|
143
|
+
"MaxLogSize": 3,
|
|
144
|
+
"WorkingDirectory": "logs",
|
|
145
|
+
"FileEncoding": "utf-8",
|
|
146
|
+
"Formats": {
|
|
147
|
+
"Timestamp": {
|
|
148
|
+
"Format": "%F %X.%f",
|
|
149
|
+
"Digits": null
|
|
150
|
+
},
|
|
151
|
+
"ConsoleLogFormat": "[{level}]{func} {callerFunc}{callerLine}",
|
|
152
|
+
"FileLogFormat": "({pid}) {timestamp} [{level}]{func} {callerName}{callerFunc}({callerLine})",
|
|
153
|
+
"Separator": ": "
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
|Key|Value|
|
|
160
|
+
|---|-----|
|
|
161
|
+
|**`ConsoleLogLevel`**|Console log level|
|
|
162
|
+
|**`FileLogLevel`**|File log level|
|
|
163
|
+
|**`MaxLogSize`**|Log file max size (MB)|
|
|
164
|
+
|**`WorkingDirectory`**|Log file output path|
|
|
165
|
+
|**`FileEncoding`**|Log file encoding|
|
|
166
|
+
|**`Formats`**|Log format settings|
|
|
167
|
+
|**`NameSpaces`**|Namespace specific log level settings|
|
|
168
|
+
|
|
169
|
+
- To disable the log output, set the log level to `NONE`.
|
|
170
|
+
- You can use a `float` number for the file max size (E.g., `2.5` for `2.5MB`)
|
|
171
|
+
- You can also use a `str` for the file max size (E.g., `"3M"`)
|
|
172
|
+
- You can set the timestamp format with the `Format` key in the `Timestamp` section of the `Formats` settings.
|
|
173
|
+
- The default format is `%F %X.%f`, which outputs the timestamp as `yyyy-MM-dd HH:mm:ss.fff`. You can use any valid Python datetime format string.
|
|
174
|
+
- You can set the number of digits for the timestamp with the `Digits` key in the `Timestamp` section of the `Formats` settings.
|
|
175
|
+
|
|
176
|
+
### Formats
|
|
177
|
+
|
|
178
|
+
`v3.2.0` or later
|
|
179
|
+
|
|
180
|
+
- You can set the log format for console and file output with the `ConsoleLogFormat` and `FileLogFormat` keys in the `Formats` settings.
|
|
181
|
+
- Also, you can set the timestamp format with the `Format` key in the `Timestamp` section of the `Formats` settings.
|
|
182
|
+
|
|
183
|
+
```json
|
|
184
|
+
{
|
|
185
|
+
"MapleLogger": {
|
|
186
|
+
"Formats": {
|
|
187
|
+
"Timestamp": {
|
|
188
|
+
"Format": "%F %X.%f",
|
|
189
|
+
"Digits": -3
|
|
190
|
+
},
|
|
191
|
+
"ConsoleLogFormat": "[{level}]{func} {callerFunc}{callerLine}",
|
|
192
|
+
"FileLogFormat": "({pid}) {timestamp} [{level}]{func} {callerName}{callerFunc}({callerLine})",
|
|
193
|
+
"Separator": ": "
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
|Key|Value|
|
|
200
|
+
|---|-----|
|
|
201
|
+
|**`Timestamp.Format`**|Timestamp format string|
|
|
202
|
+
|**`Timestamp.Digits`**|Number of digits for the timestamp|
|
|
203
|
+
|**`ConsoleLogFormat`**|Console log format string|
|
|
204
|
+
|**`FileLogFormat`**|File log format string|
|
|
205
|
+
|**`Separator`**|Separator string between prefix and message|
|
|
206
|
+
|
|
207
|
+
- You can use standard Python datetime format strings for the `Timestamp.Format` key. For example, `%F %X.%f` outputs the timestamp as `yyyy-MM-dd HH:mm:ss.fff`.
|
|
208
|
+
- You can set the number of digits for the timestamp with the `Timestamp.Digits` key.
|
|
209
|
+
- The default value is `null`, which outputs the full length of the timestamp.
|
|
210
|
+
- However, I recommend using `-3` to output the timestamp with milliseconds, which is the most common format for logging.
|
|
211
|
+
- You can use a negative number to specify the number of digits to output from the end of the timestamp. For example, `-3` cuts the last three digits of the timestamp, which outputs the timestamp as `yyyy-MM-dd HH:mm:ss.fff`.
|
|
212
|
+
- You can use the following placeholders in the log format strings:
|
|
213
|
+
|
|
214
|
+
`{pid}`: Process ID
|
|
215
|
+
`{timestamp}`: Timestamp
|
|
216
|
+
`{level}`: Log level
|
|
217
|
+
`{func}`: Function name
|
|
218
|
+
`{callerName}`: Caller function name
|
|
219
|
+
`{callerFunc}`: Caller function name (with module name)
|
|
220
|
+
`{callerLine}`: Caller line number
|
|
221
|
+
|
|
222
|
+
### Namespace Specific Log Level Settings
|
|
223
|
+
|
|
224
|
+
- You can set the log level for specific namespaces by adding a `NameSpaces` key in the configuration file.
|
|
225
|
+
- The `NameSpaces` key is a list of dictionaries, where each dictionary contains a `NameSpace`, a `ConsoleLogLevel`, and a `FileLogLevel`.
|
|
226
|
+
|
|
227
|
+
Example:
|
|
228
|
+
|
|
229
|
+
```json
|
|
230
|
+
{
|
|
231
|
+
"MapleLogger": {
|
|
232
|
+
"ConsoleLogLevel": "INFO",
|
|
233
|
+
"FileLogLevel": "INFO",
|
|
234
|
+
"NameSpaces": [
|
|
235
|
+
{
|
|
236
|
+
"NameSpace": "MyNamespace",
|
|
237
|
+
"ConsoleLogLevel": "DEBUG",
|
|
238
|
+
"FileLogLevel": "INFO"
|
|
239
|
+
}
|
|
240
|
+
]
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
- In this example, the log level for the `MyNamespace` namespace is set to `DEBUG` for console output and `INFO` for file output. All other namespaces will use the default log levels specified in the `ConsoleLogLevel` and `FileLogLevel` keys.
|
|
246
|
+
- You can use this setting to control the log output for different parts of your application, allowing you to have more detailed logs for specific namespaces while keeping the overall log output at a higher level.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MapleX
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.2.0
|
|
4
4
|
Summary: A Python library for simple logging, json file operations, Maple file format operations, and console color utilities.
|
|
5
5
|
Author: Ryuji Hazama
|
|
6
6
|
Project-URL: PyPI, https://pypi.org/project/MapleX/
|
|
@@ -16,8 +16,8 @@ Classifier: Operating System :: OS Independent
|
|
|
16
16
|
Requires-Python: >=3.12
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
|
-
Requires-Dist: cryptography>=
|
|
20
|
-
Requires-Dist: pydantic>=2.
|
|
19
|
+
Requires-Dist: cryptography>=49.0.0
|
|
20
|
+
Requires-Dist: pydantic>=2.13.4
|
|
21
21
|
Dynamic: license-file
|
|
22
22
|
|
|
23
23
|
# MapleX
|
|
@@ -29,6 +29,10 @@ src/maplex/library/logger/file_handler.py
|
|
|
29
29
|
src/maplex/library/logger/formatter.py
|
|
30
30
|
src/maplex/library/logger/log_levels.py
|
|
31
31
|
src/maplex/library/logger/utilities.py
|
|
32
|
+
src/maplex/library/logger/consts/__init__.py
|
|
33
|
+
src/maplex/library/logger/consts/config_keys.py
|
|
34
|
+
src/maplex/library/logger/consts/defaults.py
|
|
35
|
+
src/maplex/library/logger/consts/dict_keys.py
|
|
32
36
|
tests/test_logger_unittest.py
|
|
33
37
|
tests/test_maplejson_unittest.py
|
|
34
38
|
tests/test_mapletree_unittest.py
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Split mapleLogger.py into multiple files for better organization and maintainability.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .config import LoggerConfig
|
|
5
|
+
from .config import LoggerConfig, TimeStamp
|
|
6
6
|
from .file_handler import FileHandler
|
|
7
7
|
from .formatter import Formatter
|
|
8
8
|
from .log_levels import LogLevel
|
|
@@ -14,6 +14,7 @@ __all__ = [
|
|
|
14
14
|
"LoggerConfig",
|
|
15
15
|
"LogLevel",
|
|
16
16
|
"getConsoleColors",
|
|
17
|
+
"TimeStamp",
|
|
17
18
|
"toLogLevel",
|
|
18
19
|
"toLogSize",
|
|
19
20
|
"isLogLevel"
|
|
@@ -21,6 +21,18 @@ from .utilities import *
|
|
|
21
21
|
from library.logger.log_levels import LogLevel
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
class TimeStamp(BaseModel):
|
|
25
|
+
|
|
26
|
+
timestampFormat: str | None = None
|
|
27
|
+
digits: int | None = None
|
|
28
|
+
|
|
29
|
+
class Formats(BaseModel):
|
|
30
|
+
|
|
31
|
+
consoleFormat: str | None = None
|
|
32
|
+
fileFormat: str | None = None
|
|
33
|
+
separator: str | None = None
|
|
34
|
+
timestamp: TimeStamp | None = None
|
|
35
|
+
|
|
24
36
|
class LoggerConfig(BaseModel):
|
|
25
37
|
|
|
26
38
|
func: str | None = None
|
|
@@ -32,12 +44,10 @@ class LoggerConfig(BaseModel):
|
|
|
32
44
|
fileMode: Literal["append", "overwrite", "daily"] | None = None
|
|
33
45
|
configFile: str = "config.json"
|
|
34
46
|
encoding: str | None = None
|
|
35
|
-
timestampFormat: str | None = None
|
|
36
47
|
getLogger: bool | None = None
|
|
37
48
|
consoleAlignWidth: int | None = None
|
|
38
49
|
fileAlignWidth: int | None = None
|
|
39
|
-
|
|
40
|
-
fileFormat: str = FILE_FORMAT
|
|
50
|
+
formats: Formats | None = None
|
|
41
51
|
|
|
42
52
|
logConfInstance: None = None
|
|
43
53
|
logConf: dict[str, object] | None = None
|
|
@@ -51,9 +61,7 @@ class LoggerConfig(BaseModel):
|
|
|
51
61
|
try:
|
|
52
62
|
|
|
53
63
|
super().__init__(**config)
|
|
54
|
-
|
|
55
64
|
self.consoleColors = getConsoleColors()
|
|
56
|
-
|
|
57
65
|
self.logConfInstance = self.checkConfigFile(config.get(CONFIG_FILE, self.configFile))
|
|
58
66
|
self.checkOutputDirectory(config.get(WORKING_DIRECTORY, None))
|
|
59
67
|
self.setLogFileName(config.get(FILE_MODE, "append"))
|
|
@@ -62,11 +70,13 @@ class LoggerConfig(BaseModel):
|
|
|
62
70
|
self.setLogFileSize(config.get(MAX_LOG_SIZE, None))
|
|
63
71
|
self.setOutputLogLevels(config.get(CONSOLE_LOG_LEVEL, None), config.get(FILE_LOG_LEVEL, None))
|
|
64
72
|
self.setFileEncoding(config.get(FILE_ENCODING, None))
|
|
65
|
-
self.setTimestampFormat(config.get(
|
|
73
|
+
self.setTimestampFormat(config.get(PARAM_TIMESTAMP, None))
|
|
74
|
+
self.setOutputFormat(config.get(CONSOLE_LOG_FORMAT, None), config.get(FILE_LOG_FORMAT, None), config.get(SEPARATOR, None))
|
|
66
75
|
self.saveLogSettings(self.logConfInstance)
|
|
67
76
|
|
|
68
77
|
except Exception as ex:
|
|
69
78
|
|
|
79
|
+
print(ex)
|
|
70
80
|
print(f"{self.consoleColors.Red}Error: Failed to initialize logger config: {ex}{self.consoleColors.Reset}")
|
|
71
81
|
raise ex
|
|
72
82
|
|
|
@@ -245,10 +255,26 @@ class LoggerConfig(BaseModel):
|
|
|
245
255
|
print(f"{self.consoleColors.Red}Warning: Infinite log file size is not recommended. Using default value.{self.consoleColors.Reset}")
|
|
246
256
|
self.maxLogSize = 3000000
|
|
247
257
|
|
|
258
|
+
def getLogLevel(self) -> None:
|
|
259
|
+
|
|
260
|
+
'''
|
|
261
|
+
Get LogLevel configuration from config file.
|
|
262
|
+
Set namespace specific LogLevel if available, otherwise set default LogLevel.
|
|
263
|
+
'''
|
|
264
|
+
|
|
265
|
+
namespaceSettings = self.logConf.get(NAME_SPACES, [])
|
|
266
|
+
thisNamespaceSettings = next((ns for ns in namespaceSettings if ns.get(NAME_SPACE) == self.callerName), None)
|
|
267
|
+
|
|
268
|
+
if thisNamespaceSettings is not None:
|
|
269
|
+
|
|
270
|
+
self.consoleLogLevel = thisNamespaceSettings.get(CONSOLE_LOG_LEVEL, None)
|
|
271
|
+
self.fileLogLevel = thisNamespaceSettings.get(FILE_LOG_LEVEL, None)
|
|
272
|
+
|
|
248
273
|
def setOutputLogLevels(self, cmdLogLevel: object, fileLogLevel: object) -> None:
|
|
249
274
|
|
|
250
|
-
self.
|
|
251
|
-
self.
|
|
275
|
+
self.getLogLevel()
|
|
276
|
+
self.consoleLogLevel = self.__setLogLevel(CONSOLE_LOG_LEVEL, cmdLogLevel if self.consoleLogLevel is None else self.consoleLogLevel)
|
|
277
|
+
self.fileLogLevel = self.__setLogLevel(FILE_LOG_LEVEL, fileLogLevel if self.fileLogLevel is None else self.fileLogLevel)
|
|
252
278
|
|
|
253
279
|
def __setLogLevel(self, fileOrConsole, loglevel: object) -> LogLevel:
|
|
254
280
|
|
|
@@ -260,7 +286,7 @@ class LoggerConfig(BaseModel):
|
|
|
260
286
|
|
|
261
287
|
else:
|
|
262
288
|
|
|
263
|
-
tempLogLevel = self.logConf.get(fileOrConsole,
|
|
289
|
+
tempLogLevel = self.logConf.get(fileOrConsole, None)
|
|
264
290
|
|
|
265
291
|
if tempLogLevel is None:
|
|
266
292
|
|
|
@@ -293,24 +319,107 @@ class LoggerConfig(BaseModel):
|
|
|
293
319
|
|
|
294
320
|
self.encoding = fileEncoding
|
|
295
321
|
|
|
296
|
-
def setTimestampFormat(self, timestampFormat:
|
|
322
|
+
def setTimestampFormat(self, timestampFormat: dict) -> None:
|
|
297
323
|
|
|
298
324
|
"""Set timestamp format for logs. Default is "%F %X.%f" (e.g. 2024-06-01 12:34:56.789). You can set this in config file with key "TimestampFormat"."""
|
|
299
325
|
|
|
326
|
+
if self.formats is None:
|
|
327
|
+
|
|
328
|
+
self.formats = Formats()
|
|
329
|
+
|
|
330
|
+
if self.formats.timestamp is None:
|
|
331
|
+
|
|
332
|
+
self.formats.timestamp = TimeStamp()
|
|
333
|
+
|
|
300
334
|
if timestampFormat is not None:
|
|
301
335
|
|
|
302
|
-
self.timestampFormat = timestampFormat
|
|
336
|
+
self.formats.timestamp.timestampFormat = timestampFormat.get(FORMAT, None)
|
|
337
|
+
self.formats.timestamp.digits = timestampFormat.get(DIGITS, 3)
|
|
303
338
|
|
|
304
339
|
else:
|
|
305
340
|
|
|
306
|
-
|
|
341
|
+
timestampSettings = self.logConf.get(FORMATS, {}).get(TIMESTAMP, {})
|
|
342
|
+
configTimestampFormat = timestampSettings.get(FORMAT, None)
|
|
343
|
+
configTimestampDigits = timestampSettings.get(DIGITS, None)
|
|
307
344
|
|
|
308
345
|
if configTimestampFormat is None:
|
|
309
346
|
|
|
310
|
-
configTimestampFormat =
|
|
311
|
-
|
|
347
|
+
configTimestampFormat = TIMESTAMP_FORMAT
|
|
348
|
+
timestampSettings[FORMAT] = configTimestampFormat
|
|
349
|
+
self.logConf.setdefault(FORMATS, {})[TIMESTAMP] = timestampSettings
|
|
350
|
+
|
|
351
|
+
if configTimestampDigits is None:
|
|
352
|
+
|
|
353
|
+
configTimestampDigits = MILLISECOND_DIGITS
|
|
354
|
+
timestampSettings[DIGITS] = configTimestampDigits
|
|
355
|
+
self.logConf.setdefault(FORMATS, {})[TIMESTAMP] = timestampSettings
|
|
356
|
+
|
|
357
|
+
if "TimestampFormat" in self.logConf:
|
|
358
|
+
|
|
359
|
+
# Show warning if old config key is used
|
|
360
|
+
print(f"{self.consoleColors.Yellow}Warning: 'TimestampFormat' key in config file is deprecated. Please use 'Formats.Timestamp' instead.{self.consoleColors.Reset}\nMore details: https://github.com/Ryuji-Hazama/MapleTree/blob/main/readmes/README_Logger.md#settings")
|
|
361
|
+
|
|
362
|
+
self.formats.timestamp.timestampFormat = configTimestampFormat
|
|
363
|
+
self.formats.timestamp.digits = configTimestampDigits
|
|
364
|
+
|
|
365
|
+
def setOutputFormat(self, consoleFormat: str, fileFormat: str, separator: str | None = None) -> None:
|
|
366
|
+
|
|
367
|
+
"""Set output format for console and file logs. Default is "[{level}]{func} {callerFunc}{callerLine}" for console and "({pid}) {timestamp} [{level}]{func} {callerName}{callerFunc}({callerLine})" for file. You can set this in config file with keys "ConsoleLogFormat" and "FileLogFormat"."""
|
|
368
|
+
|
|
369
|
+
if self.formats is None:
|
|
370
|
+
|
|
371
|
+
self.formats = Formats()
|
|
372
|
+
|
|
373
|
+
# Console format
|
|
374
|
+
|
|
375
|
+
if consoleFormat is not None:
|
|
376
|
+
|
|
377
|
+
self.formats.consoleFormat = consoleFormat
|
|
378
|
+
|
|
379
|
+
else:
|
|
380
|
+
|
|
381
|
+
self.formats.consoleFormat = self.logConf.get(FORMATS, {}).get(CONSOLE_LOG_FORMAT, None)
|
|
382
|
+
|
|
383
|
+
if self.formats.consoleFormat is None:
|
|
384
|
+
|
|
385
|
+
self.formats.consoleFormat = CONSOLE_FORMAT
|
|
386
|
+
formatConf = self.logConf.get(FORMATS, {})
|
|
387
|
+
formatConf[CONSOLE_LOG_FORMAT] = CONSOLE_FORMAT
|
|
388
|
+
self.logConf[FORMATS] = formatConf
|
|
389
|
+
|
|
390
|
+
# File format
|
|
391
|
+
|
|
392
|
+
if fileFormat is not None:
|
|
393
|
+
|
|
394
|
+
self.formats.fileFormat = fileFormat
|
|
395
|
+
|
|
396
|
+
else:
|
|
397
|
+
|
|
398
|
+
self.formats.fileFormat = self.logConf.get(FORMATS, {}).get(FILE_LOG_FORMAT, None)
|
|
399
|
+
|
|
400
|
+
if self.formats.fileFormat is None:
|
|
401
|
+
|
|
402
|
+
self.formats.fileFormat = FILE_FORMAT
|
|
403
|
+
formatConf = self.logConf.get(FORMATS, {})
|
|
404
|
+
formatConf[FILE_LOG_FORMAT] = FILE_FORMAT
|
|
405
|
+
self.logConf[FORMATS] = formatConf
|
|
406
|
+
|
|
407
|
+
# Message separator
|
|
408
|
+
|
|
409
|
+
if separator is not None:
|
|
410
|
+
|
|
411
|
+
self.formats.separator = separator
|
|
412
|
+
|
|
413
|
+
else:
|
|
414
|
+
|
|
415
|
+
self.formats.separator = self.logConf.get(FORMATS, {}).get(SEPARATOR, None)
|
|
416
|
+
|
|
417
|
+
if self.formats.separator is None:
|
|
312
418
|
|
|
313
|
-
|
|
419
|
+
self.formats.separator = DEFAULT_SEPARATOR
|
|
420
|
+
formatConf = self.logConf.get(FORMATS, {})
|
|
421
|
+
formatConf[SEPARATOR] = DEFAULT_SEPARATOR
|
|
422
|
+
self.logConf[FORMATS] = formatConf
|
|
314
423
|
|
|
315
424
|
def saveLogSettings(self, logConfInstance: MapleJson | None) -> None:
|
|
316
425
|
|
|
@@ -348,12 +457,12 @@ class LoggerConfig(BaseModel):
|
|
|
348
457
|
MAX_LOG_SIZE: self.maxLogSize,
|
|
349
458
|
FILE_MODE: "daily" if self.logfile and "log_" in self.logfile else "append",
|
|
350
459
|
FILE_ENCODING: self.encoding,
|
|
351
|
-
|
|
460
|
+
TIMESTAMP: self.formats.timestamp if self.formats.timestamp else None,
|
|
352
461
|
GET_LOGGER: bool(self.func),
|
|
353
462
|
CONSOLE_ALIGN_WIDTH: self.consoleAlignWidth,
|
|
354
463
|
FILE_ALIGN_WIDTH: self.fileAlignWidth,
|
|
355
|
-
|
|
356
|
-
|
|
464
|
+
PARAM_CONSOLE_FORMAT: self.formats.consoleFormat,
|
|
465
|
+
PARAM_FILE_FORMAT: self.formats.fileFormat,
|
|
357
466
|
PROCESS_ID: self.pid
|
|
358
467
|
}
|
|
359
468
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from .config_keys import *
|
|
2
|
+
from .defaults import *
|
|
3
|
+
from .dict_keys import *
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"CONFIG_KEY",
|
|
7
|
+
"CONSOLE",
|
|
8
|
+
"FILE",
|
|
9
|
+
"CONSOLE_LOG_LEVEL",
|
|
10
|
+
"FILE_LOG_LEVEL",
|
|
11
|
+
"MAX_LOG_SIZE",
|
|
12
|
+
"FILE_MODE",
|
|
13
|
+
"WORKING_DIRECTORY",
|
|
14
|
+
"FILE_ENCODING",
|
|
15
|
+
"FORMATS",
|
|
16
|
+
"TIMESTAMP",
|
|
17
|
+
"FORMAT",
|
|
18
|
+
"DIGITS",
|
|
19
|
+
"ALIGN_WIDTH",
|
|
20
|
+
"CONSOLE_LOG_FORMAT",
|
|
21
|
+
"FILE_LOG_FORMAT",
|
|
22
|
+
"SEPARATOR",
|
|
23
|
+
"NAME_SPACES",
|
|
24
|
+
"NAME_SPACE",
|
|
25
|
+
# Dictionary keys for internal use
|
|
26
|
+
"GET_LOGGER",
|
|
27
|
+
"FUNC",
|
|
28
|
+
"CONFIG_FILE",
|
|
29
|
+
"CONSOLE_ALIGN_WIDTH",
|
|
30
|
+
"FILE_ALIGN_WIDTH",
|
|
31
|
+
"CALLER_NAME",
|
|
32
|
+
"PROCESS_ID",
|
|
33
|
+
"PARAM_TIMESTAMP",
|
|
34
|
+
"PARAM_FORMATS",
|
|
35
|
+
"PARAM_CONSOLE_FORMAT",
|
|
36
|
+
"PARAM_FILE_FORMAT",
|
|
37
|
+
# Default values
|
|
38
|
+
"FILE_FORMAT",
|
|
39
|
+
"CONSOLE_FORMAT",
|
|
40
|
+
"DEFAULT_SEPARATOR",
|
|
41
|
+
"TIMESTAMP_FORMAT",
|
|
42
|
+
"MILLISECOND_DIGITS",
|
|
43
|
+
"FILE_MODE_OVERWRITE",
|
|
44
|
+
"FILE_MODE_DAILY",
|
|
45
|
+
]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
CONFIG_KEY = "MapleLogger"
|
|
2
|
+
CONSOLE = "Console"
|
|
3
|
+
FILE = "File"
|
|
4
|
+
CONSOLE_LOG_LEVEL = "ConsoleLogLevel"
|
|
5
|
+
FILE_LOG_LEVEL = "FileLogLevel"
|
|
6
|
+
MAX_LOG_SIZE = "MaxLogSize"
|
|
7
|
+
FILE_MODE = "FileMode"
|
|
8
|
+
WORKING_DIRECTORY = "WorkingDirectory"
|
|
9
|
+
FILE_ENCODING = "FileEncoding"
|
|
10
|
+
|
|
11
|
+
FORMATS = "Formats"
|
|
12
|
+
CONSOLE_LOG_FORMAT = "ConsoleLogFormat"
|
|
13
|
+
FILE_LOG_FORMAT = "FileLogFormat"
|
|
14
|
+
SEPARATOR = "Separator"
|
|
15
|
+
TIMESTAMP = "Timestamp"
|
|
16
|
+
FORMAT = "Format"
|
|
17
|
+
DIGITS = "Digits"
|
|
18
|
+
|
|
19
|
+
ALIGN_WIDTH = "AlignWidth"
|
|
20
|
+
NAME_SPACES = "NameSpaces"
|
|
21
|
+
NAME_SPACE = "NameSpace"
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
FILE_FORMAT = '({pid}) {timestamp} [{level}]{func} {callerName}{callerFunc}({callerLine})'
|
|
2
|
+
CONSOLE_FORMAT = '[{level}]{func} {callerFunc}{callerLine}'
|
|
3
|
+
DEFAULT_SEPARATOR = ': '
|
|
4
|
+
TIMESTAMP_FORMAT = "%F %X.%f"
|
|
5
|
+
MILLISECOND_DIGITS = None
|
|
6
|
+
FILE_MODE_OVERWRITE = 'overwrite'
|
|
7
|
+
FILE_MODE_DAILY = 'daily'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
CONFIG_FILE = "configFile"
|
|
2
|
+
FUNC = "func"
|
|
3
|
+
GET_LOGGER = "getLogger"
|
|
4
|
+
CONSOLE_ALIGN_WIDTH = "consoleAlignWidth"
|
|
5
|
+
FILE_ALIGN_WIDTH = "fileAlignWidth"
|
|
6
|
+
CALLER_NAME = "CallerName"
|
|
7
|
+
PROCESS_ID = "pid"
|
|
8
|
+
PARAM_TIMESTAMP = "timestamp"
|
|
9
|
+
PARAM_FORMATS = "formats"
|
|
10
|
+
PARAM_CONSOLE_FORMAT = "consoleFormat"
|
|
11
|
+
PARAM_FILE_FORMAT = "fileFormat"
|
|
@@ -7,6 +7,7 @@ from datetime import datetime
|
|
|
7
7
|
import inspect
|
|
8
8
|
import os
|
|
9
9
|
|
|
10
|
+
from .config import TimeStamp
|
|
10
11
|
from .consts import *
|
|
11
12
|
from .log_levels import *
|
|
12
13
|
from .utilities import *
|
|
@@ -29,8 +30,10 @@ class Formatter:
|
|
|
29
30
|
self.consoleColors = getConsoleColors()
|
|
30
31
|
self.logLevel = LogLevel
|
|
31
32
|
self.config = config
|
|
32
|
-
self.consoleFormat = config.get(
|
|
33
|
-
self.fileFormat = config.get(
|
|
33
|
+
self.consoleFormat = config.get(PARAM_CONSOLE_FORMAT, CONSOLE_FORMAT)
|
|
34
|
+
self.fileFormat = config.get(PARAM_FILE_FORMAT, FILE_FORMAT)
|
|
35
|
+
self.timestampFormat = self.config.get(TIMESTAMP, TimeStamp()).timestampFormat or TIMESTAMP_FORMAT
|
|
36
|
+
self.timestampDigits = config.get(TIMESTAMP, TimeStamp()).digits or MILLISECOND_DIGITS
|
|
34
37
|
self.pid = os.getpid()
|
|
35
38
|
self.COLOR_CODE_LENGTH = 5
|
|
36
39
|
self.COLOR_CODE_RESET_LENGTH = 4
|
|
@@ -69,7 +72,7 @@ class Formatter:
|
|
|
69
72
|
|
|
70
73
|
return colorCodeLength
|
|
71
74
|
|
|
72
|
-
def __getCurrentTimestamp(self
|
|
75
|
+
def __getCurrentTimestamp(self) -> str:
|
|
73
76
|
|
|
74
77
|
"""
|
|
75
78
|
Get the current timestamp formatted according to the specified format string.
|
|
@@ -78,7 +81,7 @@ class Formatter:
|
|
|
78
81
|
:return: The current timestamp as a formatted string.
|
|
79
82
|
"""
|
|
80
83
|
|
|
81
|
-
return datetime.now().strftime(timestampFormat)
|
|
84
|
+
return datetime.now().strftime(self.timestampFormat)[:self.timestampDigits]
|
|
82
85
|
|
|
83
86
|
def __getLogLevelColor(self, logLevel: LogLevel) -> str:
|
|
84
87
|
|
|
@@ -142,7 +145,7 @@ class Formatter:
|
|
|
142
145
|
|
|
143
146
|
if '{timestamp}' in consoleFormat:
|
|
144
147
|
|
|
145
|
-
timestamp = self.__getCurrentTimestamp(
|
|
148
|
+
timestamp = self.__getCurrentTimestamp()
|
|
146
149
|
consoleFormat = consoleFormat.replace('{timestamp}', timestamp)
|
|
147
150
|
|
|
148
151
|
if '{level}' in consoleFormat:
|
|
@@ -193,7 +196,7 @@ class Formatter:
|
|
|
193
196
|
|
|
194
197
|
if '{timestamp}' in fileFormat:
|
|
195
198
|
|
|
196
|
-
timestamp = self.__getCurrentTimestamp(
|
|
199
|
+
timestamp = self.__getCurrentTimestamp()
|
|
197
200
|
fileFormat = fileFormat.replace('{timestamp}', timestamp)
|
|
198
201
|
|
|
199
202
|
if '{level}' in fileFormat:
|
|
@@ -28,7 +28,7 @@ class Logger:
|
|
|
28
28
|
fileMode: Literal["append", "overwrite", "daily"] | None = None,
|
|
29
29
|
configFile: str = "config.json",
|
|
30
30
|
encoding: str | None = None,
|
|
31
|
-
|
|
31
|
+
timestamp: TimeStamp | None = None,
|
|
32
32
|
**kwargs
|
|
33
33
|
) -> None:
|
|
34
34
|
|
|
@@ -48,7 +48,7 @@ class Logger:
|
|
|
48
48
|
"fileMode": fileMode,
|
|
49
49
|
"configFile": configFile,
|
|
50
50
|
"encoding": encoding,
|
|
51
|
-
"
|
|
51
|
+
"timestamp": timestamp,
|
|
52
52
|
"getLogger": kwargs.get("getLogger", False),
|
|
53
53
|
"consoleAlignWidth": kwargs.get("consoleAlignWidth", 16),
|
|
54
54
|
"fileAlignWidth": kwargs.get("fileAlignWidth", 4)
|
|
@@ -166,7 +166,7 @@ class Logger:
|
|
|
166
166
|
|
|
167
167
|
if loglevel >= self.config.consoleLogLevel:
|
|
168
168
|
consolePrefix = self.formatter.format_console(loglevel, callerDepth)
|
|
169
|
-
print(f"{consolePrefix}
|
|
169
|
+
print(f"{consolePrefix}{self.config.formats.separator}{message}")
|
|
170
170
|
|
|
171
171
|
if loglevel >= self.config.fileLogLevel:
|
|
172
172
|
|
|
@@ -177,7 +177,7 @@ class Logger:
|
|
|
177
177
|
try:
|
|
178
178
|
|
|
179
179
|
with open(self.config.logfile, "a", encoding=self.config.encoding) as f:
|
|
180
|
-
print(f"{prefixString}
|
|
180
|
+
print(f"{prefixString}{self.config.formats.separator}{message}", file=f)
|
|
181
181
|
|
|
182
182
|
break
|
|
183
183
|
|
|
@@ -235,21 +235,33 @@ class Logger:
|
|
|
235
235
|
################################
|
|
236
236
|
# Error
|
|
237
237
|
|
|
238
|
-
def error(self, object: any):
|
|
238
|
+
def error(self, object: any, exception: Exception | None = None):
|
|
239
239
|
|
|
240
240
|
'''Error log'''
|
|
241
241
|
|
|
242
|
-
|
|
242
|
+
if exception is None:
|
|
243
|
+
|
|
244
|
+
self.logWriter(self.LogLevel.ERROR, object, callerDepth=self.DEFAULT_CALLER_DEPTH)
|
|
245
|
+
|
|
246
|
+
else:
|
|
247
|
+
|
|
248
|
+
self.ShowError(exception, message=f"{object}", fatal=False, additionalCallerDepth=1)
|
|
243
249
|
|
|
244
250
|
#
|
|
245
251
|
################################
|
|
246
252
|
# Fatal
|
|
247
253
|
|
|
248
|
-
def fatal(self, object: any):
|
|
254
|
+
def fatal(self, object: any, exception: Exception | None = None):
|
|
249
255
|
|
|
250
256
|
'''Fatal log'''
|
|
251
257
|
|
|
252
|
-
|
|
258
|
+
if exception is None:
|
|
259
|
+
|
|
260
|
+
self.logWriter(self.LogLevel.FATAL, object, callerDepth=self.DEFAULT_CALLER_DEPTH)
|
|
261
|
+
|
|
262
|
+
else:
|
|
263
|
+
|
|
264
|
+
self.ShowError(exception, message=f"{object}", fatal=True, additionalCallerDepth=1)
|
|
253
265
|
|
|
254
266
|
#
|
|
255
267
|
################################
|
|
@@ -265,7 +277,7 @@ class Logger:
|
|
|
265
277
|
################################
|
|
266
278
|
# Error messages
|
|
267
279
|
|
|
268
|
-
def ShowError(self, ex: Exception, message: str | None = None, fatal: bool = False):
|
|
280
|
+
def ShowError(self, ex: Exception, message: str | None = None, fatal: bool = False, additionalCallerDepth: int = 0) -> None:
|
|
269
281
|
|
|
270
282
|
'''Show and log error'''
|
|
271
283
|
|
|
@@ -279,9 +291,9 @@ class Logger:
|
|
|
279
291
|
|
|
280
292
|
if message is not None:
|
|
281
293
|
|
|
282
|
-
self.logWriter(logLevel, message, callerDepth=self.DEFAULT_CALLER_DEPTH)
|
|
294
|
+
self.logWriter(logLevel, message, callerDepth=self.DEFAULT_CALLER_DEPTH + additionalCallerDepth)
|
|
283
295
|
|
|
284
|
-
self.logWriter(logLevel, f"{ex}\n{traceback.format_exc()}", callerDepth=self.DEFAULT_CALLER_DEPTH)
|
|
296
|
+
self.logWriter(logLevel, f"{ex}\n{traceback.format_exc()}", callerDepth=self.DEFAULT_CALLER_DEPTH + additionalCallerDepth)
|
|
285
297
|
|
|
286
298
|
#
|
|
287
299
|
################################
|
|
@@ -377,9 +389,9 @@ ToDo list:
|
|
|
377
389
|
|
|
378
390
|
* Logger *
|
|
379
391
|
|
|
380
|
-
- Add option to set date format
|
|
381
|
-
- Add set* functions
|
|
382
392
|
- Configure log format in config file
|
|
393
|
+
- Configure mili sec digits
|
|
394
|
+
- Add set* functions
|
|
383
395
|
|
|
384
396
|
"""
|
|
385
397
|
""" * * * * * * * * * * * * * """
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
# Logger Class
|
|
2
|
-
|
|
3
|
-
Logger class is a logging object for Python applications. It outputs application logs to log files and to standard output.
|
|
4
|
-
|
|
5
|
-
## Logger Initialization
|
|
6
|
-
|
|
7
|
-
```python
|
|
8
|
-
def __init__(
|
|
9
|
-
func: str = "",
|
|
10
|
-
workingDirectory: str | None = None,
|
|
11
|
-
cmdLogLevel: str | None = None,
|
|
12
|
-
fileLogLevel: str | None = None,
|
|
13
|
-
maxLogSize: float | None = None,
|
|
14
|
-
fileMode: Literal["append", "overwrite", "daily"] | None = None,
|
|
15
|
-
configFile: str = "config.json",
|
|
16
|
-
encoding: str | None = None,
|
|
17
|
-
) -> None:
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
|Property|Required|Value|Version|
|
|
21
|
-
|--------|--------|-----|-------|
|
|
22
|
-
|**`func`**||Primary function name||
|
|
23
|
-
|**`workingDirectory`**||Log file output directory||
|
|
24
|
-
|**`cmdLogLevel`**||Terminal output log level||
|
|
25
|
-
|**`fileLogLevel`**||Log file output log level||
|
|
26
|
-
|**`maxLogSize`**||Log file max size (MB)||
|
|
27
|
-
|**`fileMode`**||Logging file mode|`v3.0`|
|
|
28
|
-
|**`configFile`**||Logger configuration file path|`v3.0`|
|
|
29
|
-
|**`encoding`**||Log file encoding|`v3.0`|
|
|
30
|
-
|
|
31
|
-
The parameter overwrites the settings configured in `config.mpl`.
|
|
32
|
-
|
|
33
|
-
## Functions
|
|
34
|
-
|
|
35
|
-
### `getLogger()`
|
|
36
|
-
|
|
37
|
-
```python
|
|
38
|
-
def getLogger(
|
|
39
|
-
name = "",
|
|
40
|
-
**kwargs
|
|
41
|
-
) -> maplex.Logger:
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
|Property|Required|Value|Version|
|
|
45
|
-
|--------|--------|-----|-------|
|
|
46
|
-
|**`name`**||Primary funcion name|`v3.0`|
|
|
47
|
-
|**`**kwargs`**||Other parameters|`v3.0`|
|
|
48
|
-
|
|
49
|
-
This get or creates a Logger instance.
|
|
50
|
-
|
|
51
|
-
If you already have a Logger class instance with the same name, the function returns the existing instance, and you can save your resources on the machine.
|
|
52
|
-
|
|
53
|
-
```python
|
|
54
|
-
from maplex
|
|
55
|
-
|
|
56
|
-
logger = maplex.getLogger(__name__)
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## Getters and Setters
|
|
60
|
-
|
|
61
|
-
Every class parameter has its own getter and setter functions, and you can set, change, or get those values after initializing the class.
|
|
62
|
-
|
|
63
|
-
## Logging Methods
|
|
64
|
-
|
|
65
|
-
```python
|
|
66
|
-
def trace(object: any) -> None:
|
|
67
|
-
def debug(object: any) -> None:
|
|
68
|
-
def info(object: any) -> None:
|
|
69
|
-
def warn(object: any) -> None:
|
|
70
|
-
def error(object: any) -> None:
|
|
71
|
-
def fatal(object: any) -> None:
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
Each function outputs the log in each log level.
|
|
75
|
-
|
|
76
|
-
## `ShowError` Function
|
|
77
|
-
|
|
78
|
-
This outputs the error logs and stuck trace.
|
|
79
|
-
|
|
80
|
-
Function:
|
|
81
|
-
|
|
82
|
-
```python
|
|
83
|
-
def ShowError(
|
|
84
|
-
ex: Exception,
|
|
85
|
-
message: str | None = None,
|
|
86
|
-
fatal: bool = False
|
|
87
|
-
)
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
|Property|Required|Value|
|
|
91
|
-
|--------|--------|-----|
|
|
92
|
-
|**`ex`**|\*|Exception|
|
|
93
|
-
|**`message`**||Custom error message|
|
|
94
|
-
|**`fatal`**||Show error as `FATAL`|
|
|
95
|
-
|
|
96
|
-
- If `fatal=True`, it outputs log as a `FATAL` log level.
|
|
97
|
-
|
|
98
|
-
## Usage
|
|
99
|
-
|
|
100
|
-
```python
|
|
101
|
-
from maplex
|
|
102
|
-
|
|
103
|
-
logger = maplex.getLogger("FunctionName")
|
|
104
|
-
logger.info("Hello there!")
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
This outputs:
|
|
108
|
-
|
|
109
|
-
```console
|
|
110
|
-
[INFO ][FunctionName] <module>(4) Hello there!
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
File output will be: `AppLog.log`
|
|
114
|
-
|
|
115
|
-
```log
|
|
116
|
-
(PsNo) yyyy-MM-dd HH:mm:ss.fff [INFO ][FunctionName] <module>(4) Hello there!
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
### Log Level
|
|
120
|
-
|
|
121
|
-
- `TRACE`
|
|
122
|
-
- `DEBUG`
|
|
123
|
-
- `INFO`
|
|
124
|
-
- `WARN`
|
|
125
|
-
- `ERROR`
|
|
126
|
-
- `FATAL`
|
|
127
|
-
|
|
128
|
-
## Settings
|
|
129
|
-
|
|
130
|
-
- You can configure log settings with a JSON formatted file (default: `config.json`).
|
|
131
|
-
- If the configuration file does not exist, the instance auto-generates the file.
|
|
132
|
-
- Instance uses the parameter values to auto-generate a configuration file, or uses the default value if it was not specified.
|
|
133
|
-
|
|
134
|
-
Auto-generated configuration file (parameters not specified):
|
|
135
|
-
|
|
136
|
-
```json
|
|
137
|
-
{
|
|
138
|
-
"MapleLogger": {
|
|
139
|
-
"ConsoleLogLevel": "INFO",
|
|
140
|
-
"FileLogLevel": "INFO",
|
|
141
|
-
"MaxLogSize": 3.0,
|
|
142
|
-
"WorkingDirectory": "/path/to/output/logs",
|
|
143
|
-
"FileEncoding": "utf-8"
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
|Key|Value|
|
|
149
|
-
|---|-----|
|
|
150
|
-
|**`ConsoleLogLevel`**|Console log level|
|
|
151
|
-
|**`FileLogLevel`**|File log level|
|
|
152
|
-
|**`MaxLogSize`**|Log file max size (MB)|
|
|
153
|
-
|**`WorkingDirectory`**|Log file output path|
|
|
154
|
-
|**`FileEncoding`**|Log file encoding|
|
|
155
|
-
|
|
156
|
-
- To disable the log output, set the log level to `NONE`.
|
|
157
|
-
- You can use a `float` number for the file max size (E.g., `2.5` for `2.5MB`)
|
|
158
|
-
- You can also use a `str` for the file max size (E.g., `"3M"`)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|