Updated README.md
Completed a README file containing a description of what the project is and how it works. Along with examples on how to use the library, reasons to use the project, and how it compares to built-in libraries.
This commit is contained in:
parent
f22e6ea554
commit
8ca27b5f81
206
README.md
206
README.md
|
|
@ -0,0 +1,206 @@
|
||||||
|
# CLog – ClosedLess Logger
|
||||||
|
Logging as simple as putting on a shoe.
|
||||||
|
|
||||||
|
## What is CLog?
|
||||||
|
Clog (stylised as 'CLog') is a basic Python logging module which builds on top
|
||||||
|
of the built-in `print` function to provide richer outputs for general
|
||||||
|
information and debugging, to a display console, or in-depth output written to
|
||||||
|
a dedicated file.
|
||||||
|
|
||||||
|
Logging should be simple, and effective. That's why Clog is designed to do what
|
||||||
|
it does best, as simply and effectively for developers, without adding an
|
||||||
|
abundance of features. Logging can be performed simply by invoking pseudolog
|
||||||
|
methods with a message to be written out to a file (and written to console
|
||||||
|
using the `.withConsole()` method), or as advanced as calling the `printLog`
|
||||||
|
method with additional parameters found in the built-in `print` function.
|
||||||
|
|
||||||
|
It can be difficult to identify what text is debug information, warnings or
|
||||||
|
errors, from the remaining output. With this, Clog implements terminal
|
||||||
|
highlighting depending on the level which logging information is written at.
|
||||||
|
Any level which is identified as `DEBUG` or higher, is also written to the
|
||||||
|
`STDERR` pipe.
|
||||||
|
|
||||||
|
"CLog" officially stands for, 'ClosedLess Logger'. But it may be colloqually
|
||||||
|
known as some of the following:
|
||||||
|
- Cohesive Logging.
|
||||||
|
- Console Logging, and more.
|
||||||
|
- 'Clog' (noun) - a shoe with a thick wooden sole.
|
||||||
|
|
||||||
|
## How Does it Work?
|
||||||
|
As described, Clog merely acts as a wrapper over the built-in `print` function
|
||||||
|
and does not use system-level standard PIPE write operations directly. With
|
||||||
|
this, Clog exposes all keyword optional parameters of the `print` function, so
|
||||||
|
output can be modified respectfully to the `print` function.
|
||||||
|
|
||||||
|
Clog is a Singleton+Factory pattern class. This means that once the class has
|
||||||
|
been constructed by a user, another instance invoked will simply return the
|
||||||
|
defined, currently existing instance. Using a Singleton pattern allows for the
|
||||||
|
integrity of a class' state. Something like the defined logging output file
|
||||||
|
cannot ever be changed after the instance is initially constructed. This in
|
||||||
|
turn means that every instance created for the logging system will never be
|
||||||
|
out-of-sync from any other instance created. It is a Factory pattern since the class' state can be modified and returned from an invoked method.
|
||||||
|
|
||||||
|
The core wrapper responsible for invoking the `print` function with specified
|
||||||
|
optional parameters, is a private helper method called `__printLog__` of the
|
||||||
|
`Logger` class. All other methods defined in the class, in some way, call this
|
||||||
|
helper wrapper method.
|
||||||
|
|
||||||
|
Given a `TextIOWrapper` object (or of similar with the `SupportsWrite` type),
|
||||||
|
a `print` function can write directly to that object when passed as the `file=`
|
||||||
|
parameter. This introduces the `printLog2File` method, which is similar to the
|
||||||
|
`printLog` method; however, `printLog2File` is appropriate for handling strings
|
||||||
|
as pathspecs, in addition to `TextIOWrapper` objects.
|
||||||
|
|
||||||
|
It may come to reason to allow for `printLog` to handle this ability as well,
|
||||||
|
which would make `printLog2File` redundant. Well, `printLog2File` has a lot of
|
||||||
|
dedicated functionality specifically for writing to a file, which would
|
||||||
|
otherwise make `printLog` bulky and confusing. For example, `printLog2File`
|
||||||
|
allows for timestamped messages, simple stacktraces to identify what method
|
||||||
|
invoked a log call, and to ensure that ANSI escape codes (used for terminal
|
||||||
|
highlighting) are not written to file, and a lot more.
|
||||||
|
|
||||||
|
The use of pseudolog methods can make logging very simple and short, but with
|
||||||
|
the ability to not only write to file, but also to the console, lazily. A
|
||||||
|
pseudolog (or, `Logger` pseudonyms) method is a type of `Logger` method which
|
||||||
|
implies a defined level of logging. There are three pseudologs: `debug`,
|
||||||
|
`warn`, and `error`. Each of these methods are decorated with the `classmethod`
|
||||||
|
decorator to allow for the defined Singleton instance to be modified and return
|
||||||
|
itself after being invoked. From this, the `.withConsole()` method may be
|
||||||
|
invoked directly after calling a pseudolog, or later if the returned instance
|
||||||
|
from the pseudolog is stored. This is why pseudologs are considered lazy since
|
||||||
|
the call to write to console can be performed later as the information is
|
||||||
|
stored by the class' state.
|
||||||
|
|
||||||
|
**But be careful!** Pseudologs invoked with `.withConsole()` will write the
|
||||||
|
last-most message written to the file, to the console, meaning if another
|
||||||
|
pseudolog is invoked, the class state is changed, and the previous message
|
||||||
|
stored will be lost.
|
||||||
|
|
||||||
|
## How to Use CLog
|
||||||
|
Clog is very simple to use in any project you wish to start making use of
|
||||||
|
logging systems within your code base. Simply import the package, or bring
|
||||||
|
the `Logger` class into scope directly.
|
||||||
|
|
||||||
|
```py
|
||||||
|
import clog
|
||||||
|
|
||||||
|
logger = Logger()
|
||||||
|
logger.printLog("Hello, Word!")
|
||||||
|
# NOTE: 'printLog' is a static method of 'Logger'
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```py
|
||||||
|
import clog
|
||||||
|
# or: from clog import Logger
|
||||||
|
|
||||||
|
clog.Logger.printLog("Hello, World!")
|
||||||
|
# or Logger.printLog(...) if brought into scope
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logging based on success of code
|
||||||
|
The following is an example whereby similar behaviour can be found using the
|
||||||
|
built-in `print(..., end="")` to prevent a newline character from being
|
||||||
|
printed. The following `printLog` call afterwards will print the message and a
|
||||||
|
newline character. This allows for acknowledgement of a process about to
|
||||||
|
perform a given task, with a success statement attached to the end of the line.
|
||||||
|
|
||||||
|
```py
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import clog
|
||||||
|
|
||||||
|
logger = Logger(out_f="my_log_file.txt") # custom file path
|
||||||
|
my_file = "some_important_file.txt"
|
||||||
|
|
||||||
|
logger.printLog("Checking if file exists...", end="")
|
||||||
|
logger.printLog2File(f"Ensuring that file is present: {my_file}")
|
||||||
|
|
||||||
|
if not os.path.exists(my_file):
|
||||||
|
logger.printLog2File("File could not be found in the current",
|
||||||
|
"working directory. Exiting (1)...")
|
||||||
|
logger.printLog("failed.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
logger.printLog("ok.")
|
||||||
|
logger.printLog2File("File was successfully found.")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logging with pseudologs
|
||||||
|
Sometimes it's conventient to write one message, and have it logged both to a
|
||||||
|
file, and the terminal. By using a pseudolog method, logging is guaranteed to
|
||||||
|
be written to file, and optionally the same message can be sent to the
|
||||||
|
terminal with highlighting and identical formatting using the `.withConsole()`
|
||||||
|
method.
|
||||||
|
|
||||||
|
```py
|
||||||
|
import clog
|
||||||
|
|
||||||
|
# pseudologs require accessing an instance
|
||||||
|
logger = Logger()
|
||||||
|
|
||||||
|
logger.debug("Checking integrity of operations...").withConsole()
|
||||||
|
if 1 + 1 == 2:
|
||||||
|
logger.debug("Mathematics is not broken.").withConsole()
|
||||||
|
else:
|
||||||
|
logger.error("Mathematics is broken!!").withConsole()
|
||||||
|
```
|
||||||
|
|
||||||
|
## Why Use CLog and not Another Library
|
||||||
|
It's difficult to justify a dependence into your project, especially when you
|
||||||
|
can either perform that dependence yourself, or use a different method to solve
|
||||||
|
the problem. However, here are some reasons to consider using Clog yourself:
|
||||||
|
|
||||||
|
- CLog provides you with the basic logging tools out of the box.
|
||||||
|
- Additional features, such as control over logging elevation and colouring of
|
||||||
|
text.
|
||||||
|
- CLog uses built-in functions and no external dependences (ex. testing/dev).
|
||||||
|
- There is guarantee over where information is logged to, and correctly.
|
||||||
|
- It's simple and effective to use (well documented).
|
||||||
|
- Guarantees backwards compatibility to version 3.6 and sooner.
|
||||||
|
- CLog is completely open-source under the GNU GPLv3 or later. You can inspect
|
||||||
|
the code base at will, and completely integrate the code base into your
|
||||||
|
project (with respect to the defined licence agreement).
|
||||||
|
|
||||||
|
## Comparison Between `clog` and `logging`
|
||||||
|
You might be wondering which is better: using a library that makes your code
|
||||||
|
dependent on the maintanence and upkeep of an external library; or, using a
|
||||||
|
built-in library that comes with the installation. Well it depends on the
|
||||||
|
use-case and preferences, but here are some overviews between both libraries:
|
||||||
|
|
||||||
|
- `logging` is built-in, whereas `clog` is a dependency.
|
||||||
|
- `logging` provides the ability to have multiple logging instances. `clog` is
|
||||||
|
a Singleton pattern, which can be re-instantiated if desired.
|
||||||
|
- `logging` has basic and advanced features depending on how much you want to
|
||||||
|
get out of a logging utility. `clog` just works as its intended.
|
||||||
|
- Basic output from `logging` is simple, but ugly. `clog` provides a clear
|
||||||
|
indication of log elevation using terminal hightlighting, as well as conforming
|
||||||
|
to defined standards, such as ISO 8601 timestamps in log files out-of-the-box.
|
||||||
|
- `logging` requires configuration to get more advanced behaviour. `clog`
|
||||||
|
provides majority of this behaviour without configuration, and further
|
||||||
|
configuration can be performed when logging.
|
||||||
|
- `logging` provides "handlers" for separate stream and file outputs. `clog`
|
||||||
|
handles this under-the-hood, but allows for changing between stream and file
|
||||||
|
pipes where applicable. `clog` can also do both at the same time if desired.
|
||||||
|
- Tracebacks can be essential to debugging problems, and both libraries
|
||||||
|
provide a traceback. `logging` provides this functionality during an exception
|
||||||
|
being raised. `clog` provides a basic traceback with every messaged written to
|
||||||
|
a log file (unless disabled on write), stating where the call was made to log.
|
||||||
|
- `logging` provides handlers to write to more than just streams and files. It
|
||||||
|
can write to sockets, emails, OS event systems, and more. `clog` only handles
|
||||||
|
stream and file writes; however, if `print()` can write to it, so can `clog`.
|
||||||
|
|
||||||
|
These are just some key comparisons between both libraries, and whether or not
|
||||||
|
each point is advantageous for one library or the other depends on the
|
||||||
|
developer's use-case – it does not mean one is objectively better than the
|
||||||
|
other. Which library is used depends on the use-case, but both could be used.
|
||||||
|
|
||||||
|
## Licence
|
||||||
|
This project is licensed under the GNU GPLv3 or later licence agreement, which
|
||||||
|
hereby states that this software does not come with warranty or liability.
|
||||||
|
|
||||||
|
For more, please consult the `LICENCE.txt` file.
|
||||||
|
|
||||||
|
## Author
|
||||||
|
Ethan Smith-Coss (`ethan.sc@closedless.xyz`)
|
||||||
|
|
||||||
|
Copyright (C) 2022-23
|
||||||
Loading…
Reference in New Issue
Block a user