Skip to content

Commit

Permalink
Merge pull request #1 from vfabi/develop
Browse files Browse the repository at this point in the history
[develop] rc 1.1.0
  • Loading branch information
vfabi authored Nov 25, 2024
2 parents 58da7bf + 46ea25d commit 93a0513
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 73 deletions.
25 changes: 25 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Python
__pycache__
__pycache__/
*.py[cod]
*.pyc
*.pyo

# Virtual environment
.env/
.venv/
.venv
venv/

# Special
**/.vscode
*.log
**/*.log
**/*.disabled
**/.venv
**/.tmp
**/.archive
**/.docs
**/dev
**/.dev

12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## [1.1.0] - 2024-11-25

### Added

### Changed

### Fixed

- Small fixes
- Added WARNING severity level


## [1.0.0] - 2024-03-28

### Added
Expand Down
49 changes: 24 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,38 @@
# python-app-logger

![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/vfabi/python-app-logger)
![GitHub last commit](https://img.shields.io/github/last-commit/vfabi/python-app-logger)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

A custom python applications logging handler. Use custom JSON format and sends logs via Telegram Bot Api.
Python applications custom logging handler. Use custom JSON format and sends logs via Telegram Bot API.

## Status

Production ready

## Features
- Custom stream JSON logging handler
- Custom JSON stream logging handler
- Custom Telegram logging handler
- Telegram logging handler loglevel (severity) routing

## Usage

# Requirements and dependencies
- https://github.com/vfabi/python-telegram-handler


# Usage

## Setup
### Setup
Just run: `pip install git+https://github.com/vfabi/python-app-logger`

## Application integration
`get_loger` function arguments:
### Application integration
`get_logger()` function arguments:

Name | Type | Description | Mandatory | Default | Example
--- | --- | --- | --- | --- | ---
app_name | str | application short name | True | | `myapp` |
app_version | str | application version | False | | `1.0.1` |
app_environment | str | application environment | False | | `dev` |
loglevel | str | loglevel (severity) | False | `DEBUG` | Possible values: `DEBUG`,`INFO`,`WARNING`,`ERROR`,`CRITICAL`|
logger_name | str | logger name | False | `main` | `myapp` |
telegram_bot_id | str | Telegram bot id | False | | `1234567890:AAEwtYwterrqqq4RhXhl637vvvvvv` |
telegram_chat_ids | dict | dict with severity - Telegram chat id mapping | False | | `{'debug': '1234567890', 'info': '22334455', 'critical': '9988776655'}` |

```
app_name (str): application name. (MANDATORY)
app_version (str): application version. (MANDATORY)
app_environment (str): application environment. (MANDATORY)
loglevel (str): loglevel (severity). (OPTIONAL)
logger_name (str): logger name. (OPTIONAL)
telegram_bot_id (str): Telegram bot id. (OPTIONAL)
telegram_chat_ids (dict): dict with severity - Telegram chat id mapping. Example: {'debug': '1234567890', 'info': '22334455', 'critical': '9988776655'}. (OPTIONAL)
```

Example:

Expand All @@ -58,8 +59,7 @@ logger.warning('WARNING_MESSAGE')
logger.critical('CRITICAL_MESSAGE')
```


# Contributing
## Contributing
Please refer to each project's style and contribution guidelines for submitting patches and additions. In general, we follow the "fork-and-pull" Git workflow.

1. **Fork** the repo on GitHub
Expand All @@ -70,6 +70,5 @@ Please refer to each project's style and contribution guidelines for submitting

NOTE: Be sure to merge the latest from "upstream" before making a pull request!


# License
Apache 2.0
## License
Apache 2.0
104 changes: 58 additions & 46 deletions python_app_logger/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@


DEFAULT_LOGLEVEL = 'DEBUG'
DEFAULT_LOGGER_NAME = 'main'
DEFAULT_LOGGER_NAME = 'app'


class EMOJI:
'''
Note:
More details and examples at https://www.webfx.com/tools/emoji-cheat-sheet/
Note: more details and examples at https://www.webfx.com/tools/emoji-cheat-sheet/
'''

WHITE_CIRCLE = '⚪'
GREEN_CIRCLE = '🟢'
BLUE_CIRCLE = '🔵'
RED_CIRCLE = '🔴'
YELLOW_CIRCLE = '🟡'
ORANGE_CIRCLE = '🟠'
RED_CIRCLE = '🔴'


class CustomHtmlFormatter(HtmlFormatter):
Expand All @@ -46,9 +46,13 @@ def format(self, record):
elif record.levelno == logging.INFO:
record.levelname = EMOJI.GREEN_CIRCLE + ' ' + record.levelname
elif record.levelno == logging.WARNING:
record.levelname = EMOJI.YELLOW_CIRCLE + ' ' + record.levelname
elif record.levelno == logging.ERROR:
record.levelname = EMOJI.ORANGE_CIRCLE + ' ' + record.levelname
else:
elif record.levelno == logging.CRITICAL:
record.levelname = EMOJI.RED_CIRCLE + ' ' + record.levelname
else:
record.levelname = EMOJI.BLUE_CIRCLE + ' ' + record.levelname

if hasattr(self, '_style'):
return self._style.format(record)
Expand All @@ -57,7 +61,7 @@ def format(self, record):
return self._fmt % record.__dict__


class CustomJSONOpensearchFormatter(logging.Formatter):
class CustomJSONFormatter(logging.Formatter):
'''
Custom JSON formatter to be compatible with Opensearch index format.
Expand Down Expand Up @@ -87,19 +91,18 @@ class SeverityFilter(object):
def __init__(self, level):
self.__level = level

def filter(self, logRecord):
return logRecord.levelno <= self.__level
def filter(self, log_record):
return log_record.levelno <= self.__level


def get_logger(
app_name,
app_version,
app_environment,
app_version=None,
app_environment=None,
loglevel=DEFAULT_LOGLEVEL,
logger_name=DEFAULT_LOGGER_NAME,
telegram_bot_id=None,
telegram_chat_ids={}
):
telegram_chat_ids=None):
'''
Args:
app_name (str): application name.
Expand All @@ -113,46 +116,53 @@ def get_logger(

logger = logging.getLogger(logger_name)

# Stream JSON
# Handler JSON
formatter_json = CustomJSONFormatter('{"app": {"name": "%(app_name)s", "localtime": "%(asctime)s", "environment": "%(app_environment)s", "severity": "%(levelname)s", "message": %(message)s, "version": "%(app_version)s", "logger": "%(name)s", "source": "%(pathname)s:%(funcName)s(%(lineno)d)", "source_pathname": "%(pathname)s", "source_funcname": "%(funcName)s", "source_lineno": "%(lineno)d"}}')
handler_json = logging.StreamHandler()
formatter = CustomJSONOpensearchFormatter('{"app": {"name": "%(app_name)s", "localtime": "%(asctime)s", "environment": "%(app_environment)s", "severity": "%(levelname)s", "message": %(message)s, "version": "%(app_version)s", "logger": "%(name)s", "source": "%(pathname)s:%(funcName)s(%(lineno)d)", "source_pathname": "%(pathname)s", "source_funcname": "%(funcName)s", "source_lineno": "%(lineno)d"}}')
handler_json.setFormatter(formatter)
logger.setLevel(loglevel)
handler_json.setFormatter(formatter_json)
handler_json.setLevel(loglevel)
logger.addHandler(handler_json)

# Telegram
telegram_formatter = CustomHtmlFormatter(
# Handler Telegram
formatter_telegram = CustomHtmlFormatter(
use_emoji=True,
fmt = '<b>%(app_name)s (%(app_version)s)</b> <b>%(levelname)s</b>\n\n<b>Message:</b> <code>%(message)s</code>\n<b>Environment:</b> %(app_environment)s\n<b>Source:</b> %(pathname)s:%(funcName)s(%(lineno)d)\n<b>Datetime:</b> %(asctime)s\n<b>Logger:</b> %(name)s\n'
fmt='<b>%(app_name)s (%(app_version)s)</b> <b>%(levelname)s</b>\n\n<b>Message:</b> <code>%(message)s</code>\n<b>Environment:</b> %(app_environment)s\n<b>Source:</b> %(pathname)s:%(funcName)s(%(lineno)d)\n<b>Datetime:</b> %(asctime)s\n<b>Logger:</b> %(name)s\n'
)
if telegram_bot_id and len(telegram_chat_ids) > 0:
if telegram_chat_ids.get('critical'):
handler_telegram_critical = TelegramHandler(level=logging.CRITICAL, token=telegram_bot_id, chat_id=telegram_chat_ids['critical'], message_thread_id='0')
handler_telegram_critical.setLevel('CRITICAL')
handler_telegram_critical.addFilter(SeverityFilter(logging.CRITICAL))
handler_telegram_critical.setFormatter(telegram_formatter)
logger.addHandler(handler_telegram_critical)
if telegram_chat_ids.get('warning'):
handler_telegram_warning = TelegramHandler(level=logging.WARNING, token=telegram_bot_id, chat_id=telegram_chat_ids['warning'], message_thread_id='0')
handler_telegram_warning.setLevel('WARNING')
handler_telegram_warning.addFilter(SeverityFilter(logging.WARNING))
handler_telegram_warning.setFormatter(telegram_formatter)
logger.addHandler(handler_telegram_warning)
if telegram_chat_ids.get('info'):
handler_telegram_info = TelegramHandler(level=logging.INFO, token=telegram_bot_id, chat_id=telegram_chat_ids['info'], message_thread_id='0')
handler_telegram_info.setLevel('INFO')
handler_telegram_info.addFilter(SeverityFilter(logging.INFO))
handler_telegram_info.setFormatter(telegram_formatter)
logger.addHandler(handler_telegram_info)
if telegram_chat_ids.get('debug'):
handler_telegram_debug = TelegramHandler(level=logging.DEBUG, token=telegram_bot_id, chat_id=telegram_chat_ids['debug'], message_thread_id='0')
handler_telegram_debug.setLevel('DEBUG')
handler_telegram_debug.addFilter(SeverityFilter(logging.DEBUG))
handler_telegram_debug.setFormatter(telegram_formatter)
logger.addHandler(handler_telegram_debug)
if telegram_chat_ids:
if telegram_bot_id and len(telegram_chat_ids) > 0:
if telegram_chat_ids.get('critical'):
handler_telegram_critical = TelegramHandler(level=logging.CRITICAL, token=telegram_bot_id, chat_id=telegram_chat_ids['critical'], message_thread_id='0')
handler_telegram_critical.setFormatter(formatter_telegram)
handler_telegram_critical.setLevel('CRITICAL')
handler_telegram_critical.addFilter(SeverityFilter(logging.CRITICAL))
logger.addHandler(handler_telegram_critical)
if telegram_chat_ids.get('error'):
handler_telegram_error = TelegramHandler(level=logging.ERROR, token=telegram_bot_id, chat_id=telegram_chat_ids['error'], message_thread_id='0')
handler_telegram_error.setFormatter(formatter_telegram)
handler_telegram_error.setLevel('ERROR')
handler_telegram_error.addFilter(SeverityFilter(logging.ERROR))
logger.addHandler(handler_telegram_error)
if telegram_chat_ids.get('warning'):
handler_telegram_warning = TelegramHandler(level=logging.WARNING, token=telegram_bot_id, chat_id=telegram_chat_ids['warning'], message_thread_id='0')
handler_telegram_warning.setFormatter(formatter_telegram)
handler_telegram_warning.setLevel('WARNING')
handler_telegram_warning.addFilter(SeverityFilter(logging.WARNING))
logger.addHandler(handler_telegram_warning)
if telegram_chat_ids.get('info'):
handler_telegram_info = TelegramHandler(level=logging.INFO, token=telegram_bot_id, chat_id=telegram_chat_ids['info'], message_thread_id='0')
handler_telegram_info.setFormatter(formatter_telegram)
handler_telegram_info.setLevel('INFO')
handler_telegram_info.addFilter(SeverityFilter(logging.INFO))
logger.addHandler(handler_telegram_info)
if telegram_chat_ids.get('debug'):
handler_telegram_debug = TelegramHandler(level=logging.DEBUG, token=telegram_bot_id, chat_id=telegram_chat_ids['debug'], message_thread_id='0')
handler_telegram_debug.setFormatter(formatter_telegram)
handler_telegram_debug.setLevel('DEBUG')
handler_telegram_debug.addFilter(SeverityFilter(logging.DEBUG))
logger.addHandler(handler_telegram_debug)

# Extend formatter with additional fields
logger = logging.LoggerAdapter(
logger_adapter = logging.LoggerAdapter(
logger,
{
"app_name": app_name,
Expand All @@ -161,4 +171,6 @@ def get_logger(
}
)

return logger
logger_adapter.logger.setLevel(loglevel)

return logger_adapter
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from distutils.core import setup

VERSION = '1.0.0'
VERSION = '1.1.0'
DESCRIPTION = 'A custom python applications logging handler. Use custom JSON format and sends logs via Telegram Bot Api.'
LONG_DESCRIPTION = open('README.md').read() + '\n\n' + open('CHANGELOG.md').read()

Expand All @@ -10,7 +10,7 @@
version=VERSION,
description=DESCRIPTION,
long_description=LONG_DESCRIPTION,
long_description_content_type = "text/markdown",
long_description_content_type="text/markdown",
keywords=['telegram', 'logging'],
packages=['python_app_logger'],
url='https://github.com/vfabi/python-app-logger',
Expand Down

0 comments on commit 93a0513

Please sign in to comment.