lynx-logger


Namelynx-logger JSON
Version 1.0.0 PyPI version JSON
download
home_pagehttps://github.com/NullPointerGang/lynx-logger
SummaryУниверсальная библиотека структурированного логирования на основе structlog
upload_time2025-08-17 16:18:20
maintainerNone
docs_urlNone
authorFlacSy
requires_python>=3.8
licenseNone
keywords logging structlog structured-logging tracing middleware
VCS
bugtrack_url
requirements structlog pytest pytest-cov
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # LynxLogger

Универсальная библиотека структурированного логирования на основе `structlog` с расширенными возможностями для Python приложений.

## Особенности
- **Простая настройка** - от одной строки кода до детальной конфигурации
- **Структурированное логирование** с поддержкой JSON, Key-Value и консольных форматов
- **Контекстное логирование** с автоматической трассировкой запросов
- **Фильтрация** по уровню, источнику, содержимому сообщений
- **Ротация файлов** с настраиваемыми параметрами
- **Middleware** для FastAPI, Flask, Django и ASGI приложений
- **Обратная совместимость** с вашим текущим кодом

## Установка

```bash
pip install lynx-logger
```

Дополнительные пакеты для веб-фреймворков:
```bash
pip install lynx-logger[web]  # FastAPI, Flask, Django
pip install lynx-logger[all]  # Все зависимости + dev tools
```

## Быстрый старт

### Базовое использование

```python
from lynx_logger import setup_logger

logger = setup_logger("my_app")
logger.info("Application started", version="1.0.0")

logger = setup_logger(
    name="my_app",
    level="DEBUG", 
    format="json",
    log_to_file=True,
    logs_dir="./logs"
)

logger.info("User logged in", user_id=123, ip="192.168.1.1")
```

### Продвинутая настройка

```python
from lynx_logger import LynxLogger, LogConfig, Level, Format

config = LogConfig(
    name="my_app",
    level=Level.DEBUG,
    format=Format.JSON,
    dev_mode=True,
    log_to_console=True,
    log_to_file=True,
    logs_dir="./logs"
)

logger = LynxLogger(config)
logger.info("Application configured", config=config.to_dict())
```

## Интеграция с веб-фреймворками

### FastAPI

```python
from fastapi import FastAPI
from lynx_logger import setup_logger, FastAPILoggingMiddleware

app = FastAPI()
logger = setup_logger("fastapi_app", format="json")

# Добавляем middleware
app.add_middleware(FastAPILoggingMiddleware, logger=logger.get_logger())

@app.get("/")
async def root():
    logger.info("Root endpoint called")
    return {"message": "Hello World"}
```

### Flask

```python
from flask import Flask
from lynx_logger import setup_logger, FlaskLoggingMiddleware

app = Flask(__name__)
logger = setup_logger("flask_app")

# Добавляем middleware
FlaskLoggingMiddleware(app, logger.get_logger())

@app.route("/")
def hello():
    logger.info("Hello endpoint called")
    return "Hello World"
```

### Django (в settings.py)

```python
# settings.py
MIDDLEWARE = [
    'lynx_logger.middleware.DjangoLoggingMiddleware',
    # ... другие middleware
]
```

## Форматы вывода

### Console (цветной вывод для разработки)
```python
logger = setup_logger("app", format="console", dev_mode=True)
logger.info("Server started", port=8000)
# 2025-01-16T10:30:45 [INFO] app: Server started port=8000
```

### JSON (для продакшна)
```python  
logger = setup_logger("app", format="json")
logger.info("User action", user_id=123, action="login")
# {"timestamp": "2025-01-16T10:30:45", "level": "info", "logger": "app", "event": "User action", "user_id": 123, "action": "login"}
```

### Key-Value
```python
logger = setup_logger("app", format="keyvalue")
logger.info("Payment processed", amount=100, currency="USD")
# timestamp=2025-01-16T10:30:45 level=info logger=app event='Payment processed' amount=100 currency=USD
```

## Контекстное логирование

### Автоматический контекст

```python
from lynx_logger import RequestContext

with RequestContext(request_id="req_123", user_id="user_456"):
    logger.info("Processing request")
    # Автоматически добавит request_id и user_id во все логи
```

### Привязка контекста

```python
# Создаем логгер с постоянным контекстом
user_logger = logger.bind(user_id=123, session_id="sess_456")
user_logger.info("User performed action", action="purchase")

# Временный контекст
with logger.with_context(trace_id="trace_789"):
    logger.info("Processing trace")
```

### Стековый контекст

```python
from lynx_logger import ContextLogger

context_logger = ContextLogger(logger.get_logger())

# Добавляем контекст в стек
request_logger = context_logger.with_request("req_123", "user_456")
request_logger.info("Request started")

# Добавляем еще контекст
operation_logger = request_logger.with_trace("trace_789")
operation_logger.info("Operation completed")
```

## Фильтрация логов

### Встроенные фильтры

```python
from lynx_logger import LogConfig, FilterConfig, Level

config = LogConfig(
    name="app",
    filters=FilterConfig(
        min_level=Level.WARNING,  # Только WARNING и выше
        exclude_loggers=["urllib3", "requests"],  # Исключаем библиотеки
        exclude_messages=["health.*", "ping"]  # Исключаем по regex
    )
)

logger = LynxLogger(config)
```

### Пользовательские фильтры

```python
from lynx_logger import SourceFilter, ContentFilter

# Фильтр по исходному файлу
source_filter = SourceFilter(
    include_patterns=["my_app.*"],
    exclude_patterns=["test_.*"]
)

# Фильтр по содержимому
content_filter = ContentFilter(
    exclude_patterns=["password", "secret"],
    case_sensitive=False
)
```

## Конфигурация

### Из переменных окружения

```bash
export LOG_NAME=my_app
export LOG_LEVEL=DEBUG
export LOG_FORMAT=json
export LOG_TO_FILE=true
export LOG_LOGS_DIR=/var/log/my_app
```

```python
from lynx_logger import LogConfig

config = LogConfig.from_env()
logger = LynxLogger(config)
```

### Из словаря

```python
config_dict = {
    "name": "my_app",
    "level": "INFO",
    "format": "json",
    "log_to_file": True,
    "file": {
        "filename": "app.log",
        "max_size": "50MB",
        "backup_count": 10
    }
}

config = LogConfig.from_dict(config_dict)
logger = LynxLogger(config)
```

## Продвинутые возможности

### Ротация файлов

```python
from lynx_logger import LogConfig, FileConfig

config = LogConfig(
    name="app",
    log_to_file=True,
    file=FileConfig(
        filename="app.log",
        max_size="10MB",      # Максимальный размер файла
        backup_count=5,       # Количество архивных файлов
        encoding="utf-8"
    )
)
```

### Throttling (ограничение частоты)

```python
from lynx_logger import ThrottleFilter

# Не более 10 одинаковых сообщений в минуту
throttle = ThrottleFilter(max_repeats=10, time_window=60)
```

### Пользовательские процессоры

```python
def add_hostname(logger, name, event_dict):
    import socket
    event_dict["hostname"] = socket.gethostname()
    return event_dict

config = LogConfig(
    name="app",
    extra_processors=[add_hostname]
)
```

## Примеры использования

### Микросервис с трассировкой

```python
from fastapi import FastAPI, Request
from lynx_logger import setup_logger, RequestContext
import uuid

app = FastAPI()
logger = setup_logger("payment_service", format="json")

@app.middleware("http")
async def add_request_context(request: Request, call_next):
    request_id = request.headers.get("X-Request-ID", str(uuid.uuid4()))
    
    with RequestContext(request_id=request_id):
        logger.info("Request started", path=request.url.path)
        response = await call_next(request)
        logger.info("Request completed", status=response.status_code)
        return response

@app.post("/pay")
async def process_payment(amount: float, currency: str):
    payment_logger = logger.bind(amount=amount, currency=currency)
    payment_logger.info("Payment processing started")
    
    # Бизнес-логика
    result = {"status": "success", "transaction_id": str(uuid.uuid4())}
    
    payment_logger.info("Payment completed", result=result)
    return result
```

### Обработка ошибок

```python
from lynx_logger import setup_logger

logger = setup_logger("error_handler", format="json")

def process_user_data(user_id: int, data: dict):
    user_logger = logger.bind(user_id=user_id)
    
    try:
        user_logger.info("Processing user data", data_keys=list(data.keys()))
        
        # Бизнес-логика
        if not data.get("email"):
            raise ValueError("Email is required")
        
        user_logger.info("User data processed successfully")
        return {"status": "success"}
        
    except ValueError as e:
        user_logger.warning("Validation error", error=str(e))
        return {"status": "error", "message": str(e)}
        
    except Exception as e:
        user_logger.exception("Unexpected error occurred")
        return {"status": "error", "message": "Internal error"}
```

## Лицензия

MIT License - используйте свободно в коммерческих и некоммерческих проектах.

## Поддержка

- **GitHub Issues**: [Сообщить о проблеме](https://github.com/NullPointerGang/lynx-logger/issues)
- **Email**: flacsy.x@gmail.gom

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/NullPointerGang/lynx-logger",
    "name": "lynx-logger",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "logging, structlog, structured-logging, tracing, middleware",
    "author": "FlacSy",
    "author_email": "flacsy.x@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/8c/0e/19994f76b75bb15224581a78a48911bf76cdf584efe93fe2c2b09f711d5c/lynx_logger-1.0.0.tar.gz",
    "platform": null,
    "description": "# LynxLogger\n\n\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 `structlog` \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0434\u043b\u044f Python \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.\n\n## \u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438\n- **\u041f\u0440\u043e\u0441\u0442\u0430\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430** - \u043e\u0442 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u043a\u043e\u0434\u0430 \u0434\u043e \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438\n- **\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435** \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 JSON, Key-Value \u0438 \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432\n- **\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435** \u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0442\u0440\u0430\u0441\u0441\u0438\u0440\u043e\u0432\u043a\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432\n- **\u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f** \u043f\u043e \u0443\u0440\u043e\u0432\u043d\u044e, \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0443, \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u043c\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439\n- **\u0420\u043e\u0442\u0430\u0446\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432** \u0441 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438\n- **Middleware** \u0434\u043b\u044f FastAPI, Flask, Django \u0438 ASGI \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439\n- **\u041e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c** \u0441 \u0432\u0430\u0448\u0438\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u043c \u043a\u043e\u0434\u043e\u043c\n\n## \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430\n\n```bash\npip install lynx-logger\n```\n\n\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u043a\u0435\u0442\u044b \u0434\u043b\u044f \u0432\u0435\u0431-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u0432:\n```bash\npip install lynx-logger[web]  # FastAPI, Flask, Django\npip install lynx-logger[all]  # \u0412\u0441\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 + dev tools\n```\n\n## \u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u0442\u0430\u0440\u0442\n\n### \u0411\u0430\u0437\u043e\u0432\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\n\n```python\nfrom lynx_logger import setup_logger\n\nlogger = setup_logger(\"my_app\")\nlogger.info(\"Application started\", version=\"1.0.0\")\n\nlogger = setup_logger(\n    name=\"my_app\",\n    level=\"DEBUG\", \n    format=\"json\",\n    log_to_file=True,\n    logs_dir=\"./logs\"\n)\n\nlogger.info(\"User logged in\", user_id=123, ip=\"192.168.1.1\")\n```\n\n### \u041f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u0430\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\n\n```python\nfrom lynx_logger import LynxLogger, LogConfig, Level, Format\n\nconfig = LogConfig(\n    name=\"my_app\",\n    level=Level.DEBUG,\n    format=Format.JSON,\n    dev_mode=True,\n    log_to_console=True,\n    log_to_file=True,\n    logs_dir=\"./logs\"\n)\n\nlogger = LynxLogger(config)\nlogger.info(\"Application configured\", config=config.to_dict())\n```\n\n## \u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 \u0432\u0435\u0431-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430\u043c\u0438\n\n### FastAPI\n\n```python\nfrom fastapi import FastAPI\nfrom lynx_logger import setup_logger, FastAPILoggingMiddleware\n\napp = FastAPI()\nlogger = setup_logger(\"fastapi_app\", format=\"json\")\n\n# \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c middleware\napp.add_middleware(FastAPILoggingMiddleware, logger=logger.get_logger())\n\n@app.get(\"/\")\nasync def root():\n    logger.info(\"Root endpoint called\")\n    return {\"message\": \"Hello World\"}\n```\n\n### Flask\n\n```python\nfrom flask import Flask\nfrom lynx_logger import setup_logger, FlaskLoggingMiddleware\n\napp = Flask(__name__)\nlogger = setup_logger(\"flask_app\")\n\n# \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c middleware\nFlaskLoggingMiddleware(app, logger.get_logger())\n\n@app.route(\"/\")\ndef hello():\n    logger.info(\"Hello endpoint called\")\n    return \"Hello World\"\n```\n\n### Django (\u0432 settings.py)\n\n```python\n# settings.py\nMIDDLEWARE = [\n    'lynx_logger.middleware.DjangoLoggingMiddleware',\n    # ... \u0434\u0440\u0443\u0433\u0438\u0435 middleware\n]\n```\n\n## \u0424\u043e\u0440\u043c\u0430\u0442\u044b \u0432\u044b\u0432\u043e\u0434\u0430\n\n### Console (\u0446\u0432\u0435\u0442\u043d\u043e\u0439 \u0432\u044b\u0432\u043e\u0434 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438)\n```python\nlogger = setup_logger(\"app\", format=\"console\", dev_mode=True)\nlogger.info(\"Server started\", port=8000)\n# 2025-01-16T10:30:45 [INFO] app: Server started port=8000\n```\n\n### JSON (\u0434\u043b\u044f \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0430)\n```python  \nlogger = setup_logger(\"app\", format=\"json\")\nlogger.info(\"User action\", user_id=123, action=\"login\")\n# {\"timestamp\": \"2025-01-16T10:30:45\", \"level\": \"info\", \"logger\": \"app\", \"event\": \"User action\", \"user_id\": 123, \"action\": \"login\"}\n```\n\n### Key-Value\n```python\nlogger = setup_logger(\"app\", format=\"keyvalue\")\nlogger.info(\"Payment processed\", amount=100, currency=\"USD\")\n# timestamp=2025-01-16T10:30:45 level=info logger=app event='Payment processed' amount=100 currency=USD\n```\n\n## \u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\n\n### \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\n\n```python\nfrom lynx_logger import RequestContext\n\nwith RequestContext(request_id=\"req_123\", user_id=\"user_456\"):\n    logger.info(\"Processing request\")\n    # \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442 request_id \u0438 user_id \u0432\u043e \u0432\u0441\u0435 \u043b\u043e\u0433\u0438\n```\n\n### \u041f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430\n\n```python\n# \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043b\u043e\u0433\u0433\u0435\u0440 \u0441 \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u044b\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043e\u043c\nuser_logger = logger.bind(user_id=123, session_id=\"sess_456\")\nuser_logger.info(\"User performed action\", action=\"purchase\")\n\n# \u0412\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\nwith logger.with_context(trace_id=\"trace_789\"):\n    logger.info(\"Processing trace\")\n```\n\n### \u0421\u0442\u0435\u043a\u043e\u0432\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\n\n```python\nfrom lynx_logger import ContextLogger\n\ncontext_logger = ContextLogger(logger.get_logger())\n\n# \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0432 \u0441\u0442\u0435\u043a\nrequest_logger = context_logger.with_request(\"req_123\", \"user_456\")\nrequest_logger.info(\"Request started\")\n\n# \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0449\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\noperation_logger = request_logger.with_trace(\"trace_789\")\noperation_logger.info(\"Operation completed\")\n```\n\n## \u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u043b\u043e\u0433\u043e\u0432\n\n### \u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u044b\n\n```python\nfrom lynx_logger import LogConfig, FilterConfig, Level\n\nconfig = LogConfig(\n    name=\"app\",\n    filters=FilterConfig(\n        min_level=Level.WARNING,  # \u0422\u043e\u043b\u044c\u043a\u043e WARNING \u0438 \u0432\u044b\u0448\u0435\n        exclude_loggers=[\"urllib3\", \"requests\"],  # \u0418\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438\n        exclude_messages=[\"health.*\", \"ping\"]  # \u0418\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043f\u043e regex\n    )\n)\n\nlogger = LynxLogger(config)\n```\n\n### \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u044b\n\n```python\nfrom lynx_logger import SourceFilter, ContentFilter\n\n# \u0424\u0438\u043b\u044c\u0442\u0440 \u043f\u043e \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443\nsource_filter = SourceFilter(\n    include_patterns=[\"my_app.*\"],\n    exclude_patterns=[\"test_.*\"]\n)\n\n# \u0424\u0438\u043b\u044c\u0442\u0440 \u043f\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u043c\u0443\ncontent_filter = ContentFilter(\n    exclude_patterns=[\"password\", \"secret\"],\n    case_sensitive=False\n)\n```\n\n## \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\n\n### \u0418\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f\n\n```bash\nexport LOG_NAME=my_app\nexport LOG_LEVEL=DEBUG\nexport LOG_FORMAT=json\nexport LOG_TO_FILE=true\nexport LOG_LOGS_DIR=/var/log/my_app\n```\n\n```python\nfrom lynx_logger import LogConfig\n\nconfig = LogConfig.from_env()\nlogger = LynxLogger(config)\n```\n\n### \u0418\u0437 \u0441\u043b\u043e\u0432\u0430\u0440\u044f\n\n```python\nconfig_dict = {\n    \"name\": \"my_app\",\n    \"level\": \"INFO\",\n    \"format\": \"json\",\n    \"log_to_file\": True,\n    \"file\": {\n        \"filename\": \"app.log\",\n        \"max_size\": \"50MB\",\n        \"backup_count\": 10\n    }\n}\n\nconfig = LogConfig.from_dict(config_dict)\nlogger = LynxLogger(config)\n```\n\n## \u041f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438\n\n### \u0420\u043e\u0442\u0430\u0446\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432\n\n```python\nfrom lynx_logger import LogConfig, FileConfig\n\nconfig = LogConfig(\n    name=\"app\",\n    log_to_file=True,\n    file=FileConfig(\n        filename=\"app.log\",\n        max_size=\"10MB\",      # \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430\n        backup_count=5,       # \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0430\u0440\u0445\u0438\u0432\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432\n        encoding=\"utf-8\"\n    )\n)\n```\n\n### Throttling (\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0447\u0430\u0441\u0442\u043e\u0442\u044b)\n\n```python\nfrom lynx_logger import ThrottleFilter\n\n# \u041d\u0435 \u0431\u043e\u043b\u0435\u0435 10 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432 \u043c\u0438\u043d\u0443\u0442\u0443\nthrottle = ThrottleFilter(max_repeats=10, time_window=60)\n```\n\n### \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u044b\n\n```python\ndef add_hostname(logger, name, event_dict):\n    import socket\n    event_dict[\"hostname\"] = socket.gethostname()\n    return event_dict\n\nconfig = LogConfig(\n    name=\"app\",\n    extra_processors=[add_hostname]\n)\n```\n\n## \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f\n\n### \u041c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 \u0441 \u0442\u0440\u0430\u0441\u0441\u0438\u0440\u043e\u0432\u043a\u043e\u0439\n\n```python\nfrom fastapi import FastAPI, Request\nfrom lynx_logger import setup_logger, RequestContext\nimport uuid\n\napp = FastAPI()\nlogger = setup_logger(\"payment_service\", format=\"json\")\n\n@app.middleware(\"http\")\nasync def add_request_context(request: Request, call_next):\n    request_id = request.headers.get(\"X-Request-ID\", str(uuid.uuid4()))\n    \n    with RequestContext(request_id=request_id):\n        logger.info(\"Request started\", path=request.url.path)\n        response = await call_next(request)\n        logger.info(\"Request completed\", status=response.status_code)\n        return response\n\n@app.post(\"/pay\")\nasync def process_payment(amount: float, currency: str):\n    payment_logger = logger.bind(amount=amount, currency=currency)\n    payment_logger.info(\"Payment processing started\")\n    \n    # \u0411\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430\n    result = {\"status\": \"success\", \"transaction_id\": str(uuid.uuid4())}\n    \n    payment_logger.info(\"Payment completed\", result=result)\n    return result\n```\n\n### \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a\n\n```python\nfrom lynx_logger import setup_logger\n\nlogger = setup_logger(\"error_handler\", format=\"json\")\n\ndef process_user_data(user_id: int, data: dict):\n    user_logger = logger.bind(user_id=user_id)\n    \n    try:\n        user_logger.info(\"Processing user data\", data_keys=list(data.keys()))\n        \n        # \u0411\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430\n        if not data.get(\"email\"):\n            raise ValueError(\"Email is required\")\n        \n        user_logger.info(\"User data processed successfully\")\n        return {\"status\": \"success\"}\n        \n    except ValueError as e:\n        user_logger.warning(\"Validation error\", error=str(e))\n        return {\"status\": \"error\", \"message\": str(e)}\n        \n    except Exception as e:\n        user_logger.exception(\"Unexpected error occurred\")\n        return {\"status\": \"error\", \"message\": \"Internal error\"}\n```\n\n## \u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f\n\nMIT License - \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e \u0432 \u043a\u043e\u043c\u043c\u0435\u0440\u0447\u0435\u0441\u043a\u0438\u0445 \u0438 \u043d\u0435\u043a\u043e\u043c\u043c\u0435\u0440\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445.\n\n## \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430\n\n- **GitHub Issues**: [\u0421\u043e\u043e\u0431\u0449\u0438\u0442\u044c \u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435](https://github.com/NullPointerGang/lynx-logger/issues)\n- **Email**: flacsy.x@gmail.gom\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 structlog",
    "version": "1.0.0",
    "project_urls": {
        "Bug Reports": "https://github.com/NullPointerGang/lynx-logger/issues",
        "Homepage": "https://github.com/NullPointerGang/lynx-logger",
        "Source": "https://github.com/NullPointerGang/lynx-logger"
    },
    "split_keywords": [
        "logging",
        " structlog",
        " structured-logging",
        " tracing",
        " middleware"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f39070b6879a824ea4a7f827bdd6cdf6800f064d6f3dc0a166395a2ce4e3077e",
                "md5": "46e88128abb922ce17b70f414194e37a",
                "sha256": "c26bf48b72f5d354ea93c875f4ce2d4bab6abe178eb18d920c7cafb5b957db95"
            },
            "downloads": -1,
            "filename": "lynx_logger-1.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "46e88128abb922ce17b70f414194e37a",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 20620,
            "upload_time": "2025-08-17T16:18:19",
            "upload_time_iso_8601": "2025-08-17T16:18:19.443741Z",
            "url": "https://files.pythonhosted.org/packages/f3/90/70b6879a824ea4a7f827bdd6cdf6800f064d6f3dc0a166395a2ce4e3077e/lynx_logger-1.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "8c0e19994f76b75bb15224581a78a48911bf76cdf584efe93fe2c2b09f711d5c",
                "md5": "ce6d4dcd639109c90bb6d833907d51a2",
                "sha256": "62e26751e2504cd0bf9dcf055b8a505940339af63db9a09f43190774ef0ba8d2"
            },
            "downloads": -1,
            "filename": "lynx_logger-1.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "ce6d4dcd639109c90bb6d833907d51a2",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 21050,
            "upload_time": "2025-08-17T16:18:20",
            "upload_time_iso_8601": "2025-08-17T16:18:20.660820Z",
            "url": "https://files.pythonhosted.org/packages/8c/0e/19994f76b75bb15224581a78a48911bf76cdf584efe93fe2c2b09f711d5c/lynx_logger-1.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-17 16:18:20",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "NullPointerGang",
    "github_project": "lynx-logger",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "structlog",
            "specs": [
                [
                    "==",
                    "25.4.0"
                ]
            ]
        },
        {
            "name": "pytest",
            "specs": [
                [
                    ">=",
                    "7.0.0"
                ]
            ]
        },
        {
            "name": "pytest-cov",
            "specs": [
                [
                    ">=",
                    "4.0.0"
                ]
            ]
        }
    ],
    "lcname": "lynx-logger"
}
        
Elapsed time: 1.73188s