https://github.com/novemberfiveco/skidder-python
November Five's logging framework for Python
https://github.com/novemberfiveco/skidder-python
logging logging-framework logging-library python
Last synced: 3 months ago
JSON representation
November Five's logging framework for Python
- Host: GitHub
- URL: https://github.com/novemberfiveco/skidder-python
- Owner: novemberfiveco
- Created: 2021-06-08T13:46:44.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2023-09-14T07:43:02.000Z (over 2 years ago)
- Last Synced: 2024-12-28T10:29:00.029Z (about 1 year ago)
- Topics: logging, logging-framework, logging-library, python
- Language: Python
- Homepage:
- Size: 22.5 KB
- Stars: 2
- Watchers: 6
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Skidder
Skidder will drag your logs to where they need to go. A small, uniform and extensible logging library, implemented across major technologies.
## Installation
```commandline
pip install git+https://github.com/novemberfiveco/skidder-python@3.0.0
```
or using poetry
```commandline
poetry add git+https://github.com/novemberfiveco/skidder-python@3.0.0
```
## Usage
### Setup
Configure logging using the `configure_logging()` function once at the beginning of your program.
You can pass a value for the `component` field as required by N5's standards.
```python
from skidder import configure_logging
configure_logging(component='my-backend-service')
# note that we configure logging outside the AWS Lambda handler function
def handler(event, context):
...
```
### Logging events
Now that the logger is configured, just use the `get_logger()` function from *structlog* to get the correctly configured
logger anywhere inside your project.
```python
from structlog import get_logger
log = get_logger()
log.debug("This is a debug log")
log.info("This is an info log")
log.warn("This is a warn log")
log.error("This is an error log")
log.critical("This is a critical log")
```
When running this program locally, you receive pretty formatted log output:
````commandline
2021-07-12T18:04:48.248064Z [info ] This is an info log component=foo environment=None source=application type=event
````
However, in an actual environment, you should set the `ENV` environment variable, which will enable JSON logging:
````json5
{"component": "foo", "environment": "dev", "level": "info", "message": "This is an info log", "source": "application", "timestamp": "2021-07-12T18:07:08.674527Z", "type": "event"}
````
### Logging exceptions
You can pass an exception parameter to include a stacktrace in the log event:
````python
try:
raise Exception
except Exception as e:
log.error("API call to external service X failed due to timeout", exception=e)
````
### Including additional fields
You can also pass extra parameters to populate the `data` field with additional structured information:
````python
log.info("Synchronizing product catalog to store", store_id='store-123')
````
### Setting a request ID on your log events
Whenever possible, you should set the `requestId` field on log events to link them to a specific request for easy investigation.
You can manually set or unset:
```python
from structlog import bind_request_id, unbind_request_id
log.info("This log event is not part of a request")
def handler(event, context):
bind_request_id("my-request-123")
log.info("This log event is part of my-request-123")
unbind_request_id()
```
For convenience, there is also a decorator that automatically (un)binds a request ID whenever your function is called. By default, a new UUID is generated.
```python
from structlog import request_context_logging
log.info("This log event is not part of a request")
@request_context_logging
def handler(event, context):
log.info("This log event is part of a request")
```
You can also pass a function that provides the request ID (for example you might want to get it from an HTTP request header
to continue a request spanning multiple distributed services):
```python
from structlog import request_context_logging
log.info("This log event is not part of a request")
def request_id_from_header(event, context):
return event["headers"]["X-Trace-ID"]
@request_context_logging(request_id_provider=request_id_from_header)
def handler(event, context):
log.info("This log event is part of a request")
```
### Adding a LUMIGO_LOG prefix to error logs
When you want to have your error logs get noticed by Lumigo, they need a LUMIGO_LOG prefix.
This can be enabled by enabling the corresponding flag:
```python
from skidder import configure_logging
configure_logging(component='my-backend-service', enable_lumigo_prefix=True)
```
## Changelog
- 3.1.1
- removed Lumigo prefix from warning logs
- 3.1.0
- added Lumigo prefix to error logs
- 3.0.0
- rename repo to Skidder
- 2.0.2
- set minimum python version to 3.7
- 2.0.1
- Added check for IS_LOCAL env variable to check local development env
- 2.0.0
- Pin structlog dependency (because using private function that is not part of public structlog API and can change without notice)
- Set minimum logging level to DEBUG when in dev environment
- Log uncaught exceptions
- Intercept & process STDLIB logging
- Populate type field dynamically
- Populate source field dynamically
- Refactor into functions
- Allow binding request ID field
- Allow binding component field
- Disable JSON logging & enable pretty logging when executing locally
- Nest extra fields under the 'data' key
- 1.0.0
- basic setup according to N5 standard.