Skip to content

Commit

Permalink
Merge pull request #6 from MissterHao/feature/logging
Browse files Browse the repository at this point in the history
Add documentation and type hint for v1.1.1
  • Loading branch information
MissterHao authored Feb 13, 2023
2 parents 291138b + aaea2ed commit 0609efb
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 33 deletions.
48 changes: 35 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,26 @@ DynamoDB is Fast, flexible NoSQL database service for single-digit millisecond p

Using DynamoDB for session storage alleviates issues that occur with session handling in a distributed web application by moving sessions off of the local file system and into a shared location. [[1]]

+ Easy to use! All you need is add two lines of Code!
+ Support ttl attribute
+ Easy to use! All you need is add **2 lines** of Code!
+ Support **TTL(Time to Live) attribute**
Django's default session won't delete expired session data.
By using DynamoDB, we can take advantage of DynamoDB's ttl attrubute to auto delete expired session data.
+ Taking advantage of AWS serverless service! ( No more effort to maintain and autoscale )
+ No more effort to maintain and autoscale your session database ( Taking advantage of AWS serverless service! )
+ Provide beautiful, clearful and colorful error log


## Requirements
django-dysession use `boto3` to communicate with DynamoDB.
**django-dysession** use [boto3](https://aws.amazon.com/tw/sdk-for-python/) to interact with AWS DynamoDB.
Boto3 is the Amazon Web Services (AWS) Software Development Kit (SDK) for Python, which allows Python developers to write software that makes use of services like **DynamoDB**.

+ Django >= 3.2
+ boto3 >= 1.26.59

## Installation

Install from PyPI ( or manually download from PyPI):
Install from PyPI ( or manually download from [PyPI](https://pypi.org/project/django-dysession/#files) ):
```bash
pip install django-dysession
pip install -U django-dysession
```

## Getting Started
Expand Down Expand Up @@ -125,15 +126,36 @@ DYSESSION = {
"TTL_ATTRIBUTE_NAME": "ttl",
"CACHE_PERIOD": 3600,
"DYNAMODB_REGION": "ap-northeast-1",
"LOGGING": {
"TYPE": "CONSOLE",
},
}
```

| Argument | Default | Description |
|----------------------|----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| DYNAMODB_TABLENAME | sessions | DynamoDB table name |
| PARTITION_KEY_NAME | PK | Partition key name |
| TTL_ATTRIBUTE_NAME | ttl | Time to live attribute name |
| CACHE_PERIOD | 3600 | Define how long should be the cache live in DynamoDB's table |
| DYNAMODB_REGION | ap-northeast-1 | The region of the DynamoDB table |
| LOGGING | Dict | Configuration of Logging |
| LOGGING["TYPE"] | CONSOLE | Only accept two kinds of parameters: `CONSOLE`, `FILE`. If this set to `CONSOLE`, django-dysession will use `StreamHandler` to stream to the console. If this set to `FILE`, django-dysession will use `FileHandler` to stream to `LOGGING["FILE_PATH"]`. |
| LOGGING["FILE_PATH"] | session.log | Optional. Only use this configuration when LOGGING["TYPE"] is set to `FILE`. The file path to save logs of session managements. |

| Argument | Default | Description |
| ------------------ | -------------- | ------------------------------------------------------------ |
| DYNAMODB_TABLENAME | sessions | DynamoDB table name |
| PARTITION_KEY_NAME | PK | Partition key name |
| TTL_ATTRIBUTE_NAME | ttl | Time to live attribute name |
| CACHE_PERIOD | 3600 | Define how long should be the cache live in DynamoDB's table |
| DYNAMODB_REGION | ap-northeast-1 | The region of the DynamoDB table |

## Logging

Django-Dysession support three kinds of logging.

1. Colorful TTY-based Console Log

Support colorful and beautiful log when django-dysession interacting with AWS Dysession.
![](/asset/dysession-beautiful-error-log-example.png)
2. Default logging stream

Django-Dysession use python core library `logging.StreamHandler`
3. Default File Stream

Django-Dysession use python core library `logging.FileHandler`

Binary file added asset/dysession-beautiful-error-log-example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 3 additions & 4 deletions dysession/backends/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def _get_session(self, no_load=False) -> SessionDataModel:
def key_salt(self):
return "dysession.backends." + self.__class__.__qualname__

def is_empty(self):
def is_empty(self) -> bool:
"Return True when there is no session_key and the session is empty."
try:
return not self._session_key and not self._session_cache.is_empty
Expand All @@ -69,10 +69,10 @@ def clear(self):
super().clear()
self._session_cache = SessionDataModel()

def items(self):
def items(self) -> Dict[str, Any]:
return self._session.items()

def __str__(self):
def __str__(self) -> str:
return str(self._get_session())

# Methods that subclass must implement
Expand Down Expand Up @@ -124,7 +124,6 @@ def delete(self, session_key=None):
if session_key is None:
session_key = self._session_key


try:
self.db.delete(self._get_session())
except DeleteSessionError:
Expand Down
6 changes: 3 additions & 3 deletions dysession/backends/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,20 @@ def __delitem__(self, key):
def __iter__(self):
return iter(self.__variables_names)

def __is_empty(self):
def __is_empty(self) -> bool:
return len(self.__variables_names) == 0

is_empty = property(__is_empty)

def get(self, key, default=...):
def get(self, key, default=...) -> Any:
try:
return self[key]
except AttributeError:
if default is Ellipsis:
raise
return default

def pop(self, key, default=...):
def pop(self, key, default=...) -> Any:
try:
ret = self[key]
del self[key]
Expand Down
19 changes: 17 additions & 2 deletions dysession/logger/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
from functools import lru_cache
from typing import Literal

from dysession.settings import get_config

from .handler.colorful_console import ColorfulConsoleLoggerHandler


class LoggingType(Enum):
"""Enum of python logger type."""

PLAINTEXT_CONSOLE = auto()
COLOR_CONSOLE = auto()
Expand All @@ -23,7 +26,7 @@ def is_tty() -> bool:

def get_logger(
logger_name: str = "dysession",
logger_type: Literal[LoggingType.CONSOLE, LoggingType.FILE] = LoggingType.CONSOLE,
logger_type: Literal[None, LoggingType.CONSOLE, LoggingType.FILE] = None,
level: int = logging.DEBUG,
) -> logging.Logger:
"""
Expand All @@ -40,6 +43,17 @@ def get_logger(
```
"""

if logger_type is None:
try:
logger_type = LoggingType[get_config()["LOGGING"]["TYPE"]]
if (
logger_type == LoggingType.PLAINTEXT_CONSOLE
or logger_type == LoggingType.COLOR_CONSOLE
):
raise KeyError
except KeyError:
raise KeyError("logger_type only accept 'CONSOLE' and 'FILE'")

logger = logging.getLogger(logger_name)
format = logging.Formatter(
"[%(asctime)-s] [%(levelname)-8s] %(name)s %(message)s ... ( %(filename)s:%(levelno)s )"
Expand All @@ -53,7 +67,8 @@ def get_logger(
else:
handler = logging.StreamHandler()
elif logger_type == LoggingType.FILE:
handler = logging.FileHandler("session.log", "a", encoding="utf-8")
filepath = get_config()["LOGGING"].get("FILE_PATH", "session.log")
handler = logging.FileHandler(filepath, "a", encoding="utf-8")

handler.setFormatter(format)
logger.addHandler(handler)
Expand Down
3 changes: 2 additions & 1 deletion dysession/logger/handler/colorful_console.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import logging
from typing import Dict

from .ansi import ANSIColor

LOGLEVEL_TRANSFORM = {
LOGLEVEL_TRANSFORM: Dict[int, str] = {
logging.DEBUG: ANSIColor.DEBUG.value,
logging.INFO: ANSIColor.OKCYAN.value,
logging.WARNING: ANSIColor.WARNING.value,
Expand Down
6 changes: 6 additions & 0 deletions dysession/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
"TTL_ATTRIBUTE_NAME": "ttl",
"CACHE_PERIOD": 3600,
"DYNAMODB_REGION": "ap-northeast-1",
"LOGGING": {
"TYPE": "CONSOLE",
},
}


Expand All @@ -26,6 +29,9 @@ def get_config() -> Dict[str, Union[str, int]]:
* TTL_ATTRIBUTE_NAME
* CACHE_PERIOD
* DYNAMODB_REGION
* LOGGING
* TYPE
* FILE_PATH
Returns:
Dict[str, Union[str, int]]
Expand Down
2 changes: 1 addition & 1 deletion dysession/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.0
1.1.1
13 changes: 4 additions & 9 deletions tests/test_aws_dynamodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,10 @@
from moto import mock_dynamodb
from parameterized import parameterized

from dysession.aws.dynamodb import (
check_dynamodb_table_exists,
create_dynamodb_table,
delete_session_item,
destory_dynamodb_table,
get_item,
insert_session_item,
key_exists,
)
from dysession.aws.dynamodb import (check_dynamodb_table_exists,
create_dynamodb_table, delete_session_item,
destory_dynamodb_table, get_item,
insert_session_item, key_exists)
from dysession.aws.error import DynamodbItemNotFound, DynamodbTableNotFound
from dysession.backends.model import SessionDataModel
from dysession.settings import get_config
Expand Down

0 comments on commit 0609efb

Please sign in to comment.