Skip to main content

Escalite

Escalite Logo PyPI version Python versions codecov Snyk PyPI - Downloads Downloads License: MIT

A Python library for per-request logging and escalation, designed for API services.

Features

  • Supports multiple notifiers (Email, Slack, Telegram, WhatsApp)
  • Per-request logging using contextvars
  • Unique alert_id generation for each log session
  • Pluggable notifiers: Email, Slack, Telegram, WhatsApp and can be extended with custom notifiers
  • Flexible escalation with severity filtering (from_level)
  • Easy integration with FastAPI and other Python frameworks
  • Service call lifecycle logging (start_service_log/stop_service_log)
  • Context manager and manual logging support

Installation

Using pip:

pip install escalite

Using Poetry:

poetry add escalite

Configuration

Configure notifiers (e.g., email) in a dictionary format. Example:

notifier_configs = {
    "notifiers": [
        {
            "type": "email",
            "config": {
                "smtp_server": "smtp.example.com",
                "smtp_port": 587,
                "sender_email": "your@email.com",
                "sender_password": "yourpassword",
                "recipient_emails": ["admin@example.com"],
                "use_tls": True
            }
        }
    ]
}

Usage Example with FastAPI

from fastapi import FastAPI, Request
from escalite.escalite import Escalite

app = FastAPI()
notifier_configs = {
    "notifiers": [
        {
            "type": "email",
            "config": {
                "smtp_server": "smtp.example.com",
                "smtp_port": 587,
                "sender_email": "your@email.com",
                "sender_password": "yourpassword",
                "recipient_emails": ["admin@example.com"],
                "use_tls": True
            }
        }
    ]
}

@app.middleware("http")
async def escalite_logging_middleware(request: Request, call_next):
    with Escalite().logging_context(notifier_configs):
        Escalite.add_to_log("request_path", str(request.url.path), tag="api_logs")
        response = await call_next(request)
        Escalite.add_to_log("response_status", response.status_code, tag="api_logs")
        return response

@app.get("/")
def read_root():
    Escalite.add_service_log("root_service", "Root endpoint accessed")
    return {"Hello": "World"}

Manual Usage Example

Here is an additional usage example for showing how to use Escalite without the logging_context() context manager. This demonstrates manual configuration, starting and ending logging, and triggering escalation.

from escalite.escalite import Escalite

notifier_configs = {
    "notifiers": [
        {
            "type": "email",
            "config": {
                "smtp_server": "smtp.example.com",
                "smtp_port": 587,
                "sender_email": "your@email.com",
                "sender_password": "yourpassword",
                "recipient_emails": ["admin@example.com"],
                "use_tls": True
            }
        }
    ]
}

# Set up notifiers from configs
Escalite.set_notifiers_from_configs(notifier_configs)

# Start logging for a request or operation
Escalite.start_logging()

# Add logs as needed
Escalite.add_to_log("event", "User login", tag="api_logs")
Escalite.add_service_log("auth_service", "User authenticated", level="info")

# End logging and collect logs
logs = Escalite.end_logging()
print("Collected logs:", logs)

# Trigger escalation (e.g., send notifications)
Escalite.escalate()

This example shows explicit control over the logging lifecycle and escalation, suitable for use outside of context managers or in custom workflows.

Usage Example - Service Call Logging

We can use start_service_log and stop_service_log to track the lifecycle of a service call:

from escalite import Escalite

# Start logging for the request
Escalite.start_logging()

# Log the start of a service call
Escalite.start_service_log(
    "oauth_service",
    "Starting OAuth service",
    url="/oauth/start",
    code=200
)

# ... your service logic here ...

# Log the end of a service call
Escalite.stop_service_log(
    "oauth_service",
    "OAuth service completed",
    url="/oauth/start",
    code=200
)

# End logging and retrieve logs
Escalite.end_logging()
logs = Escalite.get_all_logs()
print(logs)

Notifiers

Here are some notifier configuration examples that are currently supported. Replace the configuration values with your actual credentials or endpoints.

Telegram Notifier

from escalite.escalite import Escalite

notifier_configs = {
    "notifiers": [
        {
            "type": "telegram",
            "config": {
                "bot_token": "your-telegram-bot-token",
                "chat_id": "your-chat-id"
            }
        }
    ]
}

Escalite.set_notifiers_from_configs(notifier_configs)
Escalite.start_logging()
Escalite.add_to_log("event", "Telegram notifier test", tag="api_logs")
Escalite.end_logging()
Escalite.escalate()

WhatsApp Notifier

from escalite.escalite import Escalite

notifier_configs = {
    "notifiers": [
        {
            "type": "whatsapp",
            "config": {
                "api_url": "https://graph.facebook.com/[version]/[phone_number_id]/messages", # Replace with your actual API URL
                "details_url": "https://escalite.com/escalite-alerts?id=", # Replace with your actual URL, Optional
                "token": "your-access-token", # Replace with your actual access token
                "to": "recipient-phone-number", # Replace with the recipient's phone number
                "payload_template": {
                    "messaging_product": "whatsapp",
                    "recipient_type": "individual",
                    "to": "PHONE_NUMBER", # Will be replaced with the recipient's phone number from above
                    "type": "template",
                    "template": {
                        "name": "TEMPLATE_NAME", # Replace with your actual template name
                        "language": {
                            "code": "LANGUAGE_AND_LOCALE_CODE" # Replace with your actual language and locale code, e.g., "en_US"
                        },
                        "components": [
                            # Replace with your named and positional parameter inputs
                            # Currently we only support the following parameters:
                            # name, date, message, data
                            # name, data are optional
                            # message is the message generated when escalite.escalate() is called
                            # date is the current date and time when the message is sent, auto generated
                            # Format the template following this example:
                            # {
                                #"type": "body",
                                #"parameters": [
                                #    {"type": "text", "parameter_name": "name", "text": ""},
                                #    {
                                #        "type": "text",
                                #        "parameter_name": "date",
                                #        "text": time.strftime("%Y-%m-%d %H:%M:%S"),
                                #   },
                                #   {"type": "text", "parameter_name": "message", "text": None},
                                #   {"type": "text", "parameter_name": "data", "text": ""},
                                # ],
                            # }
                       ]
                     }
                }
            }
        }
    ]
}

Escalite.set_notifiers_from_configs(notifier_configs)
Escalite.start_logging()
Escalite.add_to_log("event", "WhatsApp notifier test", tag="api_logs")
Escalite.end_logging()
Escalite.escalate()

Slack Notifier

from escalite.escalite import Escalite

notifier_configs = {
    "notifiers": [
        {
            "type": "slack",
            "config": {
                "webhook_url": "https://hooks.slack.com/services/your/webhook/url"
            }
        }
    ]
}

Escalite.set_notifiers_from_configs(notifier_configs)
Escalite.start_logging()
Escalite.add_to_log("event", "Slack notifier test", tag="api_logs")
Escalite.end_logging()
Escalite.escalate()

Email Notifier

from escalite.escalite import Escalite

notifier_configs = {
    "notifiers": [
        {
            "type": "email",
            "config": {
                "smtp_server": "smtp.example.com",
                "smtp_port": 587,
                "sender_email": "your@email.com",
                "sender_password": "yourpassword",
                "recipient_emails": ["admin@example.com"],
                "use_tls": True
            }
        }
    ]
}

Escalite.set_notifiers_from_configs(notifier_configs)
Escalite.start_logging()
Escalite.add_to_log("event", "Email notifier test", tag="api_logs")
Escalite.end_logging()
Escalite.escalate()

Escalite.escalate() with the from_level argument:

  • The from_level parameter controls the minimum log level required to trigger escalation (e.g., "warning", "error", "critical").
  • In this example, escalation will only occur if the log level is "error" or higher.

Here is an example showing how to use This allows escalation to be triggered only if the log level is equal to or higher than the specified level.

from escalite.escalite import Escalite

notifier_configs = {
    "notifiers": [
        {
            "type": "email",
            "config": {
                "smtp_server": "smtp.example.com",
                "smtp_port": 587,
                "sender_email": "your@email.com",
                "sender_password": "yourpassword",
                "recipient_emails": ["admin@example.com"],
                "use_tls": True
            }
        }
    ]
}

Escalite.set_notifiers_from_configs(notifier_configs)
Escalite.start_logging()
Escalite.add_to_log("event", "Something went wrong", tag="api_logs")
Escalite.add_service_log("my_service", "An error occurred", level="error")
Escalite.end_logging()

# Only escalate if the log level is "error" or higher
Escalite.escalate(from_level="error")

This ensures notifications are sent only for logs at the specified severity or above.

Contributing

Contributions are welcome! Please see the CONTRIBUTING.md file for guidelines.

License

MIT


Metadata

Release files for escalite 0.1.12

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for escalite 0.1.12
File Size Uploaded Provenance
escalite-0.1.12.tar.gz 11.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for escalite 0.1.12
File Interpreter ABI Platform
escalite-0.1.12-py3-none-any.whl Python 3 none any Details

Total release size: 25.2 kB

Release files / escalite-0.1.12.tar.gz

Download URL escalite-0.1.12.tar.gz
Size 11.5 kB
Tags Source
SHA-256 checksum
How to use checksums
a69edb2a4c8dc21d2a48725c0681c60ccd778da84da69c745db526491c0538f0
BLAKE2b-256 checksum
How to use checksums
c22e2b0919e73dff8a79cece0f20b69bbd2bb1b38f7e664b6573ef6ce6d3846f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.3 CPython/3.13.2 Darwin/24.3.0

Release files / escalite-0.1.12-py3-none-any.whl

Download URL escalite-0.1.12-py3-none-any.whl
Size 13.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c646d95823d5d237ec1301e3d8cf9f1f74e75773a8a632efa03401ecd599c7db
BLAKE2b-256 checksum
How to use checksums
beb9adc1f0a7621bfb9d09d14a032ce6ecf7ccd2253f6e512c386c3ef1e5292a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.3 CPython/3.13.2 Darwin/24.3.0

Security for escalite 0.1.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page