Minimal logging setup with utilities to represent interpreter stacks.
Project description
Yogger
Yogger provides a minimal logging setup with utilities to represent interpreter stacks.
Supports
requests.Requestandrequests.Responseobjects if the Requests package is installed.
Example of common usage:
import logging
import yogger
logger = logging.getLogger(__name__)
def main():
yogger.install()
yogger.configure(__name__, verbosity=2, dump_locals=True)
with yogger.dump_on_exception():
# Code goes here
if __name__ == "__main__":
main()
Requirements:
Yogger requires Python 3.10 or higher, is platform independent, and has no outside dependencies.
Issue reporting
If you discover an issue with Yogger, please report it at https://github.com/Phosmic/yogger/issues.
License
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
Requirements Installing Usage Library
Installing
Most stable version from PyPi:
python3 -m pip install yogger
Development version from GitHub:
git clone git+https://github.com/Phosmic/yogger.git
cd yogger
python3 -m pip install -e .
Usage
Import packages and instantiate a logger:
import logging
import yogger
logger = logging.getLogger(__name__)
Install the logger class and configure with your package name:
Place at the start of the top-level function.
def main():
yogger.install()
yogger.configure(__name__)
# Code goes here
Output
Example of logger output:
[ 2023-01-17 10:16:09.0918 INFO my_package ] Something we want to log.
[ 2023-01-17 10:16:09.0918 DEBUG my_package ] Something we want to log.
[ 2023-01-17 10:16:09.0918 WARNING my_package ] Something we want to log.
[ 2023-01-17 10:16:09.0918 ERROR my_package ] Something we want to log.`
[ 2023-01-17 10:16:09.0918 CRITICAL my_package ] Something we want to log.
Note: Support for rich text has not yet been added for Windows platforms.
Support for dumping the stack
Traces and exceptions
Using the dump_on_exception context manager dumps the exception and trace if an exception is raised:
with yogger.dump_on_exception(
# Uncomment to override
# dump_path="./stack_dump.txt",
):
raise SomeException
This is nearly equivalent to:
import inspect
try:
raise SomeException
except Exception as e:
trace = inspect.trace()
if len(trace) > 1:
with open("./stack_dump.txt", mode="a", encoding="utf-8") as f:
yogger.dump(f, trace[1:], e=e, package_name="my_package")
Stacks
Setting dump_locals=True when running yogger.configure dumps a representation of the caller's stack upon logging with a level of warning or higher.
To manually dump the stack, something like this would suffice:
import inspect
stack = inspect.stack()
if len(stack) > 2:
with open("./example.log", mode="w", encoding="utf-8") as f:
yogger.dump(f, stack[2:][::-1])
If you simply want the string representation, use the yogger.dumps function:
stack = inspect.stack()
if len(stack) > 2:
trace_repr = yogger.dumps(stack[2:][::-1])
Output
Example of dictionary representation in dump:
example = {
"user_id": 123456790,
"profile": {
"name": "John Doe",
"birthdate": datetime.date(2000, 1, 1),
"weight_kg": 86.18,
},
"video_ids": [123, 456, 789],
}
example = <builtins.dict>
example['user_id'] = 123456790
example['profile'] = <builtins.dict>
example['profile']['name'] = 'John Doe'
example['profile']['birthdate'] = datetime.date(2000, 1, 1)
example['profile']['weight_kg'] = 86.18
example['video_ids'] = [123, 456, 789]
Similarly for a dataclass:
@dataclasses.dataclass
class Example:
user_id: int
profile: dict[str, str | float | datetime.date]
video_ids: list[int]
example = <my_package.Example>
example.user_id = 'user_id' = example.user_id = 123456790
example.profile = 'profile' = example.profile = <builtins.dict>
example.profile['name'] = 'John Doe'
example.profile['birthdate'] = datetime.date(2000, 1, 1)
example.profile['weight_kg'] = 86.18
example.video_ids = 'video_ids' = example.video_ids = [123, 456, 789]
Library
About the package_name parameter
The package_name parameter gives Yogger an idea of what belongs to your application. This name is used to identify which frames to dump in the stack. So it’s important what you provide there. If you are using a single module, __name__ is always the correct value. If you are using a package, it’s usually recommended to hardcode the name of your package there.
For example, if your application is defined in "my_package/app.py", you should create it with one of the two versions below:
yogger.configure("my_package")
yogger.configure(__name__.split(".")[0])
Why is that? The application will work even with __name__, thanks to how resources are looked up. However, it will make debugging more painful. Yogger makes assumptions based on the import name of your application. If the import name is not properly set up, that debugging information may be lost.
yogger.pformat
Create a formatted representation of a variable's name and value.
This module is used to create a formatted representation of a variable's name and value.
pformat
def pformat(name: str,
value: Any,
outer_line_continuation: bool = True) -> str
Create a formatted representation of a variable's name and value.
Arguments:
namestr - Name of the variable to represent.valueAny - Value to represent.outer_line_continuationbool, optional - Whether the outermost representation should be line continued. Defaults to True.
Returns:
- str - Formatted representation of a variable's name and value.
yogger.base
Yogger Base Module
This module contains the base classes and functions for Yogger.
Yogger Objects
class Yogger(logging.Logger)
Yogger Logger Class
This class is used to override the default logging.Logger class.
install
def install() -> None
Install the Yogger Logger Class and Instantiate the Global Logger
configure
def configure(package_name: str,
*,
verbosity: int = 0,
dump_locals: bool = False,
dump_path: str | bytes | os.PathLike | None = None,
remove_handlers: bool = True) -> None
Prepare for Logging
Arguments:
package_namestr - Name of the package to dump from the stack.verbosityint, optional - Level of verbosity (0-2) for log messages. Defaults to 0.dump_localsbool, optional - Dump the caller's stack when logging with a level of warning or higher. Defaults to False.dump_pathstr | bytes | os.PathLike, optional - Custom path to use when dumping with 'dump_on_exception' or when 'dump_locals=True', otherwise use a temporary path if None. Defaults to None.remove_handlersbool, optional - Remove existing logging handlers before adding the new stream handler. Defaults to True.
dumps
def dumps(stack: list[inspect.FrameInfo],
*,
err: Exception | None = None,
package_name: str | None = None) -> str
Create a String Representation of an Interpreter Stack
Externalizes '_stack_dumps' to be accessed by the user.
Arguments:
stacklist[inspect.FrameInfo] - Stack of frames to represent.errException | None, optional - Exception that was raised. Defaults to None.package_namestr | None, optional - Name of the package to dump from the stack, otherwise non-exclusive if set to None. Defaults to None.
Returns:
- str - Representation of the stack.
dump
def dump(fp: io.TextIOBase | io.BytesIO,
stack: list[inspect.FrameInfo],
*,
err: Exception | None = None,
package_name: str | None = None) -> None
Write the Representation of an Interpreter Stack using a File Object
Arguments:
fpio.TextIOBase | io.BytesIO - File object to use for writing.stacklist[inspect.FrameInfo] - Stack of frames to dump.errException | None, optional - Exception that was raised. Defaults to None.package_namestr | None, optional - Name of the package to dump from the stack, otherwise non-exclusive if set to None. Defaults to None.
dump_on_exception
@contextlib.contextmanager
def dump_on_exception(
dump_path: str | bytes | os.PathLike | None = None
) -> Generator[None, None, None]
Content Manager to Dump if an Exception is Raised
Writes a representation of the exception and trace stack to file.
Arguments:
dump_pathstr | bytes | os.PathLike | None, optional - Override the file path to use for the dump. Defaults to None.
Yields:
- Generator[None, None, None] - Context manager.
Raises:
Exception- Exception that was raised.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file yogger-0.0.7.tar.gz.
File metadata
- Download URL: yogger-0.0.7.tar.gz
- Upload date:
- Size: 54.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.10.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7daafadd1c2d6800a6bd1768d8a328e0043d6e83cceaa5a4fbe06f67b73feb60
|
|
| MD5 |
94c9a1e8021045e847dc8ffeedc0045e
|
|
| BLAKE2b-256 |
a4c9adc43fd7035d3cb165a3197eacf249012a8ab707898392c2d3aa28491782
|
File details
Details for the file yogger-0.0.7-py3-none-any.whl.
File metadata
- Download URL: yogger-0.0.7-py3-none-any.whl
- Upload date:
- Size: 36.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.10.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1eb5e2fb553f736333795279bbd7b30ebc885897329f8d57ff3c5c4264d6dcf5
|
|
| MD5 |
ef11095b98dd636d3193c3eb4305325e
|
|
| BLAKE2b-256 |
260e3680648e02709c30d46749b28ceffd7f16271db957a3d4805cc0e3adbf4f
|