├── tests
├── __init__.py
└── unit
│ ├── __init__.py
│ └── test_version.py
├── src
└── exchange
│ ├── common
│ ├── __init__.py
│ ├── logging.py
│ ├── telemetry.py
│ └── config.py
│ ├── order_service
│ ├── __init__.py
│ ├── models.py
│ ├── handlers.py
│ └── main.py
│ ├── trade_service
│ ├── __init__.py
│ ├── models.py
│ ├── handlers.py
│ └── main.py
│ ├── notification_service
│ ├── __init__.py
│ ├── handlers.py
│ └── main.py
│ └── __init__.py
├── .env
├── config
└── config.toml
├── grafana
├── provisioning
│ ├── dashboards
│ │ └── dashboards.yaml
│ └── datasources
│ │ └── datasource.yaml
└── dashboards
│ └── faststream.json
├── justfile
├── prometheus
└── prometheus.yaml
├── .github
├── dependabot.yml
└── workflows
│ └── ci.yaml
├── tempo
└── tempo.yaml
├── .gitignore
├── .pre-commit-config.yaml
├── Dockerfile
├── README.md
├── pyproject.toml
├── docker-compose.yaml
└── pdm.lock
/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/unit/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/exchange/common/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/exchange/order_service/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/exchange/trade_service/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/exchange/notification_service/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/exchange/__init__.py:
--------------------------------------------------------------------------------
1 | __version__ = "0.1.0"
2 |
--------------------------------------------------------------------------------
/tests/unit/test_version.py:
--------------------------------------------------------------------------------
1 | from exchange import __version__
2 |
3 |
4 | def test_version() -> None:
5 | assert __version__ == "0.1.0"
6 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | # App config
2 | export CONFIG_PATH=./config/config.toml
3 |
4 | # RabbitMQ
5 | export RABBITMQ_USER=admin
6 | export RABBITMQ_PASSWORD=admin
7 |
--------------------------------------------------------------------------------
/config/config.toml:
--------------------------------------------------------------------------------
1 | [rabbit]
2 | user = "admin"
3 | password = "admin"
4 | port = 5672
5 | host = "example.rabbit"
6 |
7 | [trace]
8 | otlp_endpoint = "http://example.tempo:4317"
9 |
--------------------------------------------------------------------------------
/src/exchange/common/logging.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 |
4 | def configure_logging() -> None:
5 | fmt_str = "[%(asctime)s] - %(levelname)s - [%(module)s:%(lineno)s:%(funcName)s] - %(message)s"
6 | logging.basicConfig(level=logging.INFO, format=fmt_str)
7 |
--------------------------------------------------------------------------------
/grafana/provisioning/dashboards/dashboards.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: 1
2 |
3 | providers:
4 | - name: "FastStream"
5 | orgId: 1
6 | type: "file"
7 | disableDeletion: true
8 | editable: true
9 | options:
10 | path: "/etc/grafana/dashboards/faststream.json"
11 |
--------------------------------------------------------------------------------
/src/exchange/order_service/models.py:
--------------------------------------------------------------------------------
1 | from enum import Enum
2 |
3 | from pydantic import BaseModel
4 |
5 |
6 | class Direction(Enum):
7 | BUY = "BUY"
8 | SELL = "SELL"
9 |
10 |
11 | class Order(BaseModel):
12 | symbol: str
13 | quantity: int
14 | type: Direction
15 |
--------------------------------------------------------------------------------
/src/exchange/trade_service/models.py:
--------------------------------------------------------------------------------
1 | from decimal import Decimal
2 | from enum import Enum
3 |
4 | from pydantic import BaseModel
5 |
6 | from exchange.order_service.models import Order
7 |
8 |
9 | class Status(Enum):
10 | PENDING = "PENDING"
11 | SUBMITTED = "SUBMITTED"
12 |
13 |
14 | class Trade(BaseModel):
15 | order: Order
16 | status: Status
17 | price: Decimal | None = None
18 |
--------------------------------------------------------------------------------
/justfile:
--------------------------------------------------------------------------------
1 | # Show help message
2 | [private]
3 | @default:
4 | just --list
5 |
6 | # Install all depends for developing
7 | @install:
8 | pdm install -G:all
9 | pre-commit install
10 |
11 | # Run tests
12 | @test:
13 | pytest tests --cov=pyproject --cov-append --cov-report term-missing -v
14 |
15 | # Run pre-commit
16 | @lint:
17 | pre-commit run --all-files
18 |
19 | # Run app in docker container
20 | @up:
21 | docker compose --profile exchange --profile grafana up --build -d
22 |
23 | # Stop docker containers
24 | @down:
25 | docker compose --profile exchange --profile grafana down
26 |
--------------------------------------------------------------------------------
/prometheus/prometheus.yaml:
--------------------------------------------------------------------------------
1 | global:
2 | scrape_interval: 15s
3 | evaluation_interval: 15s
4 |
5 | scrape_configs:
6 | - job_name: "prometheus"
7 | static_configs:
8 | - targets: [ "localhost:9090" ]
9 | - job_name: "tempo"
10 | static_configs:
11 | - targets: [ "example.tempo:3200" ]
12 | - job_name: "order"
13 | static_configs:
14 | - targets: [ "example.order:8080" ]
15 | - job_name: "trade"
16 | static_configs:
17 | - targets: [ "example.trade:8080" ]
18 | - job_name: "notification"
19 | static_configs:
20 | - targets: [ "example.notification:8080" ]
21 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "pip"
4 | directory: "/"
5 | schedule:
6 | interval: "weekly"
7 | open-pull-requests-limit: 10
8 | labels:
9 | - "dependencies"
10 | - "python"
11 |
12 | - package-ecosystem: "github-actions"
13 | directory: "/"
14 | schedule:
15 | interval: "weekly"
16 | open-pull-requests-limit: 10
17 | labels:
18 | - "dependencies"
19 | - "github-actions"
20 |
21 | - package-ecosystem: "docker"
22 | directory: "/"
23 | schedule:
24 | interval: "weekly"
25 | open-pull-requests-limit: 10
26 | labels:
27 | - "dependencies"
28 | - "docker"
29 |
--------------------------------------------------------------------------------
/src/exchange/notification_service/handlers.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import logging
3 | import random
4 |
5 | from faststream.rabbit import RabbitRouter
6 | from opentelemetry import trace
7 |
8 | logger = logging.getLogger(__name__)
9 | tracer = trace.get_tracer(__name__)
10 | router = RabbitRouter()
11 |
12 |
13 | async def send_notification(text: str) -> None:
14 | with tracer.start_as_current_span("send notification", attributes={"text": text}):
15 | await asyncio.sleep(random.randint(1, 50) / 10)
16 |
17 | logger.info("Notification sent successfully")
18 |
19 |
20 | @router.subscriber("notifications")
21 | async def notifications_handler(message: str) -> None:
22 | logger.info("Received message [%s]", message)
23 | await send_notification(message)
24 |
--------------------------------------------------------------------------------
/src/exchange/common/telemetry.py:
--------------------------------------------------------------------------------
1 | from opentelemetry import trace
2 | from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
3 | from opentelemetry.sdk.resources import Resource
4 | from opentelemetry.sdk.trace import TracerProvider
5 | from opentelemetry.sdk.trace.export import BatchSpanProcessor
6 |
7 |
8 | def setup_telemetry(service_name: str, otlp_endpoint: str) -> TracerProvider:
9 | resource = Resource.create(attributes={"service.name": service_name})
10 | tracer_provider = TracerProvider(resource=resource)
11 | exporter = OTLPSpanExporter(endpoint=otlp_endpoint)
12 | processor = BatchSpanProcessor(exporter)
13 | tracer_provider.add_span_processor(processor)
14 | trace.set_tracer_provider(tracer_provider)
15 | return tracer_provider
16 |
--------------------------------------------------------------------------------
/grafana/provisioning/datasources/datasource.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: 1
2 |
3 | datasources:
4 | - uid: tempo
5 | orgId: 1
6 | name: Tempo
7 | type: tempo
8 | typeName: Tempo
9 | access: proxy
10 | url: http://example.tempo:3200
11 | password: ""
12 | user: ""
13 | database: ""
14 | basicAuth: false
15 | isDefault: false
16 | readOnly: false
17 | editable: true
18 | jsonData:
19 | httpMethod: GET
20 | serviceMap:
21 | datasourceUid: prometheus
22 | - name: Prometheus
23 | type: prometheus
24 | uid: prometheus
25 | access: proxy
26 | orgId: 1
27 | url: http://example.prometheus:9090
28 | basicAuth: false
29 | isDefault: false
30 | version: 1
31 | editable: false
32 | jsonData:
33 | httpMethod: GET
34 |
--------------------------------------------------------------------------------
/src/exchange/order_service/handlers.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import logging
3 | import random
4 |
5 | from faststream.rabbit import RabbitRouter
6 | from opentelemetry import trace
7 |
8 | from exchange.order_service.models import Order
9 | from exchange.trade_service.models import Status, Trade
10 |
11 | logger = logging.getLogger(__name__)
12 | tracer = trace.get_tracer(__name__)
13 | router = RabbitRouter()
14 |
15 |
16 | @router.publisher("trades")
17 | @router.subscriber("orders")
18 | async def orders_handler(order: Order) -> Trade:
19 | logger.info("Received order [%s]", order)
20 |
21 | with tracer.start_as_current_span("validate order", attributes={"quantity": order.quantity}):
22 | await asyncio.sleep(random.randint(1, 50) / 10)
23 | if order.quantity <= 0:
24 | raise ValueError("Order quantity must be greater than zero")
25 |
26 | return Trade(order=order, status=Status.PENDING)
27 |
--------------------------------------------------------------------------------
/src/exchange/trade_service/handlers.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import logging
3 | import random
4 | from decimal import Decimal
5 |
6 | from faststream.rabbit import RabbitRouter
7 | from opentelemetry import trace
8 |
9 | from exchange.trade_service.models import Status, Trade
10 |
11 | logger = logging.getLogger(__name__)
12 | tracer = trace.get_tracer(__name__)
13 | router = RabbitRouter()
14 |
15 |
16 | @router.publisher("notifications")
17 | @router.subscriber("trades")
18 | async def trades_handler(trade: Trade) -> str:
19 | logger.info("Received trade [%s]", trade)
20 |
21 | with tracer.start_as_current_span("process trade"):
22 | price = Decimal(random.randint(1000, 1500))
23 | trade.price = price
24 | trade.status = Status.SUBMITTED
25 | await asyncio.sleep(random.randint(1, 50) / 10)
26 |
27 | message = f"Order [{trade.order}] was executed at the asset price {trade.price}$"
28 | logger.info(message)
29 |
30 | return message
31 |
--------------------------------------------------------------------------------
/src/exchange/common/config.py:
--------------------------------------------------------------------------------
1 | import os
2 | import tomllib
3 | from dataclasses import dataclass
4 | from typing import Any
5 |
6 | from adaptix import Retort
7 |
8 | DEFAULT_CONFIG_PATH = "./config/config.toml"
9 |
10 |
11 | @dataclass
12 | class RabbitConfig:
13 | user: str
14 | password: str
15 | port: int = 5672
16 | host: str = "localhost"
17 |
18 | @property
19 | def url(self) -> str:
20 | return f"amqp://{self.user}:{self.password}@{self.host}:{self.port}/"
21 |
22 |
23 | @dataclass
24 | class TraceConfig:
25 | otlp_endpoint: str
26 |
27 |
28 | @dataclass
29 | class Config:
30 | rabbit: RabbitConfig
31 | trace: TraceConfig
32 |
33 |
34 | def read_toml(path: str) -> dict[str, Any]:
35 | with open(path, "rb") as f:
36 | return tomllib.load(f)
37 |
38 |
39 | def load_config() -> Config:
40 | path = os.getenv("CONFIG_PATH", DEFAULT_CONFIG_PATH)
41 | data = read_toml(path)
42 | mapper = Retort()
43 | return mapper.load(data, Config)
44 |
--------------------------------------------------------------------------------
/tempo/tempo.yaml:
--------------------------------------------------------------------------------
1 | stream_over_http_enabled: true
2 | server:
3 | http_listen_port: 3200
4 | log_level: info
5 |
6 | query_frontend:
7 | search:
8 | duration_slo: 5s
9 | throughput_bytes_slo: 1.073741824e+09
10 | trace_by_id:
11 | duration_slo: 5s
12 |
13 | distributor:
14 | receivers:
15 | otlp:
16 | protocols:
17 | grpc:
18 | endpoint: 0.0.0.0:4317
19 |
20 | ingester:
21 | max_block_duration: 5m
22 |
23 | compactor:
24 | compaction:
25 | block_retention: 1h
26 |
27 | metrics_generator:
28 | registry:
29 | external_labels:
30 | source: tempo
31 | cluster: docker-compose
32 | storage:
33 | path: /var/tempo/generator/wal
34 | remote_write:
35 | - url: http://example.prometheus:9090/api/v1/write
36 | send_exemplars: true
37 | traces_storage:
38 | path: /var/tempo/generator/traces
39 |
40 | storage:
41 | trace:
42 | backend: local
43 | wal:
44 | path: /var/tempo/wal
45 | local:
46 | path: /var/tempo/blocks
47 |
48 | overrides:
49 | defaults:
50 | metrics_generator:
51 | processors: [service-graphs, span-metrics, local-blocks]
52 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # Unit test / coverage reports
30 | htmlcov/
31 | .tox/
32 | .nox/
33 | .coverage
34 | .coverage.*
35 | .cache
36 | nosetests.xml
37 | coverage.xml
38 | junitxml.xml
39 | *.cover
40 | *.py,cover
41 | .hypothesis/
42 | .pytest_cache/
43 | cover/
44 |
45 | # Sphinx documentation
46 | docs/_build/
47 | /docs/build/
48 | /docs-build/
49 |
50 | # pdm
51 | .pdm.toml
52 | .pdm-python
53 | .pdm-build/
54 |
55 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
56 | __pypackages__/
57 |
58 | # Environments
59 | .venv
60 | env/
61 | venv/
62 | ENV/
63 | env.bak/
64 | venv.bak/
65 |
66 | # mypy
67 | .mypy_cache/
68 | .dmypy.json
69 | dmypy.json
70 |
71 | # ruff
72 | /.ruff_cache/
73 |
74 | # IDE
75 | .idea/
76 | .vscode/
77 | tempo-data/
78 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | default_language_version:
2 | python: python3.12
3 |
4 | repos:
5 | - repo: https://github.com/compilerla/conventional-pre-commit
6 | rev: v4.2.0
7 | hooks:
8 | - id: conventional-pre-commit
9 | stages: [commit-msg]
10 |
11 | - repo: https://github.com/pre-commit/pre-commit-hooks
12 | rev: v5.0.0
13 | hooks:
14 | - id: check-ast
15 | - id: check-added-large-files
16 | - id: check-case-conflict
17 | - id: check-merge-conflict
18 | - id: detect-private-key
19 | - id: check-toml
20 | - id: check-yaml
21 | - id: debug-statements
22 | - id: end-of-file-fixer
23 | - id: mixed-line-ending
24 | - id: trailing-whitespace
25 |
26 | - repo: https://github.com/astral-sh/ruff-pre-commit
27 | rev: v0.12.7
28 | hooks:
29 | - id: ruff
30 | args: ["--fix"]
31 | - id: ruff-format
32 |
33 | - repo: local
34 | hooks:
35 | - id: mypy
36 | name: mypy
37 | entry: mypy src tests --config-file ./pyproject.toml
38 | language: python
39 | types: [python]
40 | require_serial: true
41 | pass_filenames: false
42 |
--------------------------------------------------------------------------------
/src/exchange/trade_service/main.py:
--------------------------------------------------------------------------------
1 | import uvicorn
2 | from faststream.asgi import AsgiFastStream
3 | from faststream.rabbit import RabbitBroker
4 | from faststream.rabbit.opentelemetry import RabbitTelemetryMiddleware
5 | from faststream.rabbit.prometheus import RabbitPrometheusMiddleware
6 | from prometheus_client import CollectorRegistry, make_asgi_app
7 |
8 | from exchange.common.config import load_config
9 | from exchange.common.logging import configure_logging
10 | from exchange.common.telemetry import setup_telemetry
11 | from exchange.trade_service.handlers import router
12 |
13 |
14 | def main() -> AsgiFastStream:
15 | configure_logging()
16 | config = load_config()
17 | service_name = "trade"
18 | tracer_provider = setup_telemetry(
19 | service_name=service_name,
20 | otlp_endpoint=config.trace.otlp_endpoint,
21 | )
22 | registry = CollectorRegistry()
23 |
24 | telemetry_middleware = RabbitTelemetryMiddleware(tracer_provider=tracer_provider)
25 | prometheus_middleware = RabbitPrometheusMiddleware(
26 | registry=registry, app_name=service_name, metrics_prefix="faststream"
27 | )
28 | broker = RabbitBroker(url=config.rabbit.url, middlewares=(prometheus_middleware, telemetry_middleware))
29 | broker.include_router(router)
30 | return AsgiFastStream(broker, [("/metrics", make_asgi_app(registry))])
31 |
32 |
33 | if __name__ == "__main__":
34 | uvicorn.run(main(), host="0.0.0.0", port=8080)
35 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Use the official Python image as the base image
2 | FROM python:3.12.3-slim-bookworm as python-base
3 |
4 | # Set environment variables to non-interactive
5 | ENV PYTHONUNBUFFERED=1 \
6 | PYTHONDONTWRITEBYTECODE=1 \
7 | PIP_NO_CACHE_DIR=off \
8 | PIP_DISABLE_PIP_VERSION_CHECK=on \
9 | PIP_DEFAULT_TIMEOUT=100 \
10 | PDM_HOME="/opt/pdm" \
11 | PDM_PEP582="1" \
12 | PYSETUP_PATH="/opt/pysetup" \
13 | VENV_PATH="/opt/pysetup/.venv" \
14 | PYTHONPATH="/app"
15 |
16 | # Update PATH to include PDM and the virtual environment binaries
17 | ENV PATH="$PDM_HOME/bin:$VENV_PATH/bin:$PATH"
18 |
19 | # Setup the builder base with system dependencies
20 | FROM python-base as builder-base
21 | RUN apt-get update && apt-get install -y git curl
22 |
23 | # Setup work directory and copy pyproject.toml (PDM uses the same pyproject.toml as Poetry)
24 | WORKDIR $PYSETUP_PATH
25 |
26 | # Copy dependencies
27 | COPY ./pyproject.toml .
28 | COPY ./pdm.lock .
29 |
30 | RUN pip install --no-cache-dir --upgrade pip \
31 | && pip install --no-cache-dir setuptools wheel \
32 | && pip install --no-cache-dir pdm
33 |
34 | # Install dependencies using PDM
35 | RUN pdm install --check --prod --no-editable
36 |
37 | # Setup the production environment
38 | FROM python-base as production
39 | COPY --from=builder-base $PYSETUP_PATH $PYSETUP_PATH
40 | RUN apt-get update
41 |
42 | # Set the working directory and copy your application code
43 | WORKDIR app/
44 | COPY ./src /app
45 |
--------------------------------------------------------------------------------
/src/exchange/notification_service/main.py:
--------------------------------------------------------------------------------
1 | import uvicorn
2 | from faststream.asgi import AsgiFastStream
3 | from faststream.rabbit import RabbitBroker
4 | from faststream.rabbit.opentelemetry import RabbitTelemetryMiddleware
5 | from faststream.rabbit.prometheus import RabbitPrometheusMiddleware
6 | from prometheus_client import CollectorRegistry, make_asgi_app
7 |
8 | from exchange.common.config import load_config
9 | from exchange.common.logging import configure_logging
10 | from exchange.common.telemetry import setup_telemetry
11 | from exchange.notification_service.handlers import router
12 |
13 |
14 | def main() -> AsgiFastStream:
15 | configure_logging()
16 | config = load_config()
17 | service_name = "notification"
18 | tracer_provider = setup_telemetry(
19 | service_name=service_name,
20 | otlp_endpoint=config.trace.otlp_endpoint,
21 | )
22 | registry = CollectorRegistry()
23 |
24 | telemetry_middleware = RabbitTelemetryMiddleware(tracer_provider=tracer_provider)
25 | prometheus_middleware = RabbitPrometheusMiddleware(
26 | registry=registry,
27 | app_name=service_name,
28 | metrics_prefix="faststream",
29 | )
30 | broker = RabbitBroker(url=config.rabbit.url, middlewares=(telemetry_middleware, prometheus_middleware))
31 | broker.include_router(router)
32 | return AsgiFastStream(broker, [("/metrics", make_asgi_app(registry))])
33 |
34 |
35 | if __name__ == "__main__":
36 | uvicorn.run(main(), host="0.0.0.0", port=8080)
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # [FastStream](https://github.com/ag2ai/faststream) Monitoring Example
4 |
5 | [](https://www.python.org/)
6 | [](https://pdm-project.org)
7 | [](https://mypy-lang.org/)
8 | [](https://github.com/astral-sh/ruff)
9 | [](https://github.com/draincoder/pyproject/actions/workflows/ci.yaml)
10 |
11 |
12 |
13 | ## Example of monitoring settings for FastStream
14 |
15 | [FastStream OpenTelemetry documentation](https://faststream.ag2.ai/latest/getting-started/observability/opentelemetry/)\
16 | [FastStream Prometheus documentation](https://faststream.ag2.ai/latest/getting-started/observability/prometheus/)
17 |
18 | * Three [**FastStream**](https://github.com/ag2ai/faststream) services
19 | * Exporting traces to **Grafana Tempo** via **gRPC**
20 | * Visualization of traces via **Grafana**
21 | * Collecting metrics and exporting using **Prometheus**
22 | * [**Grafana dashboard**](https://grafana.com/grafana/dashboards/22130-faststream-metrics/) for metrics
23 | * Examples with custom spans
24 | * Configured **docker-compose** with the entire infrastructure
25 |
26 | ## How to run the example
27 |
28 | 1. Clone project
29 | ```shell
30 | git clone https://github.com/draincoder/faststream-monitoring.git
31 | ```
32 | 2. Start application
33 | ```shell
34 | docker compose --profile exchange --profile grafana up --build -d
35 | ```
36 | 3. Open **Grafana** on `http://127.0.0.1:3000` with login `admin` and password `admin`
37 | 4. Go to **Explore** - **Tempo**
38 | 5. Enter TraceQL query `{}`
39 | 6. Go to **Dashboards** - **FastStream Metrics**
40 |
41 | 
42 | 
43 |
--------------------------------------------------------------------------------
/src/exchange/order_service/main.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 | import random
3 |
4 | import uvicorn
5 | from faststream.asgi import AsgiFastStream
6 | from faststream.rabbit import RabbitBroker
7 | from faststream.rabbit.opentelemetry import RabbitTelemetryMiddleware
8 | from faststream.rabbit.prometheus import RabbitPrometheusMiddleware
9 | from prometheus_client import CollectorRegistry, make_asgi_app
10 |
11 | from exchange.common.config import load_config
12 | from exchange.common.logging import configure_logging
13 | from exchange.common.telemetry import setup_telemetry
14 | from exchange.order_service.handlers import router
15 | from exchange.order_service.models import Direction, Order
16 |
17 |
18 | def main() -> AsgiFastStream:
19 | configure_logging()
20 | config = load_config()
21 | service_name = "order"
22 | tracer_provider = setup_telemetry(
23 | service_name=service_name,
24 | otlp_endpoint=config.trace.otlp_endpoint,
25 | )
26 | registry = CollectorRegistry()
27 |
28 | telemetry_middleware = RabbitTelemetryMiddleware(tracer_provider=tracer_provider)
29 | prometheus_middleware = RabbitPrometheusMiddleware(
30 | registry=registry, app_name=service_name, metrics_prefix="faststream"
31 | )
32 | broker = RabbitBroker(url=config.rabbit.url, middlewares=(telemetry_middleware, prometheus_middleware))
33 | broker.include_router(router)
34 | app = AsgiFastStream(broker, [("/metrics", make_asgi_app(registry))])
35 |
36 | @app.after_startup
37 | async def after_startup() -> None:
38 | while True:
39 | await broker.publish(Order(symbol="AAPL", quantity=10, type=Direction.BUY), "orders")
40 | await broker.publish(Order(symbol="AAPL" * 100, quantity=5, type=Direction.BUY), "orders")
41 | await broker.publish(Order(symbol="AAPL" * 300, quantity=1, type=Direction.BUY), "orders")
42 | await broker.publish(Order(symbol="AAPL", quantity=-1, type=Direction.BUY), "orders")
43 | await asyncio.sleep(random.randint(1, 50) / 10)
44 |
45 | return app
46 |
47 |
48 | if __name__ == "__main__":
49 | uvicorn.run(main(), host="0.0.0.0", port=8080)
50 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | name: ci
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - develop
8 | pull_request:
9 | branches:
10 | - master
11 | - develop
12 |
13 | jobs:
14 | lint:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - name: Checkout
18 | uses: actions/checkout@v4
19 |
20 | - name: Setup Python
21 | uses: actions/setup-python@v5
22 | with:
23 | python-version: 3.12
24 |
25 | - name: Load cached Pre-Commit Dependencies
26 | id: cached-pre-commit-dependencies
27 | uses: actions/cache@v4
28 | with:
29 | path: ~/.cache/pre-commit/
30 | key: pre-commit-4|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }}
31 |
32 | - name: Set up PDM
33 | uses: pdm-project/setup-pdm@v4
34 | with:
35 | python-version: 3.12
36 | allow-python-prereleases: false
37 | cache: true
38 | cache-dependency-path: |
39 | ./pdm.lock
40 |
41 | - name: Install dependencies
42 | run: pdm install -G:all
43 |
44 | - name: Set PYTHONPATH
45 | run: echo "PYTHONPATH=$PWD" >> $GITHUB_ENV
46 |
47 | - name: Execute Pre-Commit
48 | run: pdm run pre-commit run --show-diff-on-failure --color=always --all-files
49 |
50 | test:
51 | runs-on: ubuntu-latest
52 | steps:
53 | - name: Checkout
54 | uses: actions/checkout@v4
55 |
56 | - name: Setup Python
57 | uses: actions/setup-python@v5
58 | with:
59 | python-version: 3.12
60 |
61 | - name: Set up PDM
62 | uses: pdm-project/setup-pdm@v4
63 | with:
64 | python-version: 3.12
65 | allow-python-prereleases: false
66 | cache: true
67 | cache-dependency-path: |
68 | ./pdm.lock
69 |
70 | - name: Install dependencies
71 | run: pdm install -G:all
72 |
73 | - name: Set PYTHONPATH
74 | run: echo "PYTHONPATH=$PWD" >> $GITHUB_ENV
75 |
76 | - name: Run tests
77 | run: pdm run pytest tests --cov=exchange --junitxml=junitxml.xml --cov-report "xml:coverage.xml"; exit ${PIPESTATUS[0]}
78 |
79 | - name: Test coverage comment
80 | uses: MishaKav/pytest-coverage-comment@main
81 | with:
82 | pytest-xml-coverage-path: ./coverage.xml
83 | junitxml-path: ./junitxml.xml
84 | report-only-changed-files: true
85 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "faststream-monitoring"
3 | version = "0.1.0"
4 | description = "Example of monitoring settings for FastStream."
5 | requires-python = ">=3.12"
6 | readme = "README.md"
7 | authors = [
8 | {name = "treaditup", email = "treaditup@gmail.com"},
9 | ]
10 | classifiers = [
11 | "Programming Language :: Python :: 3.12",
12 | "Operating System :: OS Independent",
13 | ]
14 | dependencies = [
15 | "opentelemetry-exporter-otlp>=1.24.0",
16 | "adaptix>=3.0.0b5",
17 | "uvicorn>=0.32.0",
18 | "faststream[otel,prometheus,rabbit]==0.6.0rc0",
19 | ]
20 |
21 | [project.urls]
22 | "Source" = "https://github.com/draincoder/faststream-monitoring"
23 | "Homepage" = "https://github.com/draincoder/faststream-monitoring"
24 |
25 | [build-system]
26 | requires = ["setuptools>=61", "wheel"]
27 | build-backend = "setuptools.build_meta"
28 |
29 | [tool.pdm.dev-dependencies]
30 | lint = [
31 | "ruff>=0.3.4",
32 | "mypy>=1.9.0",
33 | "pre-commit>=3.7.0",
34 | ]
35 | test = [
36 | "pytest>=8.1.1",
37 | "pytest-asyncio>=0.23.6",
38 | "pytest-cov>=5.0.0",
39 | ]
40 |
41 | [tool.ruff]
42 | line-length = 120
43 | target-version="py312"
44 | src = ["src"]
45 | include = ["src/**.py", "tests/**.py"]
46 |
47 | lint.select = [
48 | "ALL",
49 | ]
50 |
51 | lint.ignore = [
52 | "ARG",
53 | "ANN",
54 | "D",
55 | "EM101",
56 | "EM102",
57 | "PT001",
58 | "PT023",
59 | "SIM108",
60 | "SIM114",
61 | "TRY003",
62 | "PLW2901",
63 | "RET505",
64 | "ISC001",
65 | "UP035",
66 | "COM812",
67 | "PTH123",
68 | "S311",
69 | "S104",
70 | ]
71 |
72 | [tool.ruff.lint.per-file-ignores]
73 | "tests/**" = ["TID252", "PLR2004", "S101", "T201", "SLF001", "PERF203", "S603", "S607"]
74 |
75 | [tool.ruff.lint.mccabe]
76 | max-complexity = 12
77 |
78 | [tool.ruff.lint.isort]
79 | known-first-party = ["src", "tests"]
80 | no-lines-before = ["local-folder"]
81 |
82 | [tool.ruff.lint.flake8-tidy-imports]
83 | ban-relative-imports = "parents"
84 |
85 | [tool.ruff.format]
86 | docstring-code-format = true
87 | docstring-code-line-length = 88
88 |
89 | [tool.mypy]
90 | packages = ["src", "tests"]
91 | python_version = "3.12"
92 |
93 | strict = true
94 | pretty = true
95 | allow_redefinition = true
96 | allow_untyped_calls = true
97 | disallow_any_explicit = false
98 | disallow_any_generics = false
99 | disallow_subclassing_any = false
100 | disallow_untyped_decorators = false
101 | ignore_missing_imports = true
102 | show_column_numbers = true
103 | show_error_context = true
104 | warn_unreachable = true
105 |
106 | [tool.pytest.ini_options]
107 | asyncio_mode = "auto"
108 | filterwarnings = "ignore::DeprecationWarning"
109 |
--------------------------------------------------------------------------------
/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | order:
3 | profiles: [ "exchange" ]
4 | container_name: example.order
5 | hostname: example.order
6 | build:
7 | context: .
8 | restart: unless-stopped
9 | depends_on:
10 | rabbit:
11 | condition: service_healthy
12 | tempo:
13 | condition: service_started
14 | networks:
15 | - example.grafana.network
16 | - example.rabbit.network
17 | volumes:
18 | - ./config:/app/config:ro
19 | environment:
20 | - CONFIG_PATH=$CONFIG_PATH
21 | command: [ "python", "-m", "exchange.order_service.main" ]
22 |
23 | trade:
24 | profiles: [ "exchange" ]
25 | container_name: example.trade
26 | hostname: example.trade
27 | build:
28 | context: .
29 | restart: unless-stopped
30 | depends_on:
31 | rabbit:
32 | condition: service_healthy
33 | tempo:
34 | condition: service_started
35 | networks:
36 | - example.grafana.network
37 | - example.rabbit.network
38 | volumes:
39 | - ./config:/app/config:ro
40 | environment:
41 | - CONFIG_PATH=$CONFIG_PATH
42 | command: [ "python", "-m", "exchange.trade_service.main" ]
43 |
44 | notification:
45 | profiles: [ "exchange" ]
46 | container_name: example.notification
47 | hostname: example.notification
48 | build:
49 | context: .
50 | restart: unless-stopped
51 | depends_on:
52 | rabbit:
53 | condition: service_healthy
54 | tempo:
55 | condition: service_started
56 | networks:
57 | - example.grafana.network
58 | - example.rabbit.network
59 | volumes:
60 | - ./config:/app/config:ro
61 | environment:
62 | - CONFIG_PATH=$CONFIG_PATH
63 | command: [ "python", "-m", "exchange.notification_service.main" ]
64 |
65 | rabbit:
66 | profiles: [ "exchange" ]
67 | image: rabbitmq:3.11-management-alpine
68 | container_name: example.rabbit
69 | hostname: example.rabbit
70 | restart: unless-stopped
71 | ports:
72 | - "5671:5671"
73 | - "5672:5672"
74 | - "15672:15672"
75 | networks:
76 | - example.rabbit.network
77 | volumes:
78 | - example.rabbit.data:/var/lib/rabbitmq/:rw
79 | environment:
80 | - RABBITMQ_DEFAULT_USER=${RABBITMQ_USER:-admin}
81 | - RABBITMQ_DEFAULT_PASS=${RABBITMQ_PASSWORD:-admin}
82 | healthcheck:
83 | test: [ "CMD-SHELL", "rabbitmq-diagnostics check_running -q" ]
84 | interval: 10s
85 | timeout: 60s
86 | retries: 5
87 | start_period: 10s
88 |
89 | grafana:
90 | profiles: [ "grafana" ]
91 | image: grafana/grafana:12.0.0
92 | container_name: example.grafana
93 | hostname: example.grafana
94 | restart: unless-stopped
95 | ports:
96 | - "3000:3000"
97 | networks:
98 | - example.grafana.network
99 | volumes:
100 | - example.grafana.data:/var/lib/grafana:rw
101 | - ./grafana/provisioning:/etc/grafana/provisioning:rw
102 | - ./grafana/dashboards:/etc/grafana/dashboards
103 | environment:
104 | - GF_SECURITY_ADMIN_USER=${GRAFANA_USER:-admin}
105 | - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin}
106 | - GF_USERS_ALLOW_SIGN_UP=false
107 | - GF_DATABASE_WAL=true
108 | - VIRTUAL_HOST=example.grafana
109 | - NETWORK_ACCESS=internal
110 | - VIRTUAL_PORT=3000
111 |
112 | tempo:
113 | profiles: [ "grafana" ]
114 | image: grafana/tempo:2.8.1
115 | container_name: example.tempo
116 | hostname: example.tempo
117 | command: [ "-config.file=/etc/tempo.yaml" ]
118 | volumes:
119 | - example.tempo.data:/var/tempo
120 | - ./tempo/tempo.yaml:/etc/tempo.yaml
121 | restart: unless-stopped
122 | ports:
123 | - "14250:14250"
124 | - "4317:4317"
125 | - "3200:3200"
126 | networks:
127 | - example.grafana.network
128 |
129 | prometheus:
130 | image: prom/prometheus:v3.3.1
131 | container_name: example.prometheus
132 | hostname: example.prometheus
133 | command:
134 | - --config.file=/etc/prometheus.yaml
135 | - --web.enable-remote-write-receiver
136 | - --enable-feature=exemplar-storage
137 | volumes:
138 | - ./prometheus/prometheus.yaml:/etc/prometheus.yaml
139 | ports:
140 | - "9090:9090"
141 | networks:
142 | - example.grafana.network
143 |
144 | volumes:
145 | example.grafana.data: {}
146 | example.rabbit.data: {}
147 | example.tempo.data: {}
148 |
149 | networks:
150 | example.grafana.network: {}
151 | example.rabbit.network: {}
152 |
--------------------------------------------------------------------------------
/grafana/dashboards/faststream.json:
--------------------------------------------------------------------------------
1 | {
2 | "__inputs": [
3 | {
4 | "name": "DS_PROMETHEUS",
5 | "label": "prometheus",
6 | "description": "Prometheus",
7 | "type": "datasource",
8 | "pluginId": "prometheus",
9 | "pluginName": "Prometheus"
10 | }
11 | ],
12 | "__requires": [
13 | {
14 | "type": "panel",
15 | "id": "bargauge",
16 | "name": "Bar gauge",
17 | "version": ""
18 | },
19 | {
20 | "type": "panel",
21 | "id": "gauge",
22 | "name": "Gauge",
23 | "version": ""
24 | },
25 | {
26 | "type": "grafana",
27 | "id": "grafana",
28 | "name": "Grafana",
29 | "version": "7.0.1"
30 | },
31 | {
32 | "type": "panel",
33 | "id": "graph",
34 | "name": "Graph",
35 | "version": ""
36 | },
37 | {
38 | "type": "datasource",
39 | "id": "prometheus",
40 | "name": "Prometheus",
41 | "version": "1.0.0"
42 | },
43 | {
44 | "type": "panel",
45 | "id": "stat",
46 | "name": "Stat",
47 | "version": ""
48 | },
49 | {
50 | "type": "panel",
51 | "id": "table",
52 | "name": "Table",
53 | "version": ""
54 | }
55 | ],
56 | "annotations": {
57 | "list": [
58 | {
59 | "builtIn": 1,
60 | "datasource": {
61 | "type": "datasource",
62 | "uid": "grafana"
63 | },
64 | "enable": true,
65 | "hide": true,
66 | "iconColor": "rgba(0, 211, 255, 1)",
67 | "name": "Annotations & Alerts",
68 | "target": {
69 | "limit": 100,
70 | "matchAny": false,
71 | "tags": [],
72 | "type": "dashboard"
73 | },
74 | "type": "dashboard"
75 | }
76 | ]
77 | },
78 | "description": "FastStream is a powerful and easy-to-use Python framework for building asynchronous services interacting with event streams such as Apache Kafka, RabbitMQ, NATS and Redis",
79 | "editable": true,
80 | "fiscalYearStartMonth": 0,
81 | "graphTooltip": 0,
82 | "links": [
83 | {
84 | "asDropdown": false,
85 | "icon": "external link",
86 | "includeVars": false,
87 | "keepTime": false,
88 | "tags": [],
89 | "targetBlank": true,
90 | "title": "FastStream",
91 | "tooltip": "",
92 | "type": "link",
93 | "url": "https://github.com/airtai/faststream"
94 | }
95 | ],
96 | "liveNow": false,
97 | "panels": [
98 | {
99 | "datasource": {
100 | "type": "prometheus",
101 | "uid": "$datasource"
102 | },
103 | "description": "All published messages of all statuses for the interval",
104 | "fieldConfig": {
105 | "defaults": {
106 | "mappings": [],
107 | "noValue": "N/A",
108 | "thresholds": {
109 | "mode": "absolute",
110 | "steps": [
111 | {
112 | "color": "green",
113 | "value": null
114 | }
115 | ]
116 | },
117 | "unit": "short",
118 | "unitScale": true
119 | },
120 | "overrides": []
121 | },
122 | "gridPos": {
123 | "h": 5,
124 | "w": 3,
125 | "x": 0,
126 | "y": 0
127 | },
128 | "id": 1,
129 | "options": {
130 | "colorMode": "value",
131 | "graphMode": "area",
132 | "justifyMode": "auto",
133 | "orientation": "auto",
134 | "reduceOptions": {
135 | "calcs": [
136 | "lastNotNull"
137 | ],
138 | "fields": "",
139 | "values": false
140 | },
141 | "showPercentChange": false,
142 | "textMode": "auto",
143 | "wideLayout": true
144 | },
145 | "pluginVersion": "10.3.3",
146 | "targets": [
147 | {
148 | "datasource": {
149 | "type": "prometheus",
150 | "uid": "$datasource"
151 | },
152 | "exemplar": true,
153 | "expr": "sum(increase({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_published_messages_total\", destination=~\"$destination\"} [$__range]))",
154 | "interval": "",
155 | "legendFormat": "",
156 | "refId": "A"
157 | }
158 | ],
159 | "title": "Total messages published",
160 | "type": "stat"
161 | },
162 | {
163 | "datasource": {
164 | "type": "prometheus",
165 | "uid": "$datasource"
166 | },
167 | "description": "The number of successfully published messages per destination in the interval",
168 | "fieldConfig": {
169 | "defaults": {
170 | "fieldMinMax": false,
171 | "mappings": [],
172 | "noValue": "N/A",
173 | "thresholds": {
174 | "mode": "absolute",
175 | "steps": [
176 | {
177 | "color": "green",
178 | "value": null
179 | }
180 | ]
181 | },
182 | "unit": "short",
183 | "unitScale": true
184 | },
185 | "overrides": []
186 | },
187 | "gridPos": {
188 | "h": 5,
189 | "w": 7,
190 | "x": 3,
191 | "y": 0
192 | },
193 | "id": 7,
194 | "options": {
195 | "colorMode": "value",
196 | "graphMode": "area",
197 | "justifyMode": "auto",
198 | "orientation": "auto",
199 | "reduceOptions": {
200 | "calcs": [
201 | "lastNotNull"
202 | ],
203 | "fields": "",
204 | "values": false
205 | },
206 | "showPercentChange": false,
207 | "textMode": "value_and_name",
208 | "wideLayout": true
209 | },
210 | "pluginVersion": "10.3.3",
211 | "targets": [
212 | {
213 | "datasource": {
214 | "type": "prometheus",
215 | "uid": "$datasource"
216 | },
217 | "editorMode": "code",
218 | "exemplar": true,
219 | "expr": "increase({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_published_messages_total\", status=\"success\", destination=~\"$destination\"} [$__range])",
220 | "interval": "",
221 | "legendFormat": "{{destination}}",
222 | "range": true,
223 | "refId": "A"
224 | }
225 | ],
226 | "title": "Messages published",
227 | "type": "stat"
228 | },
229 | {
230 | "datasource": {
231 | "type": "prometheus",
232 | "uid": "$datasource"
233 | },
234 | "description": "All received messages of all statuses for the interval",
235 | "fieldConfig": {
236 | "defaults": {
237 | "mappings": [],
238 | "noValue": "N/A",
239 | "thresholds": {
240 | "mode": "absolute",
241 | "steps": [
242 | {
243 | "color": "green",
244 | "value": null
245 | }
246 | ]
247 | },
248 | "unit": "short",
249 | "unitScale": true
250 | },
251 | "overrides": []
252 | },
253 | "gridPos": {
254 | "h": 5,
255 | "w": 3,
256 | "x": 10,
257 | "y": 0
258 | },
259 | "id": 2,
260 | "options": {
261 | "colorMode": "value",
262 | "graphMode": "area",
263 | "justifyMode": "auto",
264 | "orientation": "auto",
265 | "reduceOptions": {
266 | "calcs": [
267 | "lastNotNull"
268 | ],
269 | "fields": "",
270 | "values": false
271 | },
272 | "showPercentChange": false,
273 | "textMode": "auto",
274 | "wideLayout": true
275 | },
276 | "pluginVersion": "10.3.3",
277 | "targets": [
278 | {
279 | "datasource": {
280 | "type": "prometheus",
281 | "uid": "$datasource"
282 | },
283 | "exemplar": true,
284 | "expr": "sum(increase({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_messages_total\", handler=~\"$handler\"} [$__range]))",
285 | "interval": "",
286 | "legendFormat": "",
287 | "refId": "A"
288 | }
289 | ],
290 | "title": "Total messages received",
291 | "type": "stat"
292 | },
293 | {
294 | "datasource": {
295 | "type": "prometheus",
296 | "uid": "$datasource"
297 | },
298 | "description": "All processed messages of all statuses for the interval",
299 | "fieldConfig": {
300 | "defaults": {
301 | "mappings": [],
302 | "noValue": "N/A",
303 | "thresholds": {
304 | "mode": "absolute",
305 | "steps": [
306 | {
307 | "color": "green",
308 | "value": null
309 | }
310 | ]
311 | },
312 | "unit": "short",
313 | "unitScale": true
314 | },
315 | "overrides": []
316 | },
317 | "gridPos": {
318 | "h": 5,
319 | "w": 3,
320 | "x": 13,
321 | "y": 0
322 | },
323 | "id": 3,
324 | "options": {
325 | "colorMode": "value",
326 | "graphMode": "area",
327 | "justifyMode": "auto",
328 | "orientation": "auto",
329 | "reduceOptions": {
330 | "calcs": [
331 | "lastNotNull"
332 | ],
333 | "fields": "",
334 | "values": false
335 | },
336 | "showPercentChange": false,
337 | "textMode": "auto",
338 | "wideLayout": true
339 | },
340 | "pluginVersion": "10.3.3",
341 | "targets": [
342 | {
343 | "datasource": {
344 | "type": "prometheus",
345 | "uid": "$datasource"
346 | },
347 | "exemplar": true,
348 | "expr": "sum(increase({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", handler=~\"$handler\"} [$__range]))",
349 | "interval": "",
350 | "legendFormat": "",
351 | "refId": "A"
352 | }
353 | ],
354 | "title": "Total messages processed",
355 | "type": "stat"
356 | },
357 | {
358 | "datasource": {
359 | "type": "prometheus",
360 | "uid": "$datasource"
361 | },
362 | "description": "The number of acked messages per handler in the interval",
363 | "fieldConfig": {
364 | "defaults": {
365 | "mappings": [],
366 | "noValue": "N/A",
367 | "thresholds": {
368 | "mode": "absolute",
369 | "steps": [
370 | {
371 | "color": "green",
372 | "value": null
373 | }
374 | ]
375 | },
376 | "unit": "short",
377 | "unitScale": true
378 | },
379 | "overrides": []
380 | },
381 | "gridPos": {
382 | "h": 5,
383 | "w": 8,
384 | "x": 16,
385 | "y": 0
386 | },
387 | "id": 8,
388 | "options": {
389 | "colorMode": "value",
390 | "graphMode": "area",
391 | "justifyMode": "auto",
392 | "orientation": "auto",
393 | "reduceOptions": {
394 | "calcs": [
395 | "lastNotNull"
396 | ],
397 | "fields": "",
398 | "values": false
399 | },
400 | "showPercentChange": false,
401 | "textMode": "value_and_name",
402 | "wideLayout": true
403 | },
404 | "pluginVersion": "10.3.3",
405 | "targets": [
406 | {
407 | "datasource": {
408 | "type": "prometheus",
409 | "uid": "$datasource"
410 | },
411 | "exemplar": true,
412 | "expr": "increase({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", status=\"acked\", handler=~\"$handler\"} [$__range])",
413 | "interval": "",
414 | "legendFormat": "{{handler}}",
415 | "refId": "A"
416 | }
417 | ],
418 | "title": "Messages processed",
419 | "type": "stat"
420 | },
421 | {
422 | "datasource": {
423 | "type": "prometheus",
424 | "uid": "$datasource"
425 | },
426 | "description": "All publication errors in the interval",
427 | "fieldConfig": {
428 | "defaults": {
429 | "color": {
430 | "mode": "thresholds"
431 | },
432 | "mappings": [],
433 | "noValue": "N/A",
434 | "thresholds": {
435 | "mode": "absolute",
436 | "steps": [
437 | {
438 | "color": "green",
439 | "value": null
440 | },
441 | {
442 | "color": "red",
443 | "value": 1
444 | }
445 | ]
446 | },
447 | "unitScale": true
448 | },
449 | "overrides": []
450 | },
451 | "gridPos": {
452 | "h": 5,
453 | "w": 3,
454 | "x": 0,
455 | "y": 5
456 | },
457 | "id": 5,
458 | "options": {
459 | "colorMode": "value",
460 | "graphMode": "area",
461 | "justifyMode": "auto",
462 | "orientation": "auto",
463 | "reduceOptions": {
464 | "calcs": [
465 | "lastNotNull"
466 | ],
467 | "fields": "",
468 | "values": false
469 | },
470 | "showPercentChange": false,
471 | "textMode": "auto",
472 | "wideLayout": true
473 | },
474 | "pluginVersion": "10.3.3",
475 | "targets": [
476 | {
477 | "datasource": {
478 | "type": "prometheus",
479 | "uid": "$datasource"
480 | },
481 | "exemplar": true,
482 | "expr": "sum(increase({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_published_messages_exceptions_total\", destination=~\"$destination\"} [$__range]))",
483 | "interval": "",
484 | "legendFormat": "",
485 | "refId": "A"
486 | }
487 | ],
488 | "title": "Publish exceptions",
489 | "type": "stat"
490 | },
491 | {
492 | "datasource": {
493 | "type": "prometheus",
494 | "uid": "$datasource"
495 | },
496 | "description": "The average time of the publication duration for all messages per interval",
497 | "fieldConfig": {
498 | "defaults": {
499 | "color": {
500 | "mode": "continuous-GrYlRd"
501 | },
502 | "mappings": [],
503 | "noValue": "N/A",
504 | "thresholds": {
505 | "mode": "absolute",
506 | "steps": [
507 | {
508 | "color": "green",
509 | "value": null
510 | }
511 | ]
512 | },
513 | "unit": "s",
514 | "unitScale": true
515 | },
516 | "overrides": []
517 | },
518 | "gridPos": {
519 | "h": 5,
520 | "w": 7,
521 | "x": 3,
522 | "y": 5
523 | },
524 | "id": 9,
525 | "options": {
526 | "displayMode": "lcd",
527 | "maxVizHeight": 300,
528 | "minVizHeight": 16,
529 | "minVizWidth": 8,
530 | "namePlacement": "auto",
531 | "orientation": "horizontal",
532 | "reduceOptions": {
533 | "calcs": [
534 | "lastNotNull"
535 | ],
536 | "fields": "",
537 | "values": false
538 | },
539 | "showUnfilled": true,
540 | "sizing": "auto",
541 | "valueMode": "color"
542 | },
543 | "pluginVersion": "10.3.3",
544 | "targets": [
545 | {
546 | "datasource": {
547 | "type": "prometheus",
548 | "uid": "$datasource"
549 | },
550 | "exemplar": true,
551 | "expr": "{app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_published_messages_duration_seconds_sum\", destination=~\"$destination\"} / {app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_published_messages_duration_seconds_count\", destination=~\"$destination\"}",
552 | "interval": "",
553 | "legendFormat": "{{destination}}",
554 | "refId": "A"
555 | }
556 | ],
557 | "title": "Publish average duration",
558 | "type": "bargauge"
559 | },
560 | {
561 | "datasource": {
562 | "type": "prometheus",
563 | "uid": "$datasource"
564 | },
565 | "description": "All process errors in the interval",
566 | "fieldConfig": {
567 | "defaults": {
568 | "color": {
569 | "mode": "thresholds"
570 | },
571 | "mappings": [],
572 | "noValue": "N/A",
573 | "thresholds": {
574 | "mode": "absolute",
575 | "steps": [
576 | {
577 | "color": "green",
578 | "value": null
579 | },
580 | {
581 | "color": "red",
582 | "value": 1
583 | }
584 | ]
585 | },
586 | "unit": "none",
587 | "unitScale": true
588 | },
589 | "overrides": []
590 | },
591 | "gridPos": {
592 | "h": 5,
593 | "w": 3,
594 | "x": 10,
595 | "y": 5
596 | },
597 | "id": 6,
598 | "options": {
599 | "colorMode": "value",
600 | "graphMode": "area",
601 | "justifyMode": "auto",
602 | "orientation": "auto",
603 | "reduceOptions": {
604 | "calcs": [
605 | "lastNotNull"
606 | ],
607 | "fields": "",
608 | "values": false
609 | },
610 | "showPercentChange": false,
611 | "textMode": "auto",
612 | "wideLayout": true
613 | },
614 | "pluginVersion": "10.3.3",
615 | "targets": [
616 | {
617 | "datasource": {
618 | "type": "prometheus",
619 | "uid": "$datasource"
620 | },
621 | "exemplar": true,
622 | "expr": "sum(increase({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_exceptions_total\", handler=~\"$handler\"} [$__range]))",
623 | "interval": "",
624 | "legendFormat": "",
625 | "refId": "A"
626 | }
627 | ],
628 | "title": "Process exceptions",
629 | "type": "stat"
630 | },
631 | {
632 | "datasource": {
633 | "type": "prometheus",
634 | "uid": "$datasource"
635 | },
636 | "description": "The number of messages in the process",
637 | "fieldConfig": {
638 | "defaults": {
639 | "mappings": [],
640 | "noValue": "N/A",
641 | "thresholds": {
642 | "mode": "absolute",
643 | "steps": [
644 | {
645 | "color": "green",
646 | "value": null
647 | },
648 | {
649 | "color": "yellow",
650 | "value": 10
651 | },
652 | {
653 | "color": "red",
654 | "value": 100
655 | }
656 | ]
657 | },
658 | "unit": "none",
659 | "unitScale": true
660 | },
661 | "overrides": []
662 | },
663 | "gridPos": {
664 | "h": 5,
665 | "w": 3,
666 | "x": 13,
667 | "y": 5
668 | },
669 | "id": 4,
670 | "options": {
671 | "colorMode": "value",
672 | "graphMode": "area",
673 | "justifyMode": "auto",
674 | "orientation": "auto",
675 | "reduceOptions": {
676 | "calcs": [
677 | "lastNotNull"
678 | ],
679 | "fields": "",
680 | "values": false
681 | },
682 | "showPercentChange": false,
683 | "textMode": "auto",
684 | "wideLayout": true
685 | },
686 | "pluginVersion": "10.3.3",
687 | "targets": [
688 | {
689 | "datasource": {
690 | "type": "prometheus",
691 | "uid": "$datasource"
692 | },
693 | "exemplar": true,
694 | "expr": "sum({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_messages_in_process\", handler=~\"$handler\"})",
695 | "interval": "",
696 | "legendFormat": "",
697 | "refId": "A"
698 | }
699 | ],
700 | "title": "Messages in progress",
701 | "type": "stat"
702 | },
703 | {
704 | "datasource": {
705 | "type": "prometheus",
706 | "uid": "$datasource"
707 | },
708 | "description": "The average processing time for all messages per interval",
709 | "fieldConfig": {
710 | "defaults": {
711 | "color": {
712 | "mode": "continuous-GrYlRd"
713 | },
714 | "mappings": [],
715 | "noValue": "N/A",
716 | "thresholds": {
717 | "mode": "absolute",
718 | "steps": [
719 | {
720 | "color": "green",
721 | "value": null
722 | }
723 | ]
724 | },
725 | "unit": "s",
726 | "unitScale": true
727 | },
728 | "overrides": []
729 | },
730 | "gridPos": {
731 | "h": 5,
732 | "w": 8,
733 | "x": 16,
734 | "y": 5
735 | },
736 | "id": 10,
737 | "options": {
738 | "displayMode": "lcd",
739 | "maxVizHeight": 300,
740 | "minVizHeight": 16,
741 | "minVizWidth": 8,
742 | "namePlacement": "auto",
743 | "orientation": "horizontal",
744 | "reduceOptions": {
745 | "calcs": [
746 | "lastNotNull"
747 | ],
748 | "fields": "",
749 | "values": false
750 | },
751 | "showUnfilled": true,
752 | "sizing": "auto",
753 | "valueMode": "color"
754 | },
755 | "pluginVersion": "10.3.3",
756 | "targets": [
757 | {
758 | "datasource": {
759 | "type": "prometheus",
760 | "uid": "$datasource"
761 | },
762 | "exemplar": true,
763 | "expr": "{app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_duration_seconds_sum\", handler=~\"$handler\"} / {app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_duration_seconds_count\", handler=~\"$handler\"}",
764 | "interval": "",
765 | "legendFormat": "{{handler}}",
766 | "refId": "A"
767 | }
768 | ],
769 | "title": "Process average duration",
770 | "type": "bargauge"
771 | },
772 | {
773 | "datasource": {
774 | "type": "prometheus",
775 | "uid": "$datasource"
776 | },
777 | "description": "Publishing messages per second with the status",
778 | "fieldConfig": {
779 | "defaults": {
780 | "color": {
781 | "mode": "palette-classic"
782 | },
783 | "custom": {
784 | "axisBorderShow": false,
785 | "axisCenteredZero": false,
786 | "axisColorMode": "text",
787 | "axisLabel": "",
788 | "axisPlacement": "auto",
789 | "barAlignment": 0,
790 | "drawStyle": "line",
791 | "fillOpacity": 0,
792 | "gradientMode": "none",
793 | "hideFrom": {
794 | "legend": false,
795 | "tooltip": false,
796 | "viz": false
797 | },
798 | "insertNulls": false,
799 | "lineInterpolation": "linear",
800 | "lineStyle": {
801 | "fill": "solid"
802 | },
803 | "lineWidth": 1,
804 | "pointSize": 5,
805 | "scaleDistribution": {
806 | "type": "linear"
807 | },
808 | "showPoints": "auto",
809 | "spanNulls": false,
810 | "stacking": {
811 | "group": "A",
812 | "mode": "none"
813 | },
814 | "thresholdsStyle": {
815 | "mode": "off"
816 | }
817 | },
818 | "mappings": [],
819 | "noValue": "N/A",
820 | "thresholds": {
821 | "mode": "absolute",
822 | "steps": [
823 | {
824 | "color": "green",
825 | "value": null
826 | }
827 | ]
828 | },
829 | "unit": "mps",
830 | "unitScale": true
831 | },
832 | "overrides": []
833 | },
834 | "gridPos": {
835 | "h": 8,
836 | "w": 8,
837 | "x": 0,
838 | "y": 10
839 | },
840 | "id": 11,
841 | "options": {
842 | "legend": {
843 | "calcs": [],
844 | "displayMode": "list",
845 | "placement": "bottom",
846 | "showLegend": true
847 | },
848 | "tooltip": {
849 | "mode": "single",
850 | "sort": "none"
851 | }
852 | },
853 | "targets": [
854 | {
855 | "datasource": {
856 | "type": "prometheus",
857 | "uid": "$datasource"
858 | },
859 | "exemplar": true,
860 | "expr": "rate({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_published_messages_total\", destination=~\"$destination\"} [1m])",
861 | "interval": "",
862 | "legendFormat": "{{destination}} [{{status}}]",
863 | "refId": "A"
864 | }
865 | ],
866 | "title": "Publish per sec",
867 | "type": "timeseries"
868 | },
869 | {
870 | "datasource": {
871 | "type": "prometheus",
872 | "uid": "$datasource"
873 | },
874 | "description": "Processing messages per second with the status",
875 | "fieldConfig": {
876 | "defaults": {
877 | "color": {
878 | "mode": "palette-classic"
879 | },
880 | "custom": {
881 | "axisBorderShow": false,
882 | "axisCenteredZero": false,
883 | "axisColorMode": "text",
884 | "axisLabel": "",
885 | "axisPlacement": "auto",
886 | "barAlignment": 0,
887 | "drawStyle": "line",
888 | "fillOpacity": 0,
889 | "gradientMode": "none",
890 | "hideFrom": {
891 | "legend": false,
892 | "tooltip": false,
893 | "viz": false
894 | },
895 | "insertNulls": false,
896 | "lineInterpolation": "linear",
897 | "lineWidth": 1,
898 | "pointSize": 5,
899 | "scaleDistribution": {
900 | "type": "linear"
901 | },
902 | "showPoints": "auto",
903 | "spanNulls": false,
904 | "stacking": {
905 | "group": "A",
906 | "mode": "none"
907 | },
908 | "thresholdsStyle": {
909 | "mode": "off"
910 | }
911 | },
912 | "mappings": [],
913 | "noValue": "N/A",
914 | "thresholds": {
915 | "mode": "absolute",
916 | "steps": [
917 | {
918 | "color": "green",
919 | "value": null
920 | }
921 | ]
922 | },
923 | "unit": "mps",
924 | "unitScale": true
925 | },
926 | "overrides": []
927 | },
928 | "gridPos": {
929 | "h": 8,
930 | "w": 8,
931 | "x": 8,
932 | "y": 10
933 | },
934 | "id": 12,
935 | "options": {
936 | "legend": {
937 | "calcs": [],
938 | "displayMode": "list",
939 | "placement": "bottom",
940 | "showLegend": true
941 | },
942 | "tooltip": {
943 | "mode": "single",
944 | "sort": "none"
945 | }
946 | },
947 | "targets": [
948 | {
949 | "datasource": {
950 | "type": "prometheus",
951 | "uid": "$datasource"
952 | },
953 | "exemplar": true,
954 | "expr": "rate({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", handler=~\"$handler\"} [1m])",
955 | "interval": "",
956 | "legendFormat": "{{handler}} [{{status}}]",
957 | "refId": "A"
958 | }
959 | ],
960 | "title": "Process per sec",
961 | "type": "timeseries"
962 | },
963 | {
964 | "datasource": {
965 | "type": "prometheus",
966 | "uid": "$datasource"
967 | },
968 | "description": "Messages in process",
969 | "fieldConfig": {
970 | "defaults": {
971 | "color": {
972 | "mode": "palette-classic"
973 | },
974 | "custom": {
975 | "axisBorderShow": false,
976 | "axisCenteredZero": false,
977 | "axisColorMode": "text",
978 | "axisLabel": "",
979 | "axisPlacement": "auto",
980 | "barAlignment": 0,
981 | "drawStyle": "line",
982 | "fillOpacity": 0,
983 | "gradientMode": "none",
984 | "hideFrom": {
985 | "legend": false,
986 | "tooltip": false,
987 | "viz": false
988 | },
989 | "insertNulls": false,
990 | "lineInterpolation": "linear",
991 | "lineWidth": 1,
992 | "pointSize": 5,
993 | "scaleDistribution": {
994 | "type": "linear"
995 | },
996 | "showPoints": "auto",
997 | "spanNulls": false,
998 | "stacking": {
999 | "group": "A",
1000 | "mode": "none"
1001 | },
1002 | "thresholdsStyle": {
1003 | "mode": "off"
1004 | }
1005 | },
1006 | "mappings": [],
1007 | "noValue": "N/A",
1008 | "thresholds": {
1009 | "mode": "absolute",
1010 | "steps": [
1011 | {
1012 | "color": "green",
1013 | "value": null
1014 | }
1015 | ]
1016 | },
1017 | "unitScale": true
1018 | },
1019 | "overrides": []
1020 | },
1021 | "gridPos": {
1022 | "h": 8,
1023 | "w": 8,
1024 | "x": 16,
1025 | "y": 10
1026 | },
1027 | "id": 14,
1028 | "options": {
1029 | "legend": {
1030 | "calcs": [],
1031 | "displayMode": "list",
1032 | "placement": "bottom",
1033 | "showLegend": true
1034 | },
1035 | "tooltip": {
1036 | "mode": "single",
1037 | "sort": "none"
1038 | }
1039 | },
1040 | "targets": [
1041 | {
1042 | "datasource": {
1043 | "type": "prometheus",
1044 | "uid": "$datasource"
1045 | },
1046 | "exemplar": true,
1047 | "expr": "{app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_messages_in_process\", handler=~\"$handler\"}",
1048 | "interval": "",
1049 | "legendFormat": "{{handler}}",
1050 | "refId": "A"
1051 | }
1052 | ],
1053 | "title": "Messages in process",
1054 | "type": "timeseries"
1055 | },
1056 | {
1057 | "datasource": {
1058 | "type": "prometheus",
1059 | "uid": "$datasource"
1060 | },
1061 | "description": "The longest message publishing",
1062 | "fieldConfig": {
1063 | "defaults": {
1064 | "color": {
1065 | "mode": "palette-classic"
1066 | },
1067 | "custom": {
1068 | "axisBorderShow": false,
1069 | "axisCenteredZero": false,
1070 | "axisColorMode": "text",
1071 | "axisLabel": "",
1072 | "axisPlacement": "auto",
1073 | "barAlignment": 0,
1074 | "drawStyle": "line",
1075 | "fillOpacity": 0,
1076 | "gradientMode": "none",
1077 | "hideFrom": {
1078 | "legend": false,
1079 | "tooltip": false,
1080 | "viz": false
1081 | },
1082 | "insertNulls": false,
1083 | "lineInterpolation": "linear",
1084 | "lineWidth": 1,
1085 | "pointSize": 5,
1086 | "scaleDistribution": {
1087 | "type": "linear"
1088 | },
1089 | "showPoints": "auto",
1090 | "spanNulls": false,
1091 | "stacking": {
1092 | "group": "A",
1093 | "mode": "none"
1094 | },
1095 | "thresholdsStyle": {
1096 | "mode": "off"
1097 | }
1098 | },
1099 | "mappings": [],
1100 | "noValue": "N/A",
1101 | "thresholds": {
1102 | "mode": "absolute",
1103 | "steps": [
1104 | {
1105 | "color": "green",
1106 | "value": null
1107 | }
1108 | ]
1109 | },
1110 | "unit": "s",
1111 | "unitScale": true
1112 | },
1113 | "overrides": []
1114 | },
1115 | "gridPos": {
1116 | "h": 8,
1117 | "w": 8,
1118 | "x": 0,
1119 | "y": 18
1120 | },
1121 | "id": 16,
1122 | "options": {
1123 | "legend": {
1124 | "calcs": [],
1125 | "displayMode": "list",
1126 | "placement": "bottom",
1127 | "showLegend": true
1128 | },
1129 | "tooltip": {
1130 | "mode": "single",
1131 | "sort": "none"
1132 | }
1133 | },
1134 | "targets": [
1135 | {
1136 | "datasource": {
1137 | "type": "prometheus",
1138 | "uid": "$datasource"
1139 | },
1140 | "exemplar": true,
1141 | "expr": "histogram_quantile(.99,sum(rate({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_published_messages_duration_seconds_bucket\", destination=~\"$destination\"} [1m])) by(destination, le))",
1142 | "interval": "",
1143 | "legendFormat": "{{destination}}",
1144 | "refId": "A"
1145 | }
1146 | ],
1147 | "title": "Publish duration [PR 99]",
1148 | "type": "timeseries"
1149 | },
1150 | {
1151 | "datasource": {
1152 | "type": "prometheus",
1153 | "uid": "$datasource"
1154 | },
1155 | "description": "The longest message processing",
1156 | "fieldConfig": {
1157 | "defaults": {
1158 | "color": {
1159 | "mode": "palette-classic"
1160 | },
1161 | "custom": {
1162 | "axisBorderShow": false,
1163 | "axisCenteredZero": false,
1164 | "axisColorMode": "text",
1165 | "axisLabel": "",
1166 | "axisPlacement": "auto",
1167 | "barAlignment": 0,
1168 | "drawStyle": "line",
1169 | "fillOpacity": 0,
1170 | "gradientMode": "none",
1171 | "hideFrom": {
1172 | "legend": false,
1173 | "tooltip": false,
1174 | "viz": false
1175 | },
1176 | "insertNulls": false,
1177 | "lineInterpolation": "linear",
1178 | "lineWidth": 1,
1179 | "pointSize": 5,
1180 | "scaleDistribution": {
1181 | "type": "linear"
1182 | },
1183 | "showPoints": "auto",
1184 | "spanNulls": false,
1185 | "stacking": {
1186 | "group": "A",
1187 | "mode": "none"
1188 | },
1189 | "thresholdsStyle": {
1190 | "mode": "off"
1191 | }
1192 | },
1193 | "mappings": [],
1194 | "noValue": "N/A",
1195 | "thresholds": {
1196 | "mode": "absolute",
1197 | "steps": [
1198 | {
1199 | "color": "green",
1200 | "value": null
1201 | },
1202 | {
1203 | "color": "red",
1204 | "value": 80
1205 | }
1206 | ]
1207 | },
1208 | "unit": "s",
1209 | "unitScale": true
1210 | },
1211 | "overrides": []
1212 | },
1213 | "gridPos": {
1214 | "h": 8,
1215 | "w": 8,
1216 | "x": 8,
1217 | "y": 18
1218 | },
1219 | "id": 13,
1220 | "options": {
1221 | "legend": {
1222 | "calcs": [],
1223 | "displayMode": "list",
1224 | "placement": "bottom",
1225 | "showLegend": true
1226 | },
1227 | "tooltip": {
1228 | "mode": "single",
1229 | "sort": "none"
1230 | }
1231 | },
1232 | "targets": [
1233 | {
1234 | "datasource": {
1235 | "type": "prometheus",
1236 | "uid": "$datasource"
1237 | },
1238 | "exemplar": true,
1239 | "expr": "histogram_quantile(.99,sum(rate({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_duration_seconds_bucket\", handler=~\"$handler\"} [1m])) by(handler, le))",
1240 | "interval": "",
1241 | "legendFormat": "{{handler}}",
1242 | "refId": "A"
1243 | }
1244 | ],
1245 | "title": "Process duration [PR 99]",
1246 | "type": "timeseries"
1247 | },
1248 | {
1249 | "datasource": {
1250 | "type": "prometheus",
1251 | "uid": "$datasource"
1252 | },
1253 | "description": "The largest received messages in size",
1254 | "fieldConfig": {
1255 | "defaults": {
1256 | "color": {
1257 | "mode": "palette-classic"
1258 | },
1259 | "custom": {
1260 | "axisBorderShow": false,
1261 | "axisCenteredZero": false,
1262 | "axisColorMode": "text",
1263 | "axisLabel": "",
1264 | "axisPlacement": "auto",
1265 | "barAlignment": 0,
1266 | "drawStyle": "line",
1267 | "fillOpacity": 0,
1268 | "gradientMode": "none",
1269 | "hideFrom": {
1270 | "legend": false,
1271 | "tooltip": false,
1272 | "viz": false
1273 | },
1274 | "insertNulls": false,
1275 | "lineInterpolation": "linear",
1276 | "lineWidth": 1,
1277 | "pointSize": 5,
1278 | "scaleDistribution": {
1279 | "type": "linear"
1280 | },
1281 | "showPoints": "auto",
1282 | "spanNulls": false,
1283 | "stacking": {
1284 | "group": "A",
1285 | "mode": "none"
1286 | },
1287 | "thresholdsStyle": {
1288 | "mode": "off"
1289 | }
1290 | },
1291 | "mappings": [],
1292 | "noValue": "N/A",
1293 | "thresholds": {
1294 | "mode": "absolute",
1295 | "steps": [
1296 | {
1297 | "color": "green",
1298 | "value": null
1299 | }
1300 | ]
1301 | },
1302 | "unit": "bytes",
1303 | "unitScale": false
1304 | },
1305 | "overrides": []
1306 | },
1307 | "gridPos": {
1308 | "h": 8,
1309 | "w": 8,
1310 | "x": 16,
1311 | "y": 18
1312 | },
1313 | "id": 15,
1314 | "options": {
1315 | "legend": {
1316 | "calcs": [],
1317 | "displayMode": "list",
1318 | "placement": "bottom",
1319 | "showLegend": true
1320 | },
1321 | "tooltip": {
1322 | "mode": "single",
1323 | "sort": "none"
1324 | }
1325 | },
1326 | "targets": [
1327 | {
1328 | "datasource": {
1329 | "type": "prometheus",
1330 | "uid": "$datasource"
1331 | },
1332 | "exemplar": true,
1333 | "expr": "histogram_quantile(.99,sum(rate({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_messages_size_bytes_bucket\", handler=~\"$handler\"} [1m])) by(handler, le))",
1334 | "interval": "",
1335 | "legendFormat": "{{handler}}",
1336 | "refId": "A"
1337 | }
1338 | ],
1339 | "title": "Received message size [PR 99]",
1340 | "type": "timeseries"
1341 | },
1342 | {
1343 | "collapsed": true,
1344 | "datasource": {
1345 | "type": "$datasource",
1346 | "uid": "prometheus"
1347 | },
1348 | "gridPos": {
1349 | "h": 1,
1350 | "w": 24,
1351 | "x": 0,
1352 | "y": 26
1353 | },
1354 | "id": 22,
1355 | "panels": [
1356 | {
1357 | "datasource": {
1358 | "type": "prometheus",
1359 | "uid": "$datasource"
1360 | },
1361 | "description": "Percentage of acked messages relative to all messages",
1362 | "fieldConfig": {
1363 | "defaults": {
1364 | "color": {
1365 | "mode": "palette-classic"
1366 | },
1367 | "custom": {
1368 | "axisBorderShow": false,
1369 | "axisCenteredZero": false,
1370 | "axisColorMode": "text",
1371 | "axisLabel": "",
1372 | "axisPlacement": "auto",
1373 | "axisSoftMax": 1,
1374 | "barAlignment": 0,
1375 | "drawStyle": "line",
1376 | "fillOpacity": 0,
1377 | "gradientMode": "none",
1378 | "hideFrom": {
1379 | "legend": false,
1380 | "tooltip": false,
1381 | "viz": false
1382 | },
1383 | "insertNulls": false,
1384 | "lineInterpolation": "linear",
1385 | "lineWidth": 1,
1386 | "pointSize": 5,
1387 | "scaleDistribution": {
1388 | "type": "linear"
1389 | },
1390 | "showPoints": "auto",
1391 | "spanNulls": false,
1392 | "stacking": {
1393 | "group": "A",
1394 | "mode": "none"
1395 | },
1396 | "thresholdsStyle": {
1397 | "mode": "area"
1398 | }
1399 | },
1400 | "mappings": [],
1401 | "noValue": "N/A",
1402 | "thresholds": {
1403 | "mode": "absolute",
1404 | "steps": [
1405 | {
1406 | "color": "red"
1407 | },
1408 | {
1409 | "color": "green",
1410 | "value": 0.8
1411 | }
1412 | ]
1413 | },
1414 | "unit": "percentunit",
1415 | "unitScale": true
1416 | },
1417 | "overrides": []
1418 | },
1419 | "gridPos": {
1420 | "h": 8,
1421 | "w": 8,
1422 | "x": 0,
1423 | "y": 27
1424 | },
1425 | "id": 18,
1426 | "options": {
1427 | "legend": {
1428 | "calcs": [],
1429 | "displayMode": "list",
1430 | "placement": "bottom",
1431 | "showLegend": true
1432 | },
1433 | "tooltip": {
1434 | "mode": "single",
1435 | "sort": "none"
1436 | }
1437 | },
1438 | "targets": [
1439 | {
1440 | "datasource": {
1441 | "type": "prometheus",
1442 | "uid": "$datasource"
1443 | },
1444 | "exemplar": true,
1445 | "expr": "sum by(handler) ({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", status=\"acked\", handler=~\"$handler\"}) / sum by(handler) ({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", handler=~\"$handler\"})",
1446 | "interval": "",
1447 | "legendFormat": "{{handler}}",
1448 | "refId": "A"
1449 | }
1450 | ],
1451 | "title": "Percent of acked messages",
1452 | "type": "timeseries"
1453 | },
1454 | {
1455 | "datasource": {
1456 | "type": "prometheus",
1457 | "uid": "$datasource"
1458 | },
1459 | "description": "Percentage of error messages relative to all messages",
1460 | "fieldConfig": {
1461 | "defaults": {
1462 | "color": {
1463 | "mode": "palette-classic"
1464 | },
1465 | "custom": {
1466 | "axisBorderShow": false,
1467 | "axisCenteredZero": false,
1468 | "axisColorMode": "text",
1469 | "axisLabel": "",
1470 | "axisPlacement": "auto",
1471 | "axisSoftMax": 1,
1472 | "barAlignment": 0,
1473 | "drawStyle": "line",
1474 | "fillOpacity": 0,
1475 | "gradientMode": "none",
1476 | "hideFrom": {
1477 | "legend": false,
1478 | "tooltip": false,
1479 | "viz": false
1480 | },
1481 | "insertNulls": false,
1482 | "lineInterpolation": "linear",
1483 | "lineWidth": 1,
1484 | "pointSize": 5,
1485 | "scaleDistribution": {
1486 | "type": "linear"
1487 | },
1488 | "showPoints": "auto",
1489 | "spanNulls": false,
1490 | "stacking": {
1491 | "group": "A",
1492 | "mode": "none"
1493 | },
1494 | "thresholdsStyle": {
1495 | "mode": "area"
1496 | }
1497 | },
1498 | "mappings": [],
1499 | "noValue": "N/A",
1500 | "thresholds": {
1501 | "mode": "absolute",
1502 | "steps": [
1503 | {
1504 | "color": "red"
1505 | }
1506 | ]
1507 | },
1508 | "unit": "percentunit",
1509 | "unitScale": true
1510 | },
1511 | "overrides": []
1512 | },
1513 | "gridPos": {
1514 | "h": 8,
1515 | "w": 8,
1516 | "x": 8,
1517 | "y": 27
1518 | },
1519 | "id": 20,
1520 | "options": {
1521 | "legend": {
1522 | "calcs": [],
1523 | "displayMode": "list",
1524 | "placement": "bottom",
1525 | "showLegend": true
1526 | },
1527 | "tooltip": {
1528 | "mode": "single",
1529 | "sort": "none"
1530 | }
1531 | },
1532 | "targets": [
1533 | {
1534 | "datasource": {
1535 | "type": "prometheus",
1536 | "uid": "$datasource"
1537 | },
1538 | "exemplar": true,
1539 | "expr": "sum by(handler) ({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", status=\"error\", handler=~\"$handler\"}) / sum by(handler) ({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", handler=~\"$handler\"})",
1540 | "interval": "",
1541 | "legendFormat": "{{handler}}",
1542 | "refId": "A"
1543 | }
1544 | ],
1545 | "title": "Percent of error messages",
1546 | "type": "timeseries"
1547 | },
1548 | {
1549 | "datasource": {
1550 | "type": "prometheus",
1551 | "uid": "$datasource"
1552 | },
1553 | "description": "Percentage of nacked, rejected, skipped messages relative to all messages",
1554 | "fieldConfig": {
1555 | "defaults": {
1556 | "color": {
1557 | "mode": "palette-classic"
1558 | },
1559 | "custom": {
1560 | "axisBorderShow": false,
1561 | "axisCenteredZero": false,
1562 | "axisColorMode": "text",
1563 | "axisLabel": "",
1564 | "axisPlacement": "auto",
1565 | "axisSoftMax": 1,
1566 | "barAlignment": 0,
1567 | "drawStyle": "line",
1568 | "fillOpacity": 0,
1569 | "gradientMode": "none",
1570 | "hideFrom": {
1571 | "legend": false,
1572 | "tooltip": false,
1573 | "viz": false
1574 | },
1575 | "insertNulls": false,
1576 | "lineInterpolation": "linear",
1577 | "lineWidth": 1,
1578 | "pointSize": 5,
1579 | "scaleDistribution": {
1580 | "type": "linear"
1581 | },
1582 | "showPoints": "auto",
1583 | "spanNulls": false,
1584 | "stacking": {
1585 | "group": "A",
1586 | "mode": "none"
1587 | },
1588 | "thresholdsStyle": {
1589 | "mode": "area"
1590 | }
1591 | },
1592 | "mappings": [],
1593 | "noValue": "N/A",
1594 | "thresholds": {
1595 | "mode": "absolute",
1596 | "steps": [
1597 | {
1598 | "color": "red"
1599 | }
1600 | ]
1601 | },
1602 | "unit": "percentunit",
1603 | "unitScale": true
1604 | },
1605 | "overrides": []
1606 | },
1607 | "gridPos": {
1608 | "h": 8,
1609 | "w": 8,
1610 | "x": 16,
1611 | "y": 27
1612 | },
1613 | "id": 21,
1614 | "options": {
1615 | "legend": {
1616 | "calcs": [],
1617 | "displayMode": "list",
1618 | "placement": "bottom",
1619 | "showLegend": true
1620 | },
1621 | "tooltip": {
1622 | "mode": "single",
1623 | "sort": "none"
1624 | }
1625 | },
1626 | "targets": [
1627 | {
1628 | "datasource": {
1629 | "type": "prometheus",
1630 | "uid": "$datasource"
1631 | },
1632 | "exemplar": true,
1633 | "expr": "sum by(handler) ({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", status=~\"nacked|rejected|skipped\", handler=~\"$handler\"}) / sum by(handler) ({app_name=~\"$app_name\", __name__=~\"${metrics_prefix}_received_processed_messages_total\", handler=~\"$handler\"})",
1634 | "interval": "",
1635 | "legendFormat": "{{handler}}",
1636 | "refId": "A"
1637 | }
1638 | ],
1639 | "title": "Percent of nacked, rejected, skipped messages",
1640 | "type": "timeseries"
1641 | }
1642 | ],
1643 | "title": "Percentages of processed message statuses",
1644 | "type": "row"
1645 | }
1646 | ],
1647 | "refresh": "10s",
1648 | "schemaVersion": 39,
1649 | "tags": [
1650 | "faststream"
1651 | ],
1652 | "templating": {
1653 | "list": [
1654 | {
1655 | "current": {
1656 | "selected": false,
1657 | "text": "Prometheus",
1658 | "value": "prometheus"
1659 | },
1660 | "description": "Prometheus data source",
1661 | "hide": 0,
1662 | "includeAll": false,
1663 | "label": "Data Source",
1664 | "multi": false,
1665 | "name": "datasource",
1666 | "options": [],
1667 | "query": "prometheus",
1668 | "refresh": 1,
1669 | "regex": "",
1670 | "skipUrlSync": false,
1671 | "type": "datasource"
1672 | },
1673 | {
1674 | "current": {
1675 | "selected": false,
1676 | "text": "faststream",
1677 | "value": "faststream"
1678 | },
1679 | "description": "The prefix of metrics that is specified in PrometheusMiddleware",
1680 | "hide": 0,
1681 | "label": "Metrics Prefix",
1682 | "name": "metrics_prefix",
1683 | "options": [
1684 | {
1685 | "selected": true,
1686 | "text": "faststream",
1687 | "value": "faststream"
1688 | }
1689 | ],
1690 | "query": "faststream",
1691 | "skipUrlSync": false,
1692 | "type": "textbox"
1693 | },
1694 | {
1695 | "allValue": ".+",
1696 | "current": {
1697 | "selected": false,
1698 | "text": "All",
1699 | "value": ".+"
1700 | },
1701 | "datasource": {
1702 | "type": "prometheus",
1703 | "uid": "$datasource"
1704 | },
1705 | "definition": "label_values({__name__=~\"${metrics_prefix}_published_messages_total|${metrics_prefix}_received_messages_total\"},app_name)",
1706 | "description": "The name of the application that is specified in PrometheusMiddleware",
1707 | "hide": 0,
1708 | "includeAll": true,
1709 | "label": "App Name",
1710 | "multi": true,
1711 | "name": "app_name",
1712 | "options": [],
1713 | "query": {
1714 | "qryType": 1,
1715 | "query": "label_values(app_name)",
1716 | "refId": "PrometheusVariableQueryEditor-VariableQuery"
1717 | },
1718 | "refresh": 1,
1719 | "regex": "",
1720 | "skipUrlSync": false,
1721 | "sort": 1,
1722 | "type": "query"
1723 | },
1724 | {
1725 | "allValue": ".+",
1726 | "current": {
1727 | "selected": false,
1728 | "text": "All",
1729 | "value": ".+"
1730 | },
1731 | "datasource": {
1732 | "type": "prometheus",
1733 | "uid": "${datasource}"
1734 | },
1735 | "definition": "label_values({__name__=~\"${metrics_prefix}_published_messages_total\", app_name=~\"$app_name\"},destination)",
1736 | "description": "Destination",
1737 | "hide": 0,
1738 | "includeAll": true,
1739 | "label": "Destination",
1740 | "multi": true,
1741 | "name": "destination",
1742 | "options": [],
1743 | "query": {
1744 | "qryType": 1,
1745 | "query": "label_values({__name__=~\"${metrics_prefix}_published_messages_total\", app_name=~\"$app_name\"},destination)",
1746 | "refId": "PrometheusVariableQueryEditor-VariableQuery"
1747 | },
1748 | "refresh": 1,
1749 | "regex": "",
1750 | "skipUrlSync": false,
1751 | "sort": 1,
1752 | "type": "query"
1753 | },
1754 | {
1755 | "allValue": ".+",
1756 | "current": {
1757 | "selected": false,
1758 | "text": "All",
1759 | "value": ".+"
1760 | },
1761 | "datasource": {
1762 | "type": "prometheus",
1763 | "uid": "${datasource}"
1764 | },
1765 | "definition": "label_values({__name__=~\"${metrics_prefix}_received_messages_total\", app_name=~\"$app_name\"},handler)",
1766 | "description": "Handler",
1767 | "hide": 0,
1768 | "includeAll": true,
1769 | "label": "Handler",
1770 | "multi": true,
1771 | "name": "handler",
1772 | "options": [],
1773 | "query": {
1774 | "qryType": 1,
1775 | "query": "label_values({__name__=~\"${metrics_prefix}_received_messages_total\", app_name=~\"$app_name\"},handler)",
1776 | "refId": "PrometheusVariableQueryEditor-VariableQuery"
1777 | },
1778 | "refresh": 1,
1779 | "regex": "",
1780 | "skipUrlSync": false,
1781 | "sort": 1,
1782 | "type": "query"
1783 | }
1784 | ]
1785 | },
1786 | "time": {
1787 | "from": "now-15m",
1788 | "to": "now"
1789 | },
1790 | "timepicker": {
1791 | "refresh_intervals": [
1792 | "5s",
1793 | "10s",
1794 | "30s",
1795 | "1m",
1796 | "5m",
1797 | "15m",
1798 | "30m",
1799 | "1h",
1800 | "2h",
1801 | "1d"
1802 | ],
1803 | "time_options": [
1804 | "5m",
1805 | "15m",
1806 | "1h",
1807 | "6h",
1808 | "12h",
1809 | "24h",
1810 | "2d",
1811 | "7d",
1812 | "30d"
1813 | ]
1814 | },
1815 | "timezone": "",
1816 | "title": "FastStream Metrics",
1817 | "uid": "faststream",
1818 | "version": 3,
1819 | "weekStart": ""
1820 | }
1821 |
--------------------------------------------------------------------------------
/pdm.lock:
--------------------------------------------------------------------------------
1 | # This file is @generated by PDM.
2 | # It is not intended for manual editing.
3 |
4 | [metadata]
5 | groups = ["default", "lint", "test"]
6 | strategy = ["cross_platform", "inherit_metadata"]
7 | lock_version = "4.5.0"
8 | content_hash = "sha256:47ddaeac10e26a9c541dbfc00673ea972f40e15058564273415836dcde359e1e"
9 |
10 | [[metadata.targets]]
11 | requires_python = ">=3.12"
12 |
13 | [[package]]
14 | name = "adaptix"
15 | version = "3.0.0b11"
16 | requires_python = ">=3.9"
17 | summary = "An extremely flexible and configurable data model conversion library"
18 | groups = ["default"]
19 | dependencies = [
20 | "exceptiongroup>=1.1.3; python_version < \"3.11\"",
21 | ]
22 | files = [
23 | {file = "adaptix-3.0.0b11-py3-none-any.whl", hash = "sha256:5afa7197d1a084fc93da852bf58194de4a1c506caa3f5889c9953a27ce515bda"},
24 | {file = "adaptix-3.0.0b11.tar.gz", hash = "sha256:3d3d660d97d9e1a85d133b181fdac8a200ff3185422fdf686601bc9ed0017162"},
25 | ]
26 |
27 | [[package]]
28 | name = "aio-pika"
29 | version = "9.5.5"
30 | requires_python = "<4.0,>=3.9"
31 | summary = "Wrapper around the aiormq for asyncio and humans"
32 | groups = ["default"]
33 | dependencies = [
34 | "aiormq<6.9,>=6.8",
35 | "exceptiongroup<2,>=1",
36 | "typing-extensions; python_version < \"3.10\"",
37 | "yarl",
38 | ]
39 | files = [
40 | {file = "aio_pika-9.5.5-py3-none-any.whl", hash = "sha256:94e0ac3666398d6a28b0c3b530c1febf4c6d4ececb345620727cfd7bfe1c02e0"},
41 | {file = "aio_pika-9.5.5.tar.gz", hash = "sha256:3d2f25838860fa7e209e21fc95555f558401f9b49a832897419489f1c9e1d6a4"},
42 | ]
43 |
44 | [[package]]
45 | name = "aiormq"
46 | version = "6.8.1"
47 | requires_python = "<4.0,>=3.8"
48 | summary = "Pure python AMQP asynchronous client library"
49 | groups = ["default"]
50 | dependencies = [
51 | "pamqp==3.3.0",
52 | "setuptools; python_version < \"3.8\"",
53 | "yarl",
54 | ]
55 | files = [
56 | {file = "aiormq-6.8.1-py3-none-any.whl", hash = "sha256:5da896c8624193708f9409ffad0b20395010e2747f22aa4150593837f40aa017"},
57 | {file = "aiormq-6.8.1.tar.gz", hash = "sha256:a964ab09634be1da1f9298ce225b310859763d5cf83ef3a7eae1a6dc6bd1da1a"},
58 | ]
59 |
60 | [[package]]
61 | name = "annotated-types"
62 | version = "0.7.0"
63 | requires_python = ">=3.8"
64 | summary = "Reusable constraint types to use with typing.Annotated"
65 | groups = ["default"]
66 | dependencies = [
67 | "typing-extensions>=4.0.0; python_version < \"3.9\"",
68 | ]
69 | files = [
70 | {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
71 | {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
72 | ]
73 |
74 | [[package]]
75 | name = "anyio"
76 | version = "4.6.2.post1"
77 | requires_python = ">=3.9"
78 | summary = "High level compatibility layer for multiple asynchronous event loop implementations"
79 | groups = ["default"]
80 | dependencies = [
81 | "exceptiongroup>=1.0.2; python_version < \"3.11\"",
82 | "idna>=2.8",
83 | "sniffio>=1.1",
84 | "typing-extensions>=4.1; python_version < \"3.11\"",
85 | ]
86 | files = [
87 | {file = "anyio-4.6.2.post1-py3-none-any.whl", hash = "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d"},
88 | {file = "anyio-4.6.2.post1.tar.gz", hash = "sha256:4c8bc31ccdb51c7f7bd251f51c609e038d63e34219b44aa86e47576389880b4c"},
89 | ]
90 |
91 | [[package]]
92 | name = "certifi"
93 | version = "2024.8.30"
94 | requires_python = ">=3.6"
95 | summary = "Python package for providing Mozilla's CA Bundle."
96 | groups = ["default"]
97 | files = [
98 | {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"},
99 | {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"},
100 | ]
101 |
102 | [[package]]
103 | name = "cfgv"
104 | version = "3.4.0"
105 | requires_python = ">=3.8"
106 | summary = "Validate configuration and produce human readable error messages."
107 | groups = ["lint"]
108 | files = [
109 | {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
110 | {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
111 | ]
112 |
113 | [[package]]
114 | name = "charset-normalizer"
115 | version = "3.4.0"
116 | requires_python = ">=3.7.0"
117 | summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
118 | groups = ["default"]
119 | files = [
120 | {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"},
121 | {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"},
122 | {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"},
123 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"},
124 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"},
125 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"},
126 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"},
127 | {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"},
128 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"},
129 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"},
130 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"},
131 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"},
132 | {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"},
133 | {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"},
134 | {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"},
135 | {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"},
136 | {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"},
137 | {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"},
138 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"},
139 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"},
140 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"},
141 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"},
142 | {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"},
143 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"},
144 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"},
145 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"},
146 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"},
147 | {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"},
148 | {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"},
149 | {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"},
150 | {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"},
151 | {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"},
152 | ]
153 |
154 | [[package]]
155 | name = "click"
156 | version = "8.1.7"
157 | requires_python = ">=3.7"
158 | summary = "Composable command line interface toolkit"
159 | groups = ["default"]
160 | dependencies = [
161 | "colorama; platform_system == \"Windows\"",
162 | "importlib-metadata; python_version < \"3.8\"",
163 | ]
164 | files = [
165 | {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
166 | {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
167 | ]
168 |
169 | [[package]]
170 | name = "colorama"
171 | version = "0.4.6"
172 | requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
173 | summary = "Cross-platform colored terminal text."
174 | groups = ["default", "test"]
175 | marker = "sys_platform == \"win32\" or platform_system == \"Windows\""
176 | files = [
177 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
178 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
179 | ]
180 |
181 | [[package]]
182 | name = "coverage"
183 | version = "7.6.4"
184 | requires_python = ">=3.9"
185 | summary = "Code coverage measurement for Python"
186 | groups = ["test"]
187 | files = [
188 | {file = "coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2"},
189 | {file = "coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117"},
190 | {file = "coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613"},
191 | {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27"},
192 | {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52"},
193 | {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2"},
194 | {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1"},
195 | {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5"},
196 | {file = "coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17"},
197 | {file = "coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08"},
198 | {file = "coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9"},
199 | {file = "coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba"},
200 | {file = "coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c"},
201 | {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06"},
202 | {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f"},
203 | {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b"},
204 | {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21"},
205 | {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a"},
206 | {file = "coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e"},
207 | {file = "coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963"},
208 | {file = "coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f"},
209 | {file = "coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806"},
210 | {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11"},
211 | {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3"},
212 | {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a"},
213 | {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc"},
214 | {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70"},
215 | {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef"},
216 | {file = "coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e"},
217 | {file = "coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1"},
218 | {file = "coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73"},
219 | ]
220 |
221 | [[package]]
222 | name = "coverage"
223 | version = "7.6.4"
224 | extras = ["toml"]
225 | requires_python = ">=3.9"
226 | summary = "Code coverage measurement for Python"
227 | groups = ["test"]
228 | dependencies = [
229 | "coverage==7.6.4",
230 | "tomli; python_full_version <= \"3.11.0a6\"",
231 | ]
232 | files = [
233 | {file = "coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2"},
234 | {file = "coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117"},
235 | {file = "coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613"},
236 | {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27"},
237 | {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52"},
238 | {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2"},
239 | {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1"},
240 | {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5"},
241 | {file = "coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17"},
242 | {file = "coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08"},
243 | {file = "coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9"},
244 | {file = "coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba"},
245 | {file = "coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c"},
246 | {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06"},
247 | {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f"},
248 | {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b"},
249 | {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21"},
250 | {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a"},
251 | {file = "coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e"},
252 | {file = "coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963"},
253 | {file = "coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f"},
254 | {file = "coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806"},
255 | {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11"},
256 | {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3"},
257 | {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a"},
258 | {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc"},
259 | {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70"},
260 | {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef"},
261 | {file = "coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e"},
262 | {file = "coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1"},
263 | {file = "coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73"},
264 | ]
265 |
266 | [[package]]
267 | name = "distlib"
268 | version = "0.3.9"
269 | summary = "Distribution utilities"
270 | groups = ["lint"]
271 | files = [
272 | {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"},
273 | {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"},
274 | ]
275 |
276 | [[package]]
277 | name = "exceptiongroup"
278 | version = "1.3.0"
279 | requires_python = ">=3.7"
280 | summary = "Backport of PEP 654 (exception groups)"
281 | groups = ["default"]
282 | dependencies = [
283 | "typing-extensions>=4.6.0; python_version < \"3.13\"",
284 | ]
285 | files = [
286 | {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"},
287 | {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"},
288 | ]
289 |
290 | [[package]]
291 | name = "fast-depends"
292 | version = "3.0.0a12"
293 | requires_python = ">=3.9"
294 | summary = "FastDepends - extracted and cleared from HTTP domain logic FastAPI Dependency Injection System. Async and sync are both supported."
295 | groups = ["default"]
296 | dependencies = [
297 | "anyio<5.0.0,>=3.0.0",
298 | "typing-extensions!=4.12.1",
299 | ]
300 | files = [
301 | {file = "fast_depends-3.0.0a12-py3-none-any.whl", hash = "sha256:8e16ad4c0666d031a26013c45f3f1c93bbf12ebe6e126ee5b816106137818b12"},
302 | {file = "fast_depends-3.0.0a12.tar.gz", hash = "sha256:782fd4d4e78893dc1e39e7373aff34d3a1ccdc5b50f53ba4e8df70d3a69b139a"},
303 | ]
304 |
305 | [[package]]
306 | name = "fast-depends"
307 | version = "3.0.0a12"
308 | extras = ["pydantic"]
309 | requires_python = ">=3.9"
310 | summary = "FastDepends - extracted and cleared from HTTP domain logic FastAPI Dependency Injection System. Async and sync are both supported."
311 | groups = ["default"]
312 | dependencies = [
313 | "fast-depends==3.0.0a12",
314 | "pydantic!=1.8,!=1.8.1,<3.0.0,>=1.7.4",
315 | ]
316 | files = [
317 | {file = "fast_depends-3.0.0a12-py3-none-any.whl", hash = "sha256:8e16ad4c0666d031a26013c45f3f1c93bbf12ebe6e126ee5b816106137818b12"},
318 | {file = "fast_depends-3.0.0a12.tar.gz", hash = "sha256:782fd4d4e78893dc1e39e7373aff34d3a1ccdc5b50f53ba4e8df70d3a69b139a"},
319 | ]
320 |
321 | [[package]]
322 | name = "faststream"
323 | version = "0.6.0rc0"
324 | requires_python = ">=3.10"
325 | summary = "FastStream: the simplest way to work with a messaging queues"
326 | groups = ["default"]
327 | dependencies = [
328 | "anyio<5,>=3.7.1",
329 | "fast-depends[pydantic]<4.0.0,>=3.0.0a12",
330 | "typing-extensions>=4.8.0",
331 | ]
332 | files = [
333 | {file = "faststream-0.6.0rc0-py3-none-any.whl", hash = "sha256:6f2a054e82a173d41ffc60f43ca40e828b28894f76639f69797ecfed44fcca9b"},
334 | {file = "faststream-0.6.0rc0.tar.gz", hash = "sha256:94d461dfc8cb5ad7f87030c99e23041dc67b2f41075d5f59a6cd60d7d83d9dc9"},
335 | ]
336 |
337 | [[package]]
338 | name = "faststream"
339 | version = "0.6.0rc0"
340 | extras = ["otel", "prometheus", "rabbit"]
341 | requires_python = ">=3.10"
342 | summary = "FastStream: the simplest way to work with a messaging queues"
343 | groups = ["default"]
344 | dependencies = [
345 | "aio-pika<10,>=9",
346 | "faststream==0.6.0rc0",
347 | "opentelemetry-sdk<2.0.0,>=1.24.0",
348 | "prometheus-client<0.30.0,>=0.20.0",
349 | ]
350 | files = [
351 | {file = "faststream-0.6.0rc0-py3-none-any.whl", hash = "sha256:6f2a054e82a173d41ffc60f43ca40e828b28894f76639f69797ecfed44fcca9b"},
352 | {file = "faststream-0.6.0rc0.tar.gz", hash = "sha256:94d461dfc8cb5ad7f87030c99e23041dc67b2f41075d5f59a6cd60d7d83d9dc9"},
353 | ]
354 |
355 | [[package]]
356 | name = "filelock"
357 | version = "3.16.1"
358 | requires_python = ">=3.8"
359 | summary = "A platform independent file lock."
360 | groups = ["lint"]
361 | files = [
362 | {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"},
363 | {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"},
364 | ]
365 |
366 | [[package]]
367 | name = "googleapis-common-protos"
368 | version = "1.65.0"
369 | requires_python = ">=3.7"
370 | summary = "Common protobufs used in Google APIs"
371 | groups = ["default"]
372 | dependencies = [
373 | "protobuf!=3.20.0,!=3.20.1,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<6.0.0.dev0,>=3.20.2",
374 | ]
375 | files = [
376 | {file = "googleapis_common_protos-1.65.0-py2.py3-none-any.whl", hash = "sha256:2972e6c496f435b92590fd54045060867f3fe9be2c82ab148fc8885035479a63"},
377 | {file = "googleapis_common_protos-1.65.0.tar.gz", hash = "sha256:334a29d07cddc3aa01dee4988f9afd9b2916ee2ff49d6b757155dc0d197852c0"},
378 | ]
379 |
380 | [[package]]
381 | name = "grpcio"
382 | version = "1.67.0"
383 | requires_python = ">=3.8"
384 | summary = "HTTP/2-based RPC framework"
385 | groups = ["default"]
386 | files = [
387 | {file = "grpcio-1.67.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:227316b5631260e0bef8a3ce04fa7db4cc81756fea1258b007950b6efc90c05d"},
388 | {file = "grpcio-1.67.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d90cfdafcf4b45a7a076e3e2a58e7bc3d59c698c4f6470b0bb13a4d869cf2273"},
389 | {file = "grpcio-1.67.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:77196216d5dd6f99af1c51e235af2dd339159f657280e65ce7e12c1a8feffd1d"},
390 | {file = "grpcio-1.67.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:15c05a26a0f7047f720da41dc49406b395c1470eef44ff7e2c506a47ac2c0591"},
391 | {file = "grpcio-1.67.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3840994689cc8cbb73d60485c594424ad8adb56c71a30d8948d6453083624b52"},
392 | {file = "grpcio-1.67.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:5a1e03c3102b6451028d5dc9f8591131d6ab3c8a0e023d94c28cb930ed4b5f81"},
393 | {file = "grpcio-1.67.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:682968427a63d898759474e3b3178d42546e878fdce034fd7474ef75143b64e3"},
394 | {file = "grpcio-1.67.0-cp312-cp312-win32.whl", hash = "sha256:d01793653248f49cf47e5695e0a79805b1d9d4eacef85b310118ba1dfcd1b955"},
395 | {file = "grpcio-1.67.0-cp312-cp312-win_amd64.whl", hash = "sha256:985b2686f786f3e20326c4367eebdaed3e7aa65848260ff0c6644f817042cb15"},
396 | {file = "grpcio-1.67.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:8c9a35b8bc50db35ab8e3e02a4f2a35cfba46c8705c3911c34ce343bd777813a"},
397 | {file = "grpcio-1.67.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:42199e704095b62688998c2d84c89e59a26a7d5d32eed86d43dc90e7a3bd04aa"},
398 | {file = "grpcio-1.67.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:c4c425f440fb81f8d0237c07b9322fc0fb6ee2b29fbef5f62a322ff8fcce240d"},
399 | {file = "grpcio-1.67.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:323741b6699cd2b04a71cb38f502db98f90532e8a40cb675393d248126a268af"},
400 | {file = "grpcio-1.67.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:662c8e105c5e5cee0317d500eb186ed7a93229586e431c1bf0c9236c2407352c"},
401 | {file = "grpcio-1.67.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:f6bd2ab135c64a4d1e9e44679a616c9bc944547357c830fafea5c3caa3de5153"},
402 | {file = "grpcio-1.67.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:2f55c1e0e2ae9bdd23b3c63459ee4c06d223b68aeb1961d83c48fb63dc29bc03"},
403 | {file = "grpcio-1.67.0-cp313-cp313-win32.whl", hash = "sha256:fd6bc27861e460fe28e94226e3673d46e294ca4673d46b224428d197c5935e69"},
404 | {file = "grpcio-1.67.0-cp313-cp313-win_amd64.whl", hash = "sha256:cf51d28063338608cd8d3cd64677e922134837902b70ce00dad7f116e3998210"},
405 | {file = "grpcio-1.67.0.tar.gz", hash = "sha256:e090b2553e0da1c875449c8e75073dd4415dd71c9bde6a406240fdf4c0ee467c"},
406 | ]
407 |
408 | [[package]]
409 | name = "h11"
410 | version = "0.14.0"
411 | requires_python = ">=3.7"
412 | summary = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
413 | groups = ["default"]
414 | dependencies = [
415 | "typing-extensions; python_version < \"3.8\"",
416 | ]
417 | files = [
418 | {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
419 | {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
420 | ]
421 |
422 | [[package]]
423 | name = "identify"
424 | version = "2.6.1"
425 | requires_python = ">=3.8"
426 | summary = "File identification library for Python"
427 | groups = ["lint"]
428 | files = [
429 | {file = "identify-2.6.1-py2.py3-none-any.whl", hash = "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0"},
430 | {file = "identify-2.6.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98"},
431 | ]
432 |
433 | [[package]]
434 | name = "idna"
435 | version = "3.10"
436 | requires_python = ">=3.6"
437 | summary = "Internationalized Domain Names in Applications (IDNA)"
438 | groups = ["default"]
439 | files = [
440 | {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
441 | {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
442 | ]
443 |
444 | [[package]]
445 | name = "importlib-metadata"
446 | version = "7.0.0"
447 | requires_python = ">=3.8"
448 | summary = "Read metadata from Python packages"
449 | groups = ["default"]
450 | dependencies = [
451 | "typing-extensions>=3.6.4; python_version < \"3.8\"",
452 | "zipp>=0.5",
453 | ]
454 | files = [
455 | {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"},
456 | {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"},
457 | ]
458 |
459 | [[package]]
460 | name = "iniconfig"
461 | version = "2.0.0"
462 | requires_python = ">=3.7"
463 | summary = "brain-dead simple config-ini parsing"
464 | groups = ["test"]
465 | files = [
466 | {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
467 | {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
468 | ]
469 |
470 | [[package]]
471 | name = "multidict"
472 | version = "6.6.3"
473 | requires_python = ">=3.9"
474 | summary = "multidict implementation"
475 | groups = ["default"]
476 | dependencies = [
477 | "typing-extensions>=4.1.0; python_version < \"3.11\"",
478 | ]
479 | files = [
480 | {file = "multidict-6.6.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:056bebbeda16b2e38642d75e9e5310c484b7c24e3841dc0fb943206a72ec89d6"},
481 | {file = "multidict-6.6.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e5f481cccb3c5c5e5de5d00b5141dc589c1047e60d07e85bbd7dea3d4580d63f"},
482 | {file = "multidict-6.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:10bea2ee839a759ee368b5a6e47787f399b41e70cf0c20d90dfaf4158dfb4e55"},
483 | {file = "multidict-6.6.3-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:2334cfb0fa9549d6ce2c21af2bfbcd3ac4ec3646b1b1581c88e3e2b1779ec92b"},
484 | {file = "multidict-6.6.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8fee016722550a2276ca2cb5bb624480e0ed2bd49125b2b73b7010b9090e888"},
485 | {file = "multidict-6.6.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5511cb35f5c50a2db21047c875eb42f308c5583edf96bd8ebf7d770a9d68f6d"},
486 | {file = "multidict-6.6.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:712b348f7f449948e0a6c4564a21c7db965af900973a67db432d724619b3c680"},
487 | {file = "multidict-6.6.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e4e15d2138ee2694e038e33b7c3da70e6b0ad8868b9f8094a72e1414aeda9c1a"},
488 | {file = "multidict-6.6.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8df25594989aebff8a130f7899fa03cbfcc5d2b5f4a461cf2518236fe6f15961"},
489 | {file = "multidict-6.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:159ca68bfd284a8860f8d8112cf0521113bffd9c17568579e4d13d1f1dc76b65"},
490 | {file = "multidict-6.6.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e098c17856a8c9ade81b4810888c5ad1914099657226283cab3062c0540b0643"},
491 | {file = "multidict-6.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:67c92ed673049dec52d7ed39f8cf9ebbadf5032c774058b4406d18c8f8fe7063"},
492 | {file = "multidict-6.6.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:bd0578596e3a835ef451784053cfd327d607fc39ea1a14812139339a18a0dbc3"},
493 | {file = "multidict-6.6.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:346055630a2df2115cd23ae271910b4cae40f4e336773550dca4889b12916e75"},
494 | {file = "multidict-6.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:555ff55a359302b79de97e0468e9ee80637b0de1fce77721639f7cd9440b3a10"},
495 | {file = "multidict-6.6.3-cp312-cp312-win32.whl", hash = "sha256:73ab034fb8d58ff85c2bcbadc470efc3fafeea8affcf8722855fb94557f14cc5"},
496 | {file = "multidict-6.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:04cbcce84f63b9af41bad04a54d4cc4e60e90c35b9e6ccb130be2d75b71f8c17"},
497 | {file = "multidict-6.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:0f1130b896ecb52d2a1e615260f3ea2af55fa7dc3d7c3003ba0c3121a759b18b"},
498 | {file = "multidict-6.6.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:540d3c06d48507357a7d57721e5094b4f7093399a0106c211f33540fdc374d55"},
499 | {file = "multidict-6.6.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9c19cea2a690f04247d43f366d03e4eb110a0dc4cd1bbeee4d445435428ed35b"},
500 | {file = "multidict-6.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7af039820cfd00effec86bda5d8debef711a3e86a1d3772e85bea0f243a4bd65"},
501 | {file = "multidict-6.6.3-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:500b84f51654fdc3944e936f2922114349bf8fdcac77c3092b03449f0e5bc2b3"},
502 | {file = "multidict-6.6.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3fc723ab8a5c5ed6c50418e9bfcd8e6dceba6c271cee6728a10a4ed8561520c"},
503 | {file = "multidict-6.6.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:94c47ea3ade005b5976789baaed66d4de4480d0a0bf31cef6edaa41c1e7b56a6"},
504 | {file = "multidict-6.6.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dbc7cf464cc6d67e83e136c9f55726da3a30176f020a36ead246eceed87f1cd8"},
505 | {file = "multidict-6.6.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:900eb9f9da25ada070f8ee4a23f884e0ee66fe4e1a38c3af644256a508ad81ca"},
506 | {file = "multidict-6.6.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c6df517cf177da5d47ab15407143a89cd1a23f8b335f3a28d57e8b0a3dbb884"},
507 | {file = "multidict-6.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4ef421045f13879e21c994b36e728d8e7d126c91a64b9185810ab51d474f27e7"},
508 | {file = "multidict-6.6.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:6c1e61bb4f80895c081790b6b09fa49e13566df8fbff817da3f85b3a8192e36b"},
509 | {file = "multidict-6.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e5e8523bb12d7623cd8300dbd91b9e439a46a028cd078ca695eb66ba31adee3c"},
510 | {file = "multidict-6.6.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:ef58340cc896219e4e653dade08fea5c55c6df41bcc68122e3be3e9d873d9a7b"},
511 | {file = "multidict-6.6.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc9dc435ec8699e7b602b94fe0cd4703e69273a01cbc34409af29e7820f777f1"},
512 | {file = "multidict-6.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9e864486ef4ab07db5e9cb997bad2b681514158d6954dd1958dfb163b83d53e6"},
513 | {file = "multidict-6.6.3-cp313-cp313-win32.whl", hash = "sha256:5633a82fba8e841bc5c5c06b16e21529573cd654f67fd833650a215520a6210e"},
514 | {file = "multidict-6.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:e93089c1570a4ad54c3714a12c2cef549dc9d58e97bcded193d928649cab78e9"},
515 | {file = "multidict-6.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:c60b401f192e79caec61f166da9c924e9f8bc65548d4246842df91651e83d600"},
516 | {file = "multidict-6.6.3-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:02fd8f32d403a6ff13864b0851f1f523d4c988051eea0471d4f1fd8010f11134"},
517 | {file = "multidict-6.6.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f3aa090106b1543f3f87b2041eef3c156c8da2aed90c63a2fbed62d875c49c37"},
518 | {file = "multidict-6.6.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e924fb978615a5e33ff644cc42e6aa241effcf4f3322c09d4f8cebde95aff5f8"},
519 | {file = "multidict-6.6.3-cp313-cp313t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:b9fe5a0e57c6dbd0e2ce81ca66272282c32cd11d31658ee9553849d91289e1c1"},
520 | {file = "multidict-6.6.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b24576f208793ebae00280c59927c3b7c2a3b1655e443a25f753c4611bc1c373"},
521 | {file = "multidict-6.6.3-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:135631cb6c58eac37d7ac0df380294fecdc026b28837fa07c02e459c7fb9c54e"},
522 | {file = "multidict-6.6.3-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:274d416b0df887aef98f19f21578653982cfb8a05b4e187d4a17103322eeaf8f"},
523 | {file = "multidict-6.6.3-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e252017a817fad7ce05cafbe5711ed40faeb580e63b16755a3a24e66fa1d87c0"},
524 | {file = "multidict-6.6.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e4cc8d848cd4fe1cdee28c13ea79ab0ed37fc2e89dd77bac86a2e7959a8c3bc"},
525 | {file = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9e236a7094b9c4c1b7585f6b9cca34b9d833cf079f7e4c49e6a4a6ec9bfdc68f"},
526 | {file = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:e0cb0ab69915c55627c933f0b555a943d98ba71b4d1c57bc0d0a66e2567c7471"},
527 | {file = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:81ef2f64593aba09c5212a3d0f8c906a0d38d710a011f2f42759704d4557d3f2"},
528 | {file = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:b9cbc60010de3562545fa198bfc6d3825df430ea96d2cc509c39bd71e2e7d648"},
529 | {file = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:70d974eaaa37211390cd02ef93b7e938de564bbffa866f0b08d07e5e65da783d"},
530 | {file = "multidict-6.6.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3713303e4a6663c6d01d648a68f2848701001f3390a030edaaf3fc949c90bf7c"},
531 | {file = "multidict-6.6.3-cp313-cp313t-win32.whl", hash = "sha256:639ecc9fe7cd73f2495f62c213e964843826f44505a3e5d82805aa85cac6f89e"},
532 | {file = "multidict-6.6.3-cp313-cp313t-win_amd64.whl", hash = "sha256:9f97e181f344a0ef3881b573d31de8542cc0dbc559ec68c8f8b5ce2c2e91646d"},
533 | {file = "multidict-6.6.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ce8b7693da41a3c4fde5871c738a81490cea5496c671d74374c8ab889e1834fb"},
534 | {file = "multidict-6.6.3-py3-none-any.whl", hash = "sha256:8db10f29c7541fc5da4defd8cd697e1ca429db743fa716325f236079b96f775a"},
535 | {file = "multidict-6.6.3.tar.gz", hash = "sha256:798a9eb12dab0a6c2e29c1de6f3468af5cb2da6053a20dfa3344907eed0937cc"},
536 | ]
537 |
538 | [[package]]
539 | name = "mypy"
540 | version = "1.17.1"
541 | requires_python = ">=3.9"
542 | summary = "Optional static typing for Python"
543 | groups = ["lint"]
544 | dependencies = [
545 | "mypy-extensions>=1.0.0",
546 | "pathspec>=0.9.0",
547 | "tomli>=1.1.0; python_version < \"3.11\"",
548 | "typing-extensions>=4.6.0",
549 | ]
550 | files = [
551 | {file = "mypy-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:69e83ea6553a3ba79c08c6e15dbd9bfa912ec1e493bf75489ef93beb65209aeb"},
552 | {file = "mypy-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b16708a66d38abb1e6b5702f5c2c87e133289da36f6a1d15f6a5221085c6403"},
553 | {file = "mypy-1.17.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89e972c0035e9e05823907ad5398c5a73b9f47a002b22359b177d40bdaee7056"},
554 | {file = "mypy-1.17.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03b6d0ed2b188e35ee6d5c36b5580cffd6da23319991c49ab5556c023ccf1341"},
555 | {file = "mypy-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c837b896b37cd103570d776bda106eabb8737aa6dd4f248451aecf53030cdbeb"},
556 | {file = "mypy-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:665afab0963a4b39dff7c1fa563cc8b11ecff7910206db4b2e64dd1ba25aed19"},
557 | {file = "mypy-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93378d3203a5c0800c6b6d850ad2f19f7a3cdf1a3701d3416dbf128805c6a6a7"},
558 | {file = "mypy-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:15d54056f7fe7a826d897789f53dd6377ec2ea8ba6f776dc83c2902b899fee81"},
559 | {file = "mypy-1.17.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:209a58fed9987eccc20f2ca94afe7257a8f46eb5df1fb69958650973230f91e6"},
560 | {file = "mypy-1.17.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:099b9a5da47de9e2cb5165e581f158e854d9e19d2e96b6698c0d64de911dd849"},
561 | {file = "mypy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa6ffadfbe6994d724c5a1bb6123a7d27dd68fc9c059561cd33b664a79578e14"},
562 | {file = "mypy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:9a2b7d9180aed171f033c9f2fc6c204c1245cf60b0cb61cf2e7acc24eea78e0a"},
563 | {file = "mypy-1.17.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:15a83369400454c41ed3a118e0cc58bd8123921a602f385cb6d6ea5df050c733"},
564 | {file = "mypy-1.17.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:55b918670f692fc9fba55c3298d8a3beae295c5cded0a55dccdc5bbead814acd"},
565 | {file = "mypy-1.17.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:62761474061feef6f720149d7ba876122007ddc64adff5ba6f374fda35a018a0"},
566 | {file = "mypy-1.17.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c49562d3d908fd49ed0938e5423daed8d407774a479b595b143a3d7f87cdae6a"},
567 | {file = "mypy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:397fba5d7616a5bc60b45c7ed204717eaddc38f826e3645402c426057ead9a91"},
568 | {file = "mypy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:9d6b20b97d373f41617bd0708fd46aa656059af57f2ef72aa8c7d6a2b73b74ed"},
569 | {file = "mypy-1.17.1-py3-none-any.whl", hash = "sha256:a9f52c0351c21fe24c21d8c0eb1f62967b262d6729393397b6f443c3b773c3b9"},
570 | {file = "mypy-1.17.1.tar.gz", hash = "sha256:25e01ec741ab5bb3eec8ba9cdb0f769230368a22c959c4937360efb89b7e9f01"},
571 | ]
572 |
573 | [[package]]
574 | name = "mypy-extensions"
575 | version = "1.0.0"
576 | requires_python = ">=3.5"
577 | summary = "Type system extensions for programs checked with the mypy type checker."
578 | groups = ["lint"]
579 | files = [
580 | {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
581 | {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
582 | ]
583 |
584 | [[package]]
585 | name = "nodeenv"
586 | version = "1.9.1"
587 | requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
588 | summary = "Node.js virtual environment builder"
589 | groups = ["lint"]
590 | files = [
591 | {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"},
592 | {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"},
593 | ]
594 |
595 | [[package]]
596 | name = "opentelemetry-api"
597 | version = "1.36.0"
598 | requires_python = ">=3.9"
599 | summary = "OpenTelemetry Python API"
600 | groups = ["default"]
601 | dependencies = [
602 | "importlib-metadata<8.8.0,>=6.0",
603 | "typing-extensions>=4.5.0",
604 | ]
605 | files = [
606 | {file = "opentelemetry_api-1.36.0-py3-none-any.whl", hash = "sha256:02f20bcacf666e1333b6b1f04e647dc1d5111f86b8e510238fcc56d7762cda8c"},
607 | {file = "opentelemetry_api-1.36.0.tar.gz", hash = "sha256:9a72572b9c416d004d492cbc6e61962c0501eaf945ece9b5a0f56597d8348aa0"},
608 | ]
609 |
610 | [[package]]
611 | name = "opentelemetry-exporter-otlp"
612 | version = "1.36.0"
613 | requires_python = ">=3.9"
614 | summary = "OpenTelemetry Collector Exporters"
615 | groups = ["default"]
616 | dependencies = [
617 | "opentelemetry-exporter-otlp-proto-grpc==1.36.0",
618 | "opentelemetry-exporter-otlp-proto-http==1.36.0",
619 | ]
620 | files = [
621 | {file = "opentelemetry_exporter_otlp-1.36.0-py3-none-any.whl", hash = "sha256:de93b7c45bcc78296998775d52add7c63729e83ef2cd6560730a6b336d7f6494"},
622 | {file = "opentelemetry_exporter_otlp-1.36.0.tar.gz", hash = "sha256:72f166ea5a8923ac42889337f903e93af57db8893de200369b07401e98e4e06b"},
623 | ]
624 |
625 | [[package]]
626 | name = "opentelemetry-exporter-otlp-proto-common"
627 | version = "1.36.0"
628 | requires_python = ">=3.9"
629 | summary = "OpenTelemetry Protobuf encoding"
630 | groups = ["default"]
631 | dependencies = [
632 | "opentelemetry-proto==1.36.0",
633 | ]
634 | files = [
635 | {file = "opentelemetry_exporter_otlp_proto_common-1.36.0-py3-none-any.whl", hash = "sha256:0fc002a6ed63eac235ada9aa7056e5492e9a71728214a61745f6ad04b923f840"},
636 | {file = "opentelemetry_exporter_otlp_proto_common-1.36.0.tar.gz", hash = "sha256:6c496ccbcbe26b04653cecadd92f73659b814c6e3579af157d8716e5f9f25cbf"},
637 | ]
638 |
639 | [[package]]
640 | name = "opentelemetry-exporter-otlp-proto-grpc"
641 | version = "1.36.0"
642 | requires_python = ">=3.9"
643 | summary = "OpenTelemetry Collector Protobuf over gRPC Exporter"
644 | groups = ["default"]
645 | dependencies = [
646 | "googleapis-common-protos~=1.57",
647 | "grpcio<2.0.0,>=1.63.2; python_version < \"3.13\"",
648 | "grpcio<2.0.0,>=1.66.2; python_version >= \"3.13\"",
649 | "opentelemetry-api~=1.15",
650 | "opentelemetry-exporter-otlp-proto-common==1.36.0",
651 | "opentelemetry-proto==1.36.0",
652 | "opentelemetry-sdk~=1.36.0",
653 | "typing-extensions>=4.6.0",
654 | ]
655 | files = [
656 | {file = "opentelemetry_exporter_otlp_proto_grpc-1.36.0-py3-none-any.whl", hash = "sha256:734e841fc6a5d6f30e7be4d8053adb703c70ca80c562ae24e8083a28fadef211"},
657 | {file = "opentelemetry_exporter_otlp_proto_grpc-1.36.0.tar.gz", hash = "sha256:b281afbf7036b325b3588b5b6c8bb175069e3978d1bd24071f4a59d04c1e5bbf"},
658 | ]
659 |
660 | [[package]]
661 | name = "opentelemetry-exporter-otlp-proto-http"
662 | version = "1.36.0"
663 | requires_python = ">=3.9"
664 | summary = "OpenTelemetry Collector Protobuf over HTTP Exporter"
665 | groups = ["default"]
666 | dependencies = [
667 | "googleapis-common-protos~=1.52",
668 | "opentelemetry-api~=1.15",
669 | "opentelemetry-exporter-otlp-proto-common==1.36.0",
670 | "opentelemetry-proto==1.36.0",
671 | "opentelemetry-sdk~=1.36.0",
672 | "requests~=2.7",
673 | "typing-extensions>=4.5.0",
674 | ]
675 | files = [
676 | {file = "opentelemetry_exporter_otlp_proto_http-1.36.0-py3-none-any.whl", hash = "sha256:3d769f68e2267e7abe4527f70deb6f598f40be3ea34c6adc35789bea94a32902"},
677 | {file = "opentelemetry_exporter_otlp_proto_http-1.36.0.tar.gz", hash = "sha256:dd3637f72f774b9fc9608ab1ac479f8b44d09b6fb5b2f3df68a24ad1da7d356e"},
678 | ]
679 |
680 | [[package]]
681 | name = "opentelemetry-proto"
682 | version = "1.36.0"
683 | requires_python = ">=3.9"
684 | summary = "OpenTelemetry Python Proto"
685 | groups = ["default"]
686 | dependencies = [
687 | "protobuf<7.0,>=5.0",
688 | ]
689 | files = [
690 | {file = "opentelemetry_proto-1.36.0-py3-none-any.whl", hash = "sha256:151b3bf73a09f94afc658497cf77d45a565606f62ce0c17acb08cd9937ca206e"},
691 | {file = "opentelemetry_proto-1.36.0.tar.gz", hash = "sha256:0f10b3c72f74c91e0764a5ec88fd8f1c368ea5d9c64639fb455e2854ef87dd2f"},
692 | ]
693 |
694 | [[package]]
695 | name = "opentelemetry-sdk"
696 | version = "1.36.0"
697 | requires_python = ">=3.9"
698 | summary = "OpenTelemetry Python SDK"
699 | groups = ["default"]
700 | dependencies = [
701 | "opentelemetry-api==1.36.0",
702 | "opentelemetry-semantic-conventions==0.57b0",
703 | "typing-extensions>=4.5.0",
704 | ]
705 | files = [
706 | {file = "opentelemetry_sdk-1.36.0-py3-none-any.whl", hash = "sha256:19fe048b42e98c5c1ffe85b569b7073576ad4ce0bcb6e9b4c6a39e890a6c45fb"},
707 | {file = "opentelemetry_sdk-1.36.0.tar.gz", hash = "sha256:19c8c81599f51b71670661ff7495c905d8fdf6976e41622d5245b791b06fa581"},
708 | ]
709 |
710 | [[package]]
711 | name = "opentelemetry-semantic-conventions"
712 | version = "0.57b0"
713 | requires_python = ">=3.9"
714 | summary = "OpenTelemetry Semantic Conventions"
715 | groups = ["default"]
716 | dependencies = [
717 | "opentelemetry-api==1.36.0",
718 | "typing-extensions>=4.5.0",
719 | ]
720 | files = [
721 | {file = "opentelemetry_semantic_conventions-0.57b0-py3-none-any.whl", hash = "sha256:757f7e76293294f124c827e514c2a3144f191ef175b069ce8d1211e1e38e9e78"},
722 | {file = "opentelemetry_semantic_conventions-0.57b0.tar.gz", hash = "sha256:609a4a79c7891b4620d64c7aac6898f872d790d75f22019913a660756f27ff32"},
723 | ]
724 |
725 | [[package]]
726 | name = "packaging"
727 | version = "24.1"
728 | requires_python = ">=3.8"
729 | summary = "Core utilities for Python packages"
730 | groups = ["test"]
731 | files = [
732 | {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
733 | {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
734 | ]
735 |
736 | [[package]]
737 | name = "pamqp"
738 | version = "3.3.0"
739 | requires_python = ">=3.7"
740 | summary = "RabbitMQ Focused AMQP low-level library"
741 | groups = ["default"]
742 | files = [
743 | {file = "pamqp-3.3.0-py2.py3-none-any.whl", hash = "sha256:c901a684794157ae39b52cbf700db8c9aae7a470f13528b9d7b4e5f7202f8eb0"},
744 | {file = "pamqp-3.3.0.tar.gz", hash = "sha256:40b8795bd4efcf2b0f8821c1de83d12ca16d5760f4507836267fd7a02b06763b"},
745 | ]
746 |
747 | [[package]]
748 | name = "pathspec"
749 | version = "0.12.1"
750 | requires_python = ">=3.8"
751 | summary = "Utility library for gitignore style pattern matching of file paths."
752 | groups = ["lint"]
753 | files = [
754 | {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
755 | {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
756 | ]
757 |
758 | [[package]]
759 | name = "platformdirs"
760 | version = "4.3.6"
761 | requires_python = ">=3.8"
762 | summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
763 | groups = ["lint"]
764 | files = [
765 | {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"},
766 | {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"},
767 | ]
768 |
769 | [[package]]
770 | name = "pluggy"
771 | version = "1.5.0"
772 | requires_python = ">=3.8"
773 | summary = "plugin and hook calling mechanisms for python"
774 | groups = ["test"]
775 | files = [
776 | {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
777 | {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
778 | ]
779 |
780 | [[package]]
781 | name = "pre-commit"
782 | version = "4.2.0"
783 | requires_python = ">=3.9"
784 | summary = "A framework for managing and maintaining multi-language pre-commit hooks."
785 | groups = ["lint"]
786 | dependencies = [
787 | "cfgv>=2.0.0",
788 | "identify>=1.0.0",
789 | "nodeenv>=0.11.1",
790 | "pyyaml>=5.1",
791 | "virtualenv>=20.10.0",
792 | ]
793 | files = [
794 | {file = "pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd"},
795 | {file = "pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146"},
796 | ]
797 |
798 | [[package]]
799 | name = "prometheus-client"
800 | version = "0.22.1"
801 | requires_python = ">=3.9"
802 | summary = "Python client for the Prometheus monitoring system."
803 | groups = ["default"]
804 | files = [
805 | {file = "prometheus_client-0.22.1-py3-none-any.whl", hash = "sha256:cca895342e308174341b2cbf99a56bef291fbc0ef7b9e5412a0f26d653ba7094"},
806 | {file = "prometheus_client-0.22.1.tar.gz", hash = "sha256:190f1331e783cf21eb60bca559354e0a4d4378facecf78f5428c39b675d20d28"},
807 | ]
808 |
809 | [[package]]
810 | name = "propcache"
811 | version = "0.3.2"
812 | requires_python = ">=3.9"
813 | summary = "Accelerated property cache"
814 | groups = ["default"]
815 | files = [
816 | {file = "propcache-0.3.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8de106b6c84506b31c27168582cd3cb3000a6412c16df14a8628e5871ff83c10"},
817 | {file = "propcache-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:28710b0d3975117239c76600ea351934ac7b5ff56e60953474342608dbbb6154"},
818 | {file = "propcache-0.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce26862344bdf836650ed2487c3d724b00fbfec4233a1013f597b78c1cb73615"},
819 | {file = "propcache-0.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bca54bd347a253af2cf4544bbec232ab982f4868de0dd684246b67a51bc6b1db"},
820 | {file = "propcache-0.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55780d5e9a2ddc59711d727226bb1ba83a22dd32f64ee15594b9392b1f544eb1"},
821 | {file = "propcache-0.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:035e631be25d6975ed87ab23153db6a73426a48db688070d925aa27e996fe93c"},
822 | {file = "propcache-0.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee6f22b6eaa39297c751d0e80c0d3a454f112f5c6481214fcf4c092074cecd67"},
823 | {file = "propcache-0.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ca3aee1aa955438c4dba34fc20a9f390e4c79967257d830f137bd5a8a32ed3b"},
824 | {file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7a4f30862869fa2b68380d677cc1c5fcf1e0f2b9ea0cf665812895c75d0ca3b8"},
825 | {file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b77ec3c257d7816d9f3700013639db7491a434644c906a2578a11daf13176251"},
826 | {file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cab90ac9d3f14b2d5050928483d3d3b8fb6b4018893fc75710e6aa361ecb2474"},
827 | {file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0b504d29f3c47cf6b9e936c1852246c83d450e8e063d50562115a6be6d3a2535"},
828 | {file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:ce2ac2675a6aa41ddb2a0c9cbff53780a617ac3d43e620f8fd77ba1c84dcfc06"},
829 | {file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:62b4239611205294cc433845b914131b2a1f03500ff3c1ed093ed216b82621e1"},
830 | {file = "propcache-0.3.2-cp312-cp312-win32.whl", hash = "sha256:df4a81b9b53449ebc90cc4deefb052c1dd934ba85012aa912c7ea7b7e38b60c1"},
831 | {file = "propcache-0.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7046e79b989d7fe457bb755844019e10f693752d169076138abf17f31380800c"},
832 | {file = "propcache-0.3.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ca592ed634a73ca002967458187109265e980422116c0a107cf93d81f95af945"},
833 | {file = "propcache-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9ecb0aad4020e275652ba3975740f241bd12a61f1a784df044cf7477a02bc252"},
834 | {file = "propcache-0.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7f08f1cc28bd2eade7a8a3d2954ccc673bb02062e3e7da09bc75d843386b342f"},
835 | {file = "propcache-0.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1a342c834734edb4be5ecb1e9fb48cb64b1e2320fccbd8c54bf8da8f2a84c33"},
836 | {file = "propcache-0.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a544caaae1ac73f1fecfae70ded3e93728831affebd017d53449e3ac052ac1e"},
837 | {file = "propcache-0.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:310d11aa44635298397db47a3ebce7db99a4cc4b9bbdfcf6c98a60c8d5261cf1"},
838 | {file = "propcache-0.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c1396592321ac83157ac03a2023aa6cc4a3cc3cfdecb71090054c09e5a7cce3"},
839 | {file = "propcache-0.3.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cabf5b5902272565e78197edb682017d21cf3b550ba0460ee473753f28d23c1"},
840 | {file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0a2f2235ac46a7aa25bdeb03a9e7060f6ecbd213b1f9101c43b3090ffb971ef6"},
841 | {file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:92b69e12e34869a6970fd2f3da91669899994b47c98f5d430b781c26f1d9f387"},
842 | {file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:54e02207c79968ebbdffc169591009f4474dde3b4679e16634d34c9363ff56b4"},
843 | {file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4adfb44cb588001f68c5466579d3f1157ca07f7504fc91ec87862e2b8e556b88"},
844 | {file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fd3e6019dc1261cd0291ee8919dd91fbab7b169bb76aeef6c716833a3f65d206"},
845 | {file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4c181cad81158d71c41a2bce88edce078458e2dd5ffee7eddd6b05da85079f43"},
846 | {file = "propcache-0.3.2-cp313-cp313-win32.whl", hash = "sha256:8a08154613f2249519e549de2330cf8e2071c2887309a7b07fb56098f5170a02"},
847 | {file = "propcache-0.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e41671f1594fc4ab0a6dec1351864713cb3a279910ae8b58f884a88a0a632c05"},
848 | {file = "propcache-0.3.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:9a3cf035bbaf035f109987d9d55dc90e4b0e36e04bbbb95af3055ef17194057b"},
849 | {file = "propcache-0.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:156c03d07dc1323d8dacaa221fbe028c5c70d16709cdd63502778e6c3ccca1b0"},
850 | {file = "propcache-0.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74413c0ba02ba86f55cf60d18daab219f7e531620c15f1e23d95563f505efe7e"},
851 | {file = "propcache-0.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f066b437bb3fa39c58ff97ab2ca351db465157d68ed0440abecb21715eb24b28"},
852 | {file = "propcache-0.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1304b085c83067914721e7e9d9917d41ad87696bf70f0bc7dee450e9c71ad0a"},
853 | {file = "propcache-0.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab50cef01b372763a13333b4e54021bdcb291fc9a8e2ccb9c2df98be51bcde6c"},
854 | {file = "propcache-0.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad3b2a085ec259ad2c2842666b2a0a49dea8463579c606426128925af1ed725"},
855 | {file = "propcache-0.3.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:261fa020c1c14deafd54c76b014956e2f86991af198c51139faf41c4d5e83892"},
856 | {file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:46d7f8aa79c927e5f987ee3a80205c987717d3659f035c85cf0c3680526bdb44"},
857 | {file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:6d8f3f0eebf73e3c0ff0e7853f68be638b4043c65a70517bb575eff54edd8dbe"},
858 | {file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:03c89c1b14a5452cf15403e291c0ccd7751d5b9736ecb2c5bab977ad6c5bcd81"},
859 | {file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:0cc17efde71e12bbaad086d679ce575268d70bc123a5a71ea7ad76f70ba30bba"},
860 | {file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:acdf05d00696bc0447e278bb53cb04ca72354e562cf88ea6f9107df8e7fd9770"},
861 | {file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4445542398bd0b5d32df908031cb1b30d43ac848e20470a878b770ec2dcc6330"},
862 | {file = "propcache-0.3.2-cp313-cp313t-win32.whl", hash = "sha256:f86e5d7cd03afb3a1db8e9f9f6eff15794e79e791350ac48a8c924e6f439f394"},
863 | {file = "propcache-0.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:9704bedf6e7cbe3c65eca4379a9b53ee6a83749f047808cbb5044d40d7d72198"},
864 | {file = "propcache-0.3.2-py3-none-any.whl", hash = "sha256:98f1ec44fb675f5052cccc8e609c46ed23a35a1cfd18545ad4e29002d858a43f"},
865 | {file = "propcache-0.3.2.tar.gz", hash = "sha256:20d7d62e4e7ef05f221e0db2856b979540686342e7dd9973b815599c7057e168"},
866 | ]
867 |
868 | [[package]]
869 | name = "protobuf"
870 | version = "5.29.5"
871 | requires_python = ">=3.8"
872 | summary = ""
873 | groups = ["default"]
874 | files = [
875 | {file = "protobuf-5.29.5-cp310-abi3-win32.whl", hash = "sha256:3f1c6468a2cfd102ff4703976138844f78ebd1fb45f49011afc5139e9e283079"},
876 | {file = "protobuf-5.29.5-cp310-abi3-win_amd64.whl", hash = "sha256:3f76e3a3675b4a4d867b52e4a5f5b78a2ef9565549d4037e06cf7b0942b1d3fc"},
877 | {file = "protobuf-5.29.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e38c5add5a311f2a6eb0340716ef9b039c1dfa428b28f25a7838ac329204a671"},
878 | {file = "protobuf-5.29.5-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:fa18533a299d7ab6c55a238bf8629311439995f2e7eca5caaff08663606e9015"},
879 | {file = "protobuf-5.29.5-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:63848923da3325e1bf7e9003d680ce6e14b07e55d0473253a690c3a8b8fd6e61"},
880 | {file = "protobuf-5.29.5-py3-none-any.whl", hash = "sha256:6cf42630262c59b2d8de33954443d94b746c952b01434fc58a417fdbd2e84bd5"},
881 | {file = "protobuf-5.29.5.tar.gz", hash = "sha256:bc1463bafd4b0929216c35f437a8e28731a2b7fe3d98bb77a600efced5a15c84"},
882 | ]
883 |
884 | [[package]]
885 | name = "pydantic"
886 | version = "2.9.2"
887 | requires_python = ">=3.8"
888 | summary = "Data validation using Python type hints"
889 | groups = ["default"]
890 | dependencies = [
891 | "annotated-types>=0.6.0",
892 | "pydantic-core==2.23.4",
893 | "typing-extensions>=4.12.2; python_version >= \"3.13\"",
894 | "typing-extensions>=4.6.1; python_version < \"3.13\"",
895 | ]
896 | files = [
897 | {file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"},
898 | {file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"},
899 | ]
900 |
901 | [[package]]
902 | name = "pydantic-core"
903 | version = "2.23.4"
904 | requires_python = ">=3.8"
905 | summary = "Core functionality for Pydantic validation and serialization"
906 | groups = ["default"]
907 | dependencies = [
908 | "typing-extensions!=4.7.0,>=4.6.0",
909 | ]
910 | files = [
911 | {file = "pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231"},
912 | {file = "pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee"},
913 | {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87"},
914 | {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8"},
915 | {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327"},
916 | {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2"},
917 | {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36"},
918 | {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126"},
919 | {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e"},
920 | {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24"},
921 | {file = "pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84"},
922 | {file = "pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9"},
923 | {file = "pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc"},
924 | {file = "pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd"},
925 | {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05"},
926 | {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d"},
927 | {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510"},
928 | {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6"},
929 | {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b"},
930 | {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327"},
931 | {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6"},
932 | {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f"},
933 | {file = "pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769"},
934 | {file = "pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5"},
935 | {file = "pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863"},
936 | ]
937 |
938 | [[package]]
939 | name = "pygments"
940 | version = "2.19.2"
941 | requires_python = ">=3.8"
942 | summary = "Pygments is a syntax highlighting package written in Python."
943 | groups = ["test"]
944 | files = [
945 | {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"},
946 | {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"},
947 | ]
948 |
949 | [[package]]
950 | name = "pytest"
951 | version = "8.4.1"
952 | requires_python = ">=3.9"
953 | summary = "pytest: simple powerful testing with Python"
954 | groups = ["test"]
955 | dependencies = [
956 | "colorama>=0.4; sys_platform == \"win32\"",
957 | "exceptiongroup>=1; python_version < \"3.11\"",
958 | "iniconfig>=1",
959 | "packaging>=20",
960 | "pluggy<2,>=1.5",
961 | "pygments>=2.7.2",
962 | "tomli>=1; python_version < \"3.11\"",
963 | ]
964 | files = [
965 | {file = "pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7"},
966 | {file = "pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c"},
967 | ]
968 |
969 | [[package]]
970 | name = "pytest-asyncio"
971 | version = "1.1.0"
972 | requires_python = ">=3.9"
973 | summary = "Pytest support for asyncio"
974 | groups = ["test"]
975 | dependencies = [
976 | "backports-asyncio-runner<2,>=1.1; python_version < \"3.11\"",
977 | "pytest<9,>=8.2",
978 | "typing-extensions>=4.12; python_version < \"3.10\"",
979 | ]
980 | files = [
981 | {file = "pytest_asyncio-1.1.0-py3-none-any.whl", hash = "sha256:5fe2d69607b0bd75c656d1211f969cadba035030156745ee09e7d71740e58ecf"},
982 | {file = "pytest_asyncio-1.1.0.tar.gz", hash = "sha256:796aa822981e01b68c12e4827b8697108f7205020f24b5793b3c41555dab68ea"},
983 | ]
984 |
985 | [[package]]
986 | name = "pytest-cov"
987 | version = "6.2.1"
988 | requires_python = ">=3.9"
989 | summary = "Pytest plugin for measuring coverage."
990 | groups = ["test"]
991 | dependencies = [
992 | "coverage[toml]>=7.5",
993 | "pluggy>=1.2",
994 | "pytest>=6.2.5",
995 | ]
996 | files = [
997 | {file = "pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5"},
998 | {file = "pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2"},
999 | ]
1000 |
1001 | [[package]]
1002 | name = "pyyaml"
1003 | version = "6.0.2"
1004 | requires_python = ">=3.8"
1005 | summary = "YAML parser and emitter for Python"
1006 | groups = ["lint"]
1007 | files = [
1008 | {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"},
1009 | {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"},
1010 | {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"},
1011 | {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"},
1012 | {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"},
1013 | {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"},
1014 | {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"},
1015 | {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"},
1016 | {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"},
1017 | {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"},
1018 | {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"},
1019 | {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"},
1020 | {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"},
1021 | {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"},
1022 | {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"},
1023 | {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"},
1024 | {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"},
1025 | {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"},
1026 | {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"},
1027 | ]
1028 |
1029 | [[package]]
1030 | name = "requests"
1031 | version = "2.32.3"
1032 | requires_python = ">=3.8"
1033 | summary = "Python HTTP for Humans."
1034 | groups = ["default"]
1035 | dependencies = [
1036 | "certifi>=2017.4.17",
1037 | "charset-normalizer<4,>=2",
1038 | "idna<4,>=2.5",
1039 | "urllib3<3,>=1.21.1",
1040 | ]
1041 | files = [
1042 | {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
1043 | {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
1044 | ]
1045 |
1046 | [[package]]
1047 | name = "ruff"
1048 | version = "0.12.7"
1049 | requires_python = ">=3.7"
1050 | summary = "An extremely fast Python linter and code formatter, written in Rust."
1051 | groups = ["lint"]
1052 | files = [
1053 | {file = "ruff-0.12.7-py3-none-linux_armv6l.whl", hash = "sha256:76e4f31529899b8c434c3c1dede98c4483b89590e15fb49f2d46183801565303"},
1054 | {file = "ruff-0.12.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:789b7a03e72507c54fb3ba6209e4bb36517b90f1a3569ea17084e3fd295500fb"},
1055 | {file = "ruff-0.12.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2e1c2a3b8626339bb6369116e7030a4cf194ea48f49b64bb505732a7fce4f4e3"},
1056 | {file = "ruff-0.12.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32dec41817623d388e645612ec70d5757a6d9c035f3744a52c7b195a57e03860"},
1057 | {file = "ruff-0.12.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47ef751f722053a5df5fa48d412dbb54d41ab9b17875c6840a58ec63ff0c247c"},
1058 | {file = "ruff-0.12.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a828a5fc25a3efd3e1ff7b241fd392686c9386f20e5ac90aa9234a5faa12c423"},
1059 | {file = "ruff-0.12.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5726f59b171111fa6a69d82aef48f00b56598b03a22f0f4170664ff4d8298efb"},
1060 | {file = "ruff-0.12.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74e6f5c04c4dd4aba223f4fe6e7104f79e0eebf7d307e4f9b18c18362124bccd"},
1061 | {file = "ruff-0.12.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d0bfe4e77fba61bf2ccadf8cf005d6133e3ce08793bbe870dd1c734f2699a3e"},
1062 | {file = "ruff-0.12.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06bfb01e1623bf7f59ea749a841da56f8f653d641bfd046edee32ede7ff6c606"},
1063 | {file = "ruff-0.12.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e41df94a957d50083fd09b916d6e89e497246698c3f3d5c681c8b3e7b9bb4ac8"},
1064 | {file = "ruff-0.12.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:4000623300563c709458d0ce170c3d0d788c23a058912f28bbadc6f905d67afa"},
1065 | {file = "ruff-0.12.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:69ffe0e5f9b2cf2b8e289a3f8945b402a1b19eff24ec389f45f23c42a3dd6fb5"},
1066 | {file = "ruff-0.12.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a07a5c8ffa2611a52732bdc67bf88e243abd84fe2d7f6daef3826b59abbfeda4"},
1067 | {file = "ruff-0.12.7-py3-none-win32.whl", hash = "sha256:c928f1b2ec59fb77dfdf70e0419408898b63998789cc98197e15f560b9e77f77"},
1068 | {file = "ruff-0.12.7-py3-none-win_amd64.whl", hash = "sha256:9c18f3d707ee9edf89da76131956aba1270c6348bfee8f6c647de841eac7194f"},
1069 | {file = "ruff-0.12.7-py3-none-win_arm64.whl", hash = "sha256:dfce05101dbd11833a0776716d5d1578641b7fddb537fe7fa956ab85d1769b69"},
1070 | {file = "ruff-0.12.7.tar.gz", hash = "sha256:1fc3193f238bc2d7968772c82831a4ff69252f673be371fb49663f0068b7ec71"},
1071 | ]
1072 |
1073 | [[package]]
1074 | name = "sniffio"
1075 | version = "1.3.1"
1076 | requires_python = ">=3.7"
1077 | summary = "Sniff out which async library your code is running under"
1078 | groups = ["default"]
1079 | files = [
1080 | {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
1081 | {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
1082 | ]
1083 |
1084 | [[package]]
1085 | name = "typing-extensions"
1086 | version = "4.12.2"
1087 | requires_python = ">=3.8"
1088 | summary = "Backported and Experimental Type Hints for Python 3.8+"
1089 | groups = ["default", "lint"]
1090 | files = [
1091 | {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
1092 | {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
1093 | ]
1094 |
1095 | [[package]]
1096 | name = "urllib3"
1097 | version = "2.2.3"
1098 | requires_python = ">=3.8"
1099 | summary = "HTTP library with thread-safe connection pooling, file post, and more."
1100 | groups = ["default"]
1101 | files = [
1102 | {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"},
1103 | {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"},
1104 | ]
1105 |
1106 | [[package]]
1107 | name = "uvicorn"
1108 | version = "0.35.0"
1109 | requires_python = ">=3.9"
1110 | summary = "The lightning-fast ASGI server."
1111 | groups = ["default"]
1112 | dependencies = [
1113 | "click>=7.0",
1114 | "h11>=0.8",
1115 | "typing-extensions>=4.0; python_version < \"3.11\"",
1116 | ]
1117 | files = [
1118 | {file = "uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a"},
1119 | {file = "uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01"},
1120 | ]
1121 |
1122 | [[package]]
1123 | name = "virtualenv"
1124 | version = "20.27.0"
1125 | requires_python = ">=3.8"
1126 | summary = "Virtual Python Environment builder"
1127 | groups = ["lint"]
1128 | dependencies = [
1129 | "distlib<1,>=0.3.7",
1130 | "filelock<4,>=3.12.2",
1131 | "importlib-metadata>=6.6; python_version < \"3.8\"",
1132 | "platformdirs<5,>=3.9.1",
1133 | ]
1134 | files = [
1135 | {file = "virtualenv-20.27.0-py3-none-any.whl", hash = "sha256:44a72c29cceb0ee08f300b314848c86e57bf8d1f13107a5e671fb9274138d655"},
1136 | {file = "virtualenv-20.27.0.tar.gz", hash = "sha256:2ca56a68ed615b8fe4326d11a0dca5dfbe8fd68510fb6c6349163bed3c15f2b2"},
1137 | ]
1138 |
1139 | [[package]]
1140 | name = "yarl"
1141 | version = "1.20.1"
1142 | requires_python = ">=3.9"
1143 | summary = "Yet another URL library"
1144 | groups = ["default"]
1145 | dependencies = [
1146 | "idna>=2.0",
1147 | "multidict>=4.0",
1148 | "propcache>=0.2.1",
1149 | ]
1150 | files = [
1151 | {file = "yarl-1.20.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdcc4cd244e58593a4379fe60fdee5ac0331f8eb70320a24d591a3be197b94a9"},
1152 | {file = "yarl-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b29a2c385a5f5b9c7d9347e5812b6f7ab267193c62d282a540b4fc528c8a9d2a"},
1153 | {file = "yarl-1.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1112ae8154186dfe2de4732197f59c05a83dc814849a5ced892b708033f40dc2"},
1154 | {file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90bbd29c4fe234233f7fa2b9b121fb63c321830e5d05b45153a2ca68f7d310ee"},
1155 | {file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:680e19c7ce3710ac4cd964e90dad99bf9b5029372ba0c7cbfcd55e54d90ea819"},
1156 | {file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a979218c1fdb4246a05efc2cc23859d47c89af463a90b99b7c56094daf25a16"},
1157 | {file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255b468adf57b4a7b65d8aad5b5138dce6a0752c139965711bdcb81bc370e1b6"},
1158 | {file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a97d67108e79cfe22e2b430d80d7571ae57d19f17cda8bb967057ca8a7bf5bfd"},
1159 | {file = "yarl-1.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8570d998db4ddbfb9a590b185a0a33dbf8aafb831d07a5257b4ec9948df9cb0a"},
1160 | {file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:97c75596019baae7c71ccf1d8cc4738bc08134060d0adfcbe5642f778d1dca38"},
1161 | {file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1c48912653e63aef91ff988c5432832692ac5a1d8f0fb8a33091520b5bbe19ef"},
1162 | {file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4c3ae28f3ae1563c50f3d37f064ddb1511ecc1d5584e88c6b7c63cf7702a6d5f"},
1163 | {file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c5e9642f27036283550f5f57dc6156c51084b458570b9d0d96100c8bebb186a8"},
1164 | {file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2c26b0c49220d5799f7b22c6838409ee9bc58ee5c95361a4d7831f03cc225b5a"},
1165 | {file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:564ab3d517e3d01c408c67f2e5247aad4019dcf1969982aba3974b4093279004"},
1166 | {file = "yarl-1.20.1-cp312-cp312-win32.whl", hash = "sha256:daea0d313868da1cf2fac6b2d3a25c6e3a9e879483244be38c8e6a41f1d876a5"},
1167 | {file = "yarl-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:48ea7d7f9be0487339828a4de0360d7ce0efc06524a48e1810f945c45b813698"},
1168 | {file = "yarl-1.20.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:0b5ff0fbb7c9f1b1b5ab53330acbfc5247893069e7716840c8e7d5bb7355038a"},
1169 | {file = "yarl-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:14f326acd845c2b2e2eb38fb1346c94f7f3b01a4f5c788f8144f9b630bfff9a3"},
1170 | {file = "yarl-1.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f60e4ad5db23f0b96e49c018596707c3ae89f5d0bd97f0ad3684bcbad899f1e7"},
1171 | {file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49bdd1b8e00ce57e68ba51916e4bb04461746e794e7c4d4bbc42ba2f18297691"},
1172 | {file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:66252d780b45189975abfed839616e8fd2dbacbdc262105ad7742c6ae58f3e31"},
1173 | {file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59174e7332f5d153d8f7452a102b103e2e74035ad085f404df2e40e663a22b28"},
1174 | {file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3968ec7d92a0c0f9ac34d5ecfd03869ec0cab0697c91a45db3fbbd95fe1b653"},
1175 | {file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1a4fbb50e14396ba3d375f68bfe02215d8e7bc3ec49da8341fe3157f59d2ff5"},
1176 | {file = "yarl-1.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11a62c839c3a8eac2410e951301309426f368388ff2f33799052787035793b02"},
1177 | {file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:041eaa14f73ff5a8986b4388ac6bb43a77f2ea09bf1913df7a35d4646db69e53"},
1178 | {file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:377fae2fef158e8fd9d60b4c8751387b8d1fb121d3d0b8e9b0be07d1b41e83dc"},
1179 | {file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1c92f4390e407513f619d49319023664643d3339bd5e5a56a3bebe01bc67ec04"},
1180 | {file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d25ddcf954df1754ab0f86bb696af765c5bfaba39b74095f27eececa049ef9a4"},
1181 | {file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:909313577e9619dcff8c31a0ea2aa0a2a828341d92673015456b3ae492e7317b"},
1182 | {file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:793fd0580cb9664548c6b83c63b43c477212c0260891ddf86809e1c06c8b08f1"},
1183 | {file = "yarl-1.20.1-cp313-cp313-win32.whl", hash = "sha256:468f6e40285de5a5b3c44981ca3a319a4b208ccc07d526b20b12aeedcfa654b7"},
1184 | {file = "yarl-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:495b4ef2fea40596bfc0affe3837411d6aa3371abcf31aac0ccc4bdd64d4ef5c"},
1185 | {file = "yarl-1.20.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f60233b98423aab21d249a30eb27c389c14929f47be8430efa7dbd91493a729d"},
1186 | {file = "yarl-1.20.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6f3eff4cc3f03d650d8755c6eefc844edde99d641d0dcf4da3ab27141a5f8ddf"},
1187 | {file = "yarl-1.20.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:69ff8439d8ba832d6bed88af2c2b3445977eba9a4588b787b32945871c2444e3"},
1188 | {file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cf34efa60eb81dd2645a2e13e00bb98b76c35ab5061a3989c7a70f78c85006d"},
1189 | {file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8e0fe9364ad0fddab2688ce72cb7a8e61ea42eff3c7caeeb83874a5d479c896c"},
1190 | {file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f64fbf81878ba914562c672024089e3401974a39767747691c65080a67b18c1"},
1191 | {file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6342d643bf9a1de97e512e45e4b9560a043347e779a173250824f8b254bd5ce"},
1192 | {file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56dac5f452ed25eef0f6e3c6a066c6ab68971d96a9fb441791cad0efba6140d3"},
1193 | {file = "yarl-1.20.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7d7f497126d65e2cad8dc5f97d34c27b19199b6414a40cb36b52f41b79014be"},
1194 | {file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:67e708dfb8e78d8a19169818eeb5c7a80717562de9051bf2413aca8e3696bf16"},
1195 | {file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:595c07bc79af2494365cc96ddeb772f76272364ef7c80fb892ef9d0649586513"},
1196 | {file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7bdd2f80f4a7df852ab9ab49484a4dee8030023aa536df41f2d922fd57bf023f"},
1197 | {file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c03bfebc4ae8d862f853a9757199677ab74ec25424d0ebd68a0027e9c639a390"},
1198 | {file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:344d1103e9c1523f32a5ed704d576172d2cabed3122ea90b1d4e11fe17c66458"},
1199 | {file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:88cab98aa4e13e1ade8c141daeedd300a4603b7132819c484841bb7af3edce9e"},
1200 | {file = "yarl-1.20.1-cp313-cp313t-win32.whl", hash = "sha256:b121ff6a7cbd4abc28985b6028235491941b9fe8fe226e6fdc539c977ea1739d"},
1201 | {file = "yarl-1.20.1-cp313-cp313t-win_amd64.whl", hash = "sha256:541d050a355bbbc27e55d906bc91cb6fe42f96c01413dd0f4ed5a5240513874f"},
1202 | {file = "yarl-1.20.1-py3-none-any.whl", hash = "sha256:83b8eb083fe4683c6115795d9fc1cfaf2cbbefb19b3a1cb68f6527460f483a77"},
1203 | {file = "yarl-1.20.1.tar.gz", hash = "sha256:d017a4997ee50c91fd5466cef416231bb82177b93b029906cefc542ce14c35ac"},
1204 | ]
1205 |
1206 | [[package]]
1207 | name = "zipp"
1208 | version = "3.20.2"
1209 | requires_python = ">=3.8"
1210 | summary = "Backport of pathlib-compatible object wrapper for zip files"
1211 | groups = ["default"]
1212 | files = [
1213 | {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"},
1214 | {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"},
1215 | ]
1216 |
--------------------------------------------------------------------------------